Commit | Line | Data |
---|---|---|
f00ff009 LOK |
1 | #pragma once |
2 | /* | |
3 | * This file is part of the libCEC(R) library. | |
4 | * | |
b492c10e | 5 | * libCEC(R) is Copyright (C) 2011-2012 Pulse-Eight Limited. All rights reserved. |
f00ff009 LOK |
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 | ||
ba65909d LOK |
34 | #include "../os.h" |
35 | ||
36 | #if defined(__WINDOWS__) | |
37 | #include "../windows/os-threads.h" | |
38 | #else | |
39 | #include "../posix/os-threads.h" | |
40 | #endif | |
41 | ||
41c655b6 LOK |
42 | #include "../util/timeutils.h" |
43 | ||
f00ff009 LOK |
44 | namespace 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 &c){ *this = c; return *this; } | |
55 | }; | |
56 | ||
57 | class CCondition; | |
58 | ||
59 | class CMutex : public PreventCopy | |
60 | { | |
61 | friend class CCondition; | |
62 | public: | |
63 | inline CMutex(void) : | |
64 | m_iLockCount(0) | |
65 | { | |
66 | MutexCreate(m_mutex); | |
67 | } | |
68 | ||
69 | inline ~CMutex(void) | |
70 | { | |
71 | Clear(); | |
72 | MutexDelete(m_mutex); | |
73 | } | |
74 | ||
75 | inline bool TryLock(void) | |
76 | { | |
77 | if (MutexTryLock(m_mutex)) | |
78 | { | |
79 | ++m_iLockCount; | |
80 | return true; | |
81 | } | |
82 | return false; | |
83 | } | |
84 | ||
85 | inline bool Lock(void) | |
86 | { | |
87 | MutexLock(m_mutex); | |
88 | ++m_iLockCount; | |
89 | return true; | |
90 | } | |
91 | ||
92 | inline void Unlock(void) | |
93 | { | |
ee2304ce LOK |
94 | if (Lock()) |
95 | { | |
96 | if (m_iLockCount >= 2) | |
97 | { | |
98 | --m_iLockCount; | |
99 | MutexUnlock(m_mutex); | |
100 | } | |
101 | ||
102 | --m_iLockCount; | |
103 | MutexUnlock(m_mutex); | |
104 | } | |
f00ff009 LOK |
105 | } |
106 | ||
107 | inline bool Clear(void) | |
108 | { | |
109 | bool bReturn(false); | |
110 | if (TryLock()) | |
111 | { | |
112 | unsigned int iLockCount = m_iLockCount; | |
113 | for (unsigned int iPtr = 0; iPtr < iLockCount; iPtr++) | |
114 | Unlock(); | |
115 | bReturn = true; | |
116 | } | |
117 | return bReturn; | |
118 | } | |
119 | ||
120 | private: | |
ee2304ce LOK |
121 | mutex_t m_mutex; |
122 | volatile unsigned int m_iLockCount; | |
f00ff009 LOK |
123 | }; |
124 | ||
125 | class CLockObject : public PreventCopy | |
126 | { | |
127 | public: | |
128 | inline CLockObject(CMutex &mutex, bool bClearOnExit = false) : | |
129 | m_mutex(mutex), | |
130 | m_bClearOnExit(bClearOnExit) | |
131 | { | |
132 | m_mutex.Lock(); | |
133 | } | |
134 | ||
135 | inline ~CLockObject(void) | |
136 | { | |
137 | if (m_bClearOnExit) | |
138 | Clear(); | |
139 | else | |
140 | Unlock(); | |
141 | } | |
142 | ||
143 | inline bool TryLock(void) | |
144 | { | |
145 | return m_mutex.TryLock(); | |
146 | } | |
147 | ||
148 | inline void Unlock(void) | |
149 | { | |
150 | m_mutex.Unlock(); | |
151 | } | |
152 | ||
153 | inline bool Clear(void) | |
154 | { | |
155 | return m_mutex.Clear(); | |
156 | } | |
157 | ||
158 | inline bool Lock(void) | |
159 | { | |
160 | return m_mutex.Lock(); | |
161 | } | |
162 | ||
163 | private: | |
164 | CMutex &m_mutex; | |
165 | bool m_bClearOnExit; | |
166 | }; | |
167 | ||
c183fa4b LOK |
168 | class CTryLockObject : public PreventCopy |
169 | { | |
170 | public: | |
171 | inline CTryLockObject(CMutex &mutex, bool bClearOnExit = false) : | |
172 | m_mutex(mutex), | |
173 | m_bClearOnExit(bClearOnExit), | |
174 | m_bIsLocked(m_mutex.TryLock()) | |
175 | { | |
176 | } | |
177 | ||
178 | inline ~CTryLockObject(void) | |
179 | { | |
180 | if (m_bClearOnExit) | |
181 | Clear(); | |
182 | else if (m_bIsLocked) | |
183 | Unlock(); | |
184 | } | |
185 | ||
186 | inline bool TryLock(void) | |
187 | { | |
188 | bool bReturn = m_mutex.TryLock(); | |
189 | m_bIsLocked |= bReturn; | |
190 | return bReturn; | |
191 | } | |
192 | ||
193 | inline void Unlock(void) | |
194 | { | |
195 | if (m_bIsLocked) | |
196 | { | |
197 | m_bIsLocked = false; | |
198 | m_mutex.Unlock(); | |
199 | } | |
200 | } | |
201 | ||
202 | inline bool Clear(void) | |
203 | { | |
204 | m_bIsLocked = false; | |
205 | return m_mutex.Clear(); | |
206 | } | |
207 | ||
208 | inline bool Lock(void) | |
209 | { | |
210 | bool bReturn = m_mutex.Lock(); | |
211 | m_bIsLocked |= bReturn; | |
212 | return bReturn; | |
213 | } | |
214 | ||
215 | inline bool IsLocked(void) const | |
216 | { | |
217 | return m_bIsLocked; | |
218 | } | |
219 | ||
220 | private: | |
221 | CMutex & m_mutex; | |
222 | bool m_bClearOnExit; | |
223 | volatile bool m_bIsLocked; | |
224 | }; | |
225 | ||
f00ff009 LOK |
226 | class CCondition : public PreventCopy |
227 | { | |
228 | public: | |
41c655b6 LOK |
229 | inline CCondition(void) : |
230 | m_bPredicate(false), | |
231 | m_iWaitingThreads(0) {} | |
f00ff009 LOK |
232 | inline ~CCondition(void) |
233 | { | |
41c655b6 | 234 | Broadcast(); |
f00ff009 LOK |
235 | } |
236 | ||
41c655b6 | 237 | void Broadcast(void) |
f00ff009 | 238 | { |
41c655b6 | 239 | Set(true); |
3a590d6a | 240 | m_condition.Broadcast(); |
f00ff009 LOK |
241 | } |
242 | ||
41c655b6 | 243 | void Signal(void) |
f00ff009 | 244 | { |
41c655b6 | 245 | Set(false); |
3a590d6a | 246 | m_condition.Signal(); |
f00ff009 LOK |
247 | } |
248 | ||
41c655b6 | 249 | bool Wait(CMutex &mutex, uint32_t iTimeout = 0) |
f00ff009 | 250 | { |
41c655b6 LOK |
251 | { |
252 | CLockObject lock(m_mutex); | |
253 | ++m_iWaitingThreads; | |
254 | } | |
255 | ||
256 | if (iTimeout > 0) | |
257 | { | |
258 | CTimeout timeout(iTimeout); | |
259 | while (!m_bPredicate && timeout.TimeLeft() > 0) | |
260 | m_condition.Wait(mutex.m_mutex, timeout.TimeLeft()); | |
261 | } | |
262 | else | |
263 | { | |
264 | while (!m_bPredicate) | |
265 | m_condition.Wait(mutex.m_mutex, 0); | |
266 | } | |
267 | ||
268 | return ResetAndReturn(); | |
f00ff009 LOK |
269 | } |
270 | ||
271 | static void Sleep(uint32_t iTimeout) | |
272 | { | |
273 | CCondition w; | |
274 | CMutex m; | |
275 | CLockObject lock(m); | |
276 | w.Wait(m, iTimeout); | |
277 | } | |
278 | ||
3a590d6a | 279 | private: |
41c655b6 LOK |
280 | void Set(bool bBroadcast = false) |
281 | { | |
282 | CLockObject lock(m_mutex); | |
283 | m_bPredicate = true; | |
284 | m_bBroadcast = bBroadcast; | |
285 | } | |
286 | ||
287 | bool ResetAndReturn(void) | |
288 | { | |
289 | CLockObject lock(m_mutex); | |
290 | bool bReturn(m_bPredicate); | |
291 | if (bReturn && (--m_iWaitingThreads == 0 || !m_bBroadcast)) | |
292 | m_bPredicate = false; | |
293 | return bReturn; | |
294 | } | |
295 | ||
296 | CMutex m_mutex; | |
3a590d6a | 297 | CConditionImpl m_condition; |
41c655b6 LOK |
298 | volatile bool m_bPredicate; |
299 | volatile bool m_bBroadcast; | |
300 | unsigned int m_iWaitingThreads; | |
f00ff009 LOK |
301 | }; |
302 | } |