• 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 <chrono>
14 #include <iostream>
15 
16 // A custom implementation of the Clock concept from the standard C++ library.
17 struct time_t_clock
18 {
19   // The duration type.
20   typedef std::chrono::steady_clock::duration duration;
21 
22   // The duration's underlying arithmetic representation.
23   typedef duration::rep rep;
24 
25   // The ratio representing the duration's tick period.
26   typedef duration::period period;
27 
28   // An absolute time point represented using the clock.
29   typedef std::chrono::time_point<time_t_clock> time_point;
30 
31   // The clock is not monotonically increasing.
32   static constexpr bool is_steady = false;
33 
34   // Get the current time.
nowtime_t_clock35   static time_point now() noexcept
36   {
37     return time_point() + std::chrono::seconds(std::time(0));
38   }
39 };
40 
41 // The boost::asio::basic_waitable_timer template accepts an optional WaitTraits
42 // template parameter. The underlying time_t clock has one-second granularity,
43 // so these traits may be customised to reduce the latency between the clock
44 // ticking over and a wait operation's completion. When the timeout is near
45 // (less than one second away) we poll the clock more frequently to detect the
46 // time change closer to when it occurs. The user can select the appropriate
47 // trade off between accuracy and the increased CPU cost of polling. In extreme
48 // cases, a zero duration may be returned to make the timers as accurate as
49 // possible, albeit with 100% CPU usage.
50 struct time_t_wait_traits
51 {
52   // Determine how long until the clock should be next polled to determine
53   // whether the duration has elapsed.
to_wait_durationtime_t_wait_traits54   static time_t_clock::duration to_wait_duration(
55       const time_t_clock::duration& d)
56   {
57     if (d > std::chrono::seconds(1))
58       return d - std::chrono::seconds(1);
59     else if (d > std::chrono::seconds(0))
60       return std::chrono::milliseconds(10);
61     else
62       return std::chrono::seconds(0);
63   }
64 
65   // Determine how long until the clock should be next polled to determine
66   // whether the absoluate time has been reached.
to_wait_durationtime_t_wait_traits67   static time_t_clock::duration to_wait_duration(
68       const time_t_clock::time_point& t)
69   {
70     return to_wait_duration(t - time_t_clock::now());
71   }
72 };
73 
74 typedef boost::asio::basic_waitable_timer<
75   time_t_clock, time_t_wait_traits> time_t_timer;
76 
main()77 int main()
78 {
79   try
80   {
81     boost::asio::io_context io_context;
82 
83     time_t_timer timer(io_context);
84 
85     timer.expires_after(std::chrono::seconds(5));
86     std::cout << "Starting synchronous wait\n";
87     timer.wait();
88     std::cout << "Finished synchronous wait\n";
89 
90     timer.expires_after(std::chrono::seconds(5));
91     std::cout << "Starting asynchronous wait\n";
92     timer.async_wait(
93         [](const boost::system::error_code& /*error*/)
94         {
95           std::cout << "timeout\n";
96         });
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