live555 中的socket的任务调度分析

时间:2023-03-10 06:35:04
live555 中的socket的任务调度分析

1.添加一个socket任务

envir().taskScheduler().setBackgroundHandling(socketNum, SOCKET_WRITABLE|SOCKET_EXCEPTION,
(TaskScheduler::BackgroundHandlerProc*)&connectionHandler, this);

2.接下来就会把相关参数设置进socket任务集合中去,接下来就是等待任务调度。

 fHandlers->assignHandler(socketNum, conditionSet, handlerProc, clientData)
class HandlerSet是一个链表类,里面存在一个成员变量fHandlers,是这个链表的头结点。
assignHandler函数会将socket相关的一些参数,函数指针等封装成一个新节点,插入链表。

live555 中的socket的任务调度分析

3.doEventLoop 是事件循环函数,用于调度事件。

void BasicTaskScheduler0::doEventLoop(char* watchVariable) {
// Repeatedly loop, handling readble sockets and timed events:
while (1) {
if (watchVariable != NULL && *watchVariable != 0) break;
SingleStep();
}
}

4.在SingleStep函数中使用select来监听socket的任务的发生

int selectResult = select(fMaxNumSockets, &readSet, &writeSet, &exceptionSet, &tv_timeToDelay); 

在SingleStep中使用了一个参数 fLastHandledSocketNum 记录了上次任务发生时该任务在链表中的位置。

a.检测是否上次的任务在任务链表中的某一个位置,如果在就从这个位置开始查找是否发生socket任务。

live555 中的socket的任务调度分析
  if (fLastHandledSocketNum >= 0) {
while ((handler = iter.next()) != NULL) {
if (handler->socketNum == fLastHandledSocketNum) break;
}
if (handler == NULL) {
fLastHandledSocketNum = -1;
iter.reset(); // start from the beginning instead
}
}
while ((handler = iter.next()) != NULL) {
int sock = handler->socketNum; // alias
int resultConditionSet = 0;
if (FD_ISSET(sock, &readSet) && FD_ISSET(sock, &fReadSet)/*sanity check*/) resultConditionSet |= SOCKET_READABLE;
if (FD_ISSET(sock, &writeSet) && FD_ISSET(sock, &fWriteSet)/*sanity check*/) resultConditionSet |= SOCKET_WRITABLE;
if (FD_ISSET(sock, &exceptionSet) && FD_ISSET(sock, &fExceptionSet)/*sanity check*/) resultConditionSet |= SOCKET_EXCEPTION;
if ((resultConditionSet&handler->conditionSet) != 0 && handler->handlerProc != NULL) {
fLastHandledSocketNum = sock;
// Note: we set "fLastHandledSocketNum" before calling the handler,
// in case the handler calls "doEventLoop()" reentrantly.
(*handler->handlerProc)(handler->clientData, resultConditionSet);
break;
}
}
live555 中的socket的任务调度分析

b. 如果没有任何soket任务发生,于是认为有可能在fLastHandledSocketNum 任务链表位置前面的某一个地方发生了socket任务。接下来就

从链表头开始遍历,查找socket任务的发生。

if (handler == NULL && fLastHandledSocketNum >= ) {
// We didn't call a handler, but we didn't get to check all of them,
// so try again from the beginning:
iter.reset();
while ((handler = iter.next()) != NULL) {
int sock = handler->socketNum; // alias
int resultConditionSet = ;
if (FD_ISSET(sock, &readSet) && FD_ISSET(sock, &fReadSet)/*sanity check*/) resultConditionSet |= SOCKET_READABLE;
if (FD_ISSET(sock, &writeSet) && FD_ISSET(sock, &fWriteSet)/*sanity check*/) resultConditionSet |= SOCKET_WRITABLE;
if (FD_ISSET(sock, &exceptionSet) && FD_ISSET(sock, &fExceptionSet)/*sanity check*/) resultConditionSet |= SOCKET_EXCEPTION;
if ((resultConditionSet&handler->conditionSet) != && handler->handlerProc != NULL) {
fLastHandledSocketNum = sock;
// Note: we set "fLastHandledSocketNum" before calling the handler,
// in case the handler calls "doEventLoop()" reentrantly.
(*handler->handlerProc)(handler->clientData, resultConditionSet);
break;
}
}
if (handler == NULL) fLastHandledSocketNum = -;//because we didn't call a handler
}

5.查找到socket任务的socket时,调度相关的函数指针,执行相关函数。同时 fLastHandledSocketNum = sock

       fLastHandledSocketNum = sock;
(*handler->handlerProc)(handler->clientData, resultConditionSet);

原文链接:https://www.cnblogs.com/superPerfect/p/3611625.html