2
Copyright (c) 2009-2011 250bpm s.r.o.
3
Copyright (c) 2007-2009 iMatix Corporation
4
Copyright (c) 2007-2011 Other contributors as noted in the AUTHORS file
6
This file is part of 0MQ.
8
0MQ is free software; you can redistribute it and/or modify it under
9
the terms of the GNU Lesser General Public License as published by
10
the Free Software Foundation; either version 3 of the License, or
11
(at your option) any later version.
13
0MQ is distributed in the hope that it will be useful,
14
but WITHOUT ANY WARRANTY; without even the implied warranty of
15
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
GNU Lesser General Public License for more details.
18
You should have received a copy of the GNU Lesser General Public License
19
along with this program. If not, see <http://www.gnu.org/licenses/>.
23
#include "../include/zmq.h"
34
// Check whether the sizes of public representation of the message (zmq_msg_t)
35
// and private represenation of the message (zmq::msg_t) match.
36
typedef char zmq_msg_size_check
37
[2 * ((sizeof (zmq::msg_t) == sizeof (zmq_msg_t)) != 0) - 1];
39
bool zmq::msg_t::check ()
41
return u.base.type >= type_min && u.base.type <= type_max;
44
int zmq::msg_t::init ()
46
u.vsm.type = type_vsm;
52
int zmq::msg_t::init_size (size_t size_)
54
if (size_ <= max_vsm_size) {
55
u.vsm.type = type_vsm;
57
u.vsm.size = (unsigned char) size_;
60
u.lmsg.type = type_lmsg;
63
(content_t*) malloc (sizeof (content_t) + size_);
64
if (!u.lmsg.content) {
69
u.lmsg.content->data = u.lmsg.content + 1;
70
u.lmsg.content->size = size_;
71
u.lmsg.content->ffn = NULL;
72
u.lmsg.content->hint = NULL;
73
new (&u.lmsg.content->refcnt) zmq::atomic_counter_t ();
78
int zmq::msg_t::init_data (void *data_, size_t size_, msg_free_fn *ffn_,
81
u.lmsg.type = type_lmsg;
83
u.lmsg.content = (content_t*) malloc (sizeof (content_t));
84
if (!u.lmsg.content) {
89
u.lmsg.content->data = data_;
90
u.lmsg.content->size = size_;
91
u.lmsg.content->ffn = ffn_;
92
u.lmsg.content->hint = hint_;
93
new (&u.lmsg.content->refcnt) zmq::atomic_counter_t ();
98
int zmq::msg_t::init_delimiter ()
100
u.delimiter.type = type_delimiter;
101
u.delimiter.flags = 0;
105
int zmq::msg_t::close ()
107
// Check the validity of the message.
108
if (unlikely (!check ())) {
113
if (u.base.type == type_lmsg) {
115
// If the content is not shared, or if it is shared and the reference
116
// count has dropped to zero, deallocate it.
117
if (!(u.lmsg.flags & msg_t::shared) ||
118
!u.lmsg.content->refcnt.sub (1)) {
120
// We used "placement new" operator to initialize the reference
121
// counter so we call the destructor explicitly now.
122
u.lmsg.content->refcnt.~atomic_counter_t ();
124
if (u.lmsg.content->ffn)
125
u.lmsg.content->ffn (u.lmsg.content->data,
126
u.lmsg.content->hint);
127
free (u.lmsg.content);
131
// Make the message invalid.
138
int zmq::msg_t::move (msg_t &src_)
140
// Check the validity of the source.
141
if (unlikely (!src_.check ())) {
147
if (unlikely (rc < 0))
153
if (unlikely (rc < 0))
159
int zmq::msg_t::copy (msg_t &src_)
161
// Check the validity of the source.
162
if (unlikely (!src_.check ())) {
168
if (unlikely (rc < 0))
171
if (src_.u.base.type == type_lmsg) {
173
// One reference is added to shared messages. Non-shared messages
174
// are turned into shared messages and reference count is set to 2.
175
if (src_.u.lmsg.flags & msg_t::shared)
176
src_.u.lmsg.content->refcnt.add (1);
178
src_.u.lmsg.flags |= msg_t::shared;
179
src_.u.lmsg.content->refcnt.set (2);
189
void *zmq::msg_t::data ()
191
// Check the validity of the message.
192
zmq_assert (check ());
194
switch (u.base.type) {
198
return u.lmsg.content->data;
205
size_t zmq::msg_t::size ()
207
// Check the validity of the message.
208
zmq_assert (check ());
210
switch (u.base.type) {
214
return u.lmsg.content->size;
221
unsigned char zmq::msg_t::flags ()
226
void zmq::msg_t::set_flags (unsigned char flags_)
228
u.base.flags |= flags_;
231
void zmq::msg_t::reset_flags (unsigned char flags_)
233
u.base.flags &= ~flags_;
236
bool zmq::msg_t::is_delimiter ()
238
return u.base.type == type_delimiter;
241
bool zmq::msg_t::is_vsm ()
243
return u.base.type == type_vsm;
246
void zmq::msg_t::add_refs (int refs_)
248
zmq_assert (refs_ >= 0);
250
// No copies required.
254
// VSMs and delimiters can be copied straight away. The only message type
255
// that needs special care are long messages.
256
if (u.base.type == type_lmsg) {
257
if (u.lmsg.flags & msg_t::shared)
258
u.lmsg.content->refcnt.add (refs_);
260
u.lmsg.content->refcnt.set (refs_ + 1);
261
u.lmsg.flags |= msg_t::shared;
266
bool zmq::msg_t::rm_refs (int refs_)
268
zmq_assert (refs_ >= 0);
270
// No copies required.
274
// If there's only one reference close the message.
275
if (u.base.type != type_lmsg || !(u.lmsg.flags & msg_t::shared)) {
280
// The only message type that needs special care are long messages.
281
if (!u.lmsg.content->refcnt.sub (refs_)) {