ZMQ从入门到掌握二

ZMQ从入门到掌握<二>


源码走读


1.zmq_ctx_new()

//返回ctx_t对象
void *zmq_ctx_new (void)
{
    //  We do this before the ctx constructor since its embedded mailbox_t
    //  object needs the network to be up and running (at least on Windows).
    if (!zmq::initialize_network ()) {
        return NULL;
    }

    //  Create 0MQ context.
    zmq::ctx_t *ctx = new (std::nothrow) zmq::ctx_t;
    if (ctx) {
        if (!ctx->valid ()) {
            delete ctx;
            return NULL;
        }
    }
    return ctx;
}

函数返回context(上下文),其实调用的是ctx_t对象(实例化)

zmq::ctx_t::ctx_t () :
    _tag (ZMQ_CTX_TAG_VALUE_GOOD),
    _starting (true),
    _terminating (false),
    _reaper (NULL),
    _max_sockets (clipped_maxsocket (ZMQ_MAX_SOCKETS_DFLT)),
    _max_msgsz (INT_MAX),
    _io_thread_count (ZMQ_IO_THREADS_DFLT),
    _blocky (true),
    _ipv6 (false),
    _zero_copy (true)
{
#ifdef HAVE_FORK
    _pid = getpid ();
#endif
#ifdef ZMQ_HAVE_VMCI
    _vmci_fd = -1;
    _vmci_family = -1;
#endif

    //  Initialise crypto library, if needed.
    zmq::random_open ();

#ifdef ZMQ_USE_NSS
    NSS_NoDB_Init (NULL);
#endif

#ifdef ZMQ_USE_GNUTLS
    gnutls_global_init ();
#endif
}

主要就是设置初始化的参数;如;_max_sockets = 1024;_io_thread_count = 1;当然还有一些状态设置等等;


2.zmq_socket()

void *zmq_socket (void *ctx_, int type_)
{
	//对象为NULL,则返回
    if (!ctx_ || !(static_cast<zmq::ctx_t *> (ctx_))->check_tag ()) {
        errno = EFAULT;
        return NULL;
    }
	//强转
    zmq::ctx_t *ctx = static_cast<zmq::ctx_t *> (ctx_);
    zmq::socket_base_t *s = ctx->create_socket (type_);
    return (void *) s;
}

参数:

void *ctx_;zmq_ctx_new返回的上下文参数;

int type_:Socket types.

Socket types:

ZMQ_PAIR 0
ZMQ_PUB 1
ZMQ_SUB 2
ZMQ_REQ 3
ZMQ_REP 4
ZMQ_DEALER 5
ZMQ_ROUTER 6
ZMQ_PULL 7
ZMQ_PUSH 8
ZMQ_XPUB 9
ZMQ_XSUB 10
ZMQ_STREAM 11

返回值:创建生成的socket


调用create_socket()

zmq::socket_base_t *zmq::ctx_t::create_socket (int type_)
{
    scoped_lock_t locker (_slot_sync);
	//初始化邮箱数组,增加两个插槽(slots),
	//zmq_ctx_term thread 和 reaper thread
    if (unlikely (_starting)) {
        if (!start ())
            return NULL;
    }

    //  Once zmq_ctx_term() was called, we can't create new sockets.
    if (_terminating) {
        errno = ETERM;
        return NULL;
    }

    //  If max_sockets limit was reached, return error.
    if (_empty_slots.empty ()) {
        errno = EMFILE;
        return NULL;
    }

    //  Choose a slot for the socket.
    uint32_t slot = _empty_slots.back ();
    _empty_slots.pop_back ();

    //  Generate new unique socket ID.
	//生成新的唯一的套接字ID。
    int sid = (static_cast<int> (max_socket_id.add (1))) + 1;

    //  Create the socket and register its mailbox.
	//创建socket并且注册邮箱
    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;
}

调用start ()函数:

bool zmq::ctx_t::start ()
{
    //  Initialise the array of mailboxes. Additional two slots are for
    //  zmq_ctx_term thread and reaper thread.
    _opt_sync.lock ();
    const int term_and_reaper_threads_count = 2;
    const int mazmq = _max_sockets; //1023
    const int ios = _io_thread_count;	//1
    _opt_sync.unlock ();
    int slot_count = mazmq + ios + term_and_reaper_threads_count;//1026
    try {
		//增加容量,不创建对象
        _slots.reserve (slot_count);
        _empty_slots.reserve (slot_count - term_and_reaper_threads_count);
    }
    catch (const std::bad_alloc &) {
        errno = ENOMEM;
        return false;
    }
	//改变了容器的大小,且创建了容器中的对象
    _slots.resize (term_and_reaper_threads_count);

    //  Initialise the infrastructure for zmq_ctx_term thread.
    _slots[term_tid] = &_term_mailbox;

	//创建线程
    _reaper = new (std::nothrow) reaper_t (this, reaper_tid);
    if (!_reaper) {
        errno = ENOMEM;
        goto fail_cleanup_slots;
    }
    if (!_reaper->get_mailbox ()->valid ())
        goto fail_cleanup_reaper;
    _slots[reaper_tid] = _reaper->get_mailbox ();
    _reaper->start ();

    //  Create I/O thread objects and launch them.
    _slots.resize (slot_count, NULL);
	//创建IO线程并启动
    for (int i = term_and_reaper_threads_count;
         i != ios + term_and_reaper_threads_count; i++) {
        io_thread_t *io_thread = new (std::nothrow) io_thread_t (this, i);
        if (!io_thread) {
            errno = ENOMEM;
            goto fail_cleanup_reaper;
        }
        if (!io_thread->get_mailbox ()->valid ()) {
            delete io_thread;
            goto fail_cleanup_reaper;
        }
        _io_threads.push_back (io_thread);
        _slots[i] = io_thread->get_mailbox ();
        io_thread->start ();
    }

    //  In the unused part of the slot array, create a list of empty slots.
    for (int32_t i = static_cast<int32_t> (_slots.size ()) - 1;
         i >= static_cast<int32_t> (ios) + term_and_reaper_threads_count; i--) {
        _empty_slots.push_back (i);
    }

    _starting = false;
    return true;

fail_cleanup_reaper:
    _reaper->stop ();
    delete _reaper;
    _reaper = NULL;

fail_cleanup_slots:
    _slots.clear ();
    return false;
}

想了解学习更多C++后台服务器方面的知识,请关注:
微信公众号:C++后台服务器开发

扫描二维码关注公众号,回复: 9351426 查看本文章

发布了197 篇原创文章 · 获赞 68 · 访问量 7万+

猜你喜欢

转载自blog.csdn.net/Travelerwz/article/details/103208171
zmq
今日推荐