PageRenderTime 83ms CodeModel.GetById 40ms app.highlight 8ms RepoModel.GetById 32ms app.codeStats 0ms

/mordor/timer.h

http://github.com/mozy/mordor
C Header | 113 lines | 66 code | 21 blank | 26 comment | 0 complexity | f6a0ea6307a2e58a56cd0958674ba0e3 MD5 | raw file
  1#ifndef __MORDOR_TIMER_H__
  2#define __MORDOR_TIMER_H__
  3// Copyright (c) 2009 - Mozy, Inc.
  4
  5#include <set>
  6#include <vector>
  7
  8#include <boost/enable_shared_from_this.hpp>
  9#include <boost/function.hpp>
 10#include <boost/noncopyable.hpp>
 11#include <boost/shared_ptr.hpp>
 12#include <boost/thread/mutex.hpp>
 13#include <boost/weak_ptr.hpp>
 14
 15namespace Mordor {
 16
 17class TimerManager;
 18
 19class Timer : public boost::noncopyable, public boost::enable_shared_from_this<Timer>
 20{
 21    friend class TimerManager;
 22public:
 23    typedef boost::shared_ptr<Timer> ptr;
 24
 25private:
 26    Timer(unsigned long long us, boost::function<void ()> dg,
 27        bool recurring, TimerManager *manager);
 28    // Constructor for dummy object
 29    Timer(unsigned long long next);
 30
 31public:
 32    /// @return If the timer was successfully cancelled before it fired
 33    /// (if non-recurring)
 34    bool cancel();
 35
 36    /// Refresh the timer from now
 37    /// @return If it was refreshed before firing
 38    bool refresh();
 39    /// Reset the timer to the new delay
 40    /// @param us The delay
 41    /// @param fromNow If us should be relative to now, or the original
 42    /// starting point
 43    /// @return If it was reset before firing
 44    bool reset(unsigned long long us, bool fromNow);
 45
 46private:
 47    bool m_recurring;
 48    unsigned long long m_next;
 49    unsigned long long m_us;
 50    boost::function<void ()> m_dg;
 51    TimerManager *m_manager;
 52
 53private:
 54    struct Comparator
 55    {
 56        bool operator()(const Timer::ptr &lhs, const Timer::ptr &rhs) const;
 57    };
 58
 59};
 60
 61class TimerManager : public boost::noncopyable
 62{
 63    friend class Timer;
 64public:
 65    TimerManager();
 66    virtual ~TimerManager();
 67
 68    virtual Timer::ptr registerTimer(unsigned long long us,
 69        boost::function<void ()> dg, bool recurring = false);
 70
 71    /// Conditionally execute the dg callback function only when weakCond is
 72    /// still in valid status, which means, the original object managed by the
 73    /// shared_ptr is not destroyed
 74    /// NOTE: this interface can't be called in class constructor while passing
 75    ///  a shared_ptr/weak_ptr of itself.
 76    Timer::ptr registerConditionTimer(unsigned long long us,
 77        boost::function<void ()> dg,
 78        boost::weak_ptr<void> weakCond,
 79        bool recurring = false);
 80
 81    /// @return How long until the next timer expires; ~0ull if no timers
 82    unsigned long long nextTimer();
 83    void executeTimers();
 84
 85    /// @return Monotonically increasing count of microseconds.  The number
 86    /// returned isn't guaranteed to be relative to any particular start time,
 87    /// however, the difference between two successive calls to now() is
 88    /// equal to the time that elapsed between calls.  This is true even if the
 89    /// system clock is changed.
 90    static unsigned long long now();
 91
 92    /// replace the built-in clock
 93    /// @param dg replacement function whose value will be returned by now()
 94    /// omit the parameter to return to the default clock.
 95    /// NOTE: as now() is static, this affects *all* TimerManager instances
 96    static void setClock(boost::function<unsigned long long()> dg = NULL);
 97
 98protected:
 99    virtual void onTimerInsertedAtFront() {}
100    std::vector<boost::function<void ()> > processTimers();
101
102private:
103    static boost::function<unsigned long long ()> ms_clockDg;
104    bool detectClockRollover(unsigned long long nowUs);
105    std::set<Timer::ptr, Timer::Comparator> m_timers;
106    boost::mutex m_mutex;
107    bool m_tickled;
108    unsigned long long m_previousTime;
109};
110
111}
112
113#endif