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_SIGNAL_H 00018 #define LOGCABIN_EVENT_SIGNAL_H 00019 00020 #include "Event/File.h" 00021 00022 namespace LogCabin { 00023 namespace Event { 00024 00025 // forward declaration 00026 class Loop; 00027 00028 /** 00029 * A Signal is called by the Event::Loop when a Unix signal is received. 00030 * The client should inherit from this and implement the handleSignalEvent() 00031 * method for when the signal is received. This is persistent; it will handle 00032 * repeated delivery of the signal. 00033 * 00034 * Signal handlers can be created from any thread, but they will always fire on 00035 * the thread running the Event::Loop. 00036 */ 00037 class Signal : private Event::File { 00038 public: 00039 /** 00040 * Blocks asynchronous signal delivery on the current thread for the given 00041 * signal. This should normally be called before any secondary threads are 00042 * started, so that all subsequent threads also have the signal blocked. 00043 * \warning 00044 * This class is not thread-safe: the caller must use an external 00045 * mutex or (more commonly) may only manipulate this class while 00046 * a single thread is running. 00047 */ 00048 class Blocker { 00049 public: 00050 /** 00051 * Constructor. 00052 * Masks asynchronous signal delivery for signalNumber. 00053 */ 00054 explicit Blocker(int signalNumber); 00055 /** 00056 * Destructor. Unmasks asynchronous signal delivery for signalNumber. 00057 */ 00058 ~Blocker(); 00059 /** 00060 * Blocks further signals if they are not already blocked. 00061 */ 00062 void block(); 00063 /** 00064 * Leave the signal blocked when this object is destroyed. 00065 */ 00066 void leaveBlocked(); 00067 /** 00068 * Unblocks signals if they are blocked. Also clears 00069 * #shouldLeaveBlocked. 00070 */ 00071 void unblock(); 00072 const int signalNumber; 00073 private: 00074 /** 00075 * Set to true if the signal is currently blocked. 00076 */ 00077 bool isBlocked; 00078 /** 00079 * Set to true if the signal should be left unblocked on destruction. 00080 */ 00081 bool shouldLeaveBlocked; 00082 }; 00083 00084 /** 00085 * Registers a Signal handler to be monitored by the Event::Loop. Once this 00086 * is constructed, the Event::Loop will call the Signal's event handler 00087 * appropriately. 00088 * 00089 * This object must be destroyed or disableForever() called BEFORE the 00090 * Signal object can be destroyed safely. 00091 */ 00092 class Monitor : private File::Monitor { 00093 public: 00094 /// See File::Monitor::Monitor. 00095 Monitor(Event::Loop& eventLoop, Signal& signal); 00096 /// See File::Monitor::~Monitor. 00097 ~Monitor(); 00098 /// See File::Monitor::disableForever. 00099 using File::Monitor::disableForever; 00100 }; 00101 00102 /** 00103 * Construct a signal handler. 00104 * See also Blocker, which you'll generally need to create first, 00105 * and Monitor, which you'll need to create after. 00106 * \param signalNumber 00107 * The signal number identifying which signal to receive 00108 * (man signal.h). 00109 */ 00110 explicit Signal(int signalNumber); 00111 00112 /** 00113 * Destructor. 00114 */ 00115 virtual ~Signal(); 00116 00117 /** 00118 * This method is overridden by a subclass and invoked when the signal 00119 * is received. This method will be invoked by the main event loop on 00120 * whatever thread is running the Event::Loop. 00121 */ 00122 virtual void handleSignalEvent() = 0; 00123 00124 /** 00125 * The signal number identifying which signal to receive (man signal.h). 00126 */ 00127 const int signalNumber; 00128 00129 private: 00130 /** 00131 * Generic event handler for files. Calls handleSignalEvent(). 00132 */ 00133 void handleFileEvent(uint32_t events); 00134 00135 // Signal is not copyable. 00136 Signal(const Signal&) = delete; 00137 Signal& operator=(const Signal&) = delete; 00138 }; 00139 00140 } // namespace LogCabin::Event 00141 } // namespace LogCabin 00142 00143 #endif /* LOGCABIN_EVENT_SIGNAL_H */