00001 #ifndef s11n_net_s11n_MUTEX_SENTRY_HPP_INCLUDED 00002 #define s11n_net_s11n_MUTEX_SENTRY_HPP_INCLUDED 00003 00004 namespace s11n { 00005 00006 /** 00007 Represents a mutex used for locking threads. 00008 00009 Notes about the underlying mutex implementation(s): 00010 00011 - On single-threaded builds this class has no underlying 00012 native mutex and does nothing. 00013 00014 - On pthreads builds, the underlying native mutex is a 00015 per-instance pthread mutex. 00016 00017 - On Win32, per-instance critical sections are used. 00018 00019 To simulate a global mutex, create a shared instance of 00020 this type, e.g., via a myApp::getGlobalMutex() function. 00021 */ 00022 class mutex 00023 { 00024 public: 00025 /** 00026 Initializes this mutex. 00027 */ 00028 mutex(); 00029 /** 00030 Closes the mutex. 00031 */ 00032 ~mutex() throw(); 00033 /** 00034 Locks this mutex. Trying to lock it a second (or 00035 subsequent) time will cause this function to wait 00036 until the previous lock(s) is (are) released. 00037 00038 Recursive locks are not supported, which means that 00039 if you call lock() twice on a mutex without an 00040 intervening unlock(), you will deadlock. Code 00041 using this mutex must be careful to avoid this case 00042 (see the mutex_sentry class, which is one 00043 solution). 00044 00045 Returns a reference to this object mainly to allow this call 00046 to be used in ctor member initialization lists, but maybe 00047 that will have some other use eventually. 00048 */ 00049 mutex & lock(); 00050 /** 00051 Unlocks this mutex. 00052 */ 00053 void unlock(); 00054 00055 /** 00056 Copying a mutex is a no-op. It does nothing but the 00057 operators are supported to enable the 00058 implementation of client classes which want 00059 per-instance mutex members. 00060 */ 00061 mutex & operator=( mutex const & ); 00062 /** 00063 This ctor ignores its argument and behaves identically 00064 to the default ctor. See operator=(). 00065 */ 00066 mutex( mutex const & ); 00067 private: 00068 struct impl; // opaque internal type 00069 impl * m_p; 00070 }; 00071 00072 /** 00073 This sentry class locks a mutex on construction and unlocks 00074 in on destruction. The intended usage is to instantiate it 00075 at the start of a routine which needs a lock. The 00076 instantiation will not return until the lock is acquired or 00077 the locking function throws an exception. Upon destruction 00078 of this object, the mutex will be unlocked. 00079 00080 Note that these objects are not copyable. 00081 */ 00082 class mutex_sentry 00083 { 00084 public: 00085 /** Calls mx.lock(). mx must outlive 00086 this object. 00087 */ 00088 explicit mutex_sentry( mutex & mx ); 00089 /** Unlocks the mutex we locked in the ctor. */ 00090 ~mutex_sentry() throw(); 00091 private: 00092 mutex_sentry & operator=( mutex_sentry const & ); // unimplemented! 00093 mutex_sentry( mutex_sentry const & ); // unimplemented! 00094 mutex & mx; 00095 }; 00096 00097 } // namespace 00098 00099 #endif // s11n_net_s11n_MUTEX_SENTRY_HPP_INCLUDED