Timer.h

Go to the documentation of this file.
00001 /*
00002  *    Copyright 2004-2006 Intel Corporation
00003  * 
00004  *    Licensed under the Apache License, Version 2.0 (the "License");
00005  *    you may not use this file except in compliance with the License.
00006  *    You may obtain a copy of the License at
00007  * 
00008  *        http://www.apache.org/licenses/LICENSE-2.0
00009  * 
00010  *    Unless required by applicable law or agreed to in writing, software
00011  *    distributed under the License is distributed on an "AS IS" BASIS,
00012  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  *    See the License for the specific language governing permissions and
00014  *    limitations under the License.
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 &notifier_; }
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          * The only time a timer should be deleted is after it fires,
00176          * so assert as such.
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 } // namespace oasys
00284 
00285 #endif /* OASYS_TIMER_H */
00286 

Generated on Thu Jun 7 12:54:30 2007 for DTN Reference Implementation by  doxygen 1.5.1