1 /*---------------------------------------------------------------------------*
2   Project:  Horizon
3   File:     os_Event.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: 19727 $
14  *---------------------------------------------------------------------------*/
15 
16 /*! @file
17   @brief    Event に関するAPI の宣言
18 
19     :include nn/os.h
20 */
21 
22 #ifndef NN_OS_OS_EVENT_H_
23 #define NN_OS_OS_EVENT_H_
24 
25 #include <nn/types.h>
26 #include <nn/Handle.h>
27 #include <nn/Result.h>
28 #include <nn/os/os_Synchronization.h>
29 
30 #include <nn/util/util_Result.h>
31 
32 #ifdef __cplusplus
33 
34 namespace nn{ namespace os {
35 
36 /*!
37     @brief ライブラリが内部的に使うクラスです。このクラスを直接使わないでください。
38 */
39 class EventBase : public InterruptEvent
40 {
41 protected:
42     explicit EventBase(ResetType resetType);
EventBase()43     EventBase() {}
~EventBase()44     ~EventBase() {}
45 
46     void        Initialize(ResetType resetType);
47     nn::Result  TryInitialize(ResetType resetType);
48     void        Finalize();
49     void        Signal();
50     void        ClearSignal();
51 
52 private:
53     Result TryInitializeImpl(ResetType resetType);
54 };
55 
56 // インライン実装
57 
TryInitializeImpl(ResetType resetType)58 inline Result EventBase::TryInitializeImpl(ResetType resetType)
59 {
60     Handle handle;
61     NN_UTIL_RETURN_IF_FAILED(nn::svc::CreateEvent(&handle, resetType));
62     this->SetHandle(handle);
63     return ResultSuccess();
64 }
65 
Initialize(ResetType resetType)66 inline void EventBase::Initialize(ResetType resetType)
67 {
68     NN_UTIL_PANIC_IF_FAILED(TryInitializeImpl(resetType));
69 }
70 
TryInitialize(ResetType resetType)71 inline nn::Result EventBase::TryInitialize(ResetType resetType)
72 {
73     Result result = TryInitializeImpl(resetType);
74     if (result.GetSummary() == Result::SUMMARY_OUT_OF_RESOURCE)
75     {
76         return result;
77     }
78     NN_UTIL_PANIC_IF_FAILED(result);
79     return result;
80 }
81 
Finalize()82 inline void EventBase::Finalize()
83 {
84     InterruptEvent::Finalize();
85 }
86 
EventBase(ResetType resetType)87 inline EventBase::EventBase(ResetType resetType)
88 {
89     Initialize(resetType);
90 }
91 
Signal()92 inline void EventBase::Signal()
93 {
94     NN_UTIL_PANIC_IF_FAILED(nn::svc::SignalEvent(GetHandle()));
95 }
96 
ClearSignal()97 inline void EventBase::ClearSignal()
98 {
99     NN_UTIL_PANIC_IF_FAILED(nn::svc::ClearEvent(GetHandle()));
100 }
101 
102 
103 /*!
104     @brief  イベントを扱う為のクラスです。イベントはイベントの発生を通知する同期オブジェクトです。
105 
106             通常は @ref nn::os::Event ではなく、@ref nn::os::LightEvent を使用すべきです。
107             複数の同期オブジェクトを同時に待つことができないという点を除いて
108             @ref nn::os::Event より @ref nn::os::LightEvent の方が優れています。
109 
110             イベントは、シグナル状態と非シグナル状態の二つの状態持ちます。
111             Event の Wait 動作では、イベントがシグナル状態になるのを待ちます。
112 
113             イベントには、「手動リセットイベント」と「自動リセットイベント」の二つがあり、
114             初期化時のパラメータによって設定することができます。
115 
116             手動リセットイベントでは、@ref Signal によってシグナル状態になると、
117             @ref ClearSignal が呼び出されるまで、常にシグナル状態が維持されます。
118             シグナル状態の間、このイベントに対する全ての Wait 動作は解放されます。
119 
120             自動リセットイベントでは、@ref Signal によってシグナル状態になると、
121             Wait 動作の解放されうるスレッドの中で最も優先度の高いもののうち唯一つだけがが解放されます。
122             そのほかのスレッドは解放されません。
123 
124     @see    nn::os::Semaphore
125 */
126 class Event : public EventBase
127 {
128 public:
129 
130     /*!
131       @brief        イベントを構築し、初期化します。
132 
133       @param[in]    manualReset   手動リセットイベントか否かを指定します。
134     */
Event(bool manualReset)135     explicit Event(bool manualReset) : EventBase(manualReset ? RESET_TYPE_STICKY: RESET_TYPE_ONESHOT) {}
136 
137     /*!
138       @brief        イベントオブジェクトを構築します。初期化はしません。
139                     イベントを使用する場合は、明示的に @ref Initialize を呼ぶ必要があります。
140     */
Event()141     Event() {}
142 
143     /*!
144       @brief        イベントを初期化します。
145 
146       @param[in]    manualReset   手動リセットイベントか否かを指定します。
147     */
Initialize(bool manualReset)148     void Initialize(bool manualReset) { EventBase::Initialize(manualReset ? RESET_TYPE_STICKY: RESET_TYPE_ONESHOT); }
Initialize(ResetType resetType)149     void Initialize(ResetType resetType) { EventBase::Initialize(resetType); }
150 
TryInitialize(bool manualReset)151     nn::Result TryInitialize(bool manualReset) { return EventBase::TryInitialize(manualReset ? RESET_TYPE_STICKY: RESET_TYPE_ONESHOT); }
152 
153     /*!
154       @brief イベントを破棄します。
155 
156              デストラクタからも自動で呼ばれます。
157       @return       無し。
158     */
Finalize()159     void Finalize() { EventBase::Finalize(); }
160 
161     /*!
162       @brief デストラクタです。
163     */
~Event()164     ~Event() {}
165 
166     /*!
167       @brief        イベントをシグナル状態にします。
168 
169       @return       無し。
170     */
Signal()171     void Signal() { EventBase::Signal(); }
172 
173     /*!
174       @brief        イベントがシグナル状態になるのを待ちます。
175 
176       @return       無し。
177     */
Wait()178     void Wait() { EventBase::WaitOne(); }
179 
180     /*!
181       @brief        イベントが発生するまでブロックします。
182 
183                     イベントがシグナル状態であれば、即座に true が返ります。
184                     シグナル状態でなかった場合、最大で timeout で指定した時間だけ待ち、
185                     その間にシグナルを受け取ることができれば true を返します。
186                     timeout で指定した時間だけ待ってもシグナルを受け取れなかった場合は、false を返します。
187 
188       @param[in]    timeout     タイムアウト時間を指定します。0 を指定すると即座に処理を返します。
189 
190       @return       タイムアウト時間までにイベントが発生したかを返します。
191     */
Wait(nn::fnd::TimeSpan timeout)192     bool Wait(nn::fnd::TimeSpan timeout) { return EventBase::WaitOne(timeout); }
193 
194     /*!
195       @brief        イベントを手動でクリアします。
196 
197       @return       無し。
198     */
ClearSignal()199     void ClearSignal() { EventBase::ClearSignal(); }
200 
201 };
202 
203 }} // namesapce nn::os
204 
205 #endif // __cplusplus
206 
207 // 以下、C 用宣言
208 
209 #include <nn/util/detail/util_CLibImpl.h>
210 
211 /*!
212   @addtogroup   nn_os
213   @{
214 
215   @defgroup     nn_os_Event_c       Event (C)
216 
217   @brief        @ref nn::os::Event の C インタフェースモジュールです。
218 
219   @{
220 */
221 
222 /*!
223   @struct       nnosEvent
224   @brief        イベントを表す C の構造体です。
225   @brief 対応するクラス @ref nn::os::Event を参照してください。
226 */
227 NN_UTIL_DETAIL_CLIBIMPL_DEFINE_BUFFER_CLASS(nnosEvent, nn::os::Event, 4, u32);
228 NN_UTIL_DETAIL_CLIBIMPL_DECLARE_CONVERSION(nnosEventToWaitObject, nnosEvent, nnosWaitObject);
229 NN_UTIL_DETAIL_CLIBIMPL_DECLARE_CONVERSION(nnosWaitObjectToEvent, nnosWaitObject, nnosEvent);
230 
231 /*!
232   @brief 対応する C++ 関数 @ref nn::os::Event::Initialize を参照してください。
233 */
234 NN_EXTERN_C void nnosEventInitialize(nnosEvent* this_, bool manualReset);
235 
236 /*!
237   @brief 対応する C++ 関数 @ref nn::os::Event::TryInitialize を参照してください。
238 */
239 NN_EXTERN_C bool nnosEventTryInitialize(nnosEvent* this_, bool manualReset);
240 
241 /*!
242   @brief 対応する C++ 関数 @ref nn::os::Event::Signal を参照してください。
243 */
244 NN_EXTERN_C void nnosEventSignal(nnosEvent* this_);
245 
246 /*!
247   @brief 対応する C++ 関数 @ref nn::os::Event::Wait を参照してください。
248 */
249 NN_EXTERN_C void nnosEventWaitSignal(nnosEvent* this_);
250 
251 /*!
252   @brief 対応する C++ 関数 @ref nn::os::Event::Wait を参照してください。
253 */
254 NN_EXTERN_C bool nnosEventTryWaitSignal(nnosEvent* this_, s64 nanoSecondsTimeout);
255 
256 /*!
257   @brief 対応する C++ 関数 @ref nn::os::Event::ClearSignal を参照してください。
258 */
259 NN_EXTERN_C void nnosEventClearSignal(nnosEvent* this_);
260 
261 /*!
262   @brief 対応する C++ 関数 @ref nn::os::Event::Finalize を参照してください。
263 */
264 NN_EXTERN_C void nnosEventFinalize(nnosEvent* this_);
265 
266 /*!
267   @}
268 
269   @}
270 */
271 
272 #endif
273 
274