Line data Source code
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 : #include "precompiled.hpp"
31 : #include "decoder_allocators.hpp"
32 :
33 : #include <cmath>
34 :
35 : #include "msg.hpp"
36 :
37 4323 : zmq::shared_message_memory_allocator::shared_message_memory_allocator (std::size_t bufsize_) :
38 : buf(NULL),
39 : bufsize(0),
40 : max_size(bufsize_),
41 : msg_content(NULL),
42 4323 : maxCounters (static_cast <size_t> (std::ceil (static_cast <double> (max_size) / static_cast <double> (msg_t::max_vsm_size))))
43 : {
44 4323 : }
45 :
46 33 : zmq::shared_message_memory_allocator::shared_message_memory_allocator (std::size_t bufsize_, std::size_t maxMessages) :
47 : buf(NULL),
48 : bufsize(0),
49 : max_size(bufsize_),
50 : msg_content(NULL),
51 33 : maxCounters(maxMessages)
52 : {
53 33 : }
54 :
55 4356 : zmq::shared_message_memory_allocator::~shared_message_memory_allocator ()
56 : {
57 4356 : deallocate();
58 4356 : }
59 :
60 13432 : unsigned char* zmq::shared_message_memory_allocator::allocate ()
61 : {
62 13432 : if (buf) {
63 : // release reference count to couple lifetime to messages
64 9047 : zmq::atomic_counter_t* c = reinterpret_cast<zmq::atomic_counter_t* >(buf);
65 :
66 : // if refcnt drops to 0, there are no message using the buffer
67 : // because either all messages have been closed or only vsm-messages
68 : // were created
69 9047 : if (c->sub (1)) {
70 : // buffer is still in use as message data. "Release" it and create a new one
71 : // release pointer because we are going to create a new buffer
72 : release ();
73 : }
74 : }
75 :
76 : // if buf != NULL it is not used by any message so we can re-use it for the next run
77 13432 : if (!buf) {
78 : // allocate memory for reference counters together with reception buffer
79 : std::size_t const allocationsize =
80 8770 : max_size + sizeof (zmq::atomic_counter_t) +
81 8770 : maxCounters * sizeof (zmq::msg_t::content_t);
82 :
83 4385 : buf = static_cast <unsigned char *> (std::malloc (allocationsize));
84 4385 : alloc_assert (buf);
85 :
86 4385 : new (buf) atomic_counter_t (1);
87 : } else {
88 : // release reference count to couple lifetime to messages
89 9047 : zmq::atomic_counter_t *c = reinterpret_cast <zmq::atomic_counter_t *> (buf);
90 : c->set (1);
91 : }
92 :
93 13432 : bufsize = max_size;
94 13432 : msg_content = reinterpret_cast <zmq::msg_t::content_t*> (buf + sizeof (atomic_counter_t) + max_size);
95 13432 : return buf + sizeof (zmq::atomic_counter_t);
96 : }
97 :
98 8679 : void zmq::shared_message_memory_allocator::deallocate ()
99 : {
100 8679 : zmq::atomic_counter_t* c = reinterpret_cast<zmq::atomic_counter_t* >(buf);
101 13031 : if (buf && !c->sub(1)) {
102 4352 : std::free(buf);
103 : }
104 : release();
105 8679 : }
106 :
107 33 : unsigned char* zmq::shared_message_memory_allocator::release ()
108 : {
109 8712 : unsigned char* b = buf;
110 8712 : buf = NULL;
111 8712 : bufsize = 0;
112 8712 : msg_content = NULL;
113 :
114 33 : return b;
115 : }
116 :
117 1200 : void zmq::shared_message_memory_allocator::inc_ref ()
118 : {
119 1200 : (reinterpret_cast <zmq::atomic_counter_t*> (buf))->add (1);
120 1200 : }
121 :
122 1233 : void zmq::shared_message_memory_allocator::call_dec_ref(void*, void* hint)
123 : {
124 1233 : zmq_assert (hint);
125 1233 : unsigned char* buf = static_cast <unsigned char*> (hint);
126 1233 : zmq::atomic_counter_t* c = reinterpret_cast <zmq::atomic_counter_t*> (buf);
127 :
128 1233 : if (!c->sub (1)) {
129 : c->~atomic_counter_t ();
130 33 : std::free (buf);
131 33 : buf = NULL;
132 : }
133 1233 : }
134 :
135 :
136 657294 : std::size_t zmq::shared_message_memory_allocator::size () const
137 : {
138 657294 : return bufsize;
139 : }
140 :
141 639189 : unsigned char* zmq::shared_message_memory_allocator::data ()
142 : {
143 639189 : return buf + sizeof (zmq::atomic_counter_t);
144 : }
|