1 /*---------------------------------------------------------------------------*
2   Project:  Horizon
3   File:     os_Synchronization.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: 16692 $
14  *---------------------------------------------------------------------------*/
15 
16 /*! @file
17     @brief      Synchronization に関する API の宣言
18 
19     :include nn/os.h
20 */
21 
22 #ifndef NN_OS_OS_SYNCHRONIZATION_H_
23 #define NN_OS_OS_SYNCHRONIZATION_H_
24 
25 #include <nn/types.h>
26 #include <nn/Result.h>
27 #include <nn/os/os_HandleObject.h>
28 #include <nn/fnd/fnd_TimeSpan.h>
29 
30 #include <nn/util/util_Result.h>
31 
32 /*!
33     @def    NN_OS_WAIT_INFINITE
34     @brief タイムアウトしないことを表します。
35 */
36 #define NN_OS_WAIT_INFINITE                 -1
37 
38 #ifdef __cplusplus
39 
40 namespace nn{ namespace os{
41 
42 const s64 WAIT_INFINITE = NN_OS_WAIT_INFINITE;
43 
44 /*!
45     @brief  Wait することができるオブジェクトの基底クラスです。
46 
47             @ref WaitOne でインスタンスオブジェクトを Wait することができます。
48             @ref WaitAny や @ref WaitAll で、複数の WaitObject を同時に Wait することができます。
49             これらの Wait 動作は、オブジェクトの状態変化によって解放されますが、
50             Wait 動作の解放が何を表すかは継承したクラスによります。
51             継承先クラスでは、Wait 動作の具体的な名前を示す名前で、独自の関数が定義されていることがあります。
52 
53             Wait 動作をしたスレッドは、Wait 動作が解放されるまでブロックされ、
54             CPU リソースを他のスレッドに明け渡します。
55 
56             このクラスを直接インスタンス化することはできません。
57             継承先のクラスを使用してください。
58 */
59 class WaitObject : public HandleObject
60 {
61 public:
62 
63     /*!
64         @brief    インスタンスオブジェクト一つを待ちます。
65 
66         @return    無し。
67     */
68     void WaitOne();
69 
70     /*!
71         @brief    インスタンスオブジェクト一つをタイムアウトつきで待ちます。
72 
73         @param[in]    timeout        タイムアウト時間を指定します。
74 
75         @return        falseが返ってきたら、タイムアウトしたことを表します。
76     */
77     bool WaitOne(nn::fnd::TimeSpan timeout);
78 
79     /*!
80         @brief        全てのオブジェクトを待ちます。
81 
82         @param[in]    objs        WaitObjectの配列を指定します。
83         @param[in]    numObjects    WaitObjectの数を指定します。
84 
85         @return        無し。
86     */
87     static void WaitAll(WaitObject* objs[], s32 numObjects);
88 
89     /*!
90         @brief        全てのオブジェクトをタイムアウトつきで待ちます。
91 
92         @param[in]    objs        WaitObjectの配列を指定します。
93         @param[in]    numObjects    WaitObjectの数を指定します。
94 
95         @param[in]    timeout        タイムアウト時間を指定します。
96 
97         @return        false が返ってきたら、タイムアウトしたことを表します。
98     */
99     static bool WaitAll(WaitObject* objs[], s32 numObjects, nn::fnd::TimeSpan timeout);
100 
101     //
102     /*!
103         @brief        どれか一つのオブジェクトを待ちます。
104 
105         @param[in]    objs        WaitObjectの配列を指定します。
106         @param[in]    numObjects    WaitObjectの数を指定します。
107 
108         @return       Wait 動作が解放されたオブジェクトの objs 配列中でのインデックスを返します。
109     */
110     static s32 WaitAny(WaitObject* objs[], s32 numObjects);
111 
112     /*!
113         @brief        どれか一つのオブジェクトをタイムアウトつきで待ちます。
114 
115         @param[in]    objs        WaitObjectの配列を指定します。
116         @param[in]    numObjects    WaitObjectの数を指定します。
117 
118         @param[in]    timeout        タイムアウト時間を指定します。
119 
120         @return       Wait 動作が解放されたオブジェクトの objs 配列中でのインデックスを返します。タイムアウトしたときには負の値が返ります。
121     */
122     static s32 WaitAny(WaitObject* objs[], s32 numObjects, nn::fnd::TimeSpan timeout);
123 
124 protected:
125 
126     // 単独インスタンス化の禁止
WaitObject()127     WaitObject() {}
~WaitObject()128     ~WaitObject() {}
129 
130 private:
131 
132     nn::Result WaitOneImpl(s64 nanoSecondsTimeout);
133     static nn::Result WaitMultiple(s32* pOut, WaitObject* objs[], s32 numObjects, bool waitAll, s64 nanoSecondsTimeout);
134 
135 };
136 
137 /*!
138     @brief  ライブラリが内部で使うための抽象クラスです。
139             直接使わないようにしてください。
140 
141 */
142 class InterruptEvent : public WaitObject
143 {
144 protected:
InterruptEvent()145     InterruptEvent() {}
~InterruptEvent()146     ~InterruptEvent() {}
147 };
148 
149 // インライン実装
150 
WaitOneImpl(s64 nanoSecondsTimeout)151 inline nn::Result WaitObject::WaitOneImpl(s64 nanoSecondsTimeout)
152 {
153     s32 dummy;
154     Handle handle = GetHandle();
155     return nn::svc::WaitSynchronization(&dummy, &handle, 1, false, nanoSecondsTimeout);
156 }
157 
WaitOne()158 inline void WaitObject::WaitOne()
159 {
160     NN_UTIL_PANIC_IF_FAILED(WaitOneImpl(WAIT_INFINITE));
161 }
162 
WaitOne(nn::fnd::TimeSpan timeout)163 inline bool WaitObject::WaitOne(nn::fnd::TimeSpan timeout)
164 {
165     nn::Result result = WaitOneImpl(timeout.GetNanoSeconds());
166     NN_UTIL_PANIC_IF_FAILED(result);
167     return result.GetDescription() != nn::Result::DESCRIPTION_TIMEOUT;
168 }
169 
WaitAll(WaitObject * objs[],s32 numObjects,nn::fnd::TimeSpan timeout)170 inline bool WaitObject::WaitAll(WaitObject* objs[], s32 numObjects, nn::fnd::TimeSpan timeout)
171 {
172     s32 dummy;
173     nn::Result result = WaitMultiple(&dummy, objs, numObjects, true, timeout.GetNanoSeconds());
174     NN_UTIL_PANIC_IF_FAILED(result);
175     return result.GetDescription() != nn::Result::DESCRIPTION_TIMEOUT;
176 }
177 
WaitAll(WaitObject * objs[],s32 numObjects)178 inline void WaitObject::WaitAll(WaitObject* objs[], s32 numObjects)
179 {
180     s32 dummy;
181     NN_UTIL_PANIC_IF_FAILED(WaitMultiple(&dummy, objs, numObjects, true, WAIT_INFINITE));
182 }
183 
WaitAny(WaitObject * objs[],s32 numObjects,nn::fnd::TimeSpan timeout)184 inline s32 WaitObject::WaitAny(WaitObject* objs[], s32 numObjects, nn::fnd::TimeSpan timeout)
185 {
186     s32 ret;
187     nn::Result result = WaitMultiple(&ret, objs, numObjects, false, timeout.GetNanoSeconds());
188     NN_UTIL_PANIC_IF_FAILED(result);
189     return (result.GetDescription() == nn::Result::DESCRIPTION_TIMEOUT) ? -1 : ret;
190 }
191 
WaitAny(WaitObject * objs[],s32 numObjects)192 inline s32 WaitObject::WaitAny(WaitObject* objs[], s32 numObjects)
193 {
194     s32 ret;
195     NN_UTIL_PANIC_IF_FAILED(WaitMultiple(&ret, objs, numObjects, false, WAIT_INFINITE));
196     return ret;
197 }
198 
199 }} // namespace nn::os
200 
201 #endif // __cplusplus
202 
203 // 以下、C 用宣言
204 #include <nn/util/detail/util_CLibImpl.h>
205 
206 NN_UTIL_DETAIL_CLIBIMPL_DEFINE_ABSTRACT_BUFFER_CLASS(nnosWaitObject)
207 
208 /*!
209   @brief 対応する C++ 関数を参照してください。@ref nn::os::WaitObject::WaitOne
210 */
211 NN_EXTERN_C bool nnosWaitObjectWaitOne(nnosWaitObject* p, s64 nanoSecondsTimeout);
212 
213 /*!
214   @brief 対応する C++ 関数を参照してください。@ref nn::os::WaitObject::WaitAll
215 */
216 NN_EXTERN_C bool nnosWaitObjectWaitAll(nnosWaitObject* objs[], s32 numObjects, s64 nanoSecondsTimeout);
217 
218 /*!
219   @brief 対応する C++ 関数を参照してください。@ref nn::os::WaitObject::WaitAny
220 */
221 NN_EXTERN_C s32 nnosWaitObjectWaitAny(nnosWaitObject* objs[], s32 numObjects, s64 nanoSecondsTimeout);
222 
223 /* NN_OS_SYNCHRONIZATION_H_ */
224 #endif /* NN_OS_OS_SYNCHRONIZATION_H_ */
225