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