Ice 3.7 C++11 API Reference
Loading...
Searching...
No Matches
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>
13
14namespace IceUtil
15{
16
17//
18// Forward declaration for friend.
19//
20class 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{
34public:
35
36 //
37 // Lock & TryLock typedefs.
38 //
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
71private:
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//
111inline
113{
114#ifdef _WIN32
115 init(PrioNone);
116#else
118#endif
119}
120
121#ifdef _WIN32
122inline
124{
125 init(PrioNone);
126}
127#else
128inline
130{
131 init(protocol);
132}
133#endif
134
135#ifdef _WIN32
136
137inline void
138Mutex::init(MutexProtocol)
139{
140 InitializeCriticalSection(&_mutex);
141}
142
143inline
145{
146 DeleteCriticalSection(&_mutex);
147}
148
149inline void
150Mutex::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
162inline bool
163Mutex::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
177inline void
178Mutex::unlock() const
179{
180 assert(_mutex.RecursionCount == 1);
181 LeaveCriticalSection(&_mutex);
182}
183
184# ifdef ICE_HAS_WIN32_CONDVAR
185inline void
186Mutex::unlock(LockState& state) const
187{
188 state.mutex = &_mutex;
189}
190
191inline void
192Mutex::lock(LockState&) const
193{
194}
195# else
196inline void
197Mutex::unlock(LockState&) const
198{
199 LeaveCriticalSection(&_mutex);
200}
201
202inline void
203Mutex::lock(LockState&) const
204{
205 EnterCriticalSection(&_mutex);
206}
207# endif
208
209#else
210
211inline void
212Mutex::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
271inline
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
283inline void
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
300inline 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
318inline void
320{
321 int rc = pthread_mutex_unlock(&_mutex);
322 if(rc != 0)
323 {
324 throw ThreadSyscallException(__FILE__, __LINE__, rc);
325 }
326}
327
328inline void
329Mutex::unlock(LockState& state) const
330{
331 state.mutex = &_mutex;
332}
333
334inline void
335Mutex::lock(LockState&) const
336{
337}
338
339#endif
340
341inline bool
343{
344 return true;
345}
346
347} // End namespace IceUtil
348
349#endif
#define ICE_API
Definition Config.h:197
Definition Cond.h:53
Definition Lock.h:37
bool tryLock() const
Definition Mutex.h:301
~Mutex()
Definition Mutex.h:272
bool willUnlock() const
Definition Mutex.h:342
friend class Cond
Definition Mutex.h:99
void unlock() const
Definition Mutex.h:319
Mutex()
Definition Mutex.h:112
TryLockT< Mutex > TryLock
Definition Mutex.h:40
void lock() const
Definition Mutex.h:284
LockT< Mutex > Lock
Definition Mutex.h:39
Definition ThreadException.h:27
Definition ThreadException.h:15
Definition Lock.h:118
Definition Optional.h:1095
MutexProtocol getDefaultMutexProtocol()
MutexProtocol
Definition MutexProtocol.h:14
@ PrioInherit
Definition MutexProtocol.h:15
@ PrioNone
Definition MutexProtocol.h:16