live555 singleStep 分析

来源:互联网 发布:视频慢放软件下载 编辑:程序博客网 时间:2024/06/06 20:13

最近看了看live555代码,看到这部分随手写下来做个记录

1. live555是用的select模型

2. 在处理函数里做了多种操作

处理各个socket上事件,回调函数

        处理延迟队列,和队列上的事件,是发送事件,控制发送数据包速度

处理事件响应

个人见解:

感觉这个模型太累了,都是在一个线程里干,效率必定低


void BasicTaskScheduler::SingleStep(unsigned maxDelayTime) {  fd_set readSet = fReadSet; // make a copy for this select() call  fd_set writeSet = fWriteSet; // ditto  fd_set exceptionSet = fExceptionSet; // ditto  //DelayInterval const& timeToDelay = fDelayQueue.timeToNextAlarm();  DelayInterval timeToDelay(0, 0);  fDelayQueue.timeToNextAlarm(timeToDelay);  struct timeval tv_timeToDelay;  tv_timeToDelay.tv_sec = timeToDelay.seconds();  tv_timeToDelay.tv_usec = timeToDelay.useconds();  // Very large "tv_sec" values cause select() to fail.  // Don't make it any larger than 1 million seconds (11.5 days)  const long MAX_TV_SEC = MILLION;  if (tv_timeToDelay.tv_sec > MAX_TV_SEC) {    tv_timeToDelay.tv_sec = MAX_TV_SEC;  }  // Also check our "maxDelayTime" parameter (if it's > 0):  if (maxDelayTime > 0 &&      (tv_timeToDelay.tv_sec > (long)maxDelayTime/MILLION ||       (tv_timeToDelay.tv_sec == (long)maxDelayTime/MILLION &&tv_timeToDelay.tv_usec > (long)maxDelayTime%MILLION))) {    tv_timeToDelay.tv_sec = maxDelayTime/MILLION;    tv_timeToDelay.tv_usec = maxDelayTime%MILLION;  }  //unsigned long tickCount = GetTickCount();  // fprintf(stderr, "BasicTaskScheduler::SingleStep() 1, time = %u, %u\n", tv_timeToDelay. tv_sec, tv_timeToDelay.tv_usec);  int selectResult = select(fMaxNumSockets, &readSet, &writeSet, &exceptionSet, &tv_timeToDelay);  //long long delayTime = tv_timeToDelay.tv_sec*1000+tv_timeToDelay.tv_usec;  if (selectResult < 0) {#if defined(__WIN32__) || defined(_WIN32)    int err = WSAGetLastError();    // For some unknown reason, select() in Windoze sometimes fails with WSAEINVAL if    // it was called with no entries set in "readSet".  If this happens, ignore it:    if (err == WSAEINVAL && readSet.fd_count == 0) {      err = EINTR;      // To stop this from happening again, create a dummy socket:      int dummySocketNum = socket(AF_INET, SOCK_DGRAM, 0);      FD_SET((unsigned)dummySocketNum, &fReadSet);    }    if (err != EINTR) {#else      if (errno != EINTR && errno != EAGAIN) {#endif      // Unexpected error - treat this as fatal:#if !defined(_WIN32_WCE)      perror("BasicTaskScheduler::SingleStep(): select() fails");#endif      //internalError();      fprintf(stderr, "BasicTaskScheduler::SingleStep(): select() fails\n");      fDelayQueue.handleAlarm();      return;      }  } // END if (selectResult < 0)  // Call the handler function for one readable socket:  lock();  HandlerIterator iter(*fHandlers);  HandlerDescriptor* handler;  // To ensure forward progress through the handlers, begin past the last  // socket number that we handled:  if (fLastHandledSocketNum >= 0) {    // 找到上次执行的socket handler的下一个    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;    // fprintf(stderr, "sock: %d, resultConditionSet:%d, %d\n", sock, resultConditionSet, handler->conditionSet);        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;    }  }    // Also handle any newly-triggered event (Note that we do this *after* calling a socket handler,  // in case the triggered event handler modifies The set of readable sockets.)
  // 待响应事件  if (fTriggersAwaitingHandling != 0) {    if (fTriggersAwaitingHandling == fLastUsedTriggerMask) {      // Common-case optimization for a single event trigger:      fTriggersAwaitingHandling = 0;      if (fTriggeredEventHandlers[fLastUsedTriggerNum] != NULL) {(*fTriggeredEventHandlers[fLastUsedTriggerNum])(fTriggeredEventClientDatas[fLastUsedTriggerNum]);      }    } else {      // Look for an event trigger that needs handling (making sure that we make forward progress through all possible triggers):      unsigned i = fLastUsedTriggerNum;      EventTriggerId mask = fLastUsedTriggerMask;      do {        i = (i+1)%MAX_NUM_EVENT_TRIGGERS;        mask >>= 1;        if (mask == 0) mask = 0x80000000;        if ((fTriggersAwaitingHandling&mask) != 0) {          fTriggersAwaitingHandling &=~ mask;          if (fTriggeredEventHandlers[i] != NULL) {            (*fTriggeredEventHandlers[i])(fTriggeredEventClientDatas[i]);          }          fLastUsedTriggerMask = mask;          fLastUsedTriggerNum = i;          break;        }      } while (i != fLastUsedTriggerNum);    }  }    // Also handle any delayed event that may have come due.  fDelayQueue.handleAlarm();}


原创粉丝点击