00001 // @(#)root/base:$Id: TTimer.cxx 28359 2009-04-27 12:36:49Z rdm $ 00002 // Author: Fons Rademakers 28/11/96 00003 00004 /************************************************************************* 00005 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. * 00006 * All rights reserved. * 00007 * * 00008 * For the licensing terms see $ROOTSYS/LICENSE. * 00009 * For the list of contributors see $ROOTSYS/README/CREDITS. * 00010 *************************************************************************/ 00011 00012 ////////////////////////////////////////////////////////////////////////// 00013 // // 00014 // TTimer // 00015 // // 00016 // Handles synchronous and a-synchronous timer events. // 00017 // 1. synchronous timer is registered into TSystem and is processed // 00018 // within the standard ROOT event-loop. // 00019 // 2. asynchronous timer is passed to the operating system which sends // 00020 // an external signal to ROOT and thus interrupts its event-loop. // 00021 // // 00022 // You can use this class in one of the following ways: // 00023 // - Sub-class TTimer and override the Notify() method. // 00024 // - Re-implement the TObject::HandleTimer() method in your class // 00025 // and pass a pointer to this object to timer, see the SetObject() // 00026 // method. // 00027 // - Pass an interpreter command to timer, see SetCommand() method. // 00028 // - Create a TTimer, connect its Timeout() signal to the // 00029 // appropriate methods. Then when the time is up it will emit a // 00030 // Timeout() signal and call connected slots. // 00031 // // 00032 // Minimum timeout interval is defined in TSystem::ESysConstants as // 00033 // kItimerResolution (currently 10 ms). // 00034 // // 00035 // Signal/slots example: // 00036 // TTimer *timer = new TTimer(); // 00037 // timer->Connect("Timeout()", "myObjectClassName", // 00038 // myObject, "TimerDone()"); // 00039 // timer->Start(2000, kTRUE); // 2 seconds single-shot // 00040 // // 00041 // To emit the Timeout signal repeadetly with minimum timeout: // 00042 // timer->Start(0, kFALSE); // 00043 // // 00044 ////////////////////////////////////////////////////////////////////////// 00045 00046 #include "TTimer.h" 00047 #include "TSystem.h" 00048 #include "TROOT.h" 00049 00050 ClassImp(TTimer) 00051 00052 00053 class TSingleShotCleaner : public TTimer { 00054 private: 00055 TList *fGarbage; 00056 public: 00057 TSingleShotCleaner() : TTimer(10, kTRUE) { fGarbage = new TList(); } 00058 virtual ~TSingleShotCleaner() { fGarbage->Delete(); delete fGarbage; } 00059 void TurnOn() { 00060 TObject *obj = (TObject*) gTQSender; 00061 fGarbage->Add(obj); 00062 Reset(); 00063 if (gSystem) 00064 gSystem->AddTimer(this); 00065 } 00066 Bool_t Notify() { 00067 fGarbage->Delete(); 00068 Reset(); 00069 if (gSystem) 00070 gSystem->RemoveTimer(this); 00071 return kTRUE; 00072 } 00073 }; 00074 00075 //______________________________________________________________________________ 00076 TTimer::TTimer(Long_t ms, Bool_t mode) : fTime(ms) 00077 { 00078 // Create timer that times out in ms milliseconds. If milliSec is 0 00079 // then the timeout will be the minimum timeout (see TSystem::ESysConstants, 00080 // i.e. 10 ms). If mode == kTRUE then the timer is synchronous else 00081 // a-synchronous. The default is synchronous. Add a timer to the system 00082 // eventloop by calling TurnOn(). Set command to be executed from Notify() 00083 // or set the object whose HandleTimer() method will be called via Notify(), 00084 // derive from TTimer and override Notify() or connect slots to the 00085 // signals Timeout(), TurnOn() and TurnOff(). 00086 00087 fObject = 0; 00088 fCommand = ""; 00089 fSync = mode; 00090 fIntSyscalls = kFALSE; 00091 Reset(); 00092 } 00093 00094 //______________________________________________________________________________ 00095 TTimer::TTimer(TObject *obj, Long_t ms, Bool_t mode) : fTime(ms) 00096 { 00097 // Create timer that times out in ms milliseconds. If mode == kTRUE then 00098 // the timer is synchronous else a-synchronous. The default is synchronous. 00099 // Add a timer to the system eventloop by calling TurnOn(). 00100 // The object's HandleTimer() will be called by Notify(). 00101 00102 fObject = obj; 00103 fCommand = ""; 00104 fSync = mode; 00105 fIntSyscalls = kFALSE; 00106 Reset(); 00107 } 00108 00109 //______________________________________________________________________________ 00110 TTimer::TTimer(const char *command, Long_t ms, Bool_t mode) : fTime(ms) 00111 { 00112 // Create timer that times out in ms milliseconds. If mode == kTRUE then 00113 // the timer is synchronous else a-synchronous. The default is synchronous. 00114 // Add a timer to the system eventloop by calling TurnOn(). 00115 // The interpreter will execute command from Notify(). 00116 00117 fObject = 0; 00118 fCommand = command; 00119 fSync = mode; 00120 fIntSyscalls = kFALSE; 00121 Reset(); 00122 } 00123 00124 //______________________________________________________________________________ 00125 Bool_t TTimer::CheckTimer(const TTime &now) 00126 { 00127 // Check if timer timed out. 00128 00129 if (fAbsTime <= now) { 00130 fTimeout = kTRUE; 00131 Notify(); 00132 return kTRUE; 00133 } 00134 return kFALSE; 00135 } 00136 00137 //______________________________________________________________________________ 00138 Bool_t TTimer::Notify() 00139 { 00140 // Notify when timer times out. The timer is always reset. To stop 00141 // the timer call TurnOff(). 00142 00143 Timeout(); // emit Timeout() signal 00144 if (fObject) fObject->HandleTimer(this); 00145 if (fCommand && fCommand.Length() > 0) 00146 gROOT->ProcessLine(fCommand); 00147 00148 Reset(); 00149 return kTRUE; 00150 } 00151 00152 //______________________________________________________________________________ 00153 void TTimer::Reset() 00154 { 00155 // Reset the timer. 00156 00157 // make sure gSystem exists 00158 ROOT::GetROOT(); 00159 00160 fTimeout = kFALSE; 00161 fAbsTime = fTime; 00162 if (gSystem) { 00163 fAbsTime += gSystem->Now(); 00164 if (!fSync) gSystem->ResetTimer(this); 00165 } 00166 } 00167 00168 //______________________________________________________________________________ 00169 void TTimer::SetCommand(const char *command) 00170 { 00171 // Set the interpreter command to be executed at time out. Removes the 00172 // object to be notified (if it was set). 00173 00174 fObject = 0; 00175 fCommand = command; 00176 } 00177 00178 //______________________________________________________________________________ 00179 void TTimer::SetObject(TObject *object) 00180 { 00181 // Set the object to be notified at time out. Removes the command to 00182 // be executed (if it was set). 00183 00184 fObject = object; 00185 fCommand = ""; 00186 } 00187 00188 //______________________________________________________________________________ 00189 void TTimer::SetInterruptSyscalls(Bool_t set) 00190 { 00191 // When the argument is true the a-synchronous timer (SIGALRM) signal 00192 // handler is set so that interrupted syscalls will not be restarted 00193 // by the kernel. This is typically used in case one wants to put a 00194 // timeout on an I/O operation. By default interrupted syscalls will 00195 // be restarted. 00196 00197 fIntSyscalls = set; 00198 } 00199 00200 //___________________________________________________________________ 00201 void TTimer::Start(Long_t milliSec, Bool_t singleShot) 00202 { 00203 // Starts the timer with a milliSec timeout. If milliSec is 0 00204 // then the timeout will be the minimum timeout (see TSystem::ESysConstants, 00205 // i.e. 10 ms), if milliSec is -1 then the time interval as previously 00206 // specified (in ctor or SetTime()) will be used. 00207 // If singleShot is kTRUE, the timer will be activated only once, 00208 // otherwise it will continue until it is stopped. 00209 // See also TurnOn(), Stop(), TurnOff(). 00210 00211 if (milliSec >= 0) 00212 SetTime(milliSec); 00213 Reset(); 00214 TurnOn(); 00215 if (singleShot) 00216 Connect(this, "Timeout()", "TTimer", this, "TurnOff()"); 00217 else 00218 Disconnect(this, "Timeout()", this, "TurnOff()"); 00219 } 00220 00221 //______________________________________________________________________________ 00222 void TTimer::TurnOff() 00223 { 00224 // Remove timer from system timer list. This requires that a timer 00225 // has been placed in the system timer list (using TurnOn()). 00226 // If a TTimer subclass is placed on another list, override TurnOff() to 00227 // remove the timer from the correct list. 00228 00229 if (gSystem) 00230 if (gSystem->RemoveTimer(this)) 00231 Emit("TurnOff()"); 00232 } 00233 00234 //______________________________________________________________________________ 00235 void TTimer::TurnOn() 00236 { 00237 // Add the timer to the system timer list. If a TTimer subclass has to be 00238 // placed on another list, override TurnOn() to add the timer to the correct 00239 // list. 00240 00241 // might have been set in a previous Start() 00242 Disconnect(this, "Timeout()", this, "TurnOff()"); 00243 00244 if (gSystem) { 00245 gSystem->AddTimer(this); 00246 Emit("TurnOn()"); 00247 } 00248 } 00249 00250 //______________________________________________________________________________ 00251 void TTimer::SingleShot(Int_t milliSec, const char *receiver_class, 00252 void *receiver, const char *method) 00253 { 00254 // This static function calls a slot after a given time interval. 00255 // Created internal timer will be deleted after that. 00256 00257 TTimer *singleShotTimer = new TTimer(milliSec); 00258 TQObject::Connect(singleShotTimer, "Timeout()", 00259 receiver_class, receiver, method); 00260 00261 static TSingleShotCleaner singleShotCleaner; // single shot timer cleaner 00262 00263 // gSingleShotCleaner will delete singleShotTimer a 00264 // short period after Timeout() signal is emitted 00265 TQObject::Connect(singleShotTimer, "Timeout()", 00266 "TTimer", &singleShotCleaner, "TurnOn()"); 00267 00268 singleShotTimer->Start(milliSec, kTRUE); 00269 }