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

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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值