00001 // -*- C++ -*- 00002 00003 //========================================================================== 00004 /** 00005 * @file Thread_Mutex.h 00006 * 00007 * Thread_Mutex.h,v 4.6 2006/04/19 12:32:55 jwillemsen Exp 00008 * 00009 * Moved from Synch.h. 00010 * 00011 * @author Douglas C. Schmidt <schmidt@cs.wustl.edu> 00012 */ 00013 //========================================================================== 00014 00015 #ifndef ACE_THREAD_MUTEX_H 00016 #define ACE_THREAD_MUTEX_H 00017 #include /**/ "ace/pre.h" 00018 00019 #include "ace/config-all.h" 00020 00021 #if !defined (ACE_LACKS_PRAGMA_ONCE) 00022 # pragma once 00023 #endif /* ACE_LACKS_PRAGMA_ONCE */ 00024 00025 #if !defined (ACE_HAS_THREADS) 00026 # include "ace/Null_Mutex.h" 00027 #else /* ACE_HAS_THREAD */ 00028 // ACE platform supports some form of threading. 00029 00030 #include "ace/ACE_export.h" 00031 #include "ace/OS_NS_Thread.h" 00032 00033 ACE_BEGIN_VERSIONED_NAMESPACE_DECL 00034 00035 /** 00036 * @class ACE_Thread_Mutex 00037 * 00038 * @brief ACE_Thread_Mutex wrapper (only valid for threads in the same 00039 * process). 00040 * 00041 * This implementation is optimized for locking threads that are 00042 * in the same process. It maps to <CRITICAL_SECTION>s on NT 00043 * and <ACE_mutex_t> with <type> set to <USYNC_THREAD> on UNIX. 00044 * ACE_Thread_Mutex is recursive on some platforms (like 00045 * Win32). However, on most platforms (like Solaris) it is not 00046 * recursive. To be totally safe and portable, developers 00047 * should use ACE_Recursive_Thread_Mutex when they need a 00048 * recursive mutex. 00049 */ 00050 class ACE_Export ACE_Thread_Mutex 00051 { 00052 friend class ACE_Condition_Thread_Mutex; 00053 public: 00054 /// Constructor. 00055 ACE_Thread_Mutex (const ACE_TCHAR *name = 0, 00056 ACE_mutexattr_t *attributes = 0); 00057 00058 /// Implicitly destroy the mutex. 00059 ~ACE_Thread_Mutex (void); 00060 00061 /** 00062 * Explicitly destroy the mutex. Note that only one thread should 00063 * call this method since it doesn't protect against race 00064 * conditions. 00065 */ 00066 int remove (void); 00067 00068 /// Acquire lock ownership (wait on queue if necessary). 00069 int acquire (void); 00070 00071 /** 00072 * Block the thread until we acquire the mutex or until @a tv times 00073 * out, in which case -1 is returned with <errno> == <ETIME>. Note 00074 * that @a tv is assumed to be in "absolute" rather than "relative" 00075 * time. The value of @a tv is updated upon return to show the 00076 * actual (absolute) acquisition time. 00077 */ 00078 int acquire (ACE_Time_Value &tv); 00079 00080 /** 00081 * If @a tv == 0 the call <acquire()> directly. Otherwise, Block the 00082 * thread until we acquire the mutex or until <tv> times out, in 00083 * which case -1 is returned with <errno> == <ETIME>. Note that 00084 * <*tv> is assumed to be in "absolute" rather than "relative" time. 00085 * The value of <*tv> is updated upon return to show the actual 00086 * (absolute) acquisition time. 00087 */ 00088 int acquire (ACE_Time_Value *tv); 00089 00090 /** 00091 * Conditionally acquire lock (i.e., don't wait on queue). Returns 00092 * -1 on failure. If we "failed" because someone else already had 00093 * the lock, <errno> is set to <EBUSY>. 00094 */ 00095 int tryacquire (void); 00096 00097 /// Release lock and unblock a thread at head of queue. 00098 int release (void); 00099 00100 /** 00101 * Acquire mutex ownership. This calls <acquire> and is only here 00102 * to make the ACE_Thread_Mutex interface consistent with the 00103 * other synchronization APIs. 00104 */ 00105 int acquire_read (void); 00106 00107 /** 00108 * Acquire mutex ownership. This calls <acquire> and is only here 00109 * to make the ACE_Thread_Mutex interface consistent with the 00110 * other synchronization APIs. 00111 */ 00112 int acquire_write (void); 00113 00114 /** 00115 * Conditionally acquire mutex (i.e., won't block). This calls 00116 * <tryacquire> and is only here to make the ACE_Thread_Mutex 00117 * interface consistent with the other synchronization APIs. 00118 * Returns -1 on failure. If we "failed" because someone else 00119 * already had the lock, <errno> is set to <EBUSY>. 00120 */ 00121 int tryacquire_read (void); 00122 00123 /** 00124 * Conditionally acquire mutex (i.e., won't block). This calls 00125 * <tryacquire> and is only here to make the ACE_Thread_Mutex 00126 * interface consistent with the other synchronization APIs. 00127 * Returns -1 on failure. If we "failed" because someone else 00128 * already had the lock, <errno> is set to <EBUSY>. 00129 */ 00130 int tryacquire_write (void); 00131 00132 /** 00133 * This is only here to make the ACE_Thread_Mutex 00134 * interface consistent with the other synchronization APIs. 00135 * Assumes the caller has already acquired the mutex using one of 00136 * the above calls, and returns 0 (success) always. 00137 */ 00138 int tryacquire_write_upgrade (void); 00139 00140 /// Return the underlying mutex. 00141 const ACE_thread_mutex_t &lock (void) const; 00142 00143 /// Dump the state of an object. 00144 void dump (void) const; 00145 00146 /// Declare the dynamic allocation hooks. 00147 ACE_ALLOC_HOOK_DECLARE; 00148 00149 // protected: 00150 /// Mutex type that supports single-process locking efficiently. 00151 ACE_thread_mutex_t lock_; 00152 00153 /// Keeps track of whether <remove> has been called yet to avoid 00154 /// multiple <remove> calls, e.g., explicitly and implicitly in the 00155 /// destructor. This flag isn't protected by a lock, so make sure 00156 /// that you don't have multiple threads simultaneously calling 00157 /// <remove> on the same object, which is a bad idea anyway... 00158 int removed_; 00159 00160 private: 00161 // = Prevent assignment and initialization. 00162 void operator= (const ACE_Thread_Mutex &); 00163 ACE_Thread_Mutex (const ACE_Thread_Mutex &); 00164 }; 00165 00166 #if defined (ACE_USES_OBSOLETE_GUARD_CLASSES) 00167 /** 00168 * @class ACE_Thread_Mutex_Guard 00169 * 00170 * @brief This data structure is meant to be used within a method or 00171 * function... It performs automatic aquisition and release of 00172 * an ACE_Thread_Mutex. 00173 * 00174 * This class is obsolete and should be replaced by 00175 * ACE_Guard<ACE_Thread_Mutex>. 00176 */ 00177 class ACE_Export ACE_Thread_Mutex_Guard 00178 { 00179 public: 00180 /// Implicitly and automatically acquire the lock. 00181 ACE_Thread_Mutex_Guard (ACE_Thread_Mutex &m, int block = 1); 00182 00183 /// Implicitly release the lock. 00184 ~ACE_Thread_Mutex_Guard (void); 00185 00186 /// 1 if locked, 0 if couldn't acquire the lock (errno will contain 00187 /// the reason for this). 00188 int locked (void); 00189 00190 /** 00191 * Explicitly release the lock. Note that only one thread should 00192 * call this method since it doesn't protect against race 00193 * conditions. 00194 */ 00195 int remove (void); 00196 00197 /// Explicitly acquire the lock. 00198 int acquire (void); 00199 00200 /** 00201 * Conditionally acquire the lock (i.e., won't block). Returns -1 00202 * on failure. If we "failed" because someone else already had the 00203 * lock, <errno> is set to <EBUSY>. 00204 */ 00205 int tryacquire (void); 00206 00207 /// Explicitly release the lock. 00208 int release (void); 00209 00210 /// Dump the state of an object. 00211 void dump (void) const; 00212 00213 /// Declare the dynamic allocation hooks. 00214 ACE_ALLOC_HOOK_DECLARE; 00215 00216 protected: 00217 /// Reference to the mutex. 00218 ACE_Thread_Mutex &lock_; 00219 00220 /// Keeps track of whether we acquired the lock or failed. 00221 int owner_; 00222 00223 private: 00224 // = Prevent assignment and initialization. 00225 void operator= (const ACE_Thread_Mutex_Guard &); 00226 ACE_Thread_Mutex_Guard (const ACE_Thread_Mutex_Guard &); 00227 }; 00228 #endif /* ACE_USES_OBSOLETE_GUARD_CLASSES */ 00229 00230 ACE_END_VERSIONED_NAMESPACE_DECL 00231 00232 #if defined (__ACE_INLINE__) 00233 #include "ace/Thread_Mutex.inl" 00234 #endif /* __ACE_INLINE__ */ 00235 00236 #endif /* !ACE_HAS_THREADS */ 00237 00238 #include /**/ "ace/post.h" 00239 #endif /* ACE_THREAD_MUTEX_H */