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