live555 delay task 和Event TriggerId 源码解析

<五> Live555的延迟任务(delay task)

  5.1scheduleDelayedTask

TaskToken BasicTaskScheduler0::scheduleDelayedTask(int64_tmicroseconds,

                             TaskFunc*proc,

                             void*clientData) {

  if (microseconds < 0)microseconds = 0;

  DelayInterval timeToDelay((long)(microseconds/1000000), (long)(microseconds%1000000));

  AlarmHandler* alarmHandler = new AlarmHandler(proc, clientData, timeToDelay);

  fDelayQueue.addEntry(alarmHandler);

 

  return (void*)(alarmHandler->token());

}

 

其中addEntry延迟任务插入队列;

void DelayQueue::addEntry(DelayQueueEntry*newEntry) {

  synchronize();

 

  DelayQueueEntry* cur = head();

  while (newEntry->fDeltaTimeRemaining >=cur->fDeltaTimeRemaining) {

    newEntry->fDeltaTimeRemaining -=cur->fDeltaTimeRemaining;

    cur = cur->fNext;

  }

 

  cur->fDeltaTimeRemaining -=newEntry->fDeltaTimeRemaining;

 

  // Add "newEntry" to the queue, just before "cur":

  newEntry->fNext =cur;

  newEntry->fPrev =cur->fPrev;

  cur->fPrev =newEntry->fPrev->fNext =newEntry;

}

 

注意队列中的数据是排好序的,队列中的第一个是还剩多久进行调度,后面的每一项保存的是和前面项的相对时间差;所以插入队列后,队列仍然是有序的;在从队列中取数据时,只要判断队列的第一个开始取就可以了;

 

其中synchronize()是将队列中的每一项减去一个运行了的时间:

void DelayQueue::synchronize() {

  // First, figure out how much time has elapsed since the last sync:

  EventTime timeNow = TimeNow();

  if (timeNow <fLastSyncTime) {

    // The system clock has apparently gone back in time; reset our sync time and return:

    fLastSyncTime  = timeNow;

    return;

  }

  DelayInterval timeSinceLastSync = timeNow - fLastSyncTime;

  fLastSyncTime = timeNow;

 

  // Then, adjust the delay queue for any entries whose time is up:

  DelayQueueEntry* curEntry = head();

  while (timeSinceLastSync >=curEntry->fDeltaTimeRemaining) {

    timeSinceLastSync -= curEntry->fDeltaTimeRemaining;

    curEntry->fDeltaTimeRemaining =DELAY_ZERO;

    curEntry = curEntry->fNext;

  }

  curEntry->fDeltaTimeRemaining -=timeSinceLastSync;

}

 

 

 

5.2)unscheduleDelayedTask

void BasicTaskScheduler0::unscheduleDelayedTask(TaskToken&prevTask) {

  DelayQueueEntry* alarmHandler = fDelayQueue.removeEntry((intptr_t)prevTask);

  prevTask = NULL;

  delete alarmHandler;

}

 

从队列中删除延迟任务(delay task)

 

5.3)rescheduleDelayedTask

void TaskScheduler::rescheduleDelayedTask(TaskToken&task,

                         int64_tmicroseconds, TaskFunc*proc,

                         void* clientData) {

  unscheduleDelayedTask(task);

  task = scheduleDelayedTask(microseconds, proc, clientData);

}

 

该函数首先删除队列中的task,然后从新插入到delay task;

 

调用例子:

void RTSPServer::RTSPClientSession::noteLiveness() {

  if (fOurServer.fReclamationTestSeconds > 0) {

    envir().taskScheduler()

      .rescheduleDelayedTask(fLivenessCheckTask,

                   fOurServer.fReclamationTestSeconds*1000000,

                   (TaskFunc*)livenessTimeoutTask,this);

  }

}

 

其中:

void RTSPServer::RTSPClientSession

::livenessTimeoutTask(RTSPClientSession*clientSession) {

  // If this gets called, the client session is assumed to have timed out,

  // so delete it:

#ifdef DEBUG

  char const* streamName

    = (clientSession->fOurServerMediaSession == NULL) ? "???" : clientSession->fOurServerMediaSession->streamName();

  fprintf(stderr, "RTSP client session (id \"%08X\", stream name \"%s\") has timed out (due to inactivity)\n",

       clientSession->fOurSessionId, streamName);

#endif

  delete clientSession;

}

 

 

<六> Live555的事件触发(Event TriggerId)

 

6.1) createEventTrigger

EventTriggerId BasicTaskScheduler0::createEventTrigger(TaskFunc*eventHandlerProc) {

  unsigned i = fLastUsedTriggerNum;

  EventTriggerId mask = fLastUsedTriggerMask;

 

  do {

    i = (i+1)%MAX_NUM_EVENT_TRIGGERS;

    mask >>= 1;

    if (mask == 0)mask = 0x80000000;

 

    if (fTriggeredEventHandlers[i] ==NULL) {

      // This trigger number is free; use it:

      fTriggeredEventHandlers[i] =eventHandlerProc;

      fTriggeredEventClientDatas[i] =NULL; // sanity

 

      fLastUsedTriggerMask = mask;

      fLastUsedTriggerNum = i;

 

      return mask;

    }

  } while (i !=fLastUsedTriggerNum);

 

  // All available event triggers are allocated; return 0 instead:

  return 0;

}

 

其中MAX_NUM_EVENT_TRIGGERS=32,最多支持32个;event handler 是被存在数组中。数组大小固定,是32 项,用EventTriggerId 来表示数组中的项,EventTriggerId 是一个32 位整数,因为数组是32 项,所以用EventTriggerId 中的第n 位置1表明对应数组中的第n项。成员变量fTriggersAwaitingHandling 也是EventTriggerId 类型,它里面置1的那些位对应了数组中所有需要处理的项; fTriggeredEventClientDatas保存数据;和fTriggeredEventHandlers对应;

 

6.2)deleteEventTrigger

void BasicTaskScheduler0::deleteEventTrigger(EventTriggerIdeventTriggerId) {

  fTriggersAwaitingHandling &=~eventTriggerId;

 

  if (eventTriggerId ==fLastUsedTriggerMask) { // common-case optimization:

    fTriggeredEventHandlers[fLastUsedTriggerNum] =NULL;

    fTriggeredEventClientDatas[fLastUsedTriggerNum] =NULL;

  } else {

    // "eventTriggerId" should have just one bit set.

    // However, we do the reasonable thing if the user happened to 'or' together two or more "EventTriggerId"s:

    EventTriggerId mask = 0x80000000;

    for (unsignedi = 0; i < MAX_NUM_EVENT_TRIGGERS; ++i) {

      if ((eventTriggerId&mask) != 0) {

     fTriggeredEventHandlers[i] =NULL;

     fTriggeredEventClientDatas[i] =NULL;

      }

      mask >>= 1;

    }

  }

}

 

 

6.3)triggerEvent

void BasicTaskScheduler0::triggerEvent(EventTriggerIdeventTriggerId, void*clientData) {

  // First, record the "clientData".  (Note that we allow "eventTriggerId" to be a combination of bits for multiple events.)

  EventTriggerId mask = 0x80000000;

  for (unsignedi = 0; i < MAX_NUM_EVENT_TRIGGERS; ++i) {

    if ((eventTriggerId&mask) != 0) {

      fTriggeredEventClientDatas[i] =clientData;

    }

    mask >>= 1;

  }

 

  // Then, note this event as being ready to be handled.

  // (Note that because this function (unlike others in the library) can be called from an external thread, we do this last, to

  //  reduce the risk of a race condition.)

  fTriggersAwaitingHandling |=eventTriggerId;

}

 

socket handler 和事件触发(Event TriggerId)及delay task都是在doEventLoop函数的SingleStep();中调用;在该函数中依次判断有没有这几种事件发生;

 

 

 

你可能感兴趣的:(live555 delay task 和Event TriggerId 源码解析)