在很多應用設計中,都設計了Timer
(定時器),
用來完成特定的世間.例如在Symbian
中就有一個CPeriodic
類,它使用定時器對象來產生規則的定時器事件;
在流媒體的應用Darwin
中設計了定時器;
在高效的中間件平臺ICE
中也設計了Timer;
在通信應用中我們必定要設計Timer
來對特定的操作進行計時;
在一些應用中通過Timer
來產生周期性的心跳,
來確定系統中的各個服務器是否工作正常 .下面我們將分別介紹Darwin
和ICE
中的定時器:Darwin
中的定時器設計:
Task
class Task
{
……
Private:
EventFlags fEvents; //該Task所對應的事件
TaskThread* fUseThisThread; // 所對應的TaskThread.
……
};
TaskThread : Darwin中用來處理Task的線程.
TaskThreadPool: Darwin中用來管理TaskThread的類.
跟定時器有關的Task: TimeOutTask, IdleTask.
TimeOutTask 包含一個Task的指針,并且含有一個指向TimeoutTaskThread的靜態指針,并且包含一個OSQueueElem,該OSQueueElem將被加到TimeoutTaskThread的隊列中.
class TimeoutTask
{
….
private:
Task* fTask;
SInt64 fTimeoutAtThisTime;
SInt64 fTimeoutInMilSecs;
//for putting on our global queue of timeout tasks
OSQueueElem fQueueElem;
static TimeoutTaskThread* sThread;
……
};
IdleTask 公共繼承于 Task. 并且包含一個指向IdleTaskThread的靜態指針,并且包含一個OSHeapElem. IdleTask 啟動IdleTaskThread.
class IdleTask : public Task
{
public:
……
void SetIdleTimer(SInt64 msec) { sIdleThread->SetIdleTimer(this, msec); }
void CancelTimeout() { sIdleThread->CancelTimeout(this); }
private:
OSHeapElem fIdleElem;
static IdleTaskThread* sIdleThread;
……
};
TimeoutTaskThread 公共繼承 IdleTask
class TimeoutTaskThread : public IdleTask
{
……
SInt64 TimeoutTaskThread::Run();
……
};
IdleTaskThread具有SetIdleTimer, CancelTimeout等方法.在這些方法中有IdleTask(activeObj)作為參數.
class IdleTaskThread : private OSThread
{
private:
……
void SetIdleTimer(IdleTask *idleObj, SInt64 msec);
void CancelTimeout(IdleTask *idleObj);
virtual void Entry();
OSHeap fIdleHeap;
OSMutex fHeapMutex;
OSCond fHeapCond;
……
};
上面所介紹的,主要是些數據結構. 定時器設計的關鍵部分如下:
在IdleTaskThread中有一個OSHeap用來存儲不同的IdleTask;
OSMutex用來對對象的同步訪問進行串行化;
OSCond用來對對象進行Monitor.
在IdleTaskThread的SetIdleTimer方法中,調用fHeapCond.Signal()發出信號,激活在該條件上等待的線程.
在IdleTaskThread的Entry方法中檢查fIdleHeap.CurrentHeapSize(),如故為0,則等代: fHeapCond.Wait(&fHeapMutex), 直到有新的IdelTimer被加入.
如果定時到了,則調用該IdleTask上的Signal(Task::kIdleEvent)方法,激活在該條件上等待的線程.然后調整等待時間, 重新進行等待: fHeapCond.Wait(&fHeapMutex, smallTime);
ICE中的定時器設計:
在ICE中有一個Time類和Timer類.
在Time中主要是定義一些對時間的轉換操作和比較操作等.
類Timer的定義如下:
class ICE_UTIL_API Timer : public virtual IceUtil::Shared, private virtual IceUtil::Thread
{
public:
……
//
// Schedule a task for execution after a given delay.
//
void schedule(const TimerTaskPtr&, const IceUtil::Time&);
//
// Schedule a task for repeated execution with the given delay
// between each execution.
//
void scheduleRepeated(const TimerTaskPtr&, const IceUtil::Time&);
//
// Cancel a task. Returns true if the task has not yet run or if
// it's a task scheduled for repeated execution. Returns false if
// the task has already run, was already cancelled or was never
// schedulded.
//
bool cancel(const TimerTaskPtr&);
private:
struct Token
{
IceUtil::Time scheduledTime;
IceUtil::Time delay;
TimerTaskPtr task;
inline Token(const IceUtil::Time&, const IceUtil::Time&, const TimerTaskPtr&);
inline bool operator<(const Token& r) const;
};
virtual void run();
IceUtil::Monitor<IceUtil::Mutex> _monitor;
bool _destroyed;
std::set<Token> _tokens;
class TimerTaskCompare : public std::binary_function<TimerTaskPtr, TimerTaskPtr, bool>
{
public:
bool operator()(const TimerTaskPtr& lhs, const TimerTaskPtr& rhs) const
{
return lhs.get() < rhs.get();
}
};
std::map<TimerTaskPtr, IceUtil::Time, TimerTaskCompare> _tasks;
IceUtil::Time _wakeUpTime;
};
該類public 繼承IceUtil::Shared, 表示它是一個共享的引用計數對象,可以使用智能指針. 該類public繼承IceUtil::Thread, 表明它為一個線程.
在Timer的destroy, schedule, scheduleRepeated 方法中調用_monitor.notify()方法,激活等待線程.
在Timer中有一個set(token) 和一個map( task).
Timer線程的運行方式:
在定時器的運做方式中,要用到Map, Set來記錄定時事件,并用Monitor對象來進行定時等待.
類TimerTask public 繼承于IceUtil::Shared, 并且要求提供一個runTimerTask的方法,該方法為純虛函數.
在ICE中的數據結構不同,但用來構造定時器的基本原理還是一致的.