<五> Live555的延迟任务(delay task)
5.1)scheduleDelayedTask
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();中调用;在该函数中依次判断有没有这几种事件发生;