asio
asio was originally an independent network library, which was selected by boost and transformed into a part of boost library. The design principle is light inheritance and recombination.
It conforms to the consistent style of c++.
Base class: boost::asio::io_service Timer class: boost::asio::basic_waitable_timer Clock class: std::chrono::steady_clock
This paper is a part of the kademlia algorithm, which is well understood by annotations. No detailed explanation is prepared.
//timer.hpp #ifndef KADEMLIA_TIMER_HPP #define KADEMLIA_TIMER_HPP #ifdef _MSC_VER #pragma once #endif #include <map> #include <chrono> #include <functional> #include <boost/asio/io_service.hpp> #include <boost/asio/basic_waitable_timer.hpp> namespace kademlia { namespace detail { class timer final { public: using clock = std::chrono::steady_clock; using duration = clock::duration; public: explicit timer( boost::asio::io_service & io_service); template < typename Callback > void expires_from_now(duration const & timeout, Callback const & on_timer_expired); private: using time_point = clock::time_point; using callback = std::function < void ( void ) >; using timeouts = std::multimap < time_point, callback >; using deadline_timer = boost::asio::basic_waitable_timer < clock >; private: void schedule_next_tick(time_point const & expiration_time); private: deadline_timer timer_; // asio timer timeouts timeouts_; // Timing task map, sorted from small to large }; // Register a business with the timer. The execution point is current time + timeout, and the execution function is on_timer_expired. template < typename Callback > void timer::expires_from_now(duration const & timeout, Callback const & on_timer_expired) { auto expiration_time = clock::now() + timeout; // If the current expiration time will be the sooner to expires // then cancel any pending wait and schedule this one instead. // If the timer map is empty or the timer is the latest, then use the timer to update the asio timer and add the timer to the timer map. if (timeouts_.empty() || expiration_time < timeouts_.begin()->first) schedule_next_tick(expiration_time); timeouts_.emplace(expiration_time, on_timer_expired); } } } #endif
//timer.cpp #include "kademlia/timer.hpp" #include "kademlia/error_impl.hpp" #include "kademlia/log.hpp" namespace kademlia { namespace detail { // To construct an ASIO timer, io_service is the base class of asio, and any object needs to be embedded in it. The general usage is specified when an object is constructed. timer::timer(boost::asio::io_service & io_service): timer_ {io_service}, timeouts_ {} { } void timer::schedule_next_tick(time_point const & expiration_time) { // This will cancel any pending task. // Setting timeout point timer_.expires_at(expiration_time); LOG_DEBUG(timer, this) << "schedule callback at " << expiration_time.time_since_epoch().count() << "." << std::endl; auto on_fire =[this] (boost::system::error_code const & failure) { // The current timeout has been canceled // hence stop right there. if (failure == boost::asio::error::operation_aborted) return; if (failure) throw std::system_error { make_error_code(TIMER_MALFUNCTION) }; // The callbacks to execute are the first // n callbacks with the same keys. auto begin = timeouts_.begin(); auto end = timeouts_.upper_bound(begin->first); // Call the user callbacks. Perform timing services for (auto i = begin; i != end; ++i) i->second(); LOG_DEBUG(timer, this) << "remove " << std::distance(begin, end) << " callback(s) scheduled at " << begin->first.time_since_epoch().count() << "." << std::endl; // And remove the timeout. timeouts_.erase(begin, end); // If there is a remaining timeout, schedule it. if (!timeouts_.empty()) { LOG_DEBUG(timer, this) << "schedule remaining timers" << std::endl; schedule_next_tick(timeouts_.begin()->first); } }; // Executing timeout tasks when asynchronous, timeout point arrives timer_.async_wait(on_fire); } } }
All objects of asio provide two versions of sync and async. The async used in this article is very convenient for timer update or scheduling because it is asynchronous.
As for the use of asio, csdn has a lot on it, but at the very most, it's the same level, so it doesn't repeat wheels.