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