1 //
2 // Copyright (c) ZeroC, Inc. All rights reserved.
3 //
4
5 #include <IceUtil/RecMutex.h>
6 #include <IceUtil/Exception.h>
7
8 using namespace std;
9
RecMutex()10 IceUtil::RecMutex::RecMutex() :
11 _count(0)
12 {
13 #ifdef _WIN32
14 init(PrioNone);
15 #else
16 init(getDefaultMutexProtocol());
17 #endif
18 }
19
RecMutex(const IceUtil::MutexProtocol protocol)20 IceUtil::RecMutex::RecMutex(const IceUtil::MutexProtocol protocol) :
21 _count(0)
22 {
23 init(protocol);
24 }
25
26 #ifdef _WIN32
27
28 void
init(const MutexProtocol)29 IceUtil::RecMutex::init(const MutexProtocol)
30 {
31 # ifdef ICE_OS_UWP
32 InitializeCriticalSectionEx(&_mutex, 0, 0);
33 # else
34 InitializeCriticalSection(&_mutex);
35 # endif
36 }
37
~RecMutex()38 IceUtil::RecMutex::~RecMutex()
39 {
40 assert(_count == 0);
41 DeleteCriticalSection(&_mutex);
42 }
43
44 void
lock() const45 IceUtil::RecMutex::lock() const
46 {
47 EnterCriticalSection(&_mutex);
48 if(++_count > 1)
49 {
50 LeaveCriticalSection(&_mutex);
51 }
52 }
53
54 bool
tryLock() const55 IceUtil::RecMutex::tryLock() const
56 {
57 if(!TryEnterCriticalSection(&_mutex))
58 {
59 return false;
60 }
61 if(++_count > 1)
62 {
63 LeaveCriticalSection(&_mutex);
64 }
65 return true;
66 }
67
68 void
unlock() const69 IceUtil::RecMutex::unlock() const
70 {
71 if(--_count == 0)
72 {
73 LeaveCriticalSection(&_mutex);
74 }
75 }
76
77 # ifdef ICE_HAS_WIN32_CONDVAR
78 void
unlock(LockState & state) const79 IceUtil::RecMutex::unlock(LockState& state) const
80 {
81 state.mutex = &_mutex;
82 state.count = _count;
83 _count = 0;
84 }
85
86 void
lock(LockState & state) const87 IceUtil::RecMutex::lock(LockState& state) const
88 {
89 _count = state.count;
90 }
91 # else
92 void
unlock(LockState & state) const93 IceUtil::RecMutex::unlock(LockState& state) const
94 {
95 state.count = _count;
96 _count = 0;
97 LeaveCriticalSection(&_mutex);
98 }
99
100 void
lock(LockState & state) const101 IceUtil::RecMutex::lock(LockState& state) const
102 {
103 EnterCriticalSection(&_mutex);
104 _count = state.count;
105 }
106 # endif
107
108 #else
109
110 void
init(ICE_MAYBE_UNUSED const MutexProtocol protocol)111 IceUtil::RecMutex::init(ICE_MAYBE_UNUSED const MutexProtocol protocol)
112 {
113 int rc;
114 pthread_mutexattr_t attr;
115 rc = pthread_mutexattr_init(&attr);
116 assert(rc == 0);
117 if(rc != 0)
118 {
119 pthread_mutexattr_destroy(&attr);
120 throw ThreadSyscallException(__FILE__, __LINE__, rc);
121 }
122
123 rc = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
124 assert(rc == 0);
125 if(rc != 0)
126 {
127 pthread_mutexattr_destroy(&attr);
128 throw ThreadSyscallException(__FILE__, __LINE__, rc);
129 }
130
131 #if defined(_POSIX_THREAD_PRIO_INHERIT) && _POSIX_THREAD_PRIO_INHERIT > 0
132 if(PrioInherit == protocol)
133 {
134 rc = pthread_mutexattr_setprotocol(&attr, PTHREAD_PRIO_INHERIT);
135 assert(rc == 0);
136 if(rc != 0)
137 {
138 throw ThreadSyscallException(__FILE__, __LINE__, rc);
139 }
140 }
141 #endif
142
143 rc = pthread_mutex_init(&_mutex, &attr);
144 assert(rc == 0);
145 if(rc != 0)
146 {
147 pthread_mutexattr_destroy(&attr);
148 throw ThreadSyscallException(__FILE__, __LINE__, rc);
149 }
150
151 rc = pthread_mutexattr_destroy(&attr);
152 assert(rc == 0);
153 if(rc != 0)
154 {
155 throw ThreadSyscallException(__FILE__, __LINE__, rc);
156 }
157 }
158
~RecMutex()159 IceUtil::RecMutex::~RecMutex()
160 {
161 assert(_count == 0);
162 #ifndef NDEBUG
163 int rc = pthread_mutex_destroy(&_mutex);
164 assert(rc == 0);
165 #else
166 pthread_mutex_destroy(&_mutex);
167 #endif
168 }
169
170 void
lock() const171 IceUtil::RecMutex::lock() const
172 {
173 int rc = pthread_mutex_lock(&_mutex);
174 if(rc != 0)
175 {
176 throw ThreadSyscallException(__FILE__, __LINE__, rc);
177 }
178 if(++_count > 1)
179 {
180 rc = pthread_mutex_unlock(&_mutex);
181 assert(rc == 0);
182 }
183 }
184
185 bool
tryLock() const186 IceUtil::RecMutex::tryLock() const
187 {
188 int rc = pthread_mutex_trylock(&_mutex);
189 bool result = (rc == 0);
190 if(!result)
191 {
192 if(rc != EBUSY)
193 {
194 throw ThreadSyscallException(__FILE__, __LINE__, rc);
195 }
196 }
197 else if(++_count > 1)
198 {
199 rc = pthread_mutex_unlock(&_mutex);
200 if(rc != 0)
201 {
202 throw ThreadSyscallException(__FILE__, __LINE__, rc);
203 }
204 }
205 return result;
206 }
207
208 void
unlock() const209 IceUtil::RecMutex::unlock() const
210 {
211 if(--_count == 0)
212 {
213 #ifndef NDEBUG
214 int rc = pthread_mutex_unlock(&_mutex);
215 assert(rc == 0);
216 #else
217 pthread_mutex_unlock(&_mutex);
218 #endif
219 }
220 }
221
222 void
unlock(LockState & state) const223 IceUtil::RecMutex::unlock(LockState& state) const
224 {
225 state.mutex = &_mutex;
226 state.count = _count;
227 _count = 0;
228 }
229
230 void
lock(LockState & state) const231 IceUtil::RecMutex::lock(LockState& state) const
232 {
233 _count = state.count;
234 }
235
236 #endif
237
238 bool
willUnlock() const239 IceUtil::RecMutex::willUnlock() const
240 {
241 return _count == 1;
242 }
243