timers.tex
上传用户:rrhhcc
上传日期:2015-12-11
资源大小:54129k
文件大小:10k
源码类别:

通讯编程

开发平台:

Visual C++

  1. %       This draft written by Tom Henderson (8/29/97) based on John Heidemann's
  2. %   code comments.
  3. %
  4. %
  5. % If you get conflicts, here's what you need to keep:  The chapter heading
  6. % in the first entry is essential.  The endinput at end is useful.
  7. % Other mods are to promote each sub*section one level up.
  8. %
  9. chapter{Timers}
  10. label{chap:timers}
  11. Timers may be implemented in C++ or OTcl.  In C++, timers are based on an 
  12. abstract base class defined in nsf{timer-handler.h}.  They are most often 
  13. used in agents, but the 
  14. framework is general enough to be used by other objects.  The discussion
  15. below is oriented towards the use of timers in agents.
  16. The procedures and functions described in this chapter can be found in
  17. nsf{tcl/ex/timer.tcl}, and nsf{timer-handler.{cc, h}}.
  18. In OTcl, a simple timer class is defined in nsf{tcl/ex/timer.tcl}.  
  19. Subclasses can be derived to provide a simple mechanism for scheduling events 
  20. at the OTcl level.
  21. section{C++ abstract base class TimerHandler}
  22. label{sec:abstractbaseclass}
  23. The abstract base class code{TimerHandler}
  24. contains the following public member functions:
  25. begin{tabularx}{linewidth}{rX}
  26.   fcn[double delay]{void sched} & schedule a timer to
  27.                                 expire delay seconds in the future \
  28. fcn[double delay]{void resched} & reschedule a timer
  29.                 (similar to fcn[]{sched}, but timer may be pending) \
  30. fcn[]{void cancel} & cancel a pending timer \
  31. fcn[]{int status} & returns timer status
  32.                         (either TIMER_IDLE, TIMER_PENDING, or TIMER_HANDLING) \
  33. end{tabularx}
  34. The abstract base class code{TimerHandler}
  35. contains the following protected members:
  36. begin{tabularx}{linewidth}{rlX}
  37. fcn[Event* e]{virtual void expire} & code{=0} &
  38.          this method must be filled in by the timer client\
  39. %changed by ratul.
  40. fcn[Event* e]{virtual void handle} & code{} &
  41.          consumes an event; invokes {it expire()} and sets {it status_} of the timer appropriately\
  42. code{int status_} & &  keeps track of the current timer status\
  43. code{Event event_} & & event to be consumed upon timer expiration\
  44. end{tabularx}
  45. The pure virtual function {it expire()} must be defined by the timer classes deriving
  46. from this abstract base class.
  47. Finally, two private inline functions are defined:
  48. begin{program}
  49.         inline void _sched(double delay) {
  50.             (void)Scheduler::instance().schedule(this, &event_, delay);
  51.         }
  52.         inline void _cancel() {
  53.             (void)Scheduler::instance().cancel(&event_);
  54.         }
  55. end{program}
  56. From this code we can see that timers make use of methods of the 
  57. code{Scheduler} class.
  58. subsection{Definition of a new timer}
  59. label{sec:definition}
  60. To define a new timer, subclass this function and
  61. define fcn[]{handle} if needed
  62. (fcn[]{handle} is not always required):
  63. % When is handle required?
  64. % If it is required, how do I define it?
  65. begin{program}
  66.         class MyTimer : public TimerHandler {
  67.         public:
  68.           MyTimer(MyAgentClass *a) : TimerHandler() { a_ = a; }
  69.           virtual double expire(Event *e);
  70.         protected:
  71.           MyAgentClass *a_;
  72.         };
  73. end{program}
  74. Then define expire:
  75. begin{program}
  76.         double
  77.         MyTimer::expire(Event *e)
  78.         {
  79.           // {cf do the work}
  80.           // return TIMER_HANDLED;    // {cf => do not reschedule timer}
  81.           // return delay;            // {cf => reschedule timer after delay}
  82.         }
  83. end{program}
  84. Note that fcn[]{expire} can return either the flag TIMER_HANDLED or a
  85. delay value, depending on the requirements for this timer.
  86. Often code{MyTimer} will be a friend of code{MyAgentClass}, or 
  87. fcn[]{expire} will only call a public function of code{MyAgentClass}.
  88. Timers are not directly accessible from the OTcl level, although users are
  89. free to establish method bindings if they so desire.
  90. % How does this relate to the OTcl comment
  91. % in the first paragraph in this chapter?
  92. % How do I establish bindings?  What type are they?
  93. subsection{Example: Tcp retransmission timer}
  94. label{sec:timerexample}
  95. TCP is an example of an agent which requires timers.  There are three timers
  96. defined in the basic Tahoe TCP agent defined in code{tcp.cc}:
  97. begin{program}
  98.         rtx_timer_;      *  Retransmission timer */
  99.         delsnd_timer_;   *  Delays sending of packets by a small random amount of time, */
  100.                         * to avoid phase effects */
  101.         burstsnd_timer_;   * Helps TCP to stagger the transmission of a large window */
  102.                                 * into several smaller bursts */
  103. end{program}
  104. In nsf{tcp.h}, three classes are derived from the base class
  105. clsref{TimerHandler}{tcp.h}:
  106. begin{program}
  107.         class RtxTimer : public TimerHandler {
  108.         public:
  109.             RtxTimer(TcpAgent *a) : TimerHandler() { a_ = a; }
  110.         protected:                   
  111.             virtual void expire(Event *e);
  112.             TcpAgent *a_;
  113.         };  
  114.             
  115.         class DelSndTimer : public TimerHandler {
  116.         public:
  117.             DelSndTimer(TcpAgent *a) : TimerHandler() { a_ = a; }
  118.         protected:
  119.             virtual void expire(Event *e);
  120.             TcpAgent *a_;
  121.         };      
  122.     
  123.         class BurstSndTimer : public TimerHandler {
  124.         public: 
  125.             BurstSndTimer(TcpAgent *a) : TimerHandler() { a_ = a; }
  126.         protected:
  127.             virtual void expire(Event *e); 
  128.             TcpAgent *a_;
  129.         };  
  130. end{program}
  131. In
  132. fcnref{the constructor for code{TcpAgent}}{../ns-2/tcp.cc}{TcpAgent::TcpAgent}
  133. in code{tcp.cc},
  134. each of these timers
  135. is initialized with the code{this} pointer,
  136. which is assigned to the pointer code{a_}.
  137. begin{program}
  138.         TcpAgent::TcpAgent() : Agent(PT_TCP), rtt_active_(0), rtt_seq_(-1), 
  139.             ldots
  140.             rtx_timer_(this), delsnd_timer_(this), burstsnd_timer_(this)
  141.         {
  142.             ldots
  143.         }
  144. end{program}
  145. In the following, we will focus only on the retransmission timer.  Various
  146. helper methods may be defined to schedule timer events; eg,
  147. begin{program}
  148.         /*
  149.          *{cf Set retransmit timer using current rtt estimate.  By calling fcn[]{resched}}
  150.          *{cf it does not matter whether the timer was already running.}
  151.          */
  152.         void TcpAgent::set_rtx_timer()
  153.         {
  154.             rtx_timer_.resched(rtt_timeout());
  155.         }
  156.         /*
  157.          * {cf Set new retransmission timer if not all outstanding}
  158.          * {cf data has been acked.  Otherwise, if a timer is still}
  159.          * {cf outstanding, cancel it.}
  160.          */
  161.         void TcpAgent::newtimer(Packet* pkt)
  162.         {
  163.             hdr_tcp *tcph = (hdr_tcp*)pkt->access(off_tcp_);
  164.             if (t_seqno_ > tcph->seqno())
  165.                 set_rtx_timer();
  166.             else if (rtx_timer_.status() == TIMER_PENDING)
  167.                 rtx_timer_.cancel();
  168.         }
  169. end{program}
  170. In the above code, the fcn[]{set_rtx_timer} method reschedules the 
  171. retransmission timer by calling fcn[]{rtx_timer_.resched}.  Note that if
  172. it is unclear whether or not the timer is already running, calling
  173. fcn[]{resched} eliminates the need to explicitly cancel the timer.  In
  174. the second function, examples are given of the use of the fcn[]{status}
  175. and fcn{cancel} methods.
  176. Finally, the fcn{expire} method for class code{RtxTimer} must be 
  177. defined.  In this case, fcn{expire} calls the fcn{timeout} method
  178. for code{TcpAgent}.  This is possible because fcn[]{timeout} is a 
  179. public member function; if it were not, then code{RtxTimer} would have
  180. had to have been declared a friend class of code{TcpAgent}.
  181. begin{program}
  182. void TcpAgent::timeout(int tno)
  183. {                     
  184.     /* retransmit timer */
  185.     if (tno == TCP_TIMER_RTX) {
  186.         if (highest_ack_ == maxseq_ && !slow_start_restart_) {
  187.             /*
  188.              * {cf TCP option:}
  189.              * {cf If no outstanding data, then don't do anything.}
  190.              */
  191.             return;  
  192.         };
  193.         recover_ = maxseq_;
  194.         recover_cause_ = 2;
  195.         closecwnd(0);
  196.         reset_rtx_timer(0,1);
  197.         send_much(0, TCP_REASON_TIMEOUT, maxburst_); 
  198.     } else {
  199.         /* 
  200.          * {cf delayed-send timer, with random overhead}
  201.          * {cf to avoid phase effects  }
  202.          */     
  203.         send_much(1, TCP_REASON_TIMEOUT, maxburst_);
  204.     }           
  205. }           
  206.             
  207. void RtxTimer::expire(Event *e) {
  208.     a_->timeout(TCP_TIMER_RTX);
  209. }
  210. end{program}
  211. The various TCP agents contain additional examples of timers.
  212. section{OTcl Timer class}
  213. label{sec:otcltimer}
  214. A simple timer class is defined in nsf{tcl/mcast/timer.tcl}.  Subclasses of
  215. code{Timer} can be defined as needed.  Unlike the C++ timer API, where a 
  216. fcn[]{sched} aborts if the timer is already set, fcn[]{sched} and
  217. fcn[]{resched} are the same; i.e., no state is kept for the OTcl timers.
  218. The following methods are defined in the code{Timer} base class:
  219. begin{program}
  220.     $self sched $delay   ; causes "$self timeout" to be called $delay seconds in the future;
  221.     $self resched $delay ; same as "$self sched $delay" ;
  222.     $self cancel         ; cancels any pending scheduled callback;
  223.     $self destroy        ; same as "$self cancel";
  224.     $self expire         ; calls "$self timeout" immediately;
  225. end{program}
  226. section{Commands at a glance}
  227. label{sec:timercommand}
  228. Following is a list of methods for the class Timer. Note that many
  229. different types of timers have been derived from this base class (viz.
  230. LogTimer, Timer/Iface, Timer/Iface/Prune, CacheTimer, Timer/Scuba etc).
  231. begin{flushleft}
  232. code{$timer sched <delay>}\
  233. This command cancels any other event that may have been scheduled and re-schedules
  234. another event after time <delay>.
  235. code{$timer resched <delay>}\
  236. Similar to "sched" described above. Added to have similar APIs as that of the
  237. C++ timers.
  238. code{$timer cancel}\
  239. This cancels any scheduled event.
  240. code{$timer destroy}\
  241. This is similar to cancel. Cancels any scheduled event.
  242. code{$timer expire}\
  243. This command calls for a time-out. However the time-out procedure needs to be
  244. defined in the sub-classes.
  245. All these procedures can be found in ns/tcl/mcast/timer.tcl.
  246. end{flushleft}
  247. endinput