1 /*---------------------------------------------------------------------------*
2   Project:  Horizon
3   File:     os_LightEvent.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: 12449 $
14  *---------------------------------------------------------------------------*/
15 
16 #ifndef NN_OS_OS_LIGHTEVENT_H_
17 #define NN_OS_OS_LIGHTEVENT_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 
26 namespace nn { namespace os {
27 
28 /*!
29     @file
30     @brief    LightEvent に関するAPI の宣言
31 
32     :include nn/os.h
33 */
34 
35 /*!--------------------------------------------------------------------------*
36   @brief        スレッド間でフラグの通知を行う同期機構です。
37 
38                 内部にフラグを持ち、このフラグをスレッド間で安全に操作したり、
39                また、フラグがセットされるのを待ち合わせたりすることができます。
40 
41                 複数の同期オブジェクトを同時に待つことができないという点を除いて
42                 nn::os::LightEvent の方が nn::os::Event より
43                 優れているため、通常は nn::os::LightEvent を使用すべきです。
44 
45                 このクラスの初期化/終了以外のメンバ関数はスレッドセーフです。
46 
47  *---------------------------------------------------------------------------*/
48 class LightEvent
49 {
50 private:
51     static const s32 SIGNALED_MANUAL        = 1;
52     static const s32 SIGNALED_AUTO          = 0;
53     static const s32 NOT_SIGNALED_AUTO      = -1;
54     static const s32 NOT_SIGNALED_MANUAL    = -2;
55 
56 private:
57     WaitableCounter     m_Counter;
58 
59 public:
60     //----------------------------------------
61     //! @name 初期化/終了
62     //@{
63 
64     /*!--------------------------------------------------------------------------*
65       @brief        コンストラクタです。
66 
67                     初期化を行わないコンストラクタです。
68 
69                     別途 @ref Initialize を呼び出す必要があります。
70 
71       @return       なし。
72 
73      *---------------------------------------------------------------------------*/
LightEvent()74     LightEvent(){}
75 
76     /*!--------------------------------------------------------------------------*
77       @brief        コンストラクタです。
78 
79                     初期化を行うコンストラクタです。
80 
81                     別途 @ref Initialize を呼び出す必要はありません。
82 
83                     自動リセットでは、いずれかのスレッドが
84                     フラグがセットされることによって起床した場合、
85                     フラグがクリアされます。
86                     このため、複数のスレッドが待機していても一回のフラグのセットでは
87                     一つのスレッドだけが起床します。
88 
89                     手動リセットではフラグが自動的にクリアされることはありません。
90                     そのため、複数のスレッドが待機しているなら一回のフラグのセットで
91                     全てのスレッドが起床します。
92 
93       @param[in]    isManualReset   手動リセットなら true、
94                                     自動リセットなら false を指定します。
95 
96       @return       なし。
97 
98      *---------------------------------------------------------------------------*/
LightEvent(bool isManualReset)99     LightEvent(bool isManualReset)
100     {
101         Initialize(isManualReset);
102     }
103 
104     /*!--------------------------------------------------------------------------*
105       @brief        初期化を行います。
106 
107       @param[in]    isManualReset   手動リセットなら true、
108                                     自動リセットなら false を指定します。
109 
110       @return       なし。
111 
112      *---------------------------------------------------------------------------*/
Initialize(bool isManualReset)113     void Initialize(bool isManualReset)
114     {
115         *m_Counter = isManualReset ? NOT_SIGNALED_MANUAL: NOT_SIGNALED_AUTO;
116     }
117 
118     /*!--------------------------------------------------------------------------*
119       @brief        終了処理を行います。
120 
121       @return       なし。
122 
123      *---------------------------------------------------------------------------*/
Finalize()124     void Finalize() {}
125 
126     //@}
127 
128     //----------------------------------------
129     //! @name デバッグ用情報取得
130     //@{
131 
132     /*!--------------------------------------------------------------------------*
133       @brief        フラグがセットされているかどうかを取得します。
134 
135                     この関数は主にデバッグ用です。
136                     通常は @ref TryWait を用いてください。
137 
138                     この関数は自動リセットか手動リセットかによらず
139                     単純にフラグがセットされているかどうかを取得します。
140                     フラグの状態を変更することはしません。
141 
142     @return         フラグがセットされているなら true、
143                     そうでなければ false を返します。
144 
145      *---------------------------------------------------------------------------*/
IsSignaled()146     bool IsSignaled() const { return *m_Counter >= 0; }
147 
148     /*!--------------------------------------------------------------------------*
149       @brief        手動リセットかどうかを取得します。
150 
151       @return       手動リセットなら true、
152                     そうでなければ false を返します。
153 
154      *---------------------------------------------------------------------------*/
IsManualReset()155     bool IsManualReset() const
156     {
157         const s32 c = *m_Counter;
158         return (c == SIGNALED_MANUAL) || (c == NOT_SIGNALED_MANUAL);
159     }
160 
161     //@}
162 
163     //----------------------------------------
164     //! @name フラグの操作と待ち合わせ
165     //@{
166 
167     /*!--------------------------------------------------------------------------*
168       @brief        フラグがセットされているかどうかを取得します。
169 
170                     自動リセットの場合、フラグがセットされているなら
171                     フラグのクリアも行います。
172 
173       @return       フラグがセットされていたなら true、
174                     そうでなければ false を返します。
175 
176      *---------------------------------------------------------------------------*/
177     bool TryWait();
178 
179     /*!--------------------------------------------------------------------------*
180       @brief        フラグがセットされるまで待機します。
181 
182                     自動リセットの場合は、フラグがセットされ待機が解除されると
183                     同時にフラグをクリアします。
184 
185       @return       なし。
186 
187      *---------------------------------------------------------------------------*/
188     void Wait();
189 
190     /*!--------------------------------------------------------------------------*
191       @brief        フラグをセットします。
192 
193                     フラグがセットされるのを待機しているスレッドが存在するなら
194                     そのスレッドを起床させます。
195 
196                     自動リセットの場合、複数のスレッドが待機していても
197                     起床するスレッドは 1 つだけです。
198                     起床するスレッドはスレッド優先度が高い方から優先的に起床します。
199                     また、待機しているスレッドが存在するなら、
200                     そのスレッドが起床すると同時にフラグがクリアされます。
201                     待機しているスレッドが存在しなければ
202                     フラグはセットされたままになります。
203 
204                     手動リセットの場合、全ての待機しているスレッドが起床します。
205                     またフラグはセットされたままになります。
206 
207       @return       なし。
208 
209      *---------------------------------------------------------------------------*/
210     void Signal();
211 
212     /*!--------------------------------------------------------------------------*
213       @brief        フラグがセットされるのを待機しているスレッドを解放します。
214 
215                     自動リセットの場合は待機しているスレッドのうち
216                     最もスレッド優先度が高いスレッドを一つだけ起床させ、
217                     その後フラグをクリアします。
218                     待機しているスレッドが存在しなくてもフラグをクリアする点が
219                     Signal と異なります。
220 
221                     手動リセットの場合は待機している全てのスレッドを起床させ、
222                     その後フラグをクリアします。
223 
224       @return       なし。
225 
226      *---------------------------------------------------------------------------*/
227     void Pulse();
228 
229     /*!--------------------------------------------------------------------------*
230       @brief        フラグをクリアします。
231 
232       @return       なし。
233 
234      *---------------------------------------------------------------------------*/
235     void ClearSignal();
236 
237     //@}
238 };
239 
240 
241 }} // namespace nn::os
242 
243 #endif // __cplusplus
244 
245 // 以下、C 用宣言
246 
247 #include <nn/util/detail/util_CLibImpl.h>
248 
249 /*!
250   @addtogroup   nn_os
251   @{
252 
253   @defgroup     nn_os_LightEvent_c       LightEvent (C)
254 
255   @brief        @ref nn::os::LightEvent の C インタフェースモジュールです。
256 
257   @{
258 */
259 
260 /*!
261   @struct       nnosLightEvent
262   @brief        ライトイベントを表す C の構造体です。
263   @brief 対応するクラス @ref nn::os::LightEvent を参照してください。
264 */
265 NN_UTIL_DETAIL_CLIBIMPL_DEFINE_BUFFER_CLASS(nnosLightEvent, nn::os::LightEvent, 4, u32);
266 
267 /*!
268   @brief 対応する C++ 関数 @ref nn::os::LightEvent::Initialize を参照してください。
269 */
270 NN_EXTERN_C void nnosLightEventInitialize(nnosLightEvent* this_, bool isManualReset);
271 
272 /*!
273   @brief 対応する C++ 関数 @ref nn::os::LightEvent::IsSignaled を参照してください。
274 */
275 NN_EXTERN_C bool nnosLightEventIsSignaled(nnosLightEvent* this_);
276 
277 /*!
278   @brief 対応する C++ 関数 @ref nn::os::LightEvent::IsManualReset を参照してください。
279 */
280 NN_EXTERN_C bool nnosLightEventIsManualReset(nnosLightEvent* this_);
281 
282 /*!
283   @brief 対応する C++ 関数 @ref nn::os::LightEvent::TryWait を参照してください。
284 */
285 NN_EXTERN_C bool nnosLightEventTryWait(nnosLightEvent* this_);
286 
287 /*!
288   @brief 対応する C++ 関数 @ref nn::os::LightEvent::Wait を参照してください。
289 */
290 NN_EXTERN_C void nnosLightEventWait(nnosLightEvent* this_);
291 
292 /*!
293   @brief 対応する C++ 関数 @ref nn::os::LightEvent::Signal を参照してください。
294 */
295 NN_EXTERN_C void nnosLightEventSignal(nnosLightEvent* this_);
296 
297 /*!
298   @brief 対応する C++ 関数 @ref nn::os::LightEvent::Pulse を参照してください。
299 */
300 NN_EXTERN_C void nnosLightEventPulse(nnosLightEvent* this_);
301 
302 /*!
303   @brief 対応する C++ 関数 @ref nn::os::LightEvent::ClearSignal を参照してください。
304 */
305 NN_EXTERN_C void nnosLightEventClearSignal(nnosLightEvent* this_);
306 
307 /*!
308   @brief 対応する C++ 関数 @ref nn::os::LightEvent::Finalize を参照してください。
309 */
310 NN_EXTERN_C void nnosLightEventFinalize(nnosLightEvent* this_);
311 
312 /*!
313   @}
314 
315   @}
316 */
317 
318 
319 
320 #endif  // ifndef NN_OS_OS_LIGHTEVENT_H_
321