1 // 2 // time_t_timer.cpp 3 // ~~~~~~~~~~~~~~~~ 4 // 5 // Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) 6 // 7 // Distributed under the Boost Software License, Version 1.0. (See accompanying 8 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 9 // 10 11 #include <boost/asio.hpp> 12 #include <ctime> 13 #include <iostream> 14 15 // A custom implementation of the Clock concept from the standard C++ library. 16 struct time_t_clock 17 { 18 // The duration type. 19 typedef boost::asio::chrono::steady_clock::duration duration; 20 21 // The duration's underlying arithmetic representation. 22 typedef duration::rep rep; 23 24 // The ratio representing the duration's tick period. 25 typedef duration::period period; 26 27 // An absolute time point represented using the clock. 28 typedef boost::asio::chrono::time_point<time_t_clock> time_point; 29 30 // The clock is not monotonically increasing. 31 static const bool is_steady = false; 32 33 // Get the current time. nowtime_t_clock34 static time_point now() 35 { 36 return time_point() + boost::asio::chrono::seconds(std::time(0)); 37 } 38 }; 39 40 // The boost::asio::basic_waitable_timer template accepts an optional WaitTraits 41 // template parameter. The underlying time_t clock has one-second granularity, 42 // so these traits may be customised to reduce the latency between the clock 43 // ticking over and a wait operation's completion. When the timeout is near 44 // (less than one second away) we poll the clock more frequently to detect the 45 // time change closer to when it occurs. The user can select the appropriate 46 // trade off between accuracy and the increased CPU cost of polling. In extreme 47 // cases, a zero duration may be returned to make the timers as accurate as 48 // possible, albeit with 100% CPU usage. 49 struct time_t_wait_traits 50 { 51 // Determine how long until the clock should be next polled to determine 52 // whether the duration has elapsed. to_wait_durationtime_t_wait_traits53 static time_t_clock::duration to_wait_duration( 54 const time_t_clock::duration& d) 55 { 56 if (d > boost::asio::chrono::seconds(1)) 57 return d - boost::asio::chrono::seconds(1); 58 else if (d > boost::asio::chrono::seconds(0)) 59 return boost::asio::chrono::milliseconds(10); 60 else 61 return boost::asio::chrono::seconds(0); 62 } 63 64 // Determine how long until the clock should be next polled to determine 65 // whether the absoluate time has been reached. to_wait_durationtime_t_wait_traits66 static time_t_clock::duration to_wait_duration( 67 const time_t_clock::time_point& t) 68 { 69 return to_wait_duration(t - time_t_clock::now()); 70 } 71 }; 72 73 typedef boost::asio::basic_waitable_timer< 74 time_t_clock, time_t_wait_traits> time_t_timer; 75 handle_timeout(const boost::system::error_code &)76void handle_timeout(const boost::system::error_code&) 77 { 78 std::cout << "handle_timeout\n"; 79 } 80 main()81int main() 82 { 83 try 84 { 85 boost::asio::io_context io_context; 86 87 time_t_timer timer(io_context); 88 89 timer.expires_after(boost::asio::chrono::seconds(5)); 90 std::cout << "Starting synchronous wait\n"; 91 timer.wait(); 92 std::cout << "Finished synchronous wait\n"; 93 94 timer.expires_after(boost::asio::chrono::seconds(5)); 95 std::cout << "Starting asynchronous wait\n"; 96 timer.async_wait(&handle_timeout); 97 io_context.run(); 98 std::cout << "Finished asynchronous wait\n"; 99 } 100 catch (std::exception& e) 101 { 102 std::cout << "Exception: " << e.what() << "\n"; 103 } 104 105 return 0; 106 } 107