00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #ifndef OASYS_TIMER_H
00019 #define OASYS_TIMER_H
00020
00021 #include <errno.h>
00022 #include <sys/types.h>
00023 #include <sys/time.h>
00024 #include <queue>
00025 #include <signal.h>
00026
00027 #include "config.h"
00028 #include "../debug/DebugUtils.h"
00029 #include "../debug/Log.h"
00030 #include "../util/Singleton.h"
00031 #include "MsgQueue.h"
00032 #include "OnOffNotifier.h"
00033 #include "Thread.h"
00034
00041 typedef RETSIGTYPE (sighandlerfn_t) (int);
00042
00043 namespace oasys {
00044
00048 #define TIMEVAL_DIFF(t1, t2, t3) \
00049 do { \
00050 ((t3).tv_sec = (t1).tv_sec - (t2).tv_sec); \
00051 ((t3).tv_usec = (t1).tv_usec - (t2).tv_usec); \
00052 if ((t3).tv_usec < 0) { (t3).tv_sec--; (t3).tv_usec += 1000000; } \
00053 } while (0)
00054
00055 #define TIMEVAL_DIFF_DOUBLE(t1, t2) \
00056 ((double)(((t1).tv_sec - (t2).tv_sec)) + \
00057 (double)((((t1).tv_usec - (t2).tv_usec)) * 1000000.0))
00058
00059 #define TIMEVAL_DIFF_MSEC(t1, t2) \
00060 ((unsigned long int)(((t1).tv_sec - (t2).tv_sec) * 1000) + \
00061 (((t1).tv_usec - (t2).tv_usec) / 1000))
00062
00063 #define TIMEVAL_DIFF_USEC(t1, t2) \
00064 ((unsigned long int)(((t1).tv_sec - (t2).tv_sec) * 1000000) + \
00065 (((t1).tv_usec - (t2).tv_usec)))
00066
00067 #define TIMEVAL_GT(t1, t2) \
00068 (((t1).tv_sec > (t2).tv_sec) || \
00069 (((t1).tv_sec == (t2).tv_sec) && ((t1).tv_usec > (t2).tv_usec)))
00070
00071 #define TIMEVAL_LT(t1, t2) \
00072 (((t1).tv_sec < (t2).tv_sec) || \
00073 (((t1).tv_sec == (t2).tv_sec) && ((t1).tv_usec < (t2).tv_usec)))
00074
00075 class SpinLock;
00076 class Timer;
00077
00081 class TimerCompare {
00082 public:
00083 inline bool operator ()(Timer* a, Timer* b);
00084 };
00085
00090 class TimerSystem : public Singleton<TimerSystem>,
00091 public Logger {
00092 public:
00093 void schedule_at(struct timeval *when, Timer* timer);
00094 void schedule_in(int milliseconds, Timer* timer);
00095 void schedule_immediate(Timer* timer);
00096 bool cancel(Timer* timer);
00097
00101 void add_sighandler(int sig, sighandlerfn_t* handler);
00102
00107 static void post_signal(int sig);
00108
00113 int run_expired_timers();
00114
00119 OnOffNotifier* notifier() { return ¬ifier_; }
00120
00121 private:
00122 friend class Singleton<TimerSystem>;
00123 typedef std::priority_queue<Timer*,
00124 std::vector<Timer*>,
00125 TimerCompare> TimerQueue;
00126
00127
00130 sighandlerfn_t* handlers_[NSIG];
00131 bool signals_[NSIG];
00132 bool sigfired_;
00133
00134 SpinLock* system_lock_;
00135 OnOffNotifier notifier_;
00136 TimerQueue timers_;
00137
00138 TimerSystem();
00139 virtual ~TimerSystem();
00140
00141 void pop_timer(const struct timeval& now);
00142 void handle_signals();
00143
00144 };
00145
00149 class TimerThread : public Thread {
00150 public:
00151 static void init();
00152
00153 private:
00154 TimerThread() : Thread("TimerThread") {}
00155 void run();
00156
00157 static TimerThread* instance_;
00158 };
00159
00164 class Timer {
00165 public:
00166 Timer()
00167 : pending_(false),
00168 cancelled_(false),
00169 cancel_flags_(DELETE_ON_CANCEL)
00170 {
00171 }
00172
00173 virtual ~Timer() {
00174
00175
00176
00177
00178 ASSERTF(pending_ == false, "can't delete a pending timer");
00179 }
00180
00181 void schedule_at(struct timeval *when)
00182 {
00183 TimerSystem::instance()->schedule_at(when, this);
00184 }
00185
00186 void schedule_in(int milliseconds)
00187 {
00188 TimerSystem::instance()->schedule_in(milliseconds, this);
00189 }
00190 void schedule_immediate()
00191 {
00192 TimerSystem::instance()->schedule_immediate(this);
00193 }
00194
00195 bool cancel()
00196 {
00197 return TimerSystem::instance()->cancel(this);
00198 }
00199
00200 bool pending()
00201 {
00202 return pending_;
00203 }
00204
00205 bool cancelled()
00206 {
00207 return cancelled_;
00208 }
00209
00210 struct timeval when()
00211 {
00212 return when_;
00213 }
00214
00215 virtual void timeout(const struct timeval& now) = 0;
00216
00217 protected:
00218 friend class TimerSystem;
00219 friend class TimerCompare;
00220
00222 typedef enum {
00223 NO_DELETE = 0,
00224 DELETE_ON_CANCEL = 1
00225 } cancel_flags_t;
00226
00227 struct timeval when_;
00228 bool pending_;
00229 bool cancelled_;
00230 cancel_flags_t cancel_flags_;
00231
00232
00233 };
00234
00238 bool
00239 TimerCompare::operator()(Timer* a, Timer* b)
00240 {
00241 return TIMEVAL_GT(a->when_, b->when_);
00242 }
00243
00249 struct TimerEvent {
00250 TimerEvent(const Timer* timer, struct timeval* time)
00251 : timer_(timer), time_(*time)
00252 {
00253 }
00254
00255 const Timer* timer_;
00256 struct timeval time_;
00257 };
00258
00262 typedef MsgQueue<TimerEvent> TimerEventQueue;
00263
00270 class QueuingTimer : public Timer {
00271 public:
00272 QueuingTimer(TimerEventQueue* queue) : queue_(queue) {}
00273
00274 virtual void timeout(struct timeval* now)
00275 {
00276 queue_->push(TimerEvent(this, now));
00277 }
00278
00279 protected:
00280 TimerEventQueue* queue_;
00281 };
00282
00283 }
00284
00285 #endif
00286