00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039 #ifndef OASYS_TIMER_H
00040 #define OASYS_TIMER_H
00041
00042 #include <errno.h>
00043 #include <sys/types.h>
00044 #include <sys/time.h>
00045 #include <queue>
00046 #include <signal.h>
00047
00048 #include "config.h"
00049 #include "../debug/DebugUtils.h"
00050 #include "../debug/Log.h"
00051 #include "../util/Singleton.h"
00052 #include "MsgQueue.h"
00053 #include "OnOffNotifier.h"
00054 #include "Thread.h"
00055
00062 typedef RETSIGTYPE (sighandlerfn_t) (int);
00063
00064 namespace oasys {
00065
00069 #define TIMEVAL_DIFF(t1, t2, t3) \
00070 do { \
00071 ((t3).tv_sec = (t1).tv_sec - (t2).tv_sec); \
00072 ((t3).tv_usec = (t1).tv_usec - (t2).tv_usec); \
00073 if ((t3).tv_usec < 0) { (t3).tv_sec--; (t3).tv_usec += 1000000; } \
00074 } while (0)
00075
00076 #define TIMEVAL_DIFF_DOUBLE(t1, t2) \
00077 ((double)(((t1).tv_sec - (t2).tv_sec)) + \
00078 (double)((((t1).tv_usec - (t2).tv_usec)) * 1000000.0))
00079
00080 #define TIMEVAL_DIFF_MSEC(t1, t2) \
00081 ((unsigned long int)(((t1).tv_sec - (t2).tv_sec) * 1000) + \
00082 (((t1).tv_usec - (t2).tv_usec) / 1000))
00083
00084 #define TIMEVAL_DIFF_USEC(t1, t2) \
00085 ((unsigned long int)(((t1).tv_sec - (t2).tv_sec) * 1000000) + \
00086 (((t1).tv_usec - (t2).tv_usec)))
00087
00088 #define TIMEVAL_GT(t1, t2) \
00089 (((t1).tv_sec > (t2).tv_sec) || \
00090 (((t1).tv_sec == (t2).tv_sec) && ((t1).tv_usec > (t2).tv_usec)))
00091
00092 #define TIMEVAL_LT(t1, t2) \
00093 (((t1).tv_sec < (t2).tv_sec) || \
00094 (((t1).tv_sec == (t2).tv_sec) && ((t1).tv_usec < (t2).tv_usec)))
00095
00096 class SpinLock;
00097 class Timer;
00098
00102 class TimerCompare {
00103 public:
00104 inline bool operator ()(Timer* a, Timer* b);
00105 };
00106
00111 class TimerSystem : public Singleton<TimerSystem>,
00112 public Logger {
00113 public:
00114 void schedule_at(struct timeval *when, Timer* timer);
00115 void schedule_in(int milliseconds, Timer* timer);
00116 void schedule_immediate(Timer* timer);
00117 bool cancel(Timer* timer);
00118
00122 void add_sighandler(int sig, sighandlerfn_t* handler);
00123
00128 static void post_signal(int sig);
00129
00134 int run_expired_timers();
00135
00140 OnOffNotifier* notifier() { return ¬ifier_; }
00141
00142 private:
00143 friend class Singleton<TimerSystem>;
00144 typedef std::priority_queue<Timer*,
00145 std::vector<Timer*>,
00146 TimerCompare> TimerQueue;
00147
00148
00151 sighandlerfn_t* handlers_[NSIG];
00152 bool signals_[NSIG];
00153 bool sigfired_;
00154
00155 SpinLock* system_lock_;
00156 OnOffNotifier notifier_;
00157 TimerQueue timers_;
00158
00159 TimerSystem();
00160
00161 void pop_timer(const struct timeval& now);
00162 void handle_signals();
00163
00164 };
00165
00169 class TimerThread : public Thread {
00170 public:
00171 static void init();
00172
00173 private:
00174 TimerThread() : Thread("TimerThread") {}
00175 void run();
00176
00177 static TimerThread* instance_;
00178 };
00179
00184 class Timer {
00185 public:
00186 Timer()
00187 : pending_(false),
00188 cancelled_(false),
00189 cancel_flags_(DELETE_ON_CANCEL)
00190 {
00191 }
00192
00193 virtual ~Timer() {
00194
00195
00196
00197
00198 ASSERTF(pending_ == false, "can't delete a pending timer");
00199 }
00200
00201 void schedule_at(struct timeval *when)
00202 {
00203 TimerSystem::instance()->schedule_at(when, this);
00204 }
00205
00206 void schedule_in(int milliseconds)
00207 {
00208 TimerSystem::instance()->schedule_in(milliseconds, this);
00209 }
00210 void schedule_immediate()
00211 {
00212 TimerSystem::instance()->schedule_immediate(this);
00213 }
00214
00215 bool cancel()
00216 {
00217 return TimerSystem::instance()->cancel(this);
00218 }
00219
00220 bool pending()
00221 {
00222 return pending_;
00223 }
00224
00225 bool cancelled()
00226 {
00227 return cancelled_;
00228 }
00229
00230 struct timeval when()
00231 {
00232 return when_;
00233 }
00234
00235 virtual void timeout(const struct timeval& now) = 0;
00236
00237 protected:
00238 friend class TimerSystem;
00239 friend class TimerCompare;
00240
00242 typedef enum {
00243 NO_DELETE = 0,
00244 DELETE_ON_CANCEL = 1
00245 } cancel_flags_t;
00246
00247 struct timeval when_;
00248 bool pending_;
00249 bool cancelled_;
00250 cancel_flags_t cancel_flags_;
00251
00252
00253 };
00254
00258 bool
00259 TimerCompare::operator()(Timer* a, Timer* b)
00260 {
00261 return TIMEVAL_GT(a->when_, b->when_);
00262 }
00263
00269 struct TimerEvent {
00270 TimerEvent(const Timer* timer, struct timeval* time)
00271 : timer_(timer), time_(*time)
00272 {
00273 }
00274
00275 const Timer* timer_;
00276 struct timeval time_;
00277 };
00278
00282 typedef MsgQueue<TimerEvent> TimerEventQueue;
00283
00290 class QueuingTimer : public Timer {
00291 public:
00292 QueuingTimer(TimerEventQueue* queue) : queue_(queue) {}
00293
00294 virtual void timeout(struct timeval* now)
00295 {
00296 queue_->push(TimerEvent(this, now));
00297 }
00298
00299 protected:
00300 TimerEventQueue* queue_;
00301 };
00302
00303 }
00304
00305 #endif
00306