Skip to content

Instantly share code, notes, and snippets.

@microcai
Created January 6, 2017 06:00
Show Gist options
  • Save microcai/5a13b0d8aeb21908e5f893abeffdbc7d to your computer and use it in GitHub Desktop.
Save microcai/5a13b0d8aeb21908e5f893abeffdbc7d to your computer and use it in GitHub Desktop.
#pragma once
#include <mutex>
#include <functional>
#include <boost/asio.hpp>
template<typename TimerType, typename T>
class smart_timer
{
public:
explicit smart_timer(boost::asio::io_service& io)
: io(io)
, m_timer(io)
{}
template<typename... TT>
void expires_from_now(TT... arg)
{
m_timer.expires_from_now(arg...);
}
template<typename Handler>
void async_wait(BOOST_ASIO_MOVE_ARG(Handler) handler)
{
std::unique_lock<std::mutex> l(m);
if (no_wait)
{
no_wait = false;
io.post(boost::asio::detail::bind_handler(handler, boost::asio::error::make_error_code(boost::asio::error::operation_aborted), T()));
return;
}
m_handler = handler;
handler_set = true;
m_timer.async_wait(std::bind(&smart_timer::handle_timer, this, std::placeholders::_1));
}
void wake_up(T arg)
{
std::unique_lock<std::mutex> l(m);
if (handler_set)
{
handler_set = false;
io.post(boost::asio::detail::bind_handler(m_handler, boost::asio::error::make_error_code(boost::asio::error::operation_aborted), arg));
boost::system::error_code ignore;
m_timer.cancel(ignore);
}
else
no_wait = true;
}
private:
void handle_timer(boost::system::error_code ec)
{
std::unique_lock<std::mutex> l(m);
if (ec == boost::asio::error::operation_aborted)
{
// check for wake_up parameter.
return;
}
handler_set = false;
io.post(boost::asio::detail::bind_handler(m_handler, boost::asio::error::make_error_code(boost::asio::error::interrupted), T()));
}
private:
boost::asio::io_service& io;
TimerType m_timer;
bool handler_set = false;
bool no_wait = false;
std::function<void(boost::system::error_code ec, T)> m_handler;
std::mutex m;
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment