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