今天抽空研究了下live555的任务实现:
TaskScheduler分为三种任务:socket handler,event handler,delay task。这三种任务的特点是,前两个加入执行队列后会一直存在,而delay task在执行完一次后会立即弃掉。
socket handler保存在队列BasicTaskScheduler0::HandlerSet* fHandlers中;
event handler保存在数组BasicTaskScheduler0::TaskFunc * fTriggeredEventHandlers[MAX_NUM_EVENT_TRIGGERS]中;
delay task保存在队列BasicTaskScheduler0::DelayQueue fDelayQueue中。

一.研究delaytask:
可以参考:http://www.cnblogs.com/nightwatcher/archive/2011/04/10/2011158.html
在学习操作delay task的函数之前,先研究下live555中的这个DelayQueue :
-
-
-
virtual ~DelayQueueEntry();
-
-
-
-
-
-
-
DelayQueueEntry(DelayInterval delay);
-
-
virtual void handleTimeout();
-
-
-
-
-
-
DelayInterval fDeltaTimeRemaining; 超时时间(倒计时),该结构体含两个参数,一个是秒,一个是微秒;
-
-
-
static intptr_t tokenCounter;
-
-
-
-
class DelayQueue: public DelayQueueEntry {
-
-
-
-
-
void addEntry(DelayQueueEntry* newEntry);
-
void updateEntry(DelayQueueEntry* entry, DelayInterval newDelay);
-
void updateEntry(intptr_t tokenToFind, DelayInterval newDelay);
-
void removeEntry(DelayQueueEntry* entry);
-
DelayQueueEntry* removeEntry(intptr_t tokenToFind);
-
-
DelayInterval const& timeToNextAlarm();
-
-
-
-
DelayQueueEntry* head() { return fNext; }
-
DelayQueueEntry* findEntryByToken(intptr_t token);
-
-
-
-
-
-
-
-
class AlarmHandler: public DelayQueueEntry {
-
-
AlarmHandler(TaskFunc* proc, void* clientData, DelayInterval timeToDelay)
-
: DelayQueueEntry(timeToDelay), fProc(proc), fClientData(clientData) {
-
-
-
-
virtual void handleTimeout() {
-
-
DelayQueueEntry::handleTimeout();
-
-
-
-
-
-
操作该队列的方法在BasicTaskScheduler0.h、BasicTaskScheduler0.cpp 中声明和实现:
-
TaskToken BasicTaskScheduler0::scheduleDelayedTask(int64_t microseconds, 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());
-
-
-
void BasicTaskScheduler0::unscheduleDelayedTask(TaskToken& prevTask) {
-
DelayQueueEntry* alarmHandler = fDelayQueue.removeEntry((intptr_t)prevTask);
-
-
-
二.event handler
event handler是被存在数组中。数组大小固定等于32(#define MAX_NUM_EVENT_TRIGGERS 32),用EventTriggerId来表示数组中的项,EventTriggerId是一个32位整数,因为数组是32项,所以用EventTriggerId中的第n位置为1,则表明对应数组中的第n项。成员变量fTriggersAwaitingHandling也是EventTriggerId类型,它里面置1的那些位对应了数组中所有需要处理的项。这样做节省了内存和计算,但降低了可读性,呵呵,而且也不够灵活,只能支持32项或64项,其它数量不被支持。
-
EventTriggerId BasicTaskScheduler0::createEventTrigger(TaskFunc* eventHandlerProc) {
-
unsigned i = fLastUsedTriggerNum;
-
EventTriggerId mask = fLastUsedTriggerMask;
-
-
-
i = (i+1)%MAX_NUM_EVENT_TRIGGERS;
-
-
if (mask == 0) mask = 0x80000000;
-
-
if (fTriggeredEventHandlers[i] == NULL) {
-
-
fTriggeredEventHandlers[i] = eventHandlerProc;
-
fTriggeredEventClientDatas[i] = NULL;
-
-
fLastUsedTriggerMask = mask;
-
-
-
-
-
} while (i != fLastUsedTriggerNum);
-
-
-
-
-
-
void BasicTaskScheduler0::deleteEventTrigger(EventTriggerId eventTriggerId) {
-
fTriggersAwaitingHandling &=~ eventTriggerId;
-
-
if (eventTriggerId == fLastUsedTriggerMask) {
-
fTriggeredEventHandlers[fLastUsedTriggerNum] = NULL;
-
fTriggeredEventClientDatas[fLastUsedTriggerNum] = NULL;
-
-
-
-
EventTriggerId mask = 0x80000000;
-
for (unsigned i = 0; i < MAX_NUM_EVENT_TRIGGERS; ++i) {
-
if ((eventTriggerId&mask) != 0) {
-
fTriggeredEventHandlers[i] = NULL;
-
fTriggeredEventClientDatas[i] = NULL;
-
-
-
-
-
-
-
void BasicTaskScheduler0::triggerEvent(EventTriggerId eventTriggerId, void* clientData) {
-
-
if (eventTriggerId == fLastUsedTriggerMask) {
-
fTriggeredEventClientDatas[fLastUsedTriggerNum] = clientData;
-
-
EventTriggerId mask = 0x80000000;
-
for (unsigned i = 0; i < MAX_NUM_EVENT_TRIGGERS; ++i) {
-
if ((eventTriggerId&mask) != 0) {
-
fTriggeredEventClientDatas[i] = clientData;
-
-
fLastUsedTriggerMask = mask;
-
-
-
-
-
-
-
-
-
-
fTriggersAwaitingHandling |= eventTriggerId;
-
最后在BasicTaskScheduler::SingleStep中执行该事件函数。
三.socket handler
先看下几个用到的结构体
-
class HandlerDescriptor {
-
HandlerDescriptor(HandlerDescriptor* nextHandler);
-
virtual ~HandlerDescriptor();
-
-
-
-
-
TaskScheduler::BackgroundHandlerProc* handlerProc;
-
-
-
-
-
-
friend class HandlerIterator;
-
HandlerDescriptor* fNextHandler;
-
HandlerDescriptor* fPrevHandler;
-
-
-
-
-
-
-
-
-
void assignHandler(int socketNum, int conditionSet, TaskScheduler::BackgroundHandlerProc* handlerProc, void* clientData);
-
void clearHandler(int socketNum);
-
void moveHandler(int oldSocketNum, int newSocketNum);
-
-
-
HandlerDescriptor* lookupHandler(int socketNum);
-
-
-
friend class HandlerIterator;
-
HandlerDescriptor fHandlers;
-
-
-
-
-
-
HandlerIterator(HandlerSet& handlerSet);
-
virtual ~HandlerIterator();
-
-
HandlerDescriptor* next();
-
-
-
-
-
HandlerDescriptor* fNextPtr;
-
处理socket handler的函数:
-
-
::setBackgroundHandling(int socketNum, int conditionSet, BackgroundHandlerProc* handlerProc, void* clientData) {
-
if (socketNum < 0) return;
-
FD_CLR((unsigned)socketNum, &fReadSet);
-
FD_CLR((unsigned)socketNum, &fWriteSet);
-
FD_CLR((unsigned)socketNum, &fExceptionSet);
-
-
fHandlers->clearHandler(socketNum);
-
if (socketNum+1 == fMaxNumSockets) {
-
-
-
-
fHandlers->assignHandler(socketNum, conditionSet, handlerProc, clientData);
-
if (socketNum+1 > fMaxNumSockets) {
-
fMaxNumSockets = socketNum+1;
-
-
if (conditionSet&SOCKET_READABLE) FD_SET((unsigned)socketNum, &fReadSet);
-
if (conditionSet&SOCKET_WRITABLE) FD_SET((unsigned)socketNum, &fWriteSet);
-
if (conditionSet&SOCKET_EXCEPTION) FD_SET((unsigned)socketNum, &fExceptionSet);
-
-
-
-
void BasicTaskScheduler::moveSocketHandling(int oldSocketNum, int newSocketNum) {
-
-
if (oldSocketNum < 0 || newSocketNum < 0) return;
-
-
if (FD_ISSET(oldSocketNum, &fReadSet)) {FD_CLR((unsigned)oldSocketNum, &fReadSet); FD_SET((unsigned)newSocketNum, &fReadSet);}
-
if (FD_ISSET(oldSocketNum, &fWriteSet)) {FD_CLR((unsigned)oldSocketNum, &fWriteSet); FD_SET((unsigned)newSocketNum, &fWriteSet);}
-
if (FD_ISSET(oldSocketNum, &fExceptionSet)) {FD_CLR((unsigned)oldSocketNum, &fExceptionSet); FD_SET((unsigned)newSocketNum, &fExceptionSet);}
-
-
fHandlers->moveHandler(oldSocketNum, newSocketNum);
-
-
if (oldSocketNum+1 == fMaxNumSockets) {
-
-
-
if (newSocketNum+1 > fMaxNumSockets) {
-
fMaxNumSockets = newSocketNum+1;
-
-
-
live555源码学习笔记之TaskScheduler
原文:https://www.cnblogs.com/lidabo/p/9467194.html