• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 &)76 void handle_timeout(const boost::system::error_code&)
77 {
78   std::cout << "handle_timeout\n";
79 }
80 
main()81 int 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