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