• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  Copyright (c) 2016, The OpenThread Authors.
3  *  All rights reserved.
4  *
5  *  Redistribution and use in source and binary forms, with or without
6  *  modification, are permitted provided that the following conditions are met:
7  *  1. Redistributions of source code must retain the above copyright
8  *     notice, this list of conditions and the following disclaimer.
9  *  2. Redistributions in binary form must reproduce the above copyright
10  *     notice, this list of conditions and the following disclaimer in the
11  *     documentation and/or other materials provided with the distribution.
12  *  3. Neither the name of the copyright holder nor the
13  *     names of its contributors may be used to endorse or promote products
14  *     derived from this software without specific prior written permission.
15  *
16  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17  *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20  *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23  *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24  *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25  *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26  *  POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 /**
30  * @file
31  *   This file includes definitions for the multiplexed timer service.
32  */
33 
34 #ifndef TIMER_HPP_
35 #define TIMER_HPP_
36 
37 #include "openthread-core-config.h"
38 
39 #include <stddef.h>
40 #include <stdint.h>
41 
42 #include <openthread/platform/alarm-micro.h>
43 #include <openthread/platform/alarm-milli.h>
44 
45 #include "common/debug.hpp"
46 #include "common/linked_list.hpp"
47 #include "common/locator.hpp"
48 #include "common/non_copyable.hpp"
49 #include "common/tasklet.hpp"
50 #include "common/time.hpp"
51 
52 namespace ot {
53 
54 /**
55  * @addtogroup core-timer
56  *
57  * @brief
58  *   This module includes definitions for the multiplexed timer service.
59  *
60  * @{
61  *
62  */
63 
64 /**
65  * This class implements a timer.
66  *
67  */
68 class Timer : public InstanceLocator, public LinkedListEntry<Timer>
69 {
70     friend class LinkedListEntry<Timer>;
71 
72 public:
73     /**
74      * This constant defines maximum delay allowed when starting a timer.
75      *
76      */
77     static const uint32_t kMaxDelay = (Time::kMaxDuration >> 1);
78 
79     /**
80      * This type defines a function reference which is invoked when the timer expires.
81      *
82      * @param[in]  aTimer    A reference to the expired timer instance.
83      *
84      */
85     typedef void (&Handler)(Timer &aTimer);
86 
87     /**
88      * This method returns the fire time of the timer.
89      *
90      * @returns The fire time.
91      *
92      */
GetFireTime(void) const93     Time GetFireTime(void) const { return mFireTime; }
94 
95     /**
96      * This method indicates whether or not the timer instance is running.
97      *
98      * @retval TRUE   If the timer is running.
99      * @retval FALSE  If the timer is not running.
100      *
101      */
IsRunning(void) const102     bool IsRunning(void) const { return (mNext != this); }
103 
104 protected:
105     class Scheduler : public InstanceLocator, private NonCopyable
106     {
107         friend class Timer;
108 
109     protected:
110         struct AlarmApi
111         {
112             void (*AlarmStartAt)(otInstance *aInstance, uint32_t aT0, uint32_t aDt);
113             void (*AlarmStop)(otInstance *aInstance);
114             uint32_t (*AlarmGetNow)(void);
115         };
116 
Scheduler(Instance & aInstance)117         explicit Scheduler(Instance &aInstance)
118             : InstanceLocator(aInstance)
119         {
120         }
121 
122         void Add(Timer &aTimer, const AlarmApi &aAlarmApi);
123         void Remove(Timer &aTimer, const AlarmApi &aAlarmApi);
124         void RemoveAll(const AlarmApi &aAlarmApi);
125         void ProcessTimers(const AlarmApi &aAlarmApi);
126         void SetAlarm(const AlarmApi &aAlarmApi);
127 
128         LinkedList<Timer> mTimerList;
129     };
130 
Timer(Instance & aInstance,Handler aHandler)131     Timer(Instance &aInstance, Handler aHandler)
132         : InstanceLocator(aInstance)
133         , mHandler(aHandler)
134         , mNext(this)
135     {
136     }
137 
138     bool DoesFireBefore(const Timer &aSecondTimer, Time aNow) const;
Fired(void)139     void Fired(void) { mHandler(*this); }
140 
141     Handler mHandler;
142     Time    mFireTime;
143     Timer * mNext;
144 };
145 
146 extern "C" void otPlatAlarmMilliFired(otInstance *aInstance);
147 
148 /**
149  * This class implements the millisecond timer.
150  *
151  */
152 class TimerMilli : public Timer
153 {
154 public:
155     /**
156      * This class implements the millisecond timer scheduler.
157      *
158      */
159     class Scheduler : private Timer::Scheduler
160     {
161         friend class TimerMilli;
162         friend void otPlatAlarmMilliFired(otInstance *aInstance);
163 
164     public:
165         /**
166          * This constructor initializes the object.
167          *
168          * @param[in]  aInstance  A reference to the instance object.
169          *
170          */
Scheduler(Instance & aInstance)171         explicit Scheduler(Instance &aInstance)
172             : Timer::Scheduler(aInstance)
173         {
174         }
175 
176     private:
Add(TimerMilli & aTimer)177         void Add(TimerMilli &aTimer) { Timer::Scheduler::Add(aTimer, sAlarmMilliApi); }
Remove(TimerMilli & aTimer)178         void Remove(TimerMilli &aTimer) { Timer::Scheduler::Remove(aTimer, sAlarmMilliApi); }
RemoveAll(void)179         void RemoveAll(void) { Timer::Scheduler::RemoveAll(sAlarmMilliApi); }
ProcessTimers(void)180         void ProcessTimers(void) { Timer::Scheduler::ProcessTimers(sAlarmMilliApi); }
181 
182         static const AlarmApi sAlarmMilliApi;
183     };
184 
185     /**
186      * This constructor creates a millisecond timer instance.
187      *
188      * @param[in]  aInstance   A reference to the OpenThread instance.
189      * @param[in]  aHandler    A pointer to a function that is called when the timer expires.
190      *
191      */
TimerMilli(Instance & aInstance,Handler aHandler)192     TimerMilli(Instance &aInstance, Handler aHandler)
193         : Timer(aInstance, aHandler)
194     {
195     }
196 
197     /**
198      * This method schedules the timer to fire after a given delay (in milliseconds) from now.
199      *
200      * @param[in]  aDelay   The delay in milliseconds. It must not be longer than `kMaxDelay`.
201      *
202      */
203     void Start(uint32_t aDelay);
204 
205     /**
206      * This method schedules the timer to fire after a given delay (in milliseconds) from a given start time.
207      *
208      * @param[in]  aStartTime  The start time.
209      * @param[in]  aDelay      The delay in milliseconds. It must not be longer than `kMaxDelay`.
210      *
211      */
212     void StartAt(TimeMilli aStartTime, uint32_t aDelay);
213 
214     /**
215      * This method schedules the timer to fire at a given fire time.
216      *
217      * @param[in]  aFireTime  The fire time.
218      *
219      */
220     void FireAt(TimeMilli aFireTime);
221 
222     /**
223      * This method (re-)schedules the timer with a given a fire time only if the timer is not running or the new given
224      * fire time is earlier than the current fire time.
225      *
226      * @param[in]  aFireTime  The fire time.
227      *
228      */
229     void FireAtIfEarlier(TimeMilli aFireTime);
230 
231     /**
232      * This method stops the timer.
233      *
234      */
235     void Stop(void);
236 
237     /**
238      * This static method returns the current time in milliseconds.
239      *
240      * @returns The current time in milliseconds.
241      *
242      */
GetNow(void)243     static TimeMilli GetNow(void) { return TimeMilli(otPlatAlarmMilliGetNow()); }
244 
245 protected:
246     static void RemoveAll(Instance &aInstance);
247 };
248 
249 /**
250  * This class implements a millisecond timer that also maintains a user context pointer.
251  *
252  * In typical `TimerMilli`/`TimerMicro` use, in the timer callback handler, the owner of the timer is determined using
253  * `GetOwner<Type>` method. This method works if there is a single instance of `Type` within OpenThread instance
254  * hierarchy. The `TimerMilliContext` is intended for cases where there may be multiple instances of the same class/type
255  * using a timer object. `TimerMilliContext` will store a context `void *` information.
256  *
257  */
258 class TimerMilliContext : public TimerMilli
259 {
260 public:
261     /**
262      * This constructor creates a millisecond timer that also maintains a user context pointer.
263      *
264      * @param[in]  aInstance   A reference to the OpenThread instance.
265      * @param[in]  aHandler    A pointer to a function that is called when the timer expires.
266      * @param[in]  aContext    A pointer to an arbitrary context information.
267      *
268      */
TimerMilliContext(Instance & aInstance,Handler aHandler,void * aContext)269     TimerMilliContext(Instance &aInstance, Handler aHandler, void *aContext)
270         : TimerMilli(aInstance, aHandler)
271         , mContext(aContext)
272     {
273     }
274 
275     /**
276      * This method returns the pointer to the arbitrary context information.
277      *
278      * @returns Pointer to the arbitrary context information.
279      *
280      */
GetContext(void)281     void *GetContext(void) { return mContext; }
282 
283 private:
284     void *mContext;
285 };
286 
287 #if OPENTHREAD_CONFIG_PLATFORM_USEC_TIMER_ENABLE
288 
289 extern "C" void otPlatAlarmMicroFired(otInstance *aInstance);
290 
291 /**
292  * This class implements the microsecond timer.
293  *
294  */
295 class TimerMicro : public Timer
296 {
297 public:
298     /**
299      * This class implements the microsecond timer scheduler.
300      *
301      */
302     class Scheduler : private Timer::Scheduler
303     {
304         friend class TimerMicro;
305         friend void otPlatAlarmMicroFired(otInstance *aInstance);
306 
307     public:
308         /**
309          * This constructor initializes the object.
310          *
311          * @param[in]  aInstance  A reference to the instance object.
312          *
313          */
Scheduler(Instance & aInstance)314         explicit Scheduler(Instance &aInstance)
315             : Timer::Scheduler(aInstance)
316         {
317         }
318 
319     private:
Add(TimerMicro & aTimer)320         void Add(TimerMicro &aTimer) { Timer::Scheduler::Add(aTimer, sAlarmMicroApi); }
Remove(TimerMicro & aTimer)321         void Remove(TimerMicro &aTimer) { Timer::Scheduler::Remove(aTimer, sAlarmMicroApi); }
RemoveAll(void)322         void RemoveAll(void) { Timer::Scheduler::RemoveAll(sAlarmMicroApi); }
ProcessTimers(void)323         void ProcessTimers(void) { Timer::Scheduler::ProcessTimers(sAlarmMicroApi); }
324 
325         static const AlarmApi sAlarmMicroApi;
326     };
327 
328     /**
329      * This constructor creates a timer instance.
330      *
331      * @param[in]  aInstance   A reference to the OpenThread instance.
332      * @param[in]  aHandler    A pointer to a function that is called when the timer expires.
333      *
334      */
TimerMicro(Instance & aInstance,Handler aHandler)335     TimerMicro(Instance &aInstance, Handler aHandler)
336         : Timer(aInstance, aHandler)
337     {
338     }
339 
340     /**
341      * This method schedules the timer to fire after a given delay (in microseconds) from now.
342      *
343      * @param[in]  aDelay   The delay in microseconds. It must not be be longer than `kMaxDelay`.
344      *
345      */
346     void Start(uint32_t aDelay);
347 
348     /**
349      * This method schedules the timer to fire after a given delay (in microseconds) from a given start time.
350      *
351      * @param[in]  aStartTime  The start time.
352      * @param[in]  aDelay      The delay in microseconds. It must not be longer than `kMaxDelay`.
353      *
354      */
355     void StartAt(TimeMicro aStartTime, uint32_t aDelay);
356 
357     /**
358      * This method schedules the timer to fire at a given fire time.
359      *
360      * @param[in]  aFireTime  The fire time.
361      *
362      */
363     void FireAt(TimeMicro aFireTime);
364 
365     /**
366      * This method stops the timer.
367      *
368      */
369     void Stop(void);
370 
371     /**
372      * This static method returns the current time in microseconds.
373      *
374      * @returns The current time in microseconds.
375      *
376      */
GetNow(void)377     static TimeMicro GetNow(void) { return Time(otPlatAlarmMicroGetNow()); }
378 
379 protected:
380     static void RemoveAll(Instance &aInstance);
381 };
382 #endif // OPENTHREAD_CONFIG_PLATFORM_USEC_TIMER_ENABLE
383 
384 /**
385  * @}
386  *
387  */
388 
389 } // namespace ot
390 
391 #endif // TIMER_HPP_
392