您的位置:首页 > 其它

Live555 BasicUsageEnvironment模块BasicUsageEnvironment.hh之BasicTaskScheduler0源码分析

2017-03-29 15:46 603 查看
class HandlerSet; // forward

#define MAX_NUM_EVENT_TRIGGERS 32

// An abstract base class, useful for subclassing
// (e.g., to redefine the implementation of socket event handling)
class BasicTaskScheduler0: public TaskScheduler {
public:
virtual ~BasicTaskScheduler0();

virtual void SingleStep(unsigned maxDelayTime = 0) = 0;
// "maxDelayTime" is in microseconds.  It allows a subclass to impose a limit
// on how long "select()" can delay, in case it wants to also do polling.
// 0 (the default value) means: There's no maximum; just look at the delay queue

public:
// Redefined virtual functions:
virtual TaskToken scheduleDelayedTask(int64_t microseconds, TaskFunc* proc,
void* clientData);
virtual void unscheduleDelayedTask(TaskToken& prevTask);

virtual void doEventLoop(char* watchVariable);

virtual EventTriggerId createEventTrigger(TaskFunc* eventHandlerProc);
virtual void deleteEventTrigger(EventTriggerId eventTriggerId);
virtual void triggerEvent(EventTriggerId eventTriggerId, void* clientData = NULL);

protected:
BasicTaskScheduler0();

protected:
// To implement delayed operations:
DelayQueue fDelayQueue;

// To implement background reads:
HandlerSet* fHandlers;
int fLastHandledSocketNum;

// To implement event triggers:
EventTriggerId fTriggersAwaitingHandling, fLastUsedTriggerMask; // implemented as 32-bit bitmaps
TaskFunc* fTriggeredEventHandlers[MAX_NUM_EVENT_TRIGGERS];
void* fTriggeredEventClientDatas[MAX_NUM_EVENT_TRIGGERS];
unsigned fLastUsedTriggerNum; // in the range [0,MAX_NUM_EVENT_TRIGGERS)
};


BasicTaskScheduler0::BasicTaskScheduler0()
: fLastHandledSocketNum(-1), fTriggersAwaitingHandling(0), fLastUsedTriggerMask(1), fLastUsedTriggerNum(MAX_NUM_EVENT_TRIGGERS-1) {
fHandlers = new HandlerSet;
for (unsigned i = 0; i < MAX_NUM_EVENT_TRIGGERS; ++i) {
fTriggeredEventHandlers[i] = NULL;
fTriggeredEventClientDatas[i] = NULL;
}
}

BasicTaskScheduler0::~BasicTaskScheduler0() {
delete fHandlers;
}

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((long)prevTask);
prevTask = NULL;
delete alarmHandler;
}

void BasicTaskScheduler0::doEventLoop(char* watchVariable) {
// Repeatedly loop, handling readble sockets and timed events:
while (1) {
if (watchVariable != NULL && *watchVariable != 0) break;
SingleStep();
}
}

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

void BasicTaskScheduler0::deleteEventTrigger(EventTriggerId eventTriggerId) {
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 (unsigned i = 0; i < MAX_NUM_EVENT_TRIGGERS; ++i) {
if ((eventTriggerId&mask) != 0) {
fTriggeredEventHandlers[i] = NULL;
fTriggeredEventClientDatas[i] = NULL;
}
mask >>= 1;
}
}
}

void BasicTaskScheduler0::triggerEvent(EventTriggerId eventTriggerId, void* clientData) {
// First, record the "clientData":
if (eventTriggerId == fLastUsedTriggerMask) { // common-case optimization:
fTriggeredEventClientDatas[fLastUsedTriggerNum] = clientData;
} else {
EventTriggerId mask = 0x80000000;
for (unsigned i = 0; i < MAX_NUM_EVENT_TRIGGERS; ++i) {
if ((eventTriggerId&mask) != 0) {
fTriggeredEventClientDatas[i] = clientData;

fLastUsedTriggerMask = mask;
fLastUsedTriggerNum = i;
}
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;
}


BasicTaskScheduler0调用了DelayQueue类跟HandlerSet类。
HandlerSet类参考http://blog.csdn.net/sz76211822/article/details/68059848

DelayQueue类参考http://blog.csdn.net/sz76211822/article/details/68060399
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: