LogCabin
|
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 */