Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #pragma once
- #include <tuple>
- #include <mutex>
- #include <utility>
- #include <functional>
- #include <boost/asio.hpp>
- namespace stdex{
- // ************************************************************************** //
- // ************** data::index_sequence ************** //
- // ************************************************************************** //
- template <std::size_t... Ns>
- struct index_sequence {};
- template<typename IS1, typename IS2>
- struct merge_index_sequence;
- template <std::size_t... Ns1, std::size_t... Ns2>
- struct merge_index_sequence<index_sequence<Ns1...>, index_sequence<Ns2...>> {
- typedef index_sequence<Ns1..., Ns2...> type;
- };
- template <std::size_t B, std::size_t E, typename Enabler = void>
- struct make_index_sequence {
- typedef typename merge_index_sequence<typename make_index_sequence<B,(B+E)/2>::type,
- typename make_index_sequence<(B+E)/2,E>::type>::type type;
- };
- template <std::size_t B, std::size_t E>
- struct make_index_sequence<B,E,typename std::enable_if<E==B+1,void>::type> {
- typedef index_sequence<B> type;
- };
- template <typename... T>
- using index_sequence_for = typename make_index_sequence<0, sizeof...(T)>::type;
- }
- 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...);
- }
- //The helper method.
- template<std::size_t... Is>
- void call_handler_with_tuple(boost::system::error_code ec, const std::tuple<T...>& tuple, stdex::index_sequence<Is...>)
- {
- m_handler(ec, std::get<Is>(tuple)...);
- }
- void m_handler_with_values(boost::system::error_code ec)
- {
- call_handler_with_tuple(ec, tuple_, stdex::index_sequence_for<T...>());
- }
- 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([this](){
- m_handler_with_values(boost::asio::error::make_error_code(boost::asio::error::interrupted));
- });
- 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([this](){
- m_handler_with_values(boost::asio::error::make_error_code(boost::asio::error::interrupted));
- });
- 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;
- m_handler_with_values(boost::asio::error::make_error_code(boost::asio::error::interrupted));
- }
- 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;
- std::tuple<T...> tuple_;
- };
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement