Logo ROOT   6.30.04
Reference Guide
 All Namespaces Files Pages
TTimer.cxx
Go to the documentation of this file.
1 // @(#)root/base:$Id$
2 // Author: Fons Rademakers 28/11/96
3 
4 /*************************************************************************
5  * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. *
6  * All rights reserved. *
7  * *
8  * For the licensing terms see $ROOTSYS/LICENSE. *
9  * For the list of contributors see $ROOTSYS/README/CREDITS. *
10  *************************************************************************/
11 
12 /** \class TTimer
13 \ingroup Base
14 
15 Handles synchronous and a-synchronous timer events.
16 1. synchronous timer is registered into TSystem and is processed
17  within the standard ROOT event-loop.
18 2. asynchronous timer is passed to the operating system which sends
19  an external signal to ROOT and thus interrupts its event-loop.
20 
21 You can use this class in one of the following ways:
22  - Sub-class TTimer and override the Notify() method.
23  - Re-implement the TObject::HandleTimer() method in your class
24  and pass a pointer to this object to timer, see the SetObject()
25  method.
26  - Pass an interpreter command to timer, see SetCommand() method.
27  - Create a TTimer, connect its Timeout() signal to the
28  appropriate methods. Then when the time is up it will emit a
29  Timeout() signal and call connected slots.
30 
31 Minimum timeout interval is defined in TSystem::ESysConstants as
32 `kItimerResolution` (currently 10 ms).
33 
34 Signal/slots example:
35 ~~~{.cpp}
36  TTimer *timer = new TTimer();
37  timer->Connect("Timeout()", "myObjectClassName",
38  myObject, "TimerDone()");
39  timer->Start(2000, kTRUE); // 2 seconds single-shot
40 ~~~
41 To emit the Timeout signal repeatedly with minimum timeout:
42 ~~~ {.cpp}
43  timer->Start(0, kFALSE);
44 ~~~
45 */
46 
47 #include "TTimer.h"
48 #include "TSystem.h"
49 #include "TROOT.h"
50 
51 ClassImp(TTimer);
52 
53 
54 class TSingleShotCleaner : public TTimer {
55 private:
56  TList *fGarbage;
57 public:
58  TSingleShotCleaner() : TTimer(10, kTRUE) { fGarbage = new TList(); }
59  virtual ~TSingleShotCleaner() { fGarbage->Delete(); delete fGarbage; }
60  void TurnOn() {
61  TObject *obj = (TObject*) gTQSender;
62  fGarbage->Add(obj);
63  Reset();
64  if (gSystem)
65  gSystem->AddTimer(this);
66  }
67  Bool_t Notify() {
68  fGarbage->Delete();
69  Reset();
70  if (gSystem)
71  gSystem->RemoveTimer(this);
72  return kTRUE;
73  }
74 };
75 
76 ////////////////////////////////////////////////////////////////////////////////
77 /// Create timer that times out in ms milliseconds. If milliSec is 0
78 /// then the timeout will be the minimum timeout (see TSystem::ESysConstants,
79 /// i.e. 10 ms). If mode == kTRUE then the timer is synchronous else
80 /// a-synchronous. The default is synchronous. Add a timer to the system
81 /// eventloop by calling TurnOn(). Set command to be executed from Notify()
82 /// or set the object whose HandleTimer() method will be called via Notify(),
83 /// derive from TTimer and override Notify() or connect slots to the
84 /// signals Timeout(), TurnOn() and TurnOff().
85 
86 TTimer::TTimer(Long_t ms, Bool_t mode) : fTime(ms)
87 {
88  fObject = 0;
89  fCommand = "";
90  fSync = mode;
91  fIntSyscalls = kFALSE;
92  Reset();
93 }
94 
95 ////////////////////////////////////////////////////////////////////////////////
96 /// Create timer that times out in ms milliseconds. If mode == kTRUE then
97 /// the timer is synchronous else a-synchronous. The default is synchronous.
98 /// Add a timer to the system eventloop by calling TurnOn().
99 /// The object's HandleTimer() will be called by Notify().
100 
101 TTimer::TTimer(TObject *obj, Long_t ms, Bool_t mode) : fTime(ms)
102 {
103  fObject = obj;
104  fCommand = "";
105  fSync = mode;
106  fIntSyscalls = kFALSE;
107  Reset();
108 }
109 
110 ////////////////////////////////////////////////////////////////////////////////
111 /// Create timer that times out in ms milliseconds. If mode == kTRUE then
112 /// the timer is synchronous else a-synchronous. The default is synchronous.
113 /// Add a timer to the system eventloop by calling TurnOn().
114 /// The interpreter will execute command from Notify().
115 
116 TTimer::TTimer(const char *command, Long_t ms, Bool_t mode) : fTime(ms)
117 {
118  fObject = 0;
119  fCommand = command;
120  fSync = mode;
121  fIntSyscalls = kFALSE;
122  Reset();
123 }
124 
125 ////////////////////////////////////////////////////////////////////////////////
126 /// Check if timer timed out.
127 
128 Bool_t TTimer::CheckTimer(const TTime &now)
129 {
130  if (fAbsTime <= now) {
131  fTimeout = kTRUE;
132  Notify();
133  return kTRUE;
134  }
135  return kFALSE;
136 }
137 
138 ////////////////////////////////////////////////////////////////////////////////
139 /// Notify when timer times out. The timer is always reset. To stop
140 /// the timer call TurnOff(). Make sure to call Reset() also in derived
141 /// Notify() so timers will keep working repeatedly.
142 
143 Bool_t TTimer::Notify()
144 {
145  Timeout(); // emit Timeout() signal
146  if (fObject) fObject->HandleTimer(this);
147  if (fCommand && fCommand.Length() > 0)
148  gROOT->ProcessLine(fCommand);
149 
150  Reset();
151  return kTRUE;
152 }
153 
154 ////////////////////////////////////////////////////////////////////////////////
155 /// Reset the timer.
156 
157 void TTimer::Reset()
158 {
159  // make sure gSystem exists
160  ROOT::GetROOT();
161 
162  fTimeout = kFALSE;
163  fAbsTime = fTime;
164  if (gSystem) {
165  fAbsTime += gSystem->Now();
166  if (!fSync) gSystem->ResetTimer(this);
167  }
168 }
169 
170 ////////////////////////////////////////////////////////////////////////////////
171 /// Set the interpreter command to be executed at time out. Removes the
172 /// object to be notified (if it was set).
173 
174 void TTimer::SetCommand(const char *command)
175 {
176  fObject = 0;
177  fCommand = command;
178 }
179 
180 ////////////////////////////////////////////////////////////////////////////////
181 /// Set the object to be notified at time out. Removes the command to
182 /// be executed (if it was set).
183 
184 void TTimer::SetObject(TObject *object)
185 {
186  fObject = object;
187  fCommand = "";
188 }
189 
190 ////////////////////////////////////////////////////////////////////////////////
191 /// When the argument is true the a-synchronous timer (SIGALRM) signal
192 /// handler is set so that interrupted syscalls will not be restarted
193 /// by the kernel. This is typically used in case one wants to put a
194 /// timeout on an I/O operation. By default interrupted syscalls will
195 /// be restarted.
196 
197 void TTimer::SetInterruptSyscalls(Bool_t set)
198 {
199  fIntSyscalls = set;
200 }
201 
202 ////////////////////////////////////////////////////////////////////////////////
203 /// Starts the timer with a milliSec timeout. If milliSec is 0
204 /// then the timeout will be the minimum timeout (see TSystem::ESysConstants,
205 /// i.e. 10 ms), if milliSec is -1 then the time interval as previously
206 /// specified (in ctor or SetTime()) will be used.
207 /// If singleShot is kTRUE, the timer will be activated only once,
208 /// otherwise it will continue until it is stopped.
209 /// See also TurnOn(), Stop(), TurnOff().
210 
211 void TTimer::Start(Long_t milliSec, Bool_t singleShot)
212 {
213  if (milliSec >= 0)
214  SetTime(milliSec);
215  Reset();
216  TurnOn();
217  if (singleShot)
218  Connect(this, "Timeout()", "TTimer", this, "TurnOff()");
219  else
220  Disconnect(this, "Timeout()", this, "TurnOff()");
221 }
222 
223 ////////////////////////////////////////////////////////////////////////////////
224 /// Remove timer from system timer list. This requires that a timer
225 /// has been placed in the system timer list (using TurnOn()).
226 /// If a TTimer subclass is placed on another list, override TurnOff() to
227 /// remove the timer from the correct list.
228 
229 void TTimer::TurnOff()
230 {
231  if (gSystem)
232  if (gSystem->RemoveTimer(this))
233  Emit("TurnOff()");
234 }
235 
236 ////////////////////////////////////////////////////////////////////////////////
237 /// Add the timer to the system timer list. If a TTimer subclass has to be
238 /// placed on another list, override TurnOn() to add the timer to the correct
239 /// list.
240 
241 void TTimer::TurnOn()
242 {
243  // might have been set in a previous Start()
244  Disconnect(this, "Timeout()", this, "TurnOff()");
245 
246  if (gSystem) {
247  gSystem->AddTimer(this);
248  Emit("TurnOn()");
249  }
250 }
251 
252 ////////////////////////////////////////////////////////////////////////////////
253 /// This static function calls a slot after a given time interval.
254 /// Created internal timer will be deleted after that.
255 
256 void TTimer::SingleShot(Int_t milliSec, const char *receiver_class,
257  void *receiver, const char *method)
258 {
259  TTimer *singleShotTimer = new TTimer(milliSec);
260  TQObject::Connect(singleShotTimer, "Timeout()",
261  receiver_class, receiver, method);
262 
263  static TSingleShotCleaner singleShotCleaner; // single shot timer cleaner
264 
265  // gSingleShotCleaner will delete singleShotTimer a
266  // short period after Timeout() signal is emitted
267  TQObject::Connect(singleShotTimer, "Timeout()",
268  "TTimer", &singleShotCleaner, "TurnOn()");
269 
270  singleShotTimer->Start(milliSec, kTRUE);
271 }