#ifndef TIMER_HPP_
#define TIMER_HPP_
#include "openthread-core-config.h"
#include <stddef.h>
#include <stdint.h>
#include <openthread/platform/alarm-micro.h>
#include <openthread/platform/alarm-milli.h>
#include "common/debug.hpp"
#include "common/linked_list.hpp"
#include "common/locator.hpp"
#include "common/non_copyable.hpp"
#include "common/tasklet.hpp"
#include "common/time.hpp"
namespace ot {
class TimerMilliScheduler;
class Timer : public InstanceLocator, public OwnerLocator, public LinkedListEntry<Timer>
{
friend class TimerScheduler;
friend class LinkedListEntry<Timer>;
public:
static const uint32_t kMaxDelay = (Time::kMaxDuration >> 1);
typedef void (*Handler)(Timer &aTimer);
Timer(Instance &aInstance, Handler aHandler, void *aOwner)
: InstanceLocator(aInstance)
, OwnerLocator(aOwner)
, mHandler(aHandler)
, mFireTime()
, mNext(this)
{
}
Time GetFireTime(void) const { return mFireTime; }
bool IsRunning(void) const { return (mNext != this); }
protected:
bool DoesFireBefore(const Timer &aSecondTimer, Time aNow);
void Fired(void) { mHandler(*this); }
Handler mHandler;
Time mFireTime;
Timer * mNext;
};
class TimerMilli : public Timer
{
public:
TimerMilli(Instance &aInstance, Handler aHandler, void *aOwner)
: Timer(aInstance, aHandler, aOwner)
{
}
void Start(uint32_t aDelay);
void StartAt(TimeMilli sStartTime, uint32_t aDelay);
void FireAt(TimeMilli aFireTime);
void FireAtIfEarlier(TimeMilli aFireTime);
void Stop(void);
static TimeMilli GetNow(void) { return TimeMilli(otPlatAlarmMilliGetNow()); }
};
class TimerMilliContext : public TimerMilli
{
public:
TimerMilliContext(Instance &aInstance, Handler aHandler, void *aContext)
: TimerMilli(aInstance, aHandler, aContext)
, mContext(aContext)
{
}
void *GetContext(void) { return mContext; }
private:
void *mContext;
};
class TimerScheduler : public InstanceLocator, private NonCopyable
{
friend class Timer;
protected:
struct AlarmApi
{
void (*AlarmStartAt)(otInstance *aInstance, uint32_t aT0, uint32_t aDt);
void (*AlarmStop)(otInstance *aInstance);
uint32_t (*AlarmGetNow)(void);
};
explicit TimerScheduler(Instance &aInstance)
: InstanceLocator(aInstance)
, mTimerList()
{
}
void Add(Timer &aTimer, const AlarmApi &aAlarmApi);
void Remove(Timer &aTimer, const AlarmApi &aAlarmApi);
void ProcessTimers(const AlarmApi &aAlarmApi);
void SetAlarm(const AlarmApi &aAlarmApi);
LinkedList<Timer> mTimerList;
};
class TimerMilliScheduler : public TimerScheduler
{
public:
explicit TimerMilliScheduler(Instance &aInstance)
: TimerScheduler(aInstance)
{
}
void Add(TimerMilli &aTimer) { TimerScheduler::Add(aTimer, sAlarmMilliApi); }
void Remove(TimerMilli &aTimer) { TimerScheduler::Remove(aTimer, sAlarmMilliApi); }
void ProcessTimers(void) { TimerScheduler::ProcessTimers(sAlarmMilliApi); }
private:
static const AlarmApi sAlarmMilliApi;
};
#if OPENTHREAD_CONFIG_PLATFORM_USEC_TIMER_ENABLE
class TimerMicroScheduler;
class TimerMicro : public Timer
{
public:
TimerMicro(Instance &aInstance, Handler aHandler, void *aOwner)
: Timer(aInstance, aHandler, aOwner)
{
}
void Start(uint32_t aDelay);
void StartAt(TimeMicro aStartTime, uint32_t aDelay);
void FireAt(TimeMicro aFireTime);
void Stop(void);
static TimeMicro GetNow(void) { return Time(otPlatAlarmMicroGetNow()); }
};
class TimerMicroScheduler : public TimerScheduler
{
public:
TimerMicroScheduler(Instance &aInstance)
: TimerScheduler(aInstance)
{
}
void Add(TimerMicro &aTimer) { TimerScheduler::Add(aTimer, sAlarmMicroApi); }
void Remove(TimerMicro &aTimer) { TimerScheduler::Remove(aTimer, sAlarmMicroApi); }
void ProcessTimers(void) { TimerScheduler::ProcessTimers(sAlarmMicroApi); }
private:
static const AlarmApi sAlarmMicroApi;
};
#endif
}
#endif