在很多应用设计中,都设计了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中的数据结构不同,但用来构造定时器的基本原理还是一致的.