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++後臺服務器開發