基于boost asio实现的定时器,包括一次性定时器、循环定时器、带开始时间的循环定时器
#pragma once
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/date_time.hpp>
#include <iostream>
using TimerCallbackFuncT = std::function<void()>;
template <bool Periodic>
class Timer
{
public:
Timer(boost::asio::io_context& io, int interval, TimerCallbackFuncT callback)
: m_interval(interval)
, m_timer(io, m_interval)
, m_callback(callback)
, m_periodic(Periodic)
{
}
~Timer() { m_timer.cancel(); }
void Start() { m_running = true; AsyncWait(); }
void Stop()
{
m_running = false;
m_timer.cancel();
}
void Reset(int interval)
{
boost::posix_time::seconds intv(interval);
m_timer.expires_from_now(intv);
}
std::string ExpiresAt()
{
auto dt = m_timer.expires_at();
boost::local_time::time_zone_ptr zone(new boost::local_time::posix_time_zone("EST+08:00:00"));
boost::local_time::local_date_time dt_with_zone(dt, zone);
std::stringstream strm;
strm.imbue(std::locale(std::cout.getloc(), new boost::local_time::local_time_facet("%Y-%m-%d %H:%M:%S UTC%Q")));
strm << dt_with_zone;
// std::cout << "timer: " << strm.str() << std::endl;
return strm.str();
}
private:
void AsyncWait() { m_timer.async_wait(boost::bind(&Timer::Hook, this, boost::asio::placeholders::error)); }
void Hook(const boost::system::error_code& ec)
{
if (ec)
{
std::cout << "Timer error_code:(" << ec.value() << ") " << ec.message() << std::endl;
}
else if (m_callback)
{
m_callback();
}
if (m_periodic && m_running)
{
m_timer.expires_from_now(m_interval);
// m_timer.expires_at(m_timer.expires_at() + m_interval);
AsyncWait();
}
}
private:
// boost::asio::io_context& m_io_context;
boost::posix_time::seconds m_interval;
boost::asio::deadline_timer m_timer;
TimerCallbackFuncT m_callback;
bool m_periodic;
std::atomic<bool> m_running{false};
};
using PeriodicTimer = Timer<true>;
using OnceTimer = Timer<false>;
class PeriodicWithStartTimer
{
public:
PeriodicWithStartTimer(boost::asio::io_context& io, int interval, int start, TimerCallbackFuncT callback)
: m_ptimer(io, interval, callback)
, m_otimer(io, start, std::bind(&PeriodicWithStartTimer::OnStart, this))
, m_interval(interval)
{
}
void Start() { m_otimer.Start(); }
void Stop()
{
m_otimer.Stop();
m_ptimer.Stop();
}
std::string ExpiresAt()
{
std::stringstream ss;
ss << "[" << m_otimer.ExpiresAt() << "][" << m_ptimer.ExpiresAt() << "]";
return ss.str();
}
private:
void OnStart()
{
m_ptimer.Reset(m_interval);
m_ptimer.Start();
}
PeriodicTimer m_ptimer;
OnceTimer m_otimer;
int m_interval;
};