zeromq源码学习——ctx创建

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;
}

你可能感兴趣的:(zeromq)