LogCabin
Event/Timer.h
Go to the documentation of this file.
00001 /* Copyright (c) 2011-2014 Stanford University
00002  * Copyright (c) 2015 Diego Ongaro
00003  *
00004  * Permission to use, copy, modify, and distribute this software for any
00005  * purpose with or without fee is hereby granted, provided that the above
00006  * copyright notice and this permission notice appear in all copies.
00007  *
00008  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR(S) DISCLAIM ALL WARRANTIES
00009  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
00010  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL AUTHORS BE LIABLE FOR
00011  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
00012  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
00013  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
00014  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
00015  */
00016 
00017 #ifndef LOGCABIN_EVENT_TIMER_H
00018 #define LOGCABIN_EVENT_TIMER_H
00019 
00020 #include "Core/Time.h"
00021 #include "Event/File.h"
00022 
00023 namespace LogCabin {
00024 namespace Event {
00025 
00026 // forward declaration
00027 class Loop;
00028 
00029 /**
00030  * A Timer is called by the Event::Loop when time has elapsed.
00031  * The client should inherit from this and implement the trigger method for
00032  * when the timer expires.
00033  *
00034  * Timers can be added and scheduled from any thread, but they will always fire
00035  * on the thread running the Event::Loop.
00036  */
00037 class Timer : private File {
00038   public:
00039 
00040     /**
00041      * Registers a Timer handler to be monitored by the Event::Loop. Once this
00042      * is constructed, the Event::Loop will call the Timer's event handler
00043      * appropriately.
00044      *
00045      * This object must be destroyed or disableForever() called BEFORE the
00046      * Timer object can be destroyed safely.
00047      */
00048     class Monitor : private File::Monitor {
00049       public:
00050         /// See File::Monitor::Monitor.
00051         Monitor(Event::Loop& eventLoop, Timer& timer);
00052         /// See File::Monitor::~Monitor.
00053         ~Monitor();
00054         /// See File::Monitor::disableForever.
00055         using File::Monitor::disableForever;
00056     };
00057 
00058     /**
00059      * Construct a timer but do not schedule it to trigger.
00060      * After this is constructed, you'll want to create an
00061      * Event::Timer::Monitor for it and also schedule() it, in either order.
00062      */
00063     Timer();
00064 
00065     /**
00066      * Destructor.
00067      */
00068     virtual ~Timer();
00069 
00070     /**
00071      * This method is overridden by a subclass and invoked when the timer
00072      * expires. This method will be invoked by the main event loop on whatever
00073      * thread is running the Event::Loop.
00074      */
00075     virtual void handleTimerEvent() = 0;
00076 
00077     /**
00078      * Start the timer.
00079      * \param nanoseconds
00080      *     The timer will trigger once this number of nanoseconds have elapsed.
00081      *     If the timer was already scheduled, the old time is forgotten.
00082      */
00083     void schedule(uint64_t nanoseconds);
00084 
00085     /**
00086      * Start the timer for an absolute point in time. If the timeout is in the
00087      * past, the timer will trigger immediately once the event loop runs.
00088      * \param timeout
00089      *     The timer will trigger once this timeout has past.
00090      *     If the timer was already scheduled, the old time is forgotten.
00091      */
00092     void scheduleAbsolute(Core::Time::SteadyClock::time_point timeout);
00093 
00094     /**
00095      * Stop the timer from calling handleTimerEvent().
00096      * This will cancel the current timer, if any, so that handleTimerEvent()
00097      * is not called until the next time it is scheduled.
00098      *
00099      * This method behaves in a friendly way when called concurrently with the
00100      * timer firing:
00101      * - If this method is called from another thread and handleTimerEvent() is
00102      *   running concurrently on the event loop thread, deschedule() will wait
00103      *   for handleTimerEvent() to complete before returning.
00104      * - If this method is called from the event loop thread and
00105      *   handleTimerEvent() is currently being fired, then deschedule() can't
00106      *   wait and returns immediately.
00107      */
00108     void deschedule();
00109 
00110   private:
00111     /**
00112      * Returns true if the timer has been scheduled and has not yet fired.
00113      * \warning
00114      *      This is prone to races; it's primarily useful for unit tests.
00115      *      It also improperly returns false after scheduleAbsolute() is called
00116      *      with a time that has expired. It's marked as private so it can't be
00117      *      accessed from normal (non-test) code.
00118      *      TODO(ongaro): remove entirely or add additional state to this
00119      *      class to make this work correctly?
00120      * \return
00121      *      True if the timer has been scheduled and will eventually call
00122      *      handleTimerEvent().
00123      *      False if the timer is currently running handleTimerEvent() or if it
00124      *      is not scheduled to call handleTimerEvent() in the future.
00125      */
00126     bool isScheduled() const;
00127 
00128     /**
00129      * Generic event handler for files. Calls handleTimerEvent().
00130      */
00131     void handleFileEvent(uint32_t events);
00132 
00133     // Timer is not copyable.
00134     Timer(const Timer&) = delete;
00135     Timer& operator=(const Timer&) = delete;
00136 };
00137 
00138 } // namespace LogCabin::Event
00139 } // namespace LogCabin
00140 
00141 #endif /* LOGCABIN_EVENT_TIMER_H */
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines