Tekkotsu Homepage | Demos | Overview | Downloads | Dev. Resources | Reference | Credits |
SemaphoreManager.hGo to the documentation of this file.00001 //-*-c++-*- 00002 #ifndef INCLUDED_SemaphoreManager_h_ 00003 #define INCLUDED_SemaphoreManager_h_ 00004 00005 #ifdef PLATFORM_APERIOS 00006 # warning SemaphoreManager is not Aperios compatable, this is not going to compile 00007 #else 00008 00009 #include "ListMemBuf.h" 00010 #include "Shared/attributes.h" 00011 00012 #ifndef SYSTEM_MAX_SEM 00013 //! Ideally, this would be SEMMSL, but that is hard to portably determine at compile time 00014 /*! If you can't increase your system's SEMMSL (and possibly SEMMNS), you 00015 * may want to consider decreasing this. */ 00016 #define SYSTEM_MAX_SEM 250 00017 #endif 00018 00019 //! initializes, manages, and releases a set of System V style semaphores 00020 /*! Should be initialized pre-fork into a shared region */ 00021 class SemaphoreManager { 00022 protected: 00023 typedef ListMemBuf<bool,SYSTEM_MAX_SEM> sems_t; //!< shorthand for the type of #sems 00024 00025 public: 00026 //! wouldn't want to claim the entire system's worth, even if we could 00027 static const unsigned int MAX_SEM=SYSTEM_MAX_SEM; 00028 00029 //! shorthand for the semaphore indexing type 00030 typedef sems_t::index_t semid_t; 00031 //! specify options for how to handle EINTR (signal occurred) error condition during a semaphore operation, see setInterruptPolicy() 00032 enum IntrPolicy_t { 00033 INTR_CANCEL_VERBOSE, //!< give up, return failure, display error message on console 00034 INTR_CANCEL, //!< give up, return failure 00035 INTR_RETRY_VERBOSE, //!< just repeat semaphore operation, display error message on console 00036 INTR_RETRY, //!< just repeat semaphore operation 00037 INTR_THROW_VERBOSE, //!< throw a std::runtime_error exception, display error message on console 00038 INTR_THROW, //!< throw a std::runtime_error exception 00039 INTR_EXIT, //!< kill process, with error message 00040 }; 00041 00042 //! Creates a SemaphoreManager with room for sems_t::MAX_ENTRIES entries 00043 /*! 2 of these entries are reserved for internal use, so user code 00044 * will actually only have access to sems_t::MAX_ENTRIES-2 entries. 00045 * Use available() to determine this value at runtime. */ 00046 SemaphoreManager(); 00047 00048 //! Creates a SemaphoreManager with room for @a numRequest entries 00049 /*! adds 2 for SemaphoreManager's own reference count and mutex lock, 00050 * so you'll actually have @a numRequest semaphores available */ 00051 explicit SemaphoreManager(unsigned int numRequest); 00052 00053 SemaphoreManager(const SemaphoreManager& mm); //!< copy supported 00054 SemaphoreManager& operator=(const SemaphoreManager& mm); //!< assignment supported 00055 ~SemaphoreManager(); //!< destructor 00056 00057 //! call this on semaphores in shared memory regions if a fork is about to occur so reference counts can be updated for the other process 00058 void aboutToFork(); 00059 //! call this if semaphores need to be released during an emergency shutdown (otherwise semaphore sets can leak past process shutdown -- bad system design IMHO!) 00060 void faultShutdown(); 00061 //! returns true if #semid is invalid, indicating further semaphore operations are bogus 00062 bool hadFault() const { return semid==-1; } 00063 00064 //! returns a new semaphore id, or invalid() if none are available 00065 semid_t getSemaphore() ATTR_must_check; 00066 //! marks a semaphore as available for reassignment 00067 void releaseSemaphore(semid_t id); 00068 00069 //! return the semaphore's interrupt policy (doesn't check @a id validity) 00070 IntrPolicy_t getInterruptPolicy(semid_t id) const { return intrPolicy[id]; } 00071 //! set the semaphore's interrupt policy (doesn't check @a id validity) 00072 void setInterruptPolicy(semid_t id, IntrPolicy_t p) { intrPolicy[id]=p; } 00073 00074 //! Lowers a semaphore's value by @a x, optionally blocking if the value would go negative until it is raised enough to succeed. 00075 /*! Returns true if the semaphore was successfully lowered. 00076 * If a thread cancellation occurs, the operation WILL NOT be undone before the call unwinds, as hitting zero can unblock threads which can't be recalled. */ 00077 bool lower(semid_t id, unsigned int x, bool block=true) const; 00078 //! raises a semaphore's value by @a x 00079 void raise(semid_t id, unsigned int x) const; 00080 00081 int getValue(semid_t id) const; //!< returns the semaphore's value 00082 void setValue(semid_t id, int x) const; //!< sets the semaphore's value 00083 int getNumZeroBlockers(semid_t id) const; //!< return the number of threads/processes which are blocking for the indicated semaphore to hit zero 00084 00085 //! tests if the semaphore's value is zero, optionally blocking until it is 00086 /*! returns true if the semaphore's value is zero. 00087 * @see testZero_add(), add_testZero() */ 00088 bool testZero(semid_t id, bool block=true) const; 00089 //! tests if the semaphore's value is zero, optionally blocking until it is, and then adding @a x 00090 /*! If @a x is negative, then @a addblock will cause it to block 00091 * again until someone else raises the semaphore. Otherwise, the 00092 * add should be performed as an atomic unit with the test. If @a 00093 * x is non-negative, then the add should never block. 00094 * If a thread cancellation occurs, the operation WILL be undone before the call unwinds, as this usage is exclusive to other threads. 00095 * @see add_testZero(), testZero() */ 00096 bool testZero_add(semid_t id, int x, bool testblock=true, bool addblock=true) const; 00097 //! adds @a x to the semaphore's value, optionally blocking in the case that @a x is negative and larger than the semaphore's value. After adding, test whether the semaphore is zero, optionally blocking again until it is. 00098 /*! If no blocking is required (e.g. @a x is positive) then the add 00099 * and test should be an atomic pair. 00100 * If a thread cancellation occurs, the operation WILL NOT be undone before the call unwinds, as adding to the count can unblock threads which can't be recalled. 00101 * @see testZero_add(), testZero() */ 00102 bool add_testZero(semid_t id, int x, bool addblock=true, bool testblock=true) const; 00103 //! adds @a x to the semaphore's value, optionally blocking in the case that @a x1 is negative and larger than the semaphore's value. After adding, test whether the semaphore is zero, optionally blocking again until it is, and then adding @a x2 00104 /*! If no blocking is required (e.g. @a x is positive) then the add 00105 * and test should be an atomic pair. 00106 * If a thread cancellation occurs, the operation WILL NOT be undone before the call unwinds, as adding to the count can unblock threads which can't be recalled. 00107 * @see testZero_add(), testZero() */ 00108 bool add_testZero_add(semid_t id, int x1, int x2, bool add1block=true, bool testblock=true, bool add2block=true) const; 00109 00110 //! returns the number of semaphores currently available in the set 00111 unsigned int available() const { return sems_t::MAX_ENTRIES-sems.size(); } 00112 //! returns the number of semaphores which have been used 00113 /*! the SemaphoreManager requires 2 semaphores from the set, one for 00114 * reference counting and one for mutual exclusion during function 00115 * calls */ 00116 unsigned int used() const { return sems.size()-(sems_t::MAX_ENTRIES-nsem); } 00117 //! returns the "invalid" id value, for testing against getSemaphore 00118 semid_t invalid() const { return sems.end(); } 00119 00120 protected: 00121 void init(); //!< basic initialization called by the constructor -- don't call twice 00122 00123 sems_t sems; //!< tracks which semaphores have been handed out; the bool value isn't actually used 00124 unsigned int nsem; //!< number of real semaphores in the set obtained from the system 00125 int semid; //!< the system's identifier for the set 00126 semid_t mysem; //!< a lock semaphore for management operations on the set (handing out or taking back semaphores from clients) 00127 semid_t refc; //!< a reference count of this semaphore set -- when it goes back to 0, the set is released from the system 00128 IntrPolicy_t intrPolicy[sems_t::MAX_ENTRIES]; //!< interrupt policy for each semaphore 00129 }; 00130 00131 /*! @file 00132 * @brief Defines SemaphoreManager, which initializes, manages, and releases a set of System V style semaphores 00133 * @author ejt (Creator) 00134 */ 00135 00136 #endif //Aperios check 00137 00138 #endif //INCLUDED 00139 |
Tekkotsu v5.1CVS |
Generated Mon May 9 04:58:50 2016 by Doxygen 1.6.3 |