1 | /* |
2 | Copyright (c) 2007-2016 Contributors as noted in the AUTHORS file |
3 | |
4 | This file is part of libzmq, the ZeroMQ core engine in C++. |
5 | |
6 | libzmq is free software; you can redistribute it and/or modify it under |
7 | the terms of the GNU Lesser General Public License (LGPL) as published |
8 | by the Free Software Foundation; either version 3 of the License, or |
9 | (at your option) any later version. |
10 | |
11 | As a special exception, the Contributors give you permission to link |
12 | this library with independent modules to produce an executable, |
13 | regardless of the license terms of these independent modules, and to |
14 | copy and distribute the resulting executable under terms of your choice, |
15 | provided that you also meet, for each linked independent module, the |
16 | terms and conditions of the license of that module. An independent |
17 | module is a module which is not derived from or based on this library. |
18 | If you modify this library, you must extend this exception to your |
19 | version of the library. |
20 | |
21 | libzmq is distributed in the hope that it will be useful, but WITHOUT |
22 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
23 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public |
24 | License for more details. |
25 | |
26 | You should have received a copy of the GNU Lesser General Public License |
27 | along with this program. If not, see <http://www.gnu.org/licenses/>. |
28 | */ |
29 | |
30 | #ifndef __ZMQ_DECODER_ALLOCATORS_HPP_INCLUDED__ |
31 | #define __ZMQ_DECODER_ALLOCATORS_HPP_INCLUDED__ |
32 | |
33 | #include <cstddef> |
34 | #include <cstdlib> |
35 | |
36 | #include "atomic_counter.hpp" |
37 | #include "msg.hpp" |
38 | #include "err.hpp" |
39 | |
40 | namespace zmq |
41 | { |
42 | // Static buffer policy. |
43 | class c_single_allocator |
44 | { |
45 | public: |
46 | explicit c_single_allocator (std::size_t bufsize_) : |
47 | _buf_size (bufsize_), |
48 | _buf (static_cast<unsigned char *> (std::malloc (_buf_size))) |
49 | { |
50 | alloc_assert (_buf); |
51 | } |
52 | |
53 | ~c_single_allocator () { std::free (_buf); } |
54 | |
55 | unsigned char *allocate () { return _buf; } |
56 | |
57 | void deallocate () {} |
58 | |
59 | std::size_t size () const { return _buf_size; } |
60 | |
61 | void resize (std::size_t new_size_) { _buf_size = new_size_; } |
62 | |
63 | private: |
64 | std::size_t _buf_size; |
65 | unsigned char *_buf; |
66 | |
67 | ZMQ_NON_COPYABLE_NOR_MOVABLE (c_single_allocator) |
68 | }; |
69 | |
70 | // This allocator allocates a reference counted buffer which is used by v2_decoder_t |
71 | // to use zero-copy msg::init_data to create messages with memory from this buffer as |
72 | // data storage. |
73 | // |
74 | // The buffer is allocated with a reference count of 1 to make sure that is is alive while |
75 | // decoding messages. Otherwise, it is possible that e.g. the first message increases the count |
76 | // from zero to one, gets passed to the user application, processed in the user thread and deleted |
77 | // which would then deallocate the buffer. The drawback is that the buffer may be allocated longer |
78 | // than necessary because it is only deleted when allocate is called the next time. |
79 | class shared_message_memory_allocator |
80 | { |
81 | public: |
82 | explicit shared_message_memory_allocator (std::size_t bufsize_); |
83 | |
84 | // Create an allocator for a maximum number of messages |
85 | shared_message_memory_allocator (std::size_t bufsize_, |
86 | std::size_t max_messages_); |
87 | |
88 | ~shared_message_memory_allocator (); |
89 | |
90 | // Allocate a new buffer |
91 | // |
92 | // This releases the current buffer to be bound to the lifetime of the messages |
93 | // created on this buffer. |
94 | unsigned char *allocate (); |
95 | |
96 | // force deallocation of buffer. |
97 | void deallocate (); |
98 | |
99 | // Give up ownership of the buffer. The buffer's lifetime is now coupled to |
100 | // the messages constructed on top of it. |
101 | unsigned char *release (); |
102 | |
103 | void inc_ref (); |
104 | |
105 | static void call_dec_ref (void *, void *hint_); |
106 | |
107 | std::size_t size () const; |
108 | |
109 | // Return pointer to the first message data byte. |
110 | unsigned char *data (); |
111 | |
112 | // Return pointer to the first byte of the buffer. |
113 | unsigned char *buffer () { return _buf; } |
114 | |
115 | void resize (std::size_t new_size_) { _buf_size = new_size_; } |
116 | |
117 | zmq::msg_t::content_t *provide_content () { return _msg_content; } |
118 | |
119 | void advance_content () { _msg_content++; } |
120 | |
121 | private: |
122 | void clear (); |
123 | |
124 | unsigned char *_buf; |
125 | std::size_t _buf_size; |
126 | const std::size_t _max_size; |
127 | zmq::msg_t::content_t *_msg_content; |
128 | std::size_t _max_counters; |
129 | }; |
130 | } |
131 | |
132 | #endif |
133 | |