xorp

timer.hh

00001 // -*- c-basic-offset: 4; tab-width: 8; indent-tabs-mode: t -*-
00002 // vim:set sts=4 ts=8:
00003 
00004 // Copyright (c) 2001-2011 XORP, Inc and Others
00005 //
00006 // This program is free software; you can redistribute it and/or modify
00007 // it under the terms of the GNU Lesser General Public License, Version
00008 // 2.1, June 1999 as published by the Free Software Foundation.
00009 // Redistribution and/or modification of this program under the terms of
00010 // any other version of the GNU Lesser General Public License is not
00011 // permitted.
00012 // 
00013 // This program is distributed in the hope that it will be useful, but
00014 // WITHOUT ANY WARRANTY; without even the implied warranty of
00015 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For more details,
00016 // see the GNU Lesser General Public License, Version 2.1, a copy of
00017 // which can be found in the XORP LICENSE.lgpl file.
00018 // 
00019 // XORP, Inc, 2953 Bunker Hill Lane, Suite 204, Santa Clara, CA 95054, USA;
00020 // http://xorp.net
00021 
00022 
00023 #ifndef __LIBXORP_TIMER_HH__
00024 #define __LIBXORP_TIMER_HH__
00025 
00026 #include <assert.h>
00027 
00028 
00029 #ifdef HAVE_SYS_TIME_H
00030 #include <sys/time.h>
00031 #endif
00032 
00033 #include "timeval.hh"
00034 #include "heap.hh"
00035 #include "callback.hh"
00036 #include "task.hh"
00037 
00038 class XorpTimer;
00039 class TimerNode;
00040 class TimerList;
00041 class ClockBase;
00042 
00043 typedef XorpCallback0<void>::RefPtr OneoffTimerCallback;
00044 
00045 // PeriodicTimerCallback methods should return true to reschedule
00046 typedef XorpCallback0<bool>::RefPtr PeriodicTimerCallback;
00047 
00048 typedef XorpCallback1<void, XorpTimer&>::RefPtr BasicTimerCallback;
00049 
00060 class TimerListObserverBase {
00061 public:
00062     virtual ~TimerListObserverBase();
00063 
00064 private:
00069     virtual void notify_scheduled(const TimeVal&) = 0;
00070 
00074     virtual void notify_unscheduled(const TimeVal&) = 0;
00075 
00076     TimerList * _observed;
00077 
00078     friend class TimerList;
00079 };
00080 
00091 class XorpTimer {
00092 public:
00093 
00098     bool scheduled() const;
00099 
00103     const TimeVal& expiry() const;
00104 
00115     bool time_remaining(TimeVal& remain) const;
00116 
00120     void schedule_now(int priority = XorpTask::PRIORITY_DEFAULT);
00121 
00125     void schedule_at(const TimeVal& when,
00126              int priority = XorpTask::PRIORITY_DEFAULT);
00127 
00132     void schedule_after(const TimeVal& wait,
00133             int priority = XorpTask::PRIORITY_DEFAULT);
00134 
00140     void schedule_after_ms(int ms,
00141                int priority = XorpTask::PRIORITY_DEFAULT);
00142 
00148     void reschedule_after(const TimeVal& wait);
00149 
00155     void reschedule_after_ms(int ms);
00156 
00161     void unschedule();          // unschedule if scheduled
00162 
00166     void clear();           // erase timer
00167 
00168     XorpTimer()             : _node(NULL) { }
00169     XorpTimer(TimerList* list, BasicTimerCallback cb);
00170     XorpTimer(const XorpTimer&);
00171     ~XorpTimer();
00172 
00173     XorpTimer& operator=(const XorpTimer&);
00174     TimerNode* node() const { return _node; }
00175 
00176 private:
00177     TimerNode* _node;
00178 
00179     XorpTimer(TimerNode* n);
00180 
00181     friend class TimerList;
00182 };
00183 
00184 
00216 class TimerList {
00217 public:
00221     TimerList(ClockBase* clock);
00222 
00223     ~TimerList();
00224 
00229     void run();
00230 
00239     XorpTimer new_oneoff_at(const TimeVal& when,
00240                 const OneoffTimerCallback& ocb,
00241                 int priority = XorpTask::PRIORITY_DEFAULT);
00242 
00251     XorpTimer new_oneoff_after(const TimeVal& wait,
00252                    const OneoffTimerCallback& ocb,
00253                    int priority = XorpTask::PRIORITY_DEFAULT);
00254 
00255     void remove_timer(XorpTimer& t);
00256 
00266     XorpTimer new_periodic(const TimeVal& wait,
00267                const PeriodicTimerCallback& pcb,
00268                int priority = XorpTask::PRIORITY_DEFAULT);
00269 
00280     XorpTimer set_flag_at(const TimeVal&    when,
00281               bool*         flag_ptr,
00282               bool          to_value = true,
00283               int priority = XorpTask::PRIORITY_DEFAULT);
00284 
00295     XorpTimer set_flag_after(const TimeVal& wait,
00296                  bool*      flag_ptr,
00297                  bool       to_value = true,
00298                  int priority = XorpTask::PRIORITY_DEFAULT);
00299 
00312     XorpTimer new_timer(const BasicTimerCallback& cb) {
00313     return XorpTimer(this, cb);
00314     }
00315 
00320     bool empty() const;
00321 
00325     size_t size() const;
00326 
00338     bool get_next_delay(TimeVal& tv) const;
00339 
00346     int get_expired_priority() const;
00347 
00354     void current_time(TimeVal& now) const;
00355 
00361     void advance_time();
00362 
00374     static void system_gettimeofday(TimeVal* tv);
00375 
00385     static void system_sleep(const TimeVal& tv);
00386 
00392     void set_observer(TimerListObserverBase& obs);
00393 
00397     void remove_observer();
00398 
00404     static TimerList* instance();
00405 
00406 private:
00407     void schedule_node(TimerNode* t);       // insert in time ordered pos.
00408     void unschedule_node(TimerNode* t);     // remove from list
00409 
00410     void acquire_lock() const       { /* nothing, for now */ }
00411     bool attempt_lock() const       { return true; }
00412     void release_lock() const       { /* nothing, for now */ }
00413 
00414 
00415     // find or create the heap assoicated with this priority level
00416     Heap* find_heap(int priority);    
00417 
00418     // expire the highest priority timer
00419     bool expire_one(int worst_priority);
00420 
00421 private:
00422     // The following is not a noncopyable candidate.
00423     TimerList(const TimerList&);        // Not copyable.
00424     TimerList& operator=(const TimerList&); // Assignable only by self.
00425 
00426 private:
00427     // we need one heap for each priority level
00428     map<int, Heap*>     _heaplist;
00429 
00430     ClockBase*          _clock;
00431     TimerListObserverBase*  _observer;
00432 #ifdef HOST_OS_WINDOWS
00433     HANDLE          _hirestimer;
00434 #endif
00435 
00436     friend class TimerNode;
00437     friend class TimerListObserverBase;
00438 };
00439 
00440 class TimerNode :
00441     public NONCOPYABLE,
00442     public HeapBase
00443 {
00444 protected:
00445     TimerNode(TimerList*, BasicTimerCallback);
00446     virtual ~TimerNode();
00447     void add_ref();
00448     void release_ref();
00449 
00450     // we want this even if it is never called, to override the
00451     // default supplied by the compiler.
00452     TimerNode(const TimerNode&);    // never called
00453     TimerNode& operator=(const TimerNode&);
00454 
00455     bool scheduled()        const   { return _pos_in_heap >= 0; }
00456     int priority()      const   { return _priority; }
00457     const TimeVal& expiry() const   { return _expires; }
00458     bool time_remaining(TimeVal& remain) const;
00459 
00460     void schedule_at(const TimeVal&, int priority);
00461     void schedule_after(const TimeVal& wait, int priority);
00462     void reschedule_after(const TimeVal& wait);
00463     void unschedule();
00464     virtual void expire(XorpTimer&, void*);
00465 
00466     int     _ref_cnt;   // Number of referring XorpTimer objects
00467 
00468     TimeVal _expires;   // Expiration time
00469     BasicTimerCallback _cb;
00470 
00471     int     _priority;  // Scheduling priority
00472 
00473     TimerList*  _list;      // TimerList this node is associated w.
00474 
00475     friend class XorpTimer;
00476     friend class TimerList;
00477 };
00478 
00479 
00480 // ----------------------------------------------------------------------------
00481 // inline Timer methods
00482 
00483 inline XorpTimer::XorpTimer(TimerNode* n)
00484     : _node(n)
00485 {
00486     if (_node)
00487     _node->add_ref();
00488 }
00489 
00490 inline XorpTimer::XorpTimer(TimerList* tlist, BasicTimerCallback cb)
00491     : _node(new TimerNode(tlist, cb))
00492 {
00493     if (_node)
00494     _node->add_ref();
00495 }
00496 
00497 inline XorpTimer::XorpTimer(const XorpTimer& t)
00498     : _node(t._node)
00499 {
00500     if (_node)
00501     _node->add_ref();
00502 }
00503 
00504 inline XorpTimer::~XorpTimer()
00505 {
00506     if (_node)
00507     _node->release_ref();
00508 }
00509 
00510 inline XorpTimer&
00511 XorpTimer::operator=(const XorpTimer& t)
00512 {
00513     if (t._node)
00514     t._node->add_ref();
00515     if (_node)
00516     _node->release_ref();
00517     _node = t._node;
00518     return *this;
00519 }
00520 
00521 inline bool
00522 XorpTimer::scheduled() const
00523 {
00524     return _node && _node->scheduled();
00525 }
00526 
00527 inline const TimeVal&
00528 XorpTimer::expiry() const
00529 {
00530     assert(_node);
00531     return _node->expiry();
00532 }
00533 
00534 inline bool
00535 XorpTimer::time_remaining(TimeVal& remain) const
00536 {
00537     if (_node == NULL) {
00538     remain = TimeVal::ZERO();
00539     return (false);
00540     }
00541     return (_node->time_remaining(remain));
00542 }
00543 
00544 inline void
00545 XorpTimer::schedule_at(const TimeVal& t, int priority)
00546 {
00547     assert(_node);
00548     _node->schedule_at(t, priority);
00549 }
00550 
00551 inline void
00552 XorpTimer::schedule_after(const TimeVal& wait, int priority)
00553 {
00554     assert(_node);
00555     _node->schedule_after(wait, priority);
00556 }
00557 
00558 inline void
00559 XorpTimer::schedule_after_ms(int ms, int priority)
00560 {
00561     assert(_node);
00562     TimeVal wait(ms / 1000, (ms % 1000) * 1000);
00563     _node->schedule_after(wait, priority);
00564 }
00565 
00566 inline void
00567 XorpTimer::schedule_now(int priority)
00568 {
00569     schedule_after(TimeVal::ZERO(), priority);
00570 }
00571 
00572 inline void
00573 XorpTimer::reschedule_after(const TimeVal& wait)
00574 {
00575     assert(_node);
00576     _node->reschedule_after(wait);
00577 }
00578 
00579 inline void
00580 XorpTimer::reschedule_after_ms(int ms)
00581 {
00582     assert(_node);
00583     TimeVal wait(ms / 1000, (ms % 1000) * 1000);
00584     _node->reschedule_after(wait);
00585 }
00586 
00587 inline void
00588 XorpTimer::unschedule()
00589 {
00590     if (_node)
00591     _node->unschedule();
00592 }
00593 
00594 inline void
00595 XorpTimer::clear()
00596 {
00597     if (_node)
00598     _node->release_ref();
00599     _node = 0;
00600 }
00601 
00602 #endif // __LIBXORP_TIMER_HH__
 All Classes Namespaces Functions Variables Typedefs Enumerations