Ice 3.7 C++11 API Reference
Mutex.h
Go to the documentation of this file.
1 
2 //
3 // Copyright (c) ZeroC, Inc. All rights reserved.
4 //
5 
6 #ifndef ICE_UTIL_MUTEX_H
7 #define ICE_UTIL_MUTEX_H
8 
9 #include <IceUtil/Config.h>
10 #include <IceUtil/Lock.h>
12 #include <IceUtil/MutexProtocol.h>
13 
14 namespace IceUtil
15 {
16 
17 //
18 // Forward declaration for friend.
19 //
20 class Cond;
21 
22 //
23 // Simple non-recursive Mutex implementation.
24 //
25 // Don't use noncopyable otherwise you end up with warnings like this:
26 //
27 // In file included from Connection.cpp:20:
28 // ../../include/Ice/Outgoing.h:88: warning: direct base
29 // `IceUtil::noncopyable' inaccessible in `IceInternal::Outgoing' due
30 // to ambiguity
31 //
33 {
34 public:
35 
36  //
37  // Lock & TryLock typedefs.
38  //
39  typedef LockT<Mutex> Lock;
41 
42  inline Mutex();
43  inline Mutex(MutexProtocol);
44  ~Mutex();
45 
46  //
47  // Note that lock/tryLock & unlock in general should not be used
48  // directly. Instead use Lock & TryLock.
49  //
50 
51  void lock() const;
52 
53  //
54  // Returns true if the lock was acquired, and false otherwise.
55  //
56  bool tryLock() const;
57 
58  void unlock() const;
59 
60  //
61  // Returns true if the mutex will unlock when calling unlock()
62  // (false otherwise). For non-recursive mutexes, this will always
63  // return true.
64  // This function is used by the Monitor implementation to know whether
65  // the Mutex has been locked for the first time, or unlocked for the
66  // last time (that is another thread is able to acquire the mutex).
67  // Pre-condition: the mutex must be locked.
68  //
69  bool willUnlock() const;
70 
71 private:
72 
73  inline void init(MutexProtocol);
74  // noncopyable
75  Mutex(const Mutex&);
76  void operator=(const Mutex&);
77 
78  //
79  // LockState and the lock/unlock variations are for use by the
80  // Condition variable implementation.
81  //
82 #ifdef _WIN32
83  struct LockState
84  {
85 # ifdef ICE_HAS_WIN32_CONDVAR
86  CRITICAL_SECTION* mutex;
87 # endif
88  };
89 #else
90  struct LockState
91  {
92  pthread_mutex_t* mutex;
93  };
94 #endif
95 
96  void unlock(LockState&) const;
97  void lock(LockState&) const;
98 
99  friend class Cond;
100 
101 #ifdef _WIN32
102  mutable CRITICAL_SECTION _mutex;
103 #else
104  mutable pthread_mutex_t _mutex;
105 #endif
106 };
107 
108 //
109 // For performance reasons the following functions are inlined.
110 //
111 inline
113 {
114 #ifdef _WIN32
115  init(PrioNone);
116 #else
117  init(getDefaultMutexProtocol());
118 #endif
119 }
120 
121 #ifdef _WIN32
122 inline
124 {
125  init(PrioNone);
126 }
127 #else
128 inline
130 {
131  init(protocol);
132 }
133 #endif
134 
135 #ifdef _WIN32
136 
137 inline void
138 Mutex::init(MutexProtocol)
139 {
140  InitializeCriticalSection(&_mutex);
141 }
142 
143 inline
145 {
146  DeleteCriticalSection(&_mutex);
147 }
148 
149 inline void
150 Mutex::lock() const
151 {
152  EnterCriticalSection(&_mutex);
153 #ifndef NDEBUG
154  if(_mutex.RecursionCount > 1)
155  {
156  LeaveCriticalSection(&_mutex);
157  throw ThreadLockedException(__FILE__, __LINE__);
158  }
159 #endif
160 }
161 
162 inline bool
163 Mutex::tryLock() const
164 {
165  if(!TryEnterCriticalSection(&_mutex))
166  {
167  return false;
168  }
169  if(_mutex.RecursionCount > 1)
170  {
171  LeaveCriticalSection(&_mutex);
172  throw ThreadLockedException(__FILE__, __LINE__);
173  }
174  return true;
175 }
176 
177 inline void
178 Mutex::unlock() const
179 {
180  assert(_mutex.RecursionCount == 1);
181  LeaveCriticalSection(&_mutex);
182 }
183 
184 # ifdef ICE_HAS_WIN32_CONDVAR
185 inline void
186 Mutex::unlock(LockState& state) const
187 {
188  state.mutex = &_mutex;
189 }
190 
191 inline void
192 Mutex::lock(LockState&) const
193 {
194 }
195 # else
196 inline void
197 Mutex::unlock(LockState&) const
198 {
199  LeaveCriticalSection(&_mutex);
200 }
201 
202 inline void
203 Mutex::lock(LockState&) const
204 {
205  EnterCriticalSection(&_mutex);
206 }
207 # endif
208 
209 #else
210 
211 inline void
212 Mutex::init(MutexProtocol
213 #if defined(_POSIX_THREAD_PRIO_INHERIT) && _POSIX_THREAD_PRIO_INHERIT > 0
214  protocol
215 #endif
216  )
217 {
218  int rc;
219  pthread_mutexattr_t attr;
220  rc = pthread_mutexattr_init(&attr);
221  assert(rc == 0);
222  if(rc != 0)
223  {
224  pthread_mutexattr_destroy(&attr);
225  throw ThreadSyscallException(__FILE__, __LINE__, rc);
226  }
227 
228  //
229  // Enable mutex error checking
230  //
231  rc = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK);
232  assert(rc == 0);
233  if(rc != 0)
234  {
235  pthread_mutexattr_destroy(&attr);
236  throw ThreadSyscallException(__FILE__, __LINE__, rc);
237  }
238 
239  //
240  // If system has support for priority inheritance we set the protocol
241  // attribute of the mutex
242  //
243 #if defined(_POSIX_THREAD_PRIO_INHERIT) && _POSIX_THREAD_PRIO_INHERIT > 0
244  if(PrioInherit == protocol)
245  {
246  rc = pthread_mutexattr_setprotocol(&attr, PTHREAD_PRIO_INHERIT);
247  if(rc != 0)
248  {
249  pthread_mutexattr_destroy(&attr);
250  throw ThreadSyscallException(__FILE__, __LINE__, rc);
251  }
252  }
253 #endif
254 
255  rc = pthread_mutex_init(&_mutex, &attr);
256  assert(rc == 0);
257  if(rc != 0)
258  {
259  pthread_mutexattr_destroy(&attr);
260  throw ThreadSyscallException(__FILE__, __LINE__, rc);
261  }
262 
263  rc = pthread_mutexattr_destroy(&attr);
264  assert(rc == 0);
265  if(rc != 0)
266  {
267  throw ThreadSyscallException(__FILE__, __LINE__, rc);
268  }
269 }
270 
271 inline
273 {
274 #ifndef NDEBUG
275  int rc = 0;
276  rc = pthread_mutex_destroy(&_mutex);
277  assert(rc == 0);
278 #else
279  pthread_mutex_destroy(&_mutex);
280 #endif
281 }
282 
283 inline void
284 Mutex::lock() const
285 {
286  int rc = pthread_mutex_lock(&_mutex);
287  if(rc != 0)
288  {
289  if(rc == EDEADLK)
290  {
291  throw ThreadLockedException(__FILE__, __LINE__);
292  }
293  else
294  {
295  throw ThreadSyscallException(__FILE__, __LINE__, rc);
296  }
297  }
298 }
299 
300 inline bool
302 {
303  int rc = pthread_mutex_trylock(&_mutex);
304  if(rc != 0 && rc != EBUSY)
305  {
306  if(rc == EDEADLK)
307  {
308  throw ThreadLockedException(__FILE__, __LINE__);
309  }
310  else
311  {
312  throw ThreadSyscallException(__FILE__, __LINE__, rc);
313  }
314  }
315  return (rc == 0);
316 }
317 
318 inline void
320 {
321  int rc = pthread_mutex_unlock(&_mutex);
322  if(rc != 0)
323  {
324  throw ThreadSyscallException(__FILE__, __LINE__, rc);
325  }
326 }
327 
328 inline void
329 Mutex::unlock(LockState& state) const
330 {
331  state.mutex = &_mutex;
332 }
333 
334 inline void
335 Mutex::lock(LockState&) const
336 {
337 }
338 
339 #endif
340 
341 inline bool
343 {
344  return true;
345 }
346 
347 } // End namespace IceUtil
348 
349 #endif
IceUtil::TryLockT
Definition: Lock.h:118
IceUtil::Cond
Definition: Cond.h:53
IceUtil::Mutex::Lock
LockT< Mutex > Lock
Definition: Mutex.h:39
IceUtil::PrioNone
@ PrioNone
Definition: MutexProtocol.h:16
IceUtil::Mutex::Mutex
Mutex()
Definition: Mutex.h:112
IceUtil::LockT
Definition: Lock.h:37
IceUtil::Mutex::TryLock
TryLockT< Mutex > TryLock
Definition: Mutex.h:40
IceUtil::Mutex::tryLock
bool tryLock() const
Definition: Mutex.h:301
IceUtil
Definition: Optional.h:1095
ICE_API
#define ICE_API
Definition: Config.h:197
IceUtil::Mutex::lock
void lock() const
Definition: Mutex.h:284
IceUtil::Mutex::unlock
void unlock() const
Definition: Mutex.h:319
IceUtil::PrioInherit
@ PrioInherit
Definition: MutexProtocol.h:15
Lock.h
IceUtil::ThreadSyscallException
Definition: ThreadException.h:15
IceUtil::ThreadLockedException
Definition: ThreadException.h:27
IceUtil::Mutex::willUnlock
bool willUnlock() const
Definition: Mutex.h:342
Config.h
IceUtil::Mutex
Definition: Mutex.h:33
MutexProtocol.h
ThreadException.h
IceUtil::MutexProtocol
MutexProtocol
Definition: MutexProtocol.h:14
IceUtil::Mutex::~Mutex
~Mutex()
Definition: Mutex.h:272
IceUtil::getDefaultMutexProtocol
MutexProtocol getDefaultMutexProtocol()