1 /*---------------------------------------------------------------------------*
2 Project: Horizon
3 File: os_Alarm.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: 30270 $
14 *---------------------------------------------------------------------------*/
15
16 /*! @file
17 @brief Alarm に関する API の宣言
18
19 :include nn/os.h
20 */
21
22 #ifndef NN_OS_OS_ALARM_H_
23 #define NN_OS_OS_ALARM_H_
24
25 #include <nn/os/os_ThreadPool.h>
26 #include <nn/os/os_Thread.h>
27 #include <nn/fnd/fnd_TimeSpan.h>
28 #include <nn/os/os_Timer.h>
29 #include <nn/util/util_NonCopyable.h>
30 #include <nn/fnd/fnd_Interlocked.h>
31
32 typedef void (*nnosAlarmHandler)(void* param, bool cancelled);
33
34 #ifdef __cplusplus
35
36 namespace nn { namespace os {
37
38 /*!
39 @brief アラームで実行されるハンドラを表す型です。
40 */
41 typedef void (*AlarmHandler)(void* param, bool cancelled);
42
43 /*!
44 @brief アラームシステムを初期化します。
45
46 この関数は将来的に削除される可能性があります。
47 */
48 void InitializeAlarmSystem(s32 priority = 0);
49
50 size_t GetRequiredMemorySizeForAlarmSystem(void);
51
52 /*!
53 @brief アラームを扱う為のクラスです。
54
55 アラームはOSのタイマ機能を利用し、指定時間経過後にハンドラを呼び出します。
56 このとき、ハンドラの第1引数はアラームをセットした際の引数、第2引数には false が入って呼ばれます。
57
58 (この段落の記述は、将来的に変更されます)
59 このクラスを使用するには、@ref nn::os::InitializeAlarmSystem を先に呼ぶ必要があります。
60 アラームハンドラの実行は特定のスレッドで行われますが、このスレッドは現時点の実装では 4 本に限られます。
61 このため、スレッドブロックするなど処理に長い時間がかかるハンドラをたくさん登録すると、
62 アラームシステムが不安定になります。
63 (将来変更される記述はここまで)
64
65 アラームにはワンショットアラームと周期アラームの二種類があります。
66
67 ワンショットアラームは @ref SetOneShot でセットし、一定時間後にハンドラが呼ばれます。
68 ハンドラが開始する前に再度 @ref SetOneShot や @ref SetPeriodic を呼び出すことはできません。
69 ハンドラ内で再度これらのセット関数を呼ぶことは可能です。
70
71 周期アラームは @ref SetPeriodic でセットし、その後一定間隔でハンドラが呼ばれます。
72 周期アラームが動作している間は再度 @ref SetOneShot や @ref SetPeriodic を呼び出すことはできません。
73
74 ハンドラが動作する前にアラームを停止したい場合は、@ref Cancel を呼び出します。
75 ハンドラが動作し始めていた場合は、@ref Cancel を呼んでも、ハンドラの動作が中断されることはありません。
76 アラームのセット中(周期アラームやワンショットアラームでハンドルが呼ばれる前)に @ref Cancel が呼ばれた場合、
77 アラームのハンドラが、第2引数に true を入れて呼び出されます。
78
79 */
80 class Alarm : private nn::os::QueueableWaitTask, private nn::util::NonCopyable<Alarm>
81 {
82 public:
83
84 /*!
85 @brief オブジェクトを構築します。初期化は行いません。
86 使用する前に、@ref Initialize を呼んで明示的に初期化する必要があります。
87 */
Alarm()88 Alarm() : m_Handler(0), m_Flags(Flags::Create(false, false, false)), m_Invoker(0) {}
89
90 /*!
91 @brief オブジェクトを破棄します。
92 内部的に @ref Finalize を呼びます。
93 アラームがセット中の場合にこの関数を呼ぶことはできません。
94 */
95 virtual ~Alarm();
96
97 /*!
98 @brief アラームオブジェクトの初期化をします。
99 */
100 void Initialize();
101
102 /*!
103 @brief アラームの終了処理をします。
104 アラームがセット中の場合にこの関数を呼ぶことはできません。
105 */
106 void Finalize();
107
108 /*!
109 @brief ワンショットアラームを設定します。
110 time 後にハンドラを一回だけ呼び出します。
111
112 @param[in] time ハンドラを呼び出すまでの時間(ns)
113 @param[in] handler アラームのハンドラ
114 @param[in] param ハンドラに与えるパラメータ
115
116 @return 無し。
117
118 */
119 void SetOneShot(nn::fnd::TimeSpan time, AlarmHandler handler, void* param);
120
121 template <typename T>
122 void SetOneShot(nn::fnd::TimeSpan time, void (*handler)(T* param, bool cancelled), T* param);
123
124 /*!
125 @brief 周期アラームを設定します。
126 initial 後にハンドラを一回だけ呼び出し、
127 その後 interval 周期でハンドラを呼び出し続けます。
128
129 @param[in] initial 一度目にハンドラを呼び出すまでの時間
130 @param[in] interval 二度目以降にハンドラを呼び出す間隔
131 @param[in] handler アラームのハンドラ
132 @param[in] param ハンドラに与えるパラメータ
133
134 @return 無し。
135
136 */
137 void SetPeriodic(nn::fnd::TimeSpan initial, nn::fnd::TimeSpan interval, AlarmHandler handler, void* param);
138
139 template <typename T>
140 void SetPeriodic(nn::fnd::TimeSpan initial, nn::fnd::TimeSpan interval, void (*handler)(T* param, bool cancelled), T* param);
141
142 /*!
143 @brief 周期アラームを設定します。
144 interval 周期でハンドラを呼び出し続けます。
145
146 @param[in] interval ハンドラを呼び出す間隔
147 @param[in] handler アラームのハンドラ
148 @param[in] param ハンドラに与えるパラメータ
149
150 @return 無し。
151
152 */
SetPeriodic(nn::fnd::TimeSpan interval,AlarmHandler handler,void * param)153 void SetPeriodic(nn::fnd::TimeSpan interval, AlarmHandler handler, void* param) { SetPeriodic(0, interval, handler, param); }
154
155 template <typename T>
156 void SetPeriodic(nn::fnd::TimeSpan interval, void (*handler)(T* param, bool cancelled), T* param);
157
158 /*!
159 @brief 設定済みのアラームを取り消します。
160
161 @return 無し。
162
163 */
164 void Cancel();
165
166 /*!
167 @brief アラームをセットできる状態であるかどうかを取得します。
168
169 アラームが既にセットされており、今後のハンドラ実行予定があるとき flase を返します。
170 @ref Cancel が呼ばれた後も、一旦ハンドラが呼ばれるまでは true は返しません。
171
172 @return アラームがセットできる状態であれば true を返し、そうでなければ false を返します。
173 */
CanSet()174 bool CanSet() const { return !m_Flags.Read().isSet; }
175
176 private:
177
178 struct Flags
179 {
180 bool cancelled;
181 bool isOneShot;
182 bool isSet;
183 NN_PADDING1;
184
CreateFlags185 static Flags Create(bool cancelled, bool isOneShot, bool isSet)
186 {
187 Flags ret = { cancelled, isOneShot, isSet };
188 return ret;
189 }
190 };
191
192 struct CancelFunc;
193 struct InvokeFunc;
194 friend struct CancelFunc;
195 friend struct InvokeFunc;
196
197 volatile AlarmHandler m_Handler;
198 void* volatile m_Parameter;
199 nn::fnd::InterlockedVariable<Flags> m_Flags;
200 IWaitTaskInvoker* m_Invoker;
201 Timer m_Timer;
202
203 virtual void Invoke();
204 virtual nn::os::WaitObject* GetWaitObject();
205 };
206
207 template <typename T>
SetOneShot(nn::fnd::TimeSpan time,void (* handler)(T * param,bool cancelled),T * param)208 inline void Alarm::SetOneShot(nn::fnd::TimeSpan time, void (*handler)(T* param, bool cancelled), T* param)
209 {
210 SetOneShot(time, reinterpret_cast<AlarmHandler&>(handler), reinterpret_cast<void*&>(param));
211 }
212
213 template <typename T>
SetPeriodic(nn::fnd::TimeSpan initial,nn::fnd::TimeSpan interval,void (* handler)(T *,bool),T * param)214 inline void Alarm::SetPeriodic(nn::fnd::TimeSpan initial, nn::fnd::TimeSpan interval, void (*handler)(T*, bool), T* param)
215 {
216 SetPeriodic(initial, interval, reinterpret_cast<AlarmHandler&>(handler), reinterpret_cast<void*&>(param));
217 }
218
219 template <typename T>
SetPeriodic(nn::fnd::TimeSpan interval,void (* handler)(T *,bool),T * param)220 inline void Alarm::SetPeriodic(nn::fnd::TimeSpan interval, void (*handler)(T*, bool), T* param)
221 {
222 SetPeriodic(interval, reinterpret_cast<AlarmHandler&>(handler), reinterpret_cast<void*&>(param));
223 }
224
225 }} // namespace nn::os
226
227 #endif // __cplusplus
228
229
230 // 以下、C 用宣言
231
232 #include <nn/util/detail/util_CLibImpl.h>
233
234 /*!
235 @addtogroup nn_os os
236 @{
237 */
238
239 /*!
240 @brief 対応する C++ 関数 @ref nn::os::InitializeAlarmSystem を参照してください。
241 */
242 NN_EXTERN_C void nnosInitializeAlarmSystem(void);
243
244 /*!
245 @}
246 */
247
248
249 /*!
250 @addtogroup nn_os os
251 @{
252
253 @defgroup nn_os_Alarm_c Alarm (C)
254
255 @brief @ref nn::os::Alarm の C インタフェースモジュールです。
256
257 @details 時間の指定は @ref nn::fnd::TimeSpan の代わりにナノ秒単位で直接指定します。
258
259 @{
260 */
261
262 /*!
263 @struct nnosAlarm
264 @brief アラームを表す C の構造体です。
265
266 @brief 対応するクラス @ref nn::os::Alarm を参照してください。
267 */
268 NN_UTIL_DETAIL_CLIBIMPL_DEFINE_BUFFER_CLASS(nnosAlarm, nn::os::Alarm, 28, u32);
269
270 /*!
271 @brief 対応する C++ 関数 @ref nn::os::Alarm::Initialize を参照してください。
272 */
273 NN_EXTERN_C void nnosAlarmInitialize(nnosAlarm* this_);
274
275 /*!
276 @brief 対応する C++ 関数 @ref nn::os::Alarm::Finalize を参照してください。
277 */
278 NN_EXTERN_C void nnosAlarmFinalize(nnosAlarm* this_);
279
280 /*!
281 @brief 対応する C++ 関数 @ref nn::os::Alarm::SetOneShot を参照してください。
282 */
283 NN_EXTERN_C void nnosAlarmSetOneShot(nnosAlarm* this_, s64 time, nnosAlarmHandler handler, void* param);
284
285 /*!
286 @brief 対応する C++ 関数 @ref nn::os::Alarm::SetPeriodic を参照してください。
287 */
288 NN_EXTERN_C void nnosAlarmSetPeriodic(nnosAlarm* this_, s64 initial, s64 interval, nnosAlarmHandler handler, void* param);
289
290 /*!
291 @brief 対応する C++ 関数 @ref nn::os::Alarm::Cancel を参照してください。
292 */
293 NN_EXTERN_C void nnosAlarmCancel(nnosAlarm* p);
294
295 /*!
296 @brief 対応する C++ 関数を参照してください。@ref nn::os::Alarm::CanSet
297 */
298 NN_EXTERN_C bool nnosAlarmCanSet(const nnosAlarm* p);
299
300 /*!
301 @}
302
303 @}
304 */
305
306 #endif
307