158 lines
3.7 KiB
C++
158 lines
3.7 KiB
C++
#include "Jtk.h"
|
|
#include <vector>
|
|
#include <memory>
|
|
#include <list>
|
|
|
|
typedef struct
|
|
{
|
|
uint64_t next; /**< Time the timer next expires (us). */
|
|
uint64_t interval; /**< Timer interval (us). */
|
|
size_t id; /**< Timer ID. */
|
|
void * user[2]; /**< User data pointers. */
|
|
} Timer;
|
|
|
|
/** Vector used to allocate timer IDs. */
|
|
static std::vector<std::shared_ptr<Timer>> g_timers;
|
|
|
|
/** Linked list used to traverse all active timers. */
|
|
static std::list<std::shared_ptr<Timer>> g_active_timers;
|
|
|
|
static size_t AllocateTimerID()
|
|
{
|
|
for (size_t i = 0; i < g_timers.size(); i++)
|
|
{
|
|
if (!g_timers[i])
|
|
{
|
|
return i;
|
|
}
|
|
}
|
|
g_timers.push_back(nullptr);
|
|
return g_timers.size() - 1u;
|
|
}
|
|
|
|
/**
|
|
* Add a timer.
|
|
*
|
|
* @param delay
|
|
* Delay time in milliseconds.
|
|
* @param interval
|
|
* Interval time in milliseconds. A value of 0 indicates that the timer
|
|
* is not periodic.
|
|
* @param user1
|
|
* User data pointer 1. This value is not used by Jtk but can be retrieved by
|
|
* the user when a timer expires.
|
|
* @param user2
|
|
* User data pointer 2. This value is not used by Jtk but can be retrieved by
|
|
* the user when a timer expires.
|
|
*
|
|
* @return
|
|
* Timer ID.
|
|
*/
|
|
size_t Jtk_AddTimer(uint32_t delay, uint32_t interval, void * user1, void * user2)
|
|
{
|
|
uint64_t current_system_time = Jtk_UsTime();
|
|
size_t timer_id = AllocateTimerID();
|
|
auto timer = std::make_shared<Timer>();
|
|
timer->next = current_system_time + (delay * 1000u);
|
|
timer->interval = interval * 1000u;
|
|
timer->id = timer_id;
|
|
timer->user[0] = user1;
|
|
timer->user[1] = user2;
|
|
g_timers[timer_id] = timer;
|
|
g_active_timers.push_back(timer);
|
|
return timer_id;
|
|
}
|
|
|
|
/**
|
|
* Remove a timer.
|
|
*
|
|
* @param timer_id
|
|
* The ID of the timer to remove.
|
|
*/
|
|
void Jtk_RemoveTimer(size_t timer_id)
|
|
{
|
|
if (timer_id < g_timers.size())
|
|
{
|
|
auto timer = g_timers[timer_id];
|
|
g_active_timers.remove(timer);
|
|
g_timers[timer_id] = nullptr;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Determine the amount of time until the next timer expires (in us).
|
|
*
|
|
* @return
|
|
* Time (in us) until the next timer expires. This will be 0 if an active
|
|
* timer has already expired, and will be (uint64_t)-1 if there are no
|
|
* active timers.
|
|
*/
|
|
uint64_t Jtk_TimeToNextTimerExpiration()
|
|
{
|
|
uint64_t time = (uint64_t)-1;
|
|
uint64_t current_system_time = Jtk_UsTime();
|
|
for (auto & timer : g_active_timers)
|
|
{
|
|
if (timer->next <= current_system_time)
|
|
{
|
|
return 0;
|
|
}
|
|
uint64_t time_until_this_timer = timer->next - current_system_time;
|
|
if (time_until_this_timer < time)
|
|
{
|
|
time = time_until_this_timer;
|
|
}
|
|
}
|
|
return time;
|
|
}
|
|
|
|
/**
|
|
* Service a timer.
|
|
*
|
|
* This will increment the timer's next activation time by its interval, or
|
|
* for a timer with an interval of 0, will remove the timer.
|
|
*
|
|
* @param timer_id
|
|
* The ID of the timer to service.
|
|
*/
|
|
void Jtk_ServiceTimer(size_t timer_id)
|
|
{
|
|
auto timer = g_timers[timer_id];
|
|
if (timer->interval == 0u)
|
|
{
|
|
Jtk_RemoveTimer(timer_id);
|
|
}
|
|
else
|
|
{
|
|
timer->next += timer->interval;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Return the ID of an expired timer.
|
|
*
|
|
* @return
|
|
* The ID of an expired timer, or (size_t)-1 if no timer is expired.
|
|
*/
|
|
size_t Jtk_GetExpiredTimer()
|
|
{
|
|
uint64_t current_system_time = Jtk_UsTime();
|
|
for (auto & timer : g_active_timers)
|
|
{
|
|
if (timer->next <= current_system_time)
|
|
{
|
|
return timer->id;
|
|
}
|
|
}
|
|
return (size_t)-1;
|
|
}
|
|
|
|
void * Jtk_GetTimerUserData(size_t timer_id, uint8_t index)
|
|
{
|
|
if (timer_id < g_timers.size())
|
|
{
|
|
return g_timers[timer_id]->user[index];
|
|
}
|
|
return nullptr;
|
|
}
|