| 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 #include <sys/types.h> 00012 #include <sys/sem.h> 00013 00014 #ifndef SYSTEM_MAX_SEM 00015 //! Ideally, this would be SEMMSL, but that is hard to portably determine at compile time 00016 /*! If you can't increase your system's SEMMSL (and possibly SEMMNS), you 00017 * may want to consider decreasing this. */ 00018 #define SYSTEM_MAX_SEM 250 00019 #endif 00020 00021 //! initializes, manages, and releases a set of System V style semaphores 00022 /*! Should be initialized pre-fork into a shared region */ 00023 class SemaphoreManager { 00024 protected: 00025 typedef ListMemBuf<bool,SYSTEM_MAX_SEM> sems_t; //!< shorthand for the type of #sems 00026 00027 public: 00028 //! wouldn't want to claim the entire system's worth, even if we could 00029 static const unsigned int MAX_SEM=SYSTEM_MAX_SEM; 00030 00031 //! shorthand for the semaphore indexing type 00032 typedef sems_t::index_t semid_t; 00033 //! specify options for how to handle EINTR (signal occurred) error condition during a semaphore operation, see setInterruptPolicy() 00034 enum IntrPolicy_t { 00035 INTR_CANCEL_VERBOSE, //!< give up, return failure, display error message on console 00036 INTR_CANCEL, //!< give up, return failure 00037 INTR_RETRY_VERBOSE, //!< just repeat semaphore operation, display error message on console 00038 INTR_RETRY, //!< just repeat semaphore operation 00039 INTR_THROW_VERBOSE, //!< throw a std::runtime_error exception, display error message on console 00040 INTR_THROW, //!< throw a std::runtime_error exception 00041 INTR_EXIT, //!< kill process, with error message 00042 }; 00043 00044 //! Creates a SemaphoreManager with room for sems_t::MAX_ENTRIES entries 00045 /*! 2 of these entries are reserved for internal use, so user code 00046 * will actually only have access to sems_t::MAX_ENTRIES-2 entries. 00047 * Use available() to determine this value at runtime. */ 00048 SemaphoreManager(); 00049 00050 //! Creates a SemaphoreManager with room for @a numRequest entries 00051 /*! adds 2 for SemaphoreManager's own reference count and mutex lock, 00052 * so you'll actually have @a numRequest semaphores available */ 00053 explicit SemaphoreManager(unsigned int numRequest); 00054 00055 SemaphoreManager(const SemaphoreManager& mm); //!< copy supported 00056 SemaphoreManager& operator=(const SemaphoreManager& mm); //!< assignment supported 00057 ~SemaphoreManager(); //!< destructor 00058 00059 //! 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 00060 void aboutToFork(); 00061 //! call this if semaphores need to be released during an emergency shutdown (otherwise semaphore sets can leak past process shutdown -- bad system design IMHO!) 00062 void faultShutdown(); 00063 //! returns true if #semid is invalid, indicating further semaphore operations are bogus 00064 bool hadFault() const { return semid==-1; } 00065 00066 //! returns a new semaphore id, or invalid() if none are available 00067 semid_t getSemaphore() ATTR_must_check; 00068 //! marks a semaphore as available for reassignment 00069 void releaseSemaphore(semid_t id); 00070 00071 //! return the semaphore's interrupt policy (doesn't check @a id validity) 00072 IntrPolicy_t getInterruptPolicy(semid_t id) const { return intrPolicy[id]; } 00073 //! set the semaphore's interrupt policy (doesn't check @a id validity) 00074 void setInterruptPolicy(semid_t id, IntrPolicy_t p) { intrPolicy[id]=p; } 00075 00076 //! lowers a semaphore's value by @a x, optionally blocking if the value would go negative until it is raised enough to succeed 00077 /*! returns true if the semaphore was successfully lowered.*/ 00078 bool lower(semid_t id, unsigned int x, bool block=true) const; 00079 //! raises a semaphore's value by @a x 00080 void raise(semid_t id, unsigned int x) const; 00081 00082 int getValue(semid_t id) const; //!< returns the semaphore's value 00083 void setValue(semid_t id, int x) const; //!< sets the semaphore's value 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 * @see add_testZero(), testZero() */ 00095 bool testZero_add(semid_t id, unsigned int x, bool testblock=true, bool addblock=true) const; 00096 //! 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. 00097 /*! If no blocking is required (e.g. @a x is positive) then the add 00098 * and test should be an atomic pair. 00099 * @see testZero_add(), testZero() */ 00100 bool add_testZero(semid_t id, unsigned int x, bool addblock=true, bool testblock=true) const; 00101 00102 //! returns the number of semaphores currently available in the set 00103 unsigned int available() const { return sems_t::MAX_ENTRIES-sems.size(); } 00104 //! returns the number of semaphores which have been used 00105 /*! the SemaphoreManager requires 2 semaphores from the set, one for 00106 * reference counting and one for mutual exclusion during function 00107 * calls */ 00108 unsigned int used() const { return sems.size()-(sems_t::MAX_ENTRIES-nsem); } 00109 //! returns the "invalid" id value, for testing against getSemaphore 00110 semid_t invalid() const { return sems.end(); } 00111 00112 protected: 00113 void init(); //!< basic initialization called by the constructor -- don't call twice 00114 00115 sems_t sems; //!< tracks which semaphores have been handed out; the bool value isn't actually used 00116 unsigned int nsem; //!< number of real semaphores in the set obtained from the system 00117 int semid; //!< the system's identifier for the set 00118 semid_t mysem; //!< a lock semaphore for management operations on the set (handing out or taking back semaphores from clients) 00119 semid_t refc; //!< a reference count of this semaphore set -- when it goes back to 0, the set is released from the system 00120 IntrPolicy_t intrPolicy[sems_t::MAX_ENTRIES]; //!< interrupt policy for each semaphore 00121 }; 00122 00123 /*! @file 00124 * @brief Defines SemaphoreManager, which initializes, manages, and releases a set of System V style semaphores 00125 * @author ejt (Creator) 00126 * 00127 * $Author: ejt $ 00128 * $Name: tekkotsu-3_0 $ 00129 * $Revision: 1.12 $ 00130 * $State: Exp $ 00131 * $Date: 2006/05/08 22:06:35 $ 00132 */ 00133 00134 #endif //Aperios check 00135 00136 #endif //INCLUDED 00137 |
|
Tekkotsu v3.0 |
Generated Wed Oct 4 00:03:46 2006 by Doxygen 1.4.7 |