[Live-devel] Performance imporved -- SingleStep improved

xue zackxue at 163.com
Thu Jul 28 19:19:12 PDT 2011


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();

  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;

  }

/* Here should process the queue data before get new frame from source, this very important for IP net work camera, the video latency will 50ms shorter than before. Zack */

if (tv_timeToDelay.tv_sec == 0 && tv_timeToDelay.tv_usec == 0){

         fDelayQueue.handleAlarm();

         return ;

}

 

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

  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);

      FD_SET((unsigned)dummySocketNum, &fWriteSet);

      FD_SET((unsigned)dummySocketNum, &fExceptionSet);

    }

    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

        abort();

      }

  }

 

  // Call the handler function for one readable socket:

  HandlerIterator iter(*fHandlers);

  HandlerDescriptor* handler;

  // To ensure forward progress through the handlers, begin past the last

  // socket number that we handled:

  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;

    }

  }

  if (handler == NULL && fLastHandledSocketNum >= 0) {

    // 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 = 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;

      }

    }

    if (handler == NULL) fLastHandledSocketNum = -1;//because we didn't call a handler

  }

 

  // Also handle any delayed event that may have come due.  (Note that we do this *after* calling a socket

  // handler, in case the delayed event handler modifies the set of readable sockets.)

  fDelayQueue.handleAlarm();

}
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.live555.com/pipermail/live-devel/attachments/20110729/d6d63483/attachment-0001.html>


More information about the live-devel mailing list