• 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  * Represents an object tracking the next fire time along with the current time (now).
65  */
66 class NextFireTime
67 {
68 public:
69     /**
70      * Initializes the `NextFireTime` with a given current time.
71      *
72      * @pram[in] aNow    The current time.
73      */
74     explicit NextFireTime(Time aNow);
75 
76     /**
77      * Initializes the `NextFireTime` using `TimerMilli::GetNow()` for current time.
78      */
79     NextFireTime(void);
80 
81     /**
82      * Gets the current time (now) tracked by the `NextFireTime` object.
83      *
84      * @returns The current time.
85      */
GetNow(void) const86     Time GetNow(void) const { return mNow; }
87 
88     /**
89      * Updates the tracked next fire time with a new given time only if it is earlier.
90      *
91      * If the given @p aTime is in the past relative to the tracked `GetNow()`, the `GetNow()` time is used instead.
92      * This ensures that the next fire time is never scheduled before the current time.
93      *
94      * @param[in] aTime   The new time.
95      */
96     void UpdateIfEarlier(Time aTime);
97 
98     /**
99      * Updates the tracked next fire time with a new given time, but only if it is earlier than the current
100      * fire time and in the future relative to `GetNow()`.
101      *
102      * If the given @p aTime is not in the future relative to `GetNow()`, it is ignored. This is unlike
103      * `UpdateIfEarlier()`, which allows all `aTime` values, including ones that are in the past (where it uses
104      * `GetNow()`).
105      *
106      * This method can be used to track the next fire time among non-expired times, ensuring the tracked next fire time
107      * will be in the future relative to `GetNow()`.
108      *
109      * @param[in] aTime     The new time.
110      */
111     void UpdateIfEarlierAndInFuture(Time aTime);
112 
113     /**
114      * Indicates whether or not next fire time is set.
115      *
116      * @retval TRUE   The next fire time is set.
117      * @retval FALSE  The next fire time is not set.
118      */
IsSet(void) const119     bool IsSet(void) const { return (mNextTime != mNow.GetDistantFuture()); }
120 
121     /**
122      * Gets the next fire time.
123      *
124      * If the next fire time is not, `GetNow().GetDistantFuture()` will be returned.
125      *
126      * @returns The next fire time.
127      */
GetNextTime(void) const128     Time GetNextTime(void) const { return mNextTime; }
129 
130 private:
131     Time mNow;
132     Time mNextTime;
133 };
134 
135 /**
136  * Implements a timer.
137  */
138 class Timer : public InstanceLocator, public LinkedListEntry<Timer>
139 {
140     friend class LinkedListEntry<Timer>;
141 
142 public:
143     /**
144      * This constant defines maximum delay allowed when starting a timer.
145      */
146     static const uint32_t kMaxDelay = (Time::kMaxDuration >> 1);
147 
148     /**
149      * Defines a function reference which is invoked when the timer expires.
150      *
151      * @param[in]  aTimer    A reference to the expired timer instance.
152      */
153     typedef void (&Handler)(Timer &aTimer);
154 
155     /**
156      * Returns the fire time of the timer.
157      *
158      * @returns The fire time.
159      */
GetFireTime(void) const160     Time GetFireTime(void) const { return mFireTime; }
161 
162     /**
163      * Indicates whether or not the timer instance is running.
164      *
165      * @retval TRUE   If the timer is running.
166      * @retval FALSE  If the timer is not running.
167      */
IsRunning(void) const168     bool IsRunning(void) const { return (mNext != this); }
169 
170 protected:
171     class Scheduler : public InstanceLocator, private NonCopyable
172     {
173         friend class Timer;
174 
175     protected:
176         struct AlarmApi
177         {
178             void (*AlarmStartAt)(otInstance *aInstance, uint32_t aT0, uint32_t aDt);
179             void (*AlarmStop)(otInstance *aInstance);
180             uint32_t (*AlarmGetNow)(void);
181         };
182 
Scheduler(Instance & aInstance)183         explicit Scheduler(Instance &aInstance)
184             : InstanceLocator(aInstance)
185         {
186         }
187 
188         void Add(Timer &aTimer, const AlarmApi &aAlarmApi);
189         void Remove(Timer &aTimer, const AlarmApi &aAlarmApi);
190         void RemoveAll(const AlarmApi &aAlarmApi);
191         void ProcessTimers(const AlarmApi &aAlarmApi);
192         void SetAlarm(const AlarmApi &aAlarmApi);
193 
194         LinkedList<Timer> mTimerList;
195     };
196 
Timer(Instance & aInstance,Handler aHandler)197     Timer(Instance &aInstance, Handler aHandler)
198         : InstanceLocator(aInstance)
199         , mHandler(aHandler)
200         , mNext(this)
201     {
202     }
203 
204     bool DoesFireBefore(const Timer &aSecondTimer, Time aNow) const;
Fired(void)205     void Fired(void) { mHandler(*this); }
206 
207     Handler mHandler;
208     Time    mFireTime;
209     Timer  *mNext;
210 };
211 
212 extern "C" void otPlatAlarmMilliFired(otInstance *aInstance);
213 
214 /**
215  * Implements the millisecond timer.
216  */
217 class TimerMilli : public Timer
218 {
219 public:
220     /**
221      * Implements the millisecond timer scheduler.
222      */
223     class Scheduler : private Timer::Scheduler
224     {
225         friend class TimerMilli;
226         friend void otPlatAlarmMilliFired(otInstance *aInstance);
227 
228     public:
229         /**
230          * Initializes the object.
231          *
232          * @param[in]  aInstance  A reference to the instance object.
233          */
Scheduler(Instance & aInstance)234         explicit Scheduler(Instance &aInstance)
235             : Timer::Scheduler(aInstance)
236         {
237         }
238 
239     private:
Add(TimerMilli & aTimer)240         void Add(TimerMilli &aTimer) { Timer::Scheduler::Add(aTimer, sAlarmMilliApi); }
Remove(TimerMilli & aTimer)241         void Remove(TimerMilli &aTimer) { Timer::Scheduler::Remove(aTimer, sAlarmMilliApi); }
RemoveAll(void)242         void RemoveAll(void) { Timer::Scheduler::RemoveAll(sAlarmMilliApi); }
ProcessTimers(void)243         void ProcessTimers(void) { Timer::Scheduler::ProcessTimers(sAlarmMilliApi); }
244 
245         static const AlarmApi sAlarmMilliApi;
246     };
247 
248     /**
249      * Creates a millisecond timer instance.
250      *
251      * @param[in]  aInstance   A reference to the OpenThread instance.
252      * @param[in]  aHandler    A pointer to a function that is called when the timer expires.
253      */
TimerMilli(Instance & aInstance,Handler aHandler)254     TimerMilli(Instance &aInstance, Handler aHandler)
255         : Timer(aInstance, aHandler)
256     {
257     }
258 
259     /**
260      * Schedules the timer to fire after a given delay (in milliseconds) from now.
261      *
262      * @param[in]  aDelay   The delay in milliseconds. It must not be longer than `kMaxDelay`.
263      */
264     void Start(uint32_t aDelay);
265 
266     /**
267      * Schedules the timer to fire after a given delay (in milliseconds) from a given start time.
268      *
269      * @param[in]  aStartTime  The start time.
270      * @param[in]  aDelay      The delay in milliseconds. It must not be longer than `kMaxDelay`.
271      */
272     void StartAt(TimeMilli aStartTime, uint32_t aDelay);
273 
274     /**
275      * Schedules the timer to fire at a given fire time.
276      *
277      * @param[in]  aFireTime  The fire time.
278      */
279     void FireAt(TimeMilli aFireTime);
280 
281     /**
282      * Schedules the timer to fire at a given fire time.
283      *
284      * Is @p aNextFireTime is not set, the timer is stopped.
285      *
286      * @param[in]  aNextFireTime  The fire time.
287      */
288     void FireAt(const NextFireTime &aNextFireTime);
289 
290     /**
291      * Re-schedules the timer with a given a fire time only if the timer is not running or the new given
292      * fire time is earlier than the current fire time.
293      *
294      * @param[in]  aFireTime  The fire time.
295      */
296     void FireAtIfEarlier(TimeMilli aFireTime);
297 
298     /**
299      * Re-schedules the timer with a given a fire time only if the timer is not running or the new given
300      * fire time is earlier than the current fire time.
301      *
302      * @param[in]  aNextFireTime  The fire time.
303      */
304     void FireAtIfEarlier(const NextFireTime &aNextFireTime);
305 
306     /**
307      * Stops the timer.
308      */
309     void Stop(void);
310 
311     /**
312      * Returns the current time in milliseconds.
313      *
314      * @returns The current time in milliseconds.
315      */
GetNow(void)316     static TimeMilli GetNow(void) { return TimeMilli(otPlatAlarmMilliGetNow()); }
317 
318 protected:
319     static void RemoveAll(Instance &aInstance);
320 };
321 
322 /**
323  * Defines a timer owned by a specific type and using a method on owner type as the callback.
324  *
325  * @tparam Owner              The type of the owner of this timer.
326  * @tparam HandleTimerPtr     A pointer to a non-static member method of `Owner` to use as timer handler.
327  *
328  * The `Owner` MUST be a type that is accessible using `InstanceLocator::Get<Owner>()`.
329  */
330 template <typename Owner, void (Owner::*HandleTimerPtr)(void)> class TimerMilliIn : public TimerMilli
331 {
332 public:
333     /**
334      * Initializes the timer.
335      *
336      * @param[in]  aInstance   The OpenThread instance.
337      */
TimerMilliIn(Instance & aInstance)338     explicit TimerMilliIn(Instance &aInstance)
339         : TimerMilli(aInstance, HandleTimer)
340     {
341     }
342 
343 private:
344     static void HandleTimer(Timer &aTimer); // Implemented in `instance.hpp`
345 };
346 
347 /**
348  * Implements a millisecond timer that also maintains a user context pointer.
349  *
350  * In typical `TimerMilli`/`TimerMicro` use, in the timer callback handler, the owner of the timer is determined using
351  * `GetOwner<Type>` method. This method works if there is a single instance of `Type` within OpenThread instance
352  * hierarchy. The `TimerMilliContext` is intended for cases where there may be multiple instances of the same class/type
353  * using a timer object. `TimerMilliContext` will store a context `void *` information.
354  */
355 class TimerMilliContext : public TimerMilli
356 {
357 public:
358     /**
359      * Creates a millisecond timer that also maintains a user context pointer.
360      *
361      * @param[in]  aInstance   A reference to the OpenThread instance.
362      * @param[in]  aHandler    A pointer to a function that is called when the timer expires.
363      * @param[in]  aContext    A pointer to an arbitrary context information.
364      */
TimerMilliContext(Instance & aInstance,Handler aHandler,void * aContext)365     TimerMilliContext(Instance &aInstance, Handler aHandler, void *aContext)
366         : TimerMilli(aInstance, aHandler)
367         , mContext(aContext)
368     {
369     }
370 
371     /**
372      * Returns the pointer to the arbitrary context information.
373      *
374      * @returns Pointer to the arbitrary context information.
375      */
GetContext(void)376     void *GetContext(void) { return mContext; }
377 
378 private:
379     void *mContext;
380 };
381 
382 #if OPENTHREAD_CONFIG_PLATFORM_USEC_TIMER_ENABLE
383 
384 extern "C" void otPlatAlarmMicroFired(otInstance *aInstance);
385 
386 /**
387  * Implements the microsecond timer.
388  */
389 class TimerMicro : public Timer
390 {
391 public:
392     /**
393      * Implements the microsecond timer scheduler.
394      */
395     class Scheduler : private Timer::Scheduler
396     {
397         friend class TimerMicro;
398         friend void otPlatAlarmMicroFired(otInstance *aInstance);
399 
400     public:
401         /**
402          * Initializes the object.
403          *
404          * @param[in]  aInstance  A reference to the instance object.
405          */
Scheduler(Instance & aInstance)406         explicit Scheduler(Instance &aInstance)
407             : Timer::Scheduler(aInstance)
408         {
409         }
410 
411     private:
Add(TimerMicro & aTimer)412         void Add(TimerMicro &aTimer) { Timer::Scheduler::Add(aTimer, sAlarmMicroApi); }
Remove(TimerMicro & aTimer)413         void Remove(TimerMicro &aTimer) { Timer::Scheduler::Remove(aTimer, sAlarmMicroApi); }
RemoveAll(void)414         void RemoveAll(void) { Timer::Scheduler::RemoveAll(sAlarmMicroApi); }
ProcessTimers(void)415         void ProcessTimers(void) { Timer::Scheduler::ProcessTimers(sAlarmMicroApi); }
416 
417         static const AlarmApi sAlarmMicroApi;
418     };
419 
420     /**
421      * Creates a timer instance.
422      *
423      * @param[in]  aInstance   A reference to the OpenThread instance.
424      * @param[in]  aHandler    A pointer to a function that is called when the timer expires.
425      */
TimerMicro(Instance & aInstance,Handler aHandler)426     TimerMicro(Instance &aInstance, Handler aHandler)
427         : Timer(aInstance, aHandler)
428     {
429     }
430 
431     /**
432      * Schedules the timer to fire after a given delay (in microseconds) from now.
433      *
434      * @param[in]  aDelay   The delay in microseconds. It must not be be longer than `kMaxDelay`.
435      */
436     void Start(uint32_t aDelay);
437 
438     /**
439      * Schedules the timer to fire after a given delay (in microseconds) from a given start time.
440      *
441      * @param[in]  aStartTime  The start time.
442      * @param[in]  aDelay      The delay in microseconds. It must not be longer than `kMaxDelay`.
443      */
444     void StartAt(TimeMicro aStartTime, uint32_t aDelay);
445 
446     /**
447      * Schedules the timer to fire at a given fire time.
448      *
449      * @param[in]  aFireTime  The fire time.
450      */
451     void FireAt(TimeMicro aFireTime);
452 
453     /**
454      * Stops the timer.
455      */
456     void Stop(void);
457 
458     /**
459      * Returns the current time in microseconds.
460      *
461      * @returns The current time in microseconds.
462      */
GetNow(void)463     static TimeMicro GetNow(void) { return Time(otPlatAlarmMicroGetNow()); }
464 
465 protected:
466     static void RemoveAll(Instance &aInstance);
467 };
468 
469 /**
470  * Defines a timer owned by a specific type and using a method on owner type as the callback.
471  *
472  * @tparam Owner              The type of the owner of this timer.
473  * @tparam HandleTimerPtr     A pointer to a non-static member method of `Owner` to use as timer handler.
474  *
475  * The `Owner` MUST be a type that is accessible using `InstanceLocator::Get<Owner>()`.
476  */
477 template <typename Owner, void (Owner::*HandleTimerPtr)(void)> class TimerMicroIn : public TimerMicro
478 {
479 public:
480     /**
481      * Initializes the timer.
482      *
483      * @param[in]  aInstance   The OpenThread instance.
484      */
TimerMicroIn(Instance & aInstance)485     explicit TimerMicroIn(Instance &aInstance)
486         : TimerMicro(aInstance, HandleTimer)
487     {
488     }
489 
490 private:
491     static void HandleTimer(Timer &aTimer); // Implemented in `instance.hpp`
492 };
493 
494 #endif // OPENTHREAD_CONFIG_PLATFORM_USEC_TIMER_ENABLE
495 
496 /**
497  * @}
498  */
499 
500 } // namespace ot
501 
502 #endif // TIMER_HPP_
503