LogCabin
Event/Loop.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_LOOP_H
00018 #define LOGCABIN_EVENT_LOOP_H
00019 
00020 #include <cinttypes>
00021 #include <memory>
00022 
00023 #include "Core/ConditionVariable.h"
00024 #include "Core/Mutex.h"
00025 #include "Event/Timer.h"
00026 
00027 namespace LogCabin {
00028 namespace Event {
00029 
00030 // forward declarations
00031 class File;
00032 
00033 /**
00034  * This class contains an event loop based on Linux's epoll interface.
00035  * It keeps track of interesting events such as timers and socket activity, and
00036  * arranges for callbacks to be invoked when the events happen.
00037  */
00038 class Loop {
00039   public:
00040 
00041     /**
00042      * Lock objects are used to synchronize between the Event::Loop thread and
00043      * other threads.  As long as a Lock object exists the following guarantees
00044      * are in effect: either
00045      * (a) the thread is the event loop thread or
00046      * (b) no other thread has a Lock object and the event loop thread has
00047      *     paused in a safe place (with no event handlers active) waiting for
00048      *     the Lock to be destroyed.
00049      * Locks may be used recursively.
00050      */
00051     class Lock {
00052       public:
00053         /// Constructor. Acquire the lock.
00054         explicit Lock(Event::Loop& eventLoop);
00055         /// Destructor. Release the lock.
00056         ~Lock();
00057         /// Event::Loop to lock.
00058         Event::Loop& eventLoop;
00059       private:
00060         // Lock is not copyable.
00061         Lock(const Lock&) = delete;
00062         Lock& operator=(const Lock&) = delete;
00063     };
00064 
00065     /**
00066      * Constructor.
00067      */
00068     Loop();
00069 
00070     /**
00071      * Destructor. The caller must ensure that no events still exist and that
00072      * the event loop is not running.
00073      */
00074     ~Loop();
00075 
00076     /**
00077      * Run the main event loop until exit() is called.
00078      * It is safe to call this again after it returns.
00079      * The caller must ensure that only one thread is executing runForever() at
00080      * a time.
00081      */
00082     void runForever();
00083 
00084     /**
00085      * Exit the main event loop, if one is running. It may return before
00086      * runForever() has returned but guarantees runForever() will return soon.
00087      *
00088      * If the event loop is not running, then the next time it runs, it will
00089      * exit right away (these semantics can be useful to avoid races).
00090      *
00091      * This may be called from an event handler or from any thread.
00092      */
00093     void exit();
00094 
00095   private:
00096 
00097     /**
00098      * Used in breakTimer, whose purpose is not to handle events but to break
00099      * runForever() out of epoll_wait.
00100      */
00101     class NullTimer : public Event::Timer {
00102       public:
00103         void handleTimerEvent();
00104     };
00105 
00106     /**
00107      * The file descriptor used in epoll calls to monitor other files.
00108      */
00109     int epollfd;
00110 
00111     /**
00112      * Used by Event::Loop::Lock to break runForever() out of epoll_wait.
00113      */
00114     NullTimer breakTimer;
00115 
00116     /**
00117      * This is a flag to runForever() to exit, set by exit().
00118      * Protected by Event::Loop::Lock (or #mutex directly inside runForever()).
00119      */
00120     bool shouldExit;
00121 
00122     /**
00123      * This mutex protects all of the members of this class defined below this
00124      * point, except breakTimerMonitor.
00125      */
00126     std::mutex mutex;
00127 
00128     /**
00129      * The thread ID of the thread running the event loop, or
00130      * Core::ThreadId::NONE if no thread is currently running the event loop.
00131      * This serves two purposes:
00132      * First, it allows Lock to tell whether it's running under the event loop.
00133      * Second, it allows Lock to tell if the event loop is running.
00134      */
00135     uint64_t runningThread;
00136 
00137     /**
00138      * The number of Lock instances, including those that are blocked and those
00139      * that are active.
00140      * runForever() waits for this to drop to 0 before running again.
00141      */
00142     uint32_t numLocks;
00143 
00144     /**
00145      * The number of Locks that are active. This is used to support reentrant
00146      * Lock objects, specifically to know when to set #lockOwner back to
00147      * Core::ThreadId::NONE.
00148      */
00149     uint32_t numActiveLocks;
00150 
00151     /**
00152      * The thread ID of the thread with active Locks, or Core::ThreadId::NONE
00153      * if no thread currently has a Lock. This allows for mutually exclusive
00154      * yet reentrant Lock objects.
00155      */
00156     uint64_t lockOwner;
00157 
00158     /**
00159      * Signaled when it may be safe for a Lock constructor to complete. This
00160      * happens either because runForever() just reached its safe place or
00161      * because some other Lock was destroyed.
00162      */
00163     Core::ConditionVariable safeToLock;
00164 
00165     /**
00166      * Signaled when there are no longer any Locks active.
00167      */
00168     Core::ConditionVariable unlocked;
00169 
00170 #if 1
00171     /**
00172      * Lockable type that compiles out entirely.
00173      */
00174     struct NoOpLockable {
00175         void lock() {}
00176         void unlock() {}
00177     } extraMutexToSatisfyRaceDetector;
00178 #else
00179     /**
00180      * Race detectors tend to know about pthreads locks and not much else. This
00181      * is a pthread lock that is acquired at the bottom of Lock's constructor
00182      * at the top of Lock's destructor, and also used by Loop::runForever(),
00183      * for the purpose of asserting to race detectors that there is a mechanism
00184      * in place for mutual exclusion.
00185      */
00186     std::recursive_mutex extraMutexToSatisfyRaceDetector;
00187 #endif
00188 
00189     /**
00190      * Watches breakTimer for events.
00191      */
00192     Event::Timer::Monitor breakTimerMonitor;
00193 
00194     friend class Event::File;
00195 
00196     // Loop is not copyable.
00197     Loop(const Loop&) = delete;
00198     Loop& operator=(const Loop&) = delete;
00199 }; // class Loop
00200 
00201 } // namespace LogCabin::Event
00202 } // namespace LogCabin
00203 
00204 #endif /* LOGCABIN_EVENT_LOOP_H */
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines