Skip to content

Instantly share code, notes, and snippets.

@maddinat0r
Last active August 29, 2015 14:21
Show Gist options
  • Save maddinat0r/3855acf9350c0884ae34 to your computer and use it in GitHub Desktop.
Save maddinat0r/3855acf9350c0884ae34 to your computer and use it in GitHub Desktop.
basic timer system
#include <list>
#include <functional>
#include <memory>
#include <chrono>
using std::list;
using std::function;
namespace chrono = std::chrono;
#include "../Dawn/System/CSingleton.h"
using Timer_t = std::shared_ptr<class CTimer>;
using TimerInterval_t = chrono::milliseconds::rep;
using TimerFunction_t = function < void() >;
static const TimerInterval_t SleepIntervalMs = 1;
class CTimer
{
friend class CTimerManager;
public:
CTimer(const chrono::milliseconds &interval,
const bool &repeat, TimerFunction_t &&func) :
m_Interval(interval),
m_Repeat(repeat),
m_Function(std::forward<TimerFunction_t>(func)),
m_LastStart(chrono::steady_clock::now())
{ }
~CTimer() = default;
private:
TimerFunction_t m_Function;
chrono::milliseconds m_Interval;
bool m_Repeat;
chrono::steady_clock::time_point m_LastStart;
bool m_Killed = false;
private:
inline void CallFunction()
{
if (m_Function)
m_Function();
}
};
class CTimerManager : public CSingleton<CTimerManager>
{
friend class CSingleton<CTimerManager>;
private:
CTimerManager() = default;
~CTimerManager() = default;
private:
list<Timer_t> m_Timers;
public:
Timer_t Create(TimerInterval_t interval_num, bool repeat, TimerFunction_t &&func)
{
chrono::milliseconds interval(interval_num - SleepIntervalMs);
Timer_t timer = std::make_shared<CTimer>(
interval, repeat, std::forward<TimerFunction_t>(func));
auto i = m_Timers.begin();
do
{
/* we give timers with a smaller interval higher priority
* by inserting them before timers with longer intervals
* (or better said, we sort the container by interval, ascending)
*/
if (i == m_Timers.end() || interval <= (*i)->m_Interval)
{
m_Timers.insert(i, timer);
break;
}
} while (i++ != m_Timers.end());
return timer;
}
void Kill(Timer_t &timer)
{
for (auto i = m_Timers.begin(); i != m_Timers.end(); ++i)
{
if ((*i) != timer)
continue;
m_Timers.erase(i);
timer->m_Killed = true;
break;
}
}
void Process()
{
auto current_timepoint = chrono::steady_clock::now();
for (auto i = m_Timers.begin(); i != m_Timers.end(); ++i)
{
auto t = *i;
if ((current_timepoint - t->m_LastStart) < t->m_Interval)
continue;
t->CallFunction();
if (!t->m_Killed)
{
if (t->m_Repeat)
t->m_LastStart = current_timepoint;
else
i = m_Timers.erase(i);
}
if (i == m_Timers.end())
break;
}
}
};
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
int main()
{
Timer_t t1 = CTimerManager::Get()->Create(1000, true, []() {printf("t1!\n"); });
Timer_t t2 = CTimerManager::Get()->Create(5000, false, [=]() mutable
{
CTimerManager::Get()->Kill(t1);
printf("killed!\n");
});
while (true)
{
CTimerManager::Get()->Process();
Sleep(SleepIntervalMs);
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment