1 /*---------------------------------------------------------------------------*
2   Project:  Horizon
3   File:     os_Semaphore.h
4 
5   Copyright (C)2009 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: 12804 $
14  *---------------------------------------------------------------------------*/
15 
16 /*!
17     @file
18     @brief    Semaphore に関するAPI の宣言
19 
20     :include nn/os.h
21 */
22 
23 #ifndef NN_OS_OS_SEMAPHORE_H_
24 #define NN_OS_OS_SEMAPHORE_H_
25 
26 #include <nn/types.h>
27 #include <nn/Handle.h>
28 #include <nn/Result.h>
29 #include <nn/os/os_Synchronization.h>
30 
31 #include <nn/util/util_Result.h>
32 #include <nn/util/detail/util_ScopedLockImpl.h>
33 
34 #ifdef __cplusplus
35 
36 namespace nn { namespace os {
37 
38 /*!
39     @brief セマフォを扱う為のクラスです。セマフォはカウンタを持つ同期オブジェクトです。
40 
41            通常は @ref nn::os::Semaphore ではなく、@ref nn::os::LightSemaphore を使用すべきです。
42            複数の同期オブジェクトを待つことができない点を除いて
43            @ref nn::os::Semaphore よりも @ref nn::os::LightSemaphore の方が優れています。
44 
45            セマフォの Wait 動作では、セマフォカウンタが 0 より大きくなることを待った後、セマフォカウンタを 1 増やします。
46            セマフォカウンタが 0 のときは、Wait 動作は解放されません。
47 
48            セマフォのカウンタを増やすには @ref Release を呼び出します。
49 
50            同期オブジェクトについては、@ref nn::os::Event を参照してください。
51 */
52 
53 class Semaphore : public InterruptEvent
54 {
55 public:
56 
57     /*!
58       @brief        セマフォを構築し、初期化します。
59 
60                     初期化しないコンストラクタと、初期化するコンストラクタが用意されています。
61                     初期化しないコンストラクタを使用した場合は、別途 @ref Initialize の呼び出しが必要です。
62 
63       @param[in]    initialCount    作成直後のセマフォのカウント値。
64       @param[in]    maxCount        このセマフォが取りうる最大カウント値。
65     */
66     Semaphore(s32 initialCount, s32 maxCount);
67 
68     /*!
69       @brief        セマフォを構築します。初期化はしません。使用する為には @ref Initialize の呼び出しが必要です。
70 
71     */
Semaphore()72     Semaphore() {}
73 
74     /*!
75       @brief        構築済みのセマフォを初期化します。
76 
77       @param[in]    initialCount    作成直後のセマフォのカウント値。
78       @param[in]    maxCount        このセマフォが取りうる最大カウント値。
79 
80       @return       無し。
81     */
82     void Initialize(s32 initialCount, s32 maxCount);
83 
84     /*!
85       @brief        構築済みのセマフォの初期化を試みます。
86 
87       @param[in]    initialCount    作成直後のセマフォのカウント値。
88       @param[in]    maxCount        このセマフォが取りうる最大カウント値。
89 
90       @return       成功するとtrue、失敗するとfalseを返します。
91     */
92     nn::Result TryInitialize(s32 initialCount, s32 maxCount);
93 
94     /*!
95       @brief        セマフォを破棄します。
96 
97                     デストラクタからも自動で呼ばれます。
98 
99       @return       無し。
100     */
Finalize()101     void Finalize() { InterruptEvent::Finalize(); }
102 
103     /*!
104       @brief デストラクタです。
105     */
~Semaphore()106     ~Semaphore() {}
107 
108     /*!
109       @brief        セマフォの解放(V 操作)を行い、カウンタ値を増やします。
110 
111                     セマフォ待ちでブロックされているスレッドがある場合には、最も優先順位の高いスレッドの 1 つがブロックから解除されます。
112 
113       @param[in]    releaseCount    カウント値の増分を指定します。
114 
115       @return       releaseCount を加える前のカウント値を返します。
116     */
117     s32 Release(s32 releaseCount = 1);
118 
119     /*!
120       @brief        セマフォの取得(P 操作)を行い、カウンタ値を 1 減らします。
121 
122       @return       無し。
123     */
Acquire()124     void Acquire() { this->WaitOne(); }
125 
126     /*!
127       @brief        セマフォの取得(P 操作)を試行します。
128 
129                     成功するとカウンタ値を 1 減らします。
130 
131       @param[in]    timeout     タイムアウト時間を指定します。0 を指定すると即座に処理を返します。
132 
133       @return       タイムアウト時間内に取得が成功したかを返します。
134     */
TryAcquire(nn::fnd::TimeSpan timeout)135     bool TryAcquire(nn::fnd::TimeSpan timeout) { return this->WaitOne(timeout); }
136 
137     class ScopedLock;
138 
139 private:
140 
141     Result TryInitializeImpl(s32 initialCount, s32 maxCount);
142 
143 };
144 
TryInitializeImpl(s32 initialCount,s32 maxCount)145 inline Result Semaphore::TryInitializeImpl(s32 initialCount, s32 maxCount)
146 {
147     Handle handle;
148     NN_UTIL_RETURN_IF_FAILED(nn::svc::CreateSemaphore(&handle, initialCount, maxCount));
149     this->SetHandle(handle);
150     return ResultSuccess();
151 }
152 
Initialize(s32 initialCount,s32 maxCount)153 inline void Semaphore::Initialize(s32 initialCount, s32 maxCount)
154 {
155     NN_UTIL_PANIC_IF_FAILED(TryInitializeImpl(initialCount, maxCount));
156 }
157 
TryInitialize(s32 initialCount,s32 maxCount)158 inline nn::Result Semaphore::TryInitialize(s32 initialCount, s32 maxCount)
159 {
160     Result result = TryInitializeImpl(initialCount, maxCount);
161     if (result.GetSummary() == Result::SUMMARY_OUT_OF_RESOURCE)
162     {
163         return result;
164     }
165     NN_UTIL_PANIC_IF_FAILED(result);
166     return result;
167 }
168 
Semaphore(s32 initialCount,s32 maxCount)169 inline Semaphore::Semaphore(s32 initialCount, s32 maxCount)
170 {
171     Initialize(initialCount, maxCount);
172 }
173 
Release(s32 releaseCount)174 inline s32 Semaphore::Release(s32 releaseCount)
175 {
176     s32 ret;
177     NN_UTIL_PANIC_IF_FAILED(nn::svc::ReleaseSemaphore(&ret, GetHandle(), releaseCount));
178     return ret;
179 }
180 
181 NN_UTIL_DETAIL_DEFINE_SCOPED_LOCK(Semaphore, Acquire(), Release());
182 
183 }} // namespace nn::os
184 
185 #endif // __cplusplus
186 
187 // 以下、C 用宣言
188 
189 #include <nn/util/detail/util_CLibImpl.h>
190 
191 /*!
192   @addtogroup   nn_os
193   @{
194 
195   @defgroup     nn_os_Semaphore_c       Semaphore (C)
196 
197   @brief        @ref nn::os::Semaphore の C インタフェースモジュールです。
198 
199   @{
200 */
201 
202 /*!
203   @struct       nnosSemaphore
204   @brief        セマフォを表す C の構造体です。
205   @brief 対応するクラス @ref nn::os::Semaphore を参照してください。
206 */
207 NN_UTIL_DETAIL_CLIBIMPL_DEFINE_BUFFER_CLASS(nnosSemaphore, nn::os::Semaphore, 4, u32);
208 NN_UTIL_DETAIL_CLIBIMPL_DECLARE_CONVERSION(nnosSemaphoreToWaitObject, nnosSemaphore, nnosWaitObject);
209 NN_UTIL_DETAIL_CLIBIMPL_DECLARE_CONVERSION(nnosWaitObjectToSemaphore, nnosWaitObject, nnosSemaphore);
210 
211 /*!
212   @brief 対応する C++ 関数 @ref nn::os::Semaphore::Semaphore を参照してください。
213 */
214 NN_EXTERN_C void nnosSemaphoreInitialize(nnosSemaphore* this_, s32 initialCount, s32 maxCount);
215 
216 /*!
217   @brief 対応する C++ 関数 @ref nn::os::Semaphore::Semaphore を参照してください。
218 */
219 NN_EXTERN_C bool nnosSemaphoreTryInitialize(nnosSemaphore* this_, s32 initialCount, s32 maxCount);
220 
221 /*!
222   @brief 対応する C++ 関数 @ref nn::os::Semaphore::Release を参照してください。
223 */
224 NN_EXTERN_C s32 nnosSemaphoreRelease(nnosSemaphore* this_, s32 releaseCount);
225 
226 /*!
227   @brief 対応する C++ 関数 @ref nn::os::Semaphore::Acquire を参照してください。
228 */
229 NN_EXTERN_C void nnosSemaphoreAcquire(nnosSemaphore* this_);
230 
231 /*!
232   @brief 対応する C++ 関数 @ref nn::os::Semaphore::TryAcquire を参照してください。
233 */
234 NN_EXTERN_C bool nnosSemaphoreTryAcquire(nnosSemaphore* this_, s64 nanoSeconds);
235 
236 /*!
237   @brief 対応する C++ 関数 @ref nn::os::Semaphore::Finalize を参照してください。
238 */
239 NN_EXTERN_C void nnosSemaphoreFinalize(nnosSemaphore* this_);
240 
241 /*!
242   @}
243 
244   @}
245 */
246 
247 #endif
248