用于从队列中读取消息,其调用如下:
string swoole_process->pop(int $maxsize = 8192);
下面我们分析下其流程。
static PHP_METHOD(swoole_process, pop)
{
long maxsize = SW_MSGMAX;
//解析输入参数,输入参数就一个maxsize,表示要读取的最大消息长度,默认为8192byte
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &maxsize) == FAILURE)
{
RETURN_FALSE;
}
if (maxsize > SW_MSGMAX || maxsize <= 0)//参数有效性检查
{
maxsize = SW_MSGMAX;
}
swWorker *process = swoole_get_object(getThis());//读取内部封装对象swWorker信息
if (!process->queue)//队列未初始化
{
swoole_php_fatal_error(E_WARNING, "no msgqueue, can not use pop()");
RETURN_FALSE;
}
struct
{
long type;
char data[SW_MSGMAX];
} message;
if (process->ipc_mode == 2)//按官方文档定义,ipc_mode为2时,表示争抢模式,即所有进程可以从队列里读取数据
{
message.type = 0;
}
else//非争抢模式,和进程关联
{
message.type = process->id;
}
//从队列中读取数据
int n = swMsgQueue_pop(process->queue, (swQueue_data *) &message, maxsize);
if (n < 0)
{
RETURN_FALSE;
}
SW_RETURN_STRINGL(message.data, n, 1);//组织成字符串返回
}
int swMsgQueue_pop(swMsgQueue *q, swQueue_data *data, int length)
{
int ret = msgrcv(q->msg_id, data, length, data->mtype, q->flags);//通过linux系统调用读取消息
if (ret < 0)//读取失败
{
SwooleG.error = errno;
if (errno != ENOMSG && errno != EINTR)//不是被信号中断和阻塞情况下无消息可读
{
swSysError("msgrcv(%d, %d, %ld) failed.", q->msg_id, length, data->mtype);//打印错误信息
}
}
return ret;
}