int zmq::msg_t::close () { // Check the validity of the message. if (unlikely (!check ())) { errno = EFAULT; return -1; } if (u.base.type == type_lmsg) { // If the content is not shared, or if it is shared and the reference // count has dropped to zero, deallocate it. if (!(u.lmsg.flags & msg_t::shared) || !u.lmsg.content->refcnt.sub (1)) { // We used "placement new" operator to initialize the reference // counter so we call the destructor explicitly now. u.lmsg.content->refcnt.~atomic_counter_t (); if (u.lmsg.content->ffn) u.lmsg.content->ffn (u.lmsg.content->data, u.lmsg.content->hint); free (u.lmsg.content); } } if (is_zcmsg()) { zmq_assert( u.zclmsg.content->ffn ); // If the content is not shared, or if it is shared and the reference // count has dropped to zero, deallocate it. if (!(u.zclmsg.flags & msg_t::shared) || !u.zclmsg.content->refcnt.sub (1)) { // We used "placement new" operator to initialize the reference // counter so we call the destructor explicitly now. u.zclmsg.content->refcnt.~atomic_counter_t (); u.zclmsg.content->ffn (u.zclmsg.content->data, u.zclmsg.content->hint); } } if (u.base.metadata != NULL) { if (u.base.metadata->drop_ref ()) { LIBZMQ_DELETE(u.base.metadata); } u.base.metadata = NULL; } // Make the message invalid. u.base.type = 0; return 0; }
bool zmq::msg_t::rm_refs (int refs_) { zmq_assert (refs_ >= 0); // Operation not supported for messages with metadata. zmq_assert (u.base.metadata == NULL); // No copies required. if (!refs_) return true; // If there's only one reference close the message. if ( (u.base.type != type_zclmsg && u.base.type != type_lmsg) || !(u.base.flags & msg_t::shared)) { close (); return false; } // The only message type that needs special care are long and zcopy messages. if (u.base.type == type_lmsg && !u.lmsg.content->refcnt.sub(refs_)) { // We used "placement new" operator to initialize the reference // counter so we call the destructor explicitly now. u.lmsg.content->refcnt.~atomic_counter_t (); if (u.lmsg.content->ffn) u.lmsg.content->ffn (u.lmsg.content->data, u.lmsg.content->hint); free (u.lmsg.content); return false; } if (is_zcmsg() && !u.zclmsg.refcnt->sub(refs_)) { // storage for rfcnt is provided externally if (u.zclmsg.ffn) { u.zclmsg.ffn(u.zclmsg.data, u.zclmsg.hint); } return false; } return true; }
void zmq::msg_t::add_refs (int refs_) { zmq_assert (refs_ >= 0); // Operation not supported for messages with metadata. zmq_assert (u.base.metadata == NULL); // No copies required. if (!refs_) return; // VSMs, CMSGS and delimiters can be copied straight away. The only // message type that needs special care are long messages. if (u.base.type == type_lmsg || is_zcmsg() ) { if (u.base.flags & msg_t::shared) refcnt()->add (refs_); else { refcnt()->set (refs_ + 1); u.base.flags |= msg_t::shared; } } }