live555 中的socket的任务调度分析

 

1.添加一个socket任务

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

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

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

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

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

 

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

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

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

a.检测是否上次的任务在任务链表中的某一个位置,如果在就从这个位置开始查找是否发生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;
    }
  }

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

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

 1   if (handler == NULL && fLastHandledSocketNum >= 0) {
 2     // We didn't call a handler, but we didn't get to check all of them,
 3     // so try again from the beginning:
 4     iter.reset();
 5     while ((handler = iter.next()) != NULL) {
 6       int sock = handler->socketNum; // alias
 7       int resultConditionSet = 0;
 8       if (FD_ISSET(sock, &readSet) && FD_ISSET(sock, &fReadSet)/*sanity check*/) resultConditionSet |= SOCKET_READABLE;
 9       if (FD_ISSET(sock, &writeSet) && FD_ISSET(sock, &fWriteSet)/*sanity check*/) resultConditionSet |= SOCKET_WRITABLE;
10       if (FD_ISSET(sock, &exceptionSet) && FD_ISSET(sock, &fExceptionSet)/*sanity check*/) resultConditionSet |= SOCKET_EXCEPTION;
11       if ((resultConditionSet&handler->conditionSet) != 0 && handler->handlerProc != NULL) {
12     fLastHandledSocketNum = sock;
13         // Note: we set "fLastHandledSocketNum" before calling the handler,
14             // in case the handler calls "doEventLoop()" reentrantly.
15     (*handler->handlerProc)(handler->clientData, resultConditionSet);
16     break;
17       }
18     }
19     if (handler == NULL) fLastHandledSocketNum = -1;//because we didn't call a handler
20   }

 

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

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

 

posted @ 2014-03-19 15:57  superPerfect  阅读(2042)  评论(0编辑  收藏  举报