1 /*---------------------------------------------------------------------------*
2   Project:  Horizon
3   File:     os_LightSemaphore.h
4 
5   Copyright (C)2009-2012 Nintendo Co., Ltd.  All rights reserved.
6 
7   These coded instructions, statements, and computer programs contain
8   proprietary information of Nintendo of America Inc. and/or Nintendo
9   Company Ltd., and are protected by Federal copyright law. They may
10   not be disclosed to third parties or copied or duplicated in any form,
11   in whole or in part, without the prior written consent of Nintendo.
12 
13   $Rev: 47236 $
14  *---------------------------------------------------------------------------*/
15 
16 #ifndef NN_OS_OS_LIGHTSEMAPHORE_H_
17 #define NN_OS_OS_LIGHTSEMAPHORE_H_
18 
19 #ifdef __cplusplus
20 
21 #include <nn/os/os_WaitableCounter.h>
22 #include <nn/assert.h>
23 #include <nn/WithInitialize.h>
24 #include <nn/util/detail/util_ScopedLockImpl.h>
25 #include <nn/util/util_NonCopyable.h>
26 #include <nn/config.h>
27 
28 namespace nn { namespace os {
29 
30 /* Please see man pages for details
31 
32 
33 
34 
35 */
36 
37 /*
38 
39 
40 
41 
42 
43 
44 
45 
46 
47 
48 
49 
50 
51 
52  */
53 class LightSemaphore : private nn::util::NonCopyable<LightSemaphore>
54 {
55 public:
56     static const s32 MAX_MAX_COUNT  = 0x7fff;
57 
58 private:
59     struct DecrementIfPositive
60     {
operatorDecrementIfPositive61         bool operator()(s32& x)
62         {
63             if( x > 0 )
64             {
65                 --x;
66                 return true;
67             }
68             else
69             {
70                 return false;
71             }
72         }
73     };
74     struct LimitedAdd
75     {
76         s32 max;
77         s32 value;
78         s32 beforeUpdate;
79 
operatorLimitedAdd80         bool operator()(s32& x)
81         {
82             beforeUpdate = x;
83 
84             if( x > max - value )
85             {
86                 x = max;
87             }
88             else
89             {
90                 x += value;
91             }
92 
93             return true;
94         }
95     };
96 
97 private:
98     WaitableCounter                 m_Counter;
99 #if NN_PLATFORM_HAS_16BIT_LL_SC
100     fnd::InterlockedVariable<s16>   m_NumWaiting;
101     s16                             m_Max;
102 #else
103     fnd::InterlockedVariable<s32>   m_NumWaiting;
104 #endif
105 
106 
107 public:
108     //----------------------------------------
109     //
110     //
111 
112     /*
113 
114 
115 
116 
117 
118 
119      */
LightSemaphore()120     LightSemaphore() {}
121 
122     /*
123 
124 
125 
126 
127 
128 
129 
130 
131 
132 
133      */
LightSemaphore(s32 initialCount,s32 maxCount)134     LightSemaphore(s32 initialCount, s32 maxCount) { Initialize(initialCount, maxCount); }
135 
LightSemaphore(s32 initialCount)136     LightSemaphore(s32 initialCount) { Initialize(initialCount); }
137 
138     /*
139 
140 
141 
142 
143 
144 
145 
146 
147      */
Initialize(s32 initialCount,s32 maxCount)148     void Initialize(s32 initialCount, s32 maxCount)
149     {
150         NN_MIN_TASSERT_( initialCount, 0 );
151         NN_MIN_TASSERT_( maxCount, 1 );
152         NN_MAX_TASSERT_( initialCount, maxCount );
153         NN_MAX_TASSERT_( maxCount, MAX_MAX_COUNT );
154 
155         *m_Counter      = initialCount;
156         m_NumWaiting    = 0;
157 #if NN_PLATFORM_HAS_16BIT_LL_SC
158         m_Max           = maxCount;
159 #else
160         NN_UNUSED_VAR(maxCount);
161 #endif
162     }
Initialize(s32 initialCount)163     void Initialize(s32 initialCount) { Initialize(initialCount, MAX_MAX_COUNT); }
164 
165     /*
166 
167 
168 
169 
170      */
Finalize()171     void Finalize() {}
172 
173     //
174 
175     //----------------------------------------
176     //
177     //
178 
179     /*
180 
181 
182 
183 
184 
185      */
186 #if NN_PLATFORM_HAS_16BIT_LL_SC
GetMax()187     s32  GetMax()   const { return m_Max; }
188 #endif
189 
190     /*
191 
192 
193 
194 
195      */
GetCount()196     s32  GetCount() const { return *m_Counter; }
197 
198     //
199 
200     //----------------------------------------
201     //
202     //
203 
204     /*
205 
206 
207 
208 
209 
210 
211 
212      */
Acquire()213     void Acquire()
214     {
215         while( ! TryAcquire() )
216         {
217             ++m_NumWaiting;
218             m_Counter.WaitIfLessThan(1);
219             --m_NumWaiting;
220         }
221     }
222 
223     /*
224 
225 
226 
227 
228 
229 
230 
231 
232 
233      */
TryAcquire()234     bool TryAcquire()
235     {
236         DecrementIfPositive updater;
237         return m_Counter->AtomicUpdateConditional(updater);
238     }
239 
240     /*
241 
242 
243 
244 
245 
246 
247 
248 
249 
250 
251 
252 
253 
254 
255      */
256     bool TryAcquire(fnd::TimeSpan timeout);
257 
258     /*
259 
260 
261 
262 
263 
264 
265 
266 
267 
268 
269 
270 
271 
272 
273 
274 
275 
276 
277 
278 
279      */
280     s32 Release(s32 releaseCount = 1);
281 
282     //
283 
284     class ScopedAcquire
285     {
286     private:
287         LightSemaphore* m_Semaphore;
288     public:
289         ScopedAcquire(LightSemaphore& semaphore, bool wait = true)
290             : m_Semaphore(wait ? (semaphore.Acquire(), &semaphore) : (semaphore.TryAcquire() ? &semaphore : 0)) {}
Aquired()291         bool Aquired() const { return m_Semaphore != 0; }
Detach()292         void Detach() { this->m_Semaphore = 0; }
~ScopedAcquire()293         ~ScopedAcquire() { if (m_Semaphore) { m_Semaphore->Release(); } }
294     };
295 };
296 
297 
298 }} // namespace nn::os
299 
300 #endif // __cplusplus
301 
302 // Below is the C declaration
303 
304 #include <nn/util/detail/util_CLibImpl.h>
305 
306 /* Please see man pages for details
307 
308 
309 
310 
311 
312 
313 
314 
315 */
316 
317 /* Please see man pages for details
318 
319 
320 
321 */
322 NN_UTIL_DETAIL_CLIBIMPL_DEFINE_BUFFER_CLASS(nnosLightSemaphore, nn::os::LightSemaphore, 8, u32);
323 
324 /* Please see man pages for details
325 
326 */
327 NN_EXTERN_C void nnosLightSemaphoreInitialize(nnosLightSemaphore* this_, s32 initialCount, s32 maxCount);
328 
329 #if NN_PLATFORM_HAS_16BIT_LL_SC
330 /* Please see man pages for details
331 
332 */
333 NN_EXTERN_C s32 nnosLightSemaphoreGetMax(nnosLightSemaphore* p);
334 #endif
335 
336 /* Please see man pages for details
337 
338 */
339 NN_EXTERN_C s32 nnosLightSemaphoreGetCount(nnosLightSemaphore* p);
340 
341 /* Please see man pages for details
342 
343 */
344 NN_EXTERN_C s32 nnosLightSemaphoreRelease(nnosLightSemaphore* this_, s32 releaseCount);
345 
346 /* Please see man pages for details
347 
348 */
349 NN_EXTERN_C void nnosLightSemaphoreAcquire(nnosLightSemaphore* this_);
350 
351 /* Please see man pages for details
352 
353 */
354 NN_EXTERN_C bool nnosLightSemaphoreTryAcquire(nnosLightSemaphore* this_);
355 
356 /* Please see man pages for details
357 
358 */
359 NN_EXTERN_C void nnosLightSemaphoreFinalize(nnosLightSemaphore* this_);
360 
361 /*
362 
363 
364 
365 */
366 
367 #endif  // ifndef NN_OS_OS_LIGHTSEMAPHORE_H_
368