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