zmq源码阅读——Msg.hpp & Msg.cpp 的 相关操作 (zmq中的消息)

来源:互联网 发布:优酷会员如何解绑淘宝 编辑:程序博客网 时间:2024/06/05 08:48
int zmq::msg_t::init_size (size_t size_){    if (size_ <= max_vsm_size) {        u.vsm.type = type_vsm; // 小消息的类型为type_vsm,这个值为101,相当于一个魔法数字,用来表示小消息        u.vsm.flags = 0;        u.vsm.size = (unsigned char) size_;    }    else {                    // 大消息        u.lmsg.type = type_lmsg;        u.lmsg.flags = 0;        u.lmsg.content =            (content_t*) malloc (sizeof (content_t) + size_); // size_就是可变长的消息大小        if (!u.lmsg.content) {            errno = ENOMEM;            return -1;        }        u.lmsg.content->data = u.lmsg.content + 1; // 指向那块可变长的内存区域        u.lmsg.content->size = size_;        u.lmsg.content->ffn = NULL;        u.lmsg.content->hint = NULL;        new (&u.lmsg.content->refcnt) zmq::atomic_counter_t (); // 设置引用计数    }    return 0;}
int zmq::msg_t::init ()   // 消息初始化函数{                             u.vsm.type = type_vsm; // 初始化一个msg消息,设置成小消息类型    u.vsm.flags = 0;      // 初始化flags    u.vsm.size = 0;       // 将小消息的大小初始化为0    return 0;             }       

根据已有的data和相应的size,和销毁函数,以及hint来初始化消息。这边消息指向data指针所指的内存区域int zmq::msg_t::init_data (void *data_, size_t size_, msg_free_fn *ffn_,    void *hint_)                 {                                    u.lmsg.type = type_lmsg;         u.lmsg.flags = 0;                u.lmsg.content = (content_t*) malloc (sizeof (content_t));    if (!u.lmsg.content) {               errno = ENOMEM;                  return -1;                   }                                                                 u.lmsg.content->data = data_;    u.lmsg.content->size = size_;    u.lmsg.content->ffn = ffn_;      u.lmsg.content->hint = hint_;    new (&u.lmsg.content->refcnt) zmq::atomic_counter_t ();    return 0;                                              }
// 获取数据的地址的函数,这样就能操作消息的数据内存了void *zmq::msg_t::data (){    //  Check the validity of the message.    zmq_assert (check ());    switch (u.base.type) {    case type_vsm:  // 如果是小消息,就返回stack上的vsm_data的地址        return u.vsm.data;    case type_lmsg: // 如果是大消息,就返回heap上的content->data        return u.lmsg.content->data;    default:  //如果是delimiter,返回是空指针         zmq_assert (false);        return NULL;    }}

// 处理方式和data()类似,返回消息的大小size_t zmq::msg_t::size (){    //  Check the validity of the message.    zmq_assert (check ());    switch (u.base.type) {    case type_vsm:        return u.vsm.size;    case type_lmsg:        return u.lmsg.content->size;    default:        zmq_assert (false);        return 0;    }

// 销毁消息int zmq::msg_t::close (){    //  Check the validity of the message.    if (unlikely (!check ())) {        errno = EFAULT;        return -1;    }    if (u.base.type == type_lmsg) {        // 如果不是共享的,或是引用计数为0,销毁它,销毁过程如下:        //  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)) {            // 1、销毁引用计数,因为创建引用计数的时候,我们使用placement new,所以我们需要调用它的析构函数。            //  We used "placement new" operator to initialize the reference            //  counter so we call the destructor explicitly now.            u.lmsg.content->refcnt.~atomic_counter_t ();            // 2、如果有注册相应的自定义的销毁函数,就调用该函数。            // 这种情况主要用于使用init_data(),自己来管理data所指向空间。            if (u.lmsg.content->ffn)                u.lmsg.content->ffn (u.lmsg.content->data,                    u.lmsg.content->hint);            // 3、调用free()释放heap的空间,注意,如果是使用init_size()来初始化消息,就会释放掉data的空间,            // 因为这块空间就是分配时多分配的size大小(在content下方)的那块            free (u.lmsg.content);        }    }    //  Make the message invalid.    u.base.type = 0; // 设置为0,表明该消息已经被废除了    return 0;}// 对于小消息,消息数据是分配在stack上的,因此不需要手动销毁// 对于大消息,消息数据是分配在heap上的,因此我们查看消息是不是shared模式,如果没有使用就直接销毁假如使用了共享模式,那么我们递减消息的引用计数,一旦引用计数为0,我们就销毁消息内容。

int zmq::msg_t::copy (msg_t &src_){    //  Check the validity of the source.    if (unlikely (!src_.check ())) {        errno = EFAULT;        return -1;    }    int rc = close ();    if (unlikely (rc < 0))        return rc;    if (src_.u.base.type == type_lmsg) {        //  One reference is added to shared messages. Non-shared messages        //  are turned into shared messages and reference count is set to 2.        if (src_.u.lmsg.flags & msg_t::shared) // 共享消息content引用,引用计数增加            src_.u.lmsg.content->refcnt.add (1);        else {            src_.u.lmsg.flags |= msg_t::shared;            src_.u.lmsg.content->refcnt.set (2);// 如果不是共享的,则设置成共享的,并将引用计数设置成2        }    }    *this = src_;    return 0;}

int zmq::msg_t::move (msg_t &src_){    //  Check the validity of the source.    if (unlikely (!src_.check ())) {        errno = EFAULT;        return -1;    }    int rc = close ();    if (unlikely (rc < 0))        return rc;    *this = src_;    rc = src_.init (); // 将source的消息充值成初始化的空消息    if (unlikely (rc < 0))        return rc;    return 0;}



0 0