Imported Upstream version 2.2.0
[deb_libcec.git] / src / lib / platform / threads / mutex.h
CommitLineData
cbbe90dd
JB
1#pragma once
2/*
3 * This file is part of the libCEC(R) library.
4 *
5 * libCEC(R) is Copyright (C) 2011-2013 Pulse-Eight Limited. All rights reserved.
6 * libCEC(R) is an original work, containing original code.
7 *
8 * libCEC(R) is a trademark of Pulse-Eight Limited.
9 *
10 * This program is dual-licensed; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 *
24 *
25 * Alternatively, you can license this library under a commercial license,
26 * please contact Pulse-Eight Licensing for more information.
27 *
28 * For more information contact:
29 * Pulse-Eight Licensing <license@pulse-eight.com>
30 * http://www.pulse-eight.com/
31 * http://www.pulse-eight.net/
32 */
33
34#include "lib/platform/os.h"
35
36#if defined(__WINDOWS__)
37#include "lib/platform/windows/os-threads.h"
38#else
39#include "lib/platform/posix/os-threads.h"
40#endif
41
42#include "lib/platform/util/timeutils.h"
43
44namespace PLATFORM
45{
46 class PreventCopy
47 {
48 public:
49 inline PreventCopy(void) {}
50 inline ~PreventCopy(void) {}
51
52 private:
53 inline PreventCopy(const PreventCopy &c) { *this = c; }
54 inline PreventCopy &operator=(const PreventCopy & UNUSED(c)){ return *this; }
55 };
56
57 template <typename _Predicate>
58 class CCondition;
59
60 class CMutex : public PreventCopy
61 {
62 template <typename _Predicate>
63 friend class CCondition;
64 public:
65 inline CMutex(void) :
66 m_iLockCount(0)
67 {
68 MutexCreate(m_mutex);
69 }
70
71 inline ~CMutex(void)
72 {
73 Clear();
74 MutexDelete(m_mutex);
75 }
76
77 inline bool TryLock(void)
78 {
79 if (MutexTryLock(m_mutex))
80 {
81 ++m_iLockCount;
82 return true;
83 }
84 return false;
85 }
86
87 inline bool Lock(void)
88 {
89 if (MutexLock(m_mutex))
90 {
91 ++m_iLockCount;
92 return true;
93 }
94 return false;
95 }
96
97 inline void Unlock(void)
98 {
99 if (Lock())
100 {
101 if (m_iLockCount >= 2)
102 {
103 --m_iLockCount;
104 MutexUnlock(m_mutex);
105 }
106
107 --m_iLockCount;
108 MutexUnlock(m_mutex);
109 }
110 }
111
112 inline bool Clear(void)
113 {
114 bool bReturn(false);
115 if (TryLock())
116 {
117 unsigned int iLockCount = m_iLockCount;
118 for (unsigned int iPtr = 0; iPtr < iLockCount; iPtr++)
119 Unlock();
120 bReturn = true;
121 }
122 return bReturn;
123 }
124
125 private:
126 mutex_t m_mutex;
127 volatile unsigned int m_iLockCount;
128 };
129
130 class CLockObject : public PreventCopy
131 {
132 public:
133 inline CLockObject(CMutex &mutex, bool bClearOnExit = false) :
134 m_mutex(mutex),
135 m_bClearOnExit(bClearOnExit)
136 {
137 m_mutex.Lock();
138 }
139
140 inline ~CLockObject(void)
141 {
142 if (m_bClearOnExit)
143 Clear();
144 else
145 Unlock();
146 }
147
148 inline bool TryLock(void)
149 {
150 return m_mutex.TryLock();
151 }
152
153 inline void Unlock(void)
154 {
155 m_mutex.Unlock();
156 }
157
158 inline bool Clear(void)
159 {
160 return m_mutex.Clear();
161 }
162
163 inline bool Lock(void)
164 {
165 return m_mutex.Lock();
166 }
167
168 private:
169 CMutex &m_mutex;
170 bool m_bClearOnExit;
171 };
172
173 class CTryLockObject : public PreventCopy
174 {
175 public:
176 inline CTryLockObject(CMutex &mutex, bool bClearOnExit = false) :
177 m_mutex(mutex),
178 m_bClearOnExit(bClearOnExit),
179 m_bIsLocked(m_mutex.TryLock())
180 {
181 }
182
183 inline ~CTryLockObject(void)
184 {
185 if (m_bClearOnExit)
186 Clear();
187 else if (m_bIsLocked)
188 Unlock();
189 }
190
191 inline bool TryLock(void)
192 {
193 bool bReturn = m_mutex.TryLock();
194 m_bIsLocked |= bReturn;
195 return bReturn;
196 }
197
198 inline void Unlock(void)
199 {
200 if (m_bIsLocked)
201 {
202 m_bIsLocked = false;
203 m_mutex.Unlock();
204 }
205 }
206
207 inline bool Clear(void)
208 {
209 m_bIsLocked = false;
210 return m_mutex.Clear();
211 }
212
213 inline bool Lock(void)
214 {
215 bool bReturn = m_mutex.Lock();
216 m_bIsLocked |= bReturn;
217 return bReturn;
218 }
219
220 inline bool IsLocked(void) const
221 {
222 return m_bIsLocked;
223 }
224
225 private:
226 CMutex & m_mutex;
227 bool m_bClearOnExit;
228 volatile bool m_bIsLocked;
229 };
230
231 template <typename _Predicate>
232 class CCondition : public PreventCopy
233 {
234 public:
235 inline CCondition(void) {}
236 inline ~CCondition(void)
237 {
238 m_condition.Broadcast();
239 }
240
241 inline void Broadcast(void)
242 {
243 m_condition.Broadcast();
244 }
245
246 inline void Signal(void)
247 {
248 m_condition.Signal();
249 }
250
251 inline bool Wait(CMutex &mutex, _Predicate &predicate)
252 {
253 while(!predicate)
254 m_condition.Wait(mutex.m_mutex);
255 return true;
256 }
257
258 inline bool Wait(CMutex &mutex, _Predicate &predicate, uint32_t iTimeout)
259 {
260 if (iTimeout == 0)
261 return Wait(mutex, predicate);
262
263 if (predicate)
264 return true;
265
266 bool bReturn(false);
267 bool bBreak(false);
268 CTimeout timeout(iTimeout);
269 uint32_t iMsLeft(0);
270
271 while (!bReturn && !bBreak)
272 {
273 iMsLeft = timeout.TimeLeft();
274 if ((bReturn = predicate) == false && (bBreak = iMsLeft == 0) == false)
275 m_condition.Wait(mutex.m_mutex, iMsLeft);
276 }
277 return bReturn;
278 }
279
280 private:
281 CConditionImpl m_condition;
282 };
283
284 class CEvent
285 {
286 public:
287 CEvent(bool bAutoReset = true) :
288 m_bSignaled(false),
289 m_bBroadcast(false),
290 m_iWaitingThreads(0),
291 m_bAutoReset(bAutoReset) {}
292 virtual ~CEvent(void) {}
293
294 void Broadcast(void)
295 {
296 Set(true);
297 m_condition.Broadcast();
298 }
299
300 void Signal(void)
301 {
302 Set(false);
303 m_condition.Signal();
304 }
305
306 bool Wait(void)
307 {
308 CLockObject lock(m_mutex);
309 ++m_iWaitingThreads;
310
311 bool bReturn = m_condition.Wait(m_mutex, m_bSignaled);
312 return ResetAndReturn() && bReturn;
313 }
314
315 bool Wait(uint32_t iTimeout)
316 {
317 if (iTimeout == 0)
318 return Wait();
319
320 CLockObject lock(m_mutex);
321 ++m_iWaitingThreads;
322 bool bReturn = m_condition.Wait(m_mutex, m_bSignaled, iTimeout);
323 return ResetAndReturn() && bReturn;
324 }
325
326 static void Sleep(uint32_t iTimeout)
327 {
328 CEvent event;
329 event.Wait(iTimeout);
330 }
331
332 private:
333 void Set(bool bBroadcast = false)
334 {
335 CLockObject lock(m_mutex);
336 m_bSignaled = true;
337 m_bBroadcast = bBroadcast;
338 }
339
340 bool ResetAndReturn(void)
341 {
342 CLockObject lock(m_mutex);
343 bool bReturn(m_bSignaled);
344 if (bReturn && (--m_iWaitingThreads == 0 || !m_bBroadcast) && m_bAutoReset)
345 m_bSignaled = false;
346 return bReturn;
347 }
348
349 volatile bool m_bSignaled;
350 CCondition<volatile bool> m_condition;
351 CMutex m_mutex;
352 volatile bool m_bBroadcast;
353 unsigned int m_iWaitingThreads;
354 bool m_bAutoReset;
355 };
356}