📄 timers.tex
字号:
% This draft written by Tom Henderson (8/29/97) based on John Heidemann's% code comments.%%% If you get conflicts, here's what you need to keep: The chapter heading% in the first entry is essential. The \endinput at end is useful.% Other mods are to promote each sub*section one level up.%\chapter{Timers}\label{chap:timers}Timers may be implemented in C++ or OTcl. In C++, timers are based on an abstract base class defined in \nsf{timer-handler.h}. They are most often used in agents, but the framework is general enough to be used by other objects. The discussionbelow is oriented towards the use of timers in agents.The procedures and functions described in this chapter can be found in\nsf{tcl/ex/timer.tcl}, and \nsf{timer-handler.\{cc, h\}}.In OTcl, a simple timer class is defined in \nsf{tcl/ex/timer.tcl}. Subclasses can be derived to provide a simple mechanism for scheduling events at the OTcl level.\section{C++ abstract base class TimerHandler}\label{sec:abstractbaseclass}The abstract base class \code{TimerHandler}contains the following public member functions:\begin{tabularx}{\linewidth}{rX} \fcn[double delay]{void sched} & schedule a timer to expire delay seconds in the future \\\fcn[double delay]{void resched} & reschedule a timer (similar to \fcn[]{sched}, but timer may be pending) \\\fcn[]{void cancel} & cancel a pending timer \\\fcn[]{int status} & returns timer status (either IDLE, PENDING, or HANDLING) \\\end{tabularx}The abstract base class \code{TimerHandler}contains the following protected members:\begin{tabularx}{\linewidth}{rlX}\fcn[Event* e]{virtual void expire} & \code{=0} & this method must be filled in by the timer client\\\fcn[Event* e]{virtual void handle} & \code{=0} & consumes an event\\\code{int status\_} & & keeps track of the current timer status\\\code{Event event\_} & & event to be consumed upon timer expiration\\\end{tabularx}The pure virtual functions must be defined by the timer classes derivingfrom this abstract base class.Finally, two private inline functions are defined:\begin{program} inline void _sched(double delay) \{ (void)Scheduler::instance().schedule(this, &event_, delay); \} inline void _cancel() \{ (void)Scheduler::instance().cancel(&event_); \}\end{program}From this code we can see that timers make use of methods of the \code{Scheduler} class.\subsection{Definition of a new timer}\label{sec:definition}To define a new timer, subclass this function anddefine \fcn[]{handle} if needed(\fcn[]{handle} is not always required):% When is handle required?% If it is required, how do I define it?\begin{program} class MyTimer : public TimerHandler \{ public: MyTimer(MyAgentClass *a) : TimerHandler() \{ a_ = a; \} virtual double expire(Event *e); protected: MyAgentClass *a_; \};\end{program}Then define expire:\begin{program} double MyTimer::expire(Event *e) \{ // {\cf do the work} // return TIMER_HANDLED; // {\cf => do not reschedule timer} // return delay; // {\cf => reschedule timer after delay} \}\end{program}Note that \fcn[]{expire} can return either the flag TIMER\_HANDLED or adelay value, depending on the requirements for this timer.Often \code{MyTimer} will be a friend of \code{MyAgentClass}, or \fcn[]{expire} will only call a public function of \code{MyAgentClass}.Timers are not directly accessible from the OTcl level, although users arefree to establish method bindings if they so desire.% How does this relate to the OTcl comment% in the first paragraph in this chapter?% How do I establish bindings? What type are they?\subsection{Example: Tcp retransmission timer}\label{sec:timerexample}TCP is an example of an agent which requires timers. There are three timersdefined in the basic Tahoe TCP agent defined in \code{tcp.cc}:\begin{program} rtx_timer_; \* Retransmission timer */ delsnd_timer_; \* Delays sending of packets by a small random amount of time, */ \* to avoid phase effects */ burstsnd_timer_; \* Helps TCP to stagger the transmission of a large window */ \* into several smaller bursts */\end{program}In \nsf{tcp.h}, three classes are derived from the base class\clsref{TimerHandler}{tcp.h}:\begin{program} class RtxTimer : public TimerHandler \{ public: RtxTimer(TcpAgent *a) : TimerHandler() \{ a_ = a; \} protected: virtual void expire(Event *e); TcpAgent *a_; \}; class DelSndTimer : public TimerHandler \{ public: DelSndTimer(TcpAgent *a) : TimerHandler() \{ a_ = a; \} protected: virtual void expire(Event *e); TcpAgent *a_; \}; class BurstSndTimer : public TimerHandler \{ public: BurstSndTimer(TcpAgent *a) : TimerHandler() \{ a_ = a; \} protected: virtual void expire(Event *e); TcpAgent *a_; \}; \end{program}In\fcnref{the constructor for \code{TcpAgent}}{../ns-2/tcp.cc}{TcpAgent::TcpAgent}in \code{tcp.cc},each of these timersis initialized with the \code{this} pointer,which is assigned to the pointer \code{a_}.\begin{program} TcpAgent::TcpAgent() : Agent(PT_TCP), rtt_active_(0), rtt_seq_(-1), \ldots rtx_timer_(this), delsnd_timer_(this), burstsnd_timer_(this) \{ \ldots \}\end{program}In the following, we will focus only on the retransmission timer. Varioushelper methods may be defined to schedule timer events; \eg,\begin{program} /* *{\cf Set retransmit timer using current rtt estimate. By calling \fcn[]{resched}} *{\cf it does not matter whether the timer was already running.} */ void TcpAgent::set_rtx_timer() \{ rtx_timer_.resched(rtt_timeout()); \} /* * {\cf Set new retransmission timer if not all outstanding} * {\cf data has been acked. Otherwise, if a timer is still} * {\cf outstanding, cancel it.} */ void TcpAgent::newtimer(Packet* pkt) \{ hdr_tcp *tcph = (hdr_tcp*)pkt->access(off_tcp_); if (t_seqno_ > tcph->seqno()) set_rtx_timer(); else if (rtx_timer_.status() == TIMER_PENDING) rtx_timer_.cancel(); \}\end{program}In the above code, the \fcn[]{set\_rtx\_timer} method reschedules the retransmission timer by calling \fcn[]{rtx\_timer\_.resched}. Note that ifit is unclear whether or not the timer is already running, calling\fcn[]{resched} eliminates the need to explicitly cancel the timer. Inthe second function, examples are given of the use of the \fcn[]{status}and \fcn{cancel} methods.Finally, the \fcn{expire} method for class \code{RtxTimer} must be defined. In this case, \fcn{expire} calls the \fcn{timeout} methodfor \code{TcpAgent}. This is possible because \fcn[]{timeout} is a public member function; if it were not, then \code{RtxTimer} would havehad to have been declared a friend class of \code{TcpAgent}.\begin{program}void TcpAgent::timeout(int tno)\{ /* retransmit timer */ if (tno == TCP_TIMER_RTX) \{ if (highest_ack_ == maxseq_ && !slow_start_restart_) \{ /* * {\cf TCP option:} * {\cf If no outstanding data, then don't do anything.} */ return; \}; recover_ = maxseq_; recover_cause_ = 2; closecwnd(0); reset_rtx_timer(0,1); send_much(0, TCP_REASON_TIMEOUT, maxburst_); \} else \{ /* * {\cf delayed-send timer, with random overhead} * {\cf to avoid phase effects } */ send_much(1, TCP_REASON_TIMEOUT, maxburst_); \} \} void RtxTimer::expire(Event *e) \{ a_->timeout(TCP_TIMER_RTX);\}\end{program}The various TCP agents contain additional examples of timers.\section{OTcl Timer class}\label{sec:otcltimer}A simple timer class is defined in \nsf{tcl/mcast/timer.tcl}. Subclasses of\code{Timer} can be defined as needed. Unlike the C++ timer API, where a \fcn[]{sched} aborts if the timer is already set, \fcn[]{sched} and\fcn[]{resched} are the same; i.e., no state is kept for the OTcl timers.The following methods are defined in the \code{Timer} base class:\begin{program} $self sched $delay \; causes "$self timeout" to be called $delay seconds in the future; $self resched $delay \; same as "$self sched $delay" ; $self cancel \; cancels any pending scheduled callback; $self destroy \; same as "$self cancel"; $self expire \; calls "$self timeout" immediately;\end{program}\section{Commands at a glance}\label{sec:timercommand}Following is a list of methods for the class Timer. Note that manydifferent types of timers have been derived from this base class (viz.LogTimer, Timer/Iface, Timer/Iface/Prune, CacheTimer, Timer/Scuba etc).\begin{flushleft}\code{$timer sched <delay>}\\This command cancels any other event that may have been scheduled and re-schedulesanother event after time <delay>.\code{$timer resched <delay>}\\Similar to "sched" described above. Added to have similar APIs as that of theC++ timers.\code{$timer cancel}\\This cancels any scheduled event.\code{$timer destroy}\\This is similar to cancel. Cancels any scheduled event.\code{$timer expire}\\This command calls for a time-out. However the time-out procedure needs to bedefined in the sub-classes.All these procedures can be found in \ns/tcl/mcast/timer.tcl.\end{flushleft}\endinput
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -