zeromq源码学习——ctx创建

来源:互联网 发布:唯一网络被收购 编辑:程序博客网 时间:2024/05/29 18:19

ctx_t封装了与zeromq库相关的全部全局状态。当使用zeromq时,需要调用zmq_ctx_new函数创建一个ctx_t对象,并返回该对象,没有对context对象进行初始化。其中一个重要的变量starting,它为true时,表示context创建,但是未创建任何一个socket对象。

当创建地一个socket时,会先初始化context对象,来准备运行环境。

void *zmq_socket (void *ctx_, int type_){    if (!ctx_ || !((zmq::ctx_t *) ctx_)->check_tag ()) {        errno = EFAULT;        return NULL;    }    zmq::ctx_t *ctx = (zmq::ctx_t *) ctx_;    zmq::socket_base_t *s = ctx->create_socket (type_);    return (void *) s;}

通过ctx_t中的create_socke函数创建socket:

zmq::socket_base_t *zmq::ctx_t::create_socket (int type_){    scoped_lock_t locker(slot_sync);    if (unlikely (starting)) {        starting = false;//确保context对象只会初始化一次        opt_sync.lock ();        int mazmq = max_sockets;//最大sockets数量        int ios = io_thread_count;//io线程数量        opt_sync.unlock ();        slot_count = mazmq + ios + 2;//槽的总数,sockets+io+term+reaper        slots = (i_mailbox **) malloc (sizeof (i_mailbox*) * slot_count);        alloc_assert (slots);        //初始化term线程的一些基础设施,用于销毁context时,执行一些清理工作        slots [term_tid] = &term_mailbox;        //创建reaper线程,并启动(还不清楚reaper线程的作用)        reaper = new (std::nothrow) reaper_t (this, reaper_tid);        alloc_assert (reaper);        slots [reaper_tid] = reaper->get_mailbox ();        reaper->start ();        //创建IO线程,并启动,可以启动多个IO线程        for (int i = 2; i != ios + 2; i++) {            io_thread_t *io_thread = new (std::nothrow) io_thread_t (this, i);            alloc_assert (io_thread);            io_threads.push_back (io_thread);            slots [i] = io_thread->get_mailbox ();            io_thread->start ();        }        //初始化未使用的socket槽索引        for (int32_t i = (int32_t) slot_count - 1;              i >= (int32_t) ios + 2; i--) {            empty_slots.push_back (i);            slots [i] = NULL;        }    }    //context已经处于销毁状态,则不能创建socket    if (terminating) {        errno = ETERM;        return NULL;    }    //socket已经达到最大数量,不能创建    if (empty_slots.empty ()) {        errno = EMFILE;        return NULL;    }    //为socket选择一个槽索引    uint32_t slot = empty_slots.back ();    empty_slots.pop_back ();    //  Generate new unique socket ID.    int sid = ((int) max_socket_id.add (1)) + 1;    //创建socket,并注册mailbox    socket_base_t *s = socket_base_t::create (type_, this, slot, sid);    if (!s) {        empty_slots.push_back (slot);        return NULL;    }    sockets.push_back (s);    slots [slot] = s->get_mailbox ();    return s;}