1 /*---------------------------------------------------------------------------*
2   Project:  Horizon
3   File:     os_Timer.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    Timer に関するAPI の宣言
18 
19 */
20 
21 #ifndef NN_OS_OS_TIMER_H_
22 #define NN_OS_OS_TIMER_H_
23 
24 #include <nn/types.h>
25 #include <nn/Handle.h>
26 #include <nn/Result.h>
27 #include <nn/os/os_Synchronization.h>
28 #include <nn/fnd/fnd_TimeSpan.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             タイマには @ref Event と同様に、シグナル状態と非シグナル状態の二つの状態持ちます。
40             Timer の Wait 動作では、イベントがシグナル状態になるのを待ちます。
41 
42             また同様に、タイマには、「手動リセットタイマ」と「自動リセットタイマ」の二つがあり、
43             初期化時のパラメータによって設定することができます。
44             二つの違いの詳細は @ref Event を参照してください。
45 
46             タイマでは、即時にシグナル状態にはなるわけではなく、
47             @ref StartOneShot 関数を呼んだ後に指定した時間だけ遅れてシグナル状態になります。
48 
49             また、@ref StartPeriodic を呼ぶことによって、周期的にシグナル状態にすることができます。
50 
51             Timer オブジェクトは 8個まで作成することが出来ます。
52             また、API によってはこの制限にカウントされるリソースを消費する場合がありますので、ご注意ください。
53 */
54 class Timer : public WaitObject
55 {
56 public:
57 
58     /*! @brief タイマ初期化
59 
60                初期化しないコンストラクタと、初期化するコンストラクタが用意されています。
61 
62                初期化しない場合、使用する前に、@ref Initialize を呼んで明示的に初期化する必要があります。
63 
64         @param[in] isManualReset @ref Initialize を参照してください。
65      */
66     explicit Timer(bool isManualReset);
67 
Timer()68     Timer() {}
69 
70     /*!
71         @brief      タイマの初期化
72 
73         @param[in]  isManualReset 手動リセットタイマとするか設定します。
74                                  手動リセットタイマの場合、タイマの時間が来た後、
75                                  @ref Wait によりタイマ待ちしようとするスレッドは、
76                                  即時に起きます。
77 
78         @return     無し。
79      */
80     void Initialize(bool isManualReset);
81 
82     /*!
83       @brief        タイマの初期化を試みます。
84 
85       @param[in]    isManualReset 手動リセットタイマとするか設定します。
86                                   手動リセットタイマの場合、タイマの時間が来た後、
87                                   @ref Wait によりタイマ待ちしようとするスレッドは、
88                                   即時に起きます。
89 
90       @return       関数の実行結果を返します。
91     */
92     nn::Result TryInitialize(bool isManualReset);
93 
94     /*!
95       @brief タイマーを破棄します。
96 
97              デストラクタからも自動で呼ばれます。
98       @return       無し。
99     */
Finalize()100     void Finalize() { WaitObject::Finalize(); }
101 
102     /*!
103       @brief デストラクタです。
104     */
~Timer()105     ~Timer() {}
106 
107     /*!
108         @brief      タイマーの開始
109 
110         @param[in]  timeSpan     最初のタイマの通知までの時間を指定します。
111 
112         @return     無し。
113     */
114     void StartOneShot(nn::fnd::TimeSpan timeSpan);
115 
116     /*!
117         @brief      タイマを開始します。
118 
119         @param[in]  first     最初のタイマの通知までの時間を指定します。
120 
121         @param[in]  interval    2 度目以降のタイマの通知の間隔を指定します。
122 
123         @return     無し。
124     */
125     void StartPeriodic(nn::fnd::TimeSpan first, nn::fnd::TimeSpan interval);
126 
127     /*!
128         @brief      タイマを即時にシグナル状態にします。
129 
130         @return     無し。
131     */
132     void Signal();
133 
134     /*!
135         @brief      タイマの通知まで待ちます。
136 
137                     複数のスレッドが同一のTimerインスタンスの @ref Wait を呼び
138                     タイマ待ちした場合、先に タイマ待ちしたスレッドが起きます。
139 
140         @return     無し。
141     */
Wait()142     void Wait() { this->WaitOne(); }
143 
144     /*!
145         @brief      開始されたタイマを停止します。
146 
147         @return     無し。
148     */
149     void Stop();
150 
151     /*!
152         @brief      タイマをクリアします。
153 
154                     手動リセットタイマを非シグナル状態にします。
155 
156         @return     無し。
157     */
158     void ClearSignal();
159 
160 private:
161 
162     Result TryInitializeImpl(bool isManualReset);
163     void StartImpl(nn::fnd::TimeSpan first, nn::fnd::TimeSpan interval);
164 
165 };
166 
167 // インライン実装
168 
TryInitializeImpl(bool isManualReset)169 inline Result Timer::TryInitializeImpl(bool isManualReset)
170 {
171     Handle handle;
172     NN_UTIL_RETURN_IF_FAILED(nn::svc::CreateTimer(&handle, isManualReset));
173     this->SetHandle(handle);
174     return ResultSuccess();
175 }
176 
Initialize(bool isManualReset)177 inline void Timer::Initialize(bool isManualReset)
178 {
179     NN_ERR_THROW_FATAL(TryInitializeImpl(isManualReset));
180 }
181 
TryInitialize(bool isManualReset)182 inline nn::Result Timer::TryInitialize(bool isManualReset)
183 {
184     Result result = TryInitializeImpl(isManualReset);
185     if (result.GetSummary() == Result::SUMMARY_OUT_OF_RESOURCE)
186     {
187         return result;
188     }
189     NN_ERR_THROW_FATAL(result);
190     return result;
191 }
192 
Timer(bool isManualReset)193 inline Timer::Timer(bool isManualReset)
194 {
195     Initialize(isManualReset);
196 }
197 
StartImpl(nn::fnd::TimeSpan initial,nn::fnd::TimeSpan interval)198 inline void Timer::StartImpl(nn::fnd::TimeSpan initial, nn::fnd::TimeSpan interval)
199 {
200     NN_ERR_THROW_FATAL(nn::svc::SetTimer(GetHandle(), initial.GetNanoSeconds(), interval.GetNanoSeconds()));
201 }
202 
StartPeriodic(nn::fnd::TimeSpan initial,nn::fnd::TimeSpan interval)203 inline void Timer::StartPeriodic(nn::fnd::TimeSpan initial, nn::fnd::TimeSpan interval)
204 {
205     NN_TASSERT_(interval > 0);
206     this->StartImpl(initial, interval);
207 }
208 
StartOneShot(nn::fnd::TimeSpan initial)209 inline void Timer::StartOneShot(nn::fnd::TimeSpan initial)
210 {
211     this->StartImpl(initial, 0);
212 }
213 
Signal()214 inline void Timer::Signal()
215 {
216     this->StartOneShot(0);
217 }
218 
Stop()219 inline void Timer::Stop()
220 {
221     NN_ERR_THROW_FATAL(nn::svc::CancelTimer(GetHandle()));
222 }
223 
ClearSignal()224 inline void Timer::ClearSignal()
225 {
226     NN_ERR_THROW_FATAL(nn::svc::ClearTimer(GetHandle()));
227 }
228 
229 }} // namesapce nn::os
230 
231 #endif // __cplusplus
232 
233 // 以下、C 用宣言
234 
235 #include <nn/util/detail/util_CLibImpl.h>
236 
237 /*!
238   @addtogroup   nn_os
239   @{
240 
241   @defgroup     nn_os_Timer_c       Timer (C)
242 
243   @brief        @ref nn::os::Timer の C インタフェースモジュールです。
244 
245   @{
246 */
247 
248 /*!
249   @struct       nnosTimer
250   @brief        タイマを表す C の構造体です。
251   @brief 対応するクラス @ref nn::os::Timer を参照してください。
252 */
253 
254 NN_UTIL_DETAIL_CLIBIMPL_DEFINE_BUFFER_CLASS(nnosTimer, nn::os::Timer, 4, u32);
255 NN_UTIL_DETAIL_CLIBIMPL_DECLARE_CONVERSION(nnosTimerToWaitObject, nnosTimer, nnosWaitObject);
256 NN_UTIL_DETAIL_CLIBIMPL_DECLARE_CONVERSION(nnosWaitObjectToTimer, nnosWaitObject, nnosTimer);
257 
258 
259 /*!
260   @brief 対応する C++ 関数 @ref nn::os::Timer::Initialize を参照してください。
261 */
262 NN_EXTERN_C void nnosTimerInitialize(nnosTimer* this_, bool isManualReset);
263 
264 /*!
265   @brief 対応する C++ 関数 @ref nn::os::Timer::TryInitialize を参照してください。
266 */
267 NN_EXTERN_C bool nnosTimerTryInitialize(nnosTimer* this_, bool isManualReset);
268 
269 /*!
270   @brief 対応する C++ 関数 @ref nn::os::Timer::StartPeriodic を参照してください。
271 */
272 NN_EXTERN_C void nnosTimerStartPeriodic(nnosTimer* this_, s64 first, s64 interval);
273 
274 /*!
275   @brief 対応する C++ 関数 @ref nn::os::Timer::StartOneShot を参照してください。
276 */
277 NN_EXTERN_C void nnosTimerStartOneShot(nnosTimer* this_, s64 time);
278 
279 /*!
280   @brief 対応する C++ 関数 @ref nn::os::Timer::Wait を参照してください。
281 */
282 NN_EXTERN_C void nnosTimerWait(nnosTimer* this_);
283 
284 /*!
285   @brief 対応する C++ 関数 @ref nn::os::Timer::Stop を参照してください。
286 */
287 NN_EXTERN_C void nnosTimerStop(nnosTimer* this_);
288 
289 /*!
290   @brief 対応する C++ 関数 @ref nn::os::Timer::ClearSignal を参照してください。
291 */
292 NN_EXTERN_C void nnosTimerClearSignal(nnosTimer* this_);
293 
294 /*!
295   @brief 対応する C++ 関数 @ref nn::os::Timer::Finalize を参照してください。
296 */
297 NN_EXTERN_C void nnosTimerFinalize(nnosTimer* this_);
298 
299 /*!
300   @brief 対応する C++ 関数 @ref nn::os::Timer::Signal を参照してください。
301 */
302 NN_EXTERN_C void nnosTimerSignal(nnosTimer* this_);
303 
304 /*!
305   @}
306 
307   @}
308 */
309 
310 #endif
311 
312