Timer.h

Go to the documentation of this file.
00001 /*
00002  * IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. By
00003  * downloading, copying, installing or using the software you agree to
00004  * this license. If you do not agree to this license, do not download,
00005  * install, copy or use the software.
00006  * 
00007  * Intel Open Source License 
00008  * 
00009  * Copyright (c) 2004 Intel Corporation. All rights reserved. 
00010  * 
00011  * Redistribution and use in source and binary forms, with or without
00012  * modification, are permitted provided that the following conditions are
00013  * met:
00014  * 
00015  *   Redistributions of source code must retain the above copyright
00016  *   notice, this list of conditions and the following disclaimer.
00017  * 
00018  *   Redistributions in binary form must reproduce the above copyright
00019  *   notice, this list of conditions and the following disclaimer in the
00020  *   documentation and/or other materials provided with the distribution.
00021  * 
00022  *   Neither the name of the Intel Corporation nor the names of its
00023  *   contributors may be used to endorse or promote products derived from
00024  *   this software without specific prior written permission.
00025  *  
00026  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00027  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00028  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
00029  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE INTEL OR
00030  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
00031  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
00032  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00033  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00034  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00035  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
00036  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
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 &notifier_; }
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          * The only time a timer should be deleted is after it fires,
00196          * so assert as such.
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 } // namespace oasys
00304 
00305 #endif /* OASYS_TIMER_H */
00306 

Generated on Fri Dec 22 14:48:01 2006 for DTN Reference Implementation by  doxygen 1.5.1