// This structure defines the commands that can be sent between threads.
struct command_t
{
// Object to process the command.
zmq::object_t *destination;
class object_t
{
public:
object_t (zmq::ctx_t *ctx_, uint32_t tid_);
void process_command (zmq::command_t &cmd_);
...
protected:
...
private:
zmq::ctx_t *ctx;// Context provides access to the global state.
uint32_t tid;// Thread ID of the thread the object belongs to.
void send_command (command_t &cmd_);
}
void zmq::io_thread_t::in_event ()
{
// TODO: Do we want to limit number of commands I/O thread can
// process in a single go?
command_t cmd;
int rc = mailbox.recv (&cmd, 0);
int zmq::socket_base_t::getsockopt (int option_, void *optval_,size_t *optvallen_)
int zmq::socket_base_t::bind (const char *addr_)
int zmq::socket_base_t::connect (const char *addr_)
int zmq::socket_base_t::term_endpoint (const char *addr_)
int zmq::socket_base_t::send (msg_t *msg_, int flags_)
int zmq::socket_base_t::recv (msg_t *msg_, int flags_)
void zmq::socket_base_t::in_event ()//这个函数只有在销毁socke的时候会被用到,在后面讲zmq_close的时候会说到
检查的手段就是调用process_commands方法:
int zmq::socket_base_t::process_commands (int timeout_, bool throttle_)
{
int rc;
command_t cmd;
if (timeout_ != 0) {
// If we are asked to wait, simply ask mailbox to wait.
rc = mailbox.recv (&cmd, timeout_);
}
else {
some code
rc = mailbox.recv (&cmd, 0);
}
// Process all available commands.
while (rc == 0) {
cmd.destination->process_command (cmd);
rc = mailbox.recv (&cmd, 0);
}
some code
}
class mailbox_t
{
public:
mailbox_t ();
~mailbox_t ();
fd_t get_fd ();
void send (const command_t &cmd_);
int recv (command_t *cmd_, int timeout_);
private: typedef ypipe_t <command_t, command_pipe_granularity> cpipe_t; // The pipe to store actual commands. cpipe_t cpipe; signaler_t signaler;// Signaler to pass signals from writer thread to reader thread.
// There’s only one thread receiving from the mailbox, but there // is arbitrary number of threads sending. Given that ypipe requires // synchronised access on both of its endpoints, we have to synchronise // the sending side. mutex_t sync;//只有一个线程从mailbox中接受消息,但是会有大量的线程往mailbox中发送消息,鉴于ypipe需要同步访问两端的两端,我们必须同步发送端 bool active; // True if the underlying pipe is active, ie. when we are allowed to read commands from it.
int zmq::mailbox_t::recv (command_t *cmd_, int timeout_)
{
// Try to get the command straight away.
if (active) {//开始的时候,信箱是未激活状态
bool ok = cpipe.read (cmd_);
if (ok)
return 0;
<span style="color: #008000;"> // If there are no more commands available, switch into passive state.</span>
<span style="color: #3366ff;"><strong>// 没有命令可读时,先把信箱设置为未激活状态,表示没命令可读,然后把对方发过来的激活信箱的信号处理一下(没什么特殊的处理,就是接受一下)</strong></span>
active = false<span>;
signaler.recv ();
}
// Wait for signal from the command sender. int rc = signaler.wait (timeout_);//signaler.wait的返回值有三种①wait函数出错,返回-1,并且设置errno=EINTR②返回-1并且errno=EAGAIN,表示信号没等到③等到信号。 if (rc != 0 && (errno == EAGAIN || errno == EINTR))//这里对应wait的前两种情况 return -1;
// We’ve got the signal. Now we can switch into active state. active = true;//等到激活信箱的信号了,激活信箱
</strong></span><span style="color: #008000;">// Get a command.</span>
errno_assert (rc == 0<span>);
bool ok =<span> cpipe.read (cmd_);
zmq_assert (ok);
return 0<span>;