1 // 2 // detail/chrono_time_traits.hpp 3 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 4 // 5 // Copyright (c) 2003-2020 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 #ifndef BOOST_ASIO_DETAIL_CHRONO_TIME_TRAITS_HPP 12 #define BOOST_ASIO_DETAIL_CHRONO_TIME_TRAITS_HPP 13 14 #if defined(_MSC_VER) && (_MSC_VER >= 1200) 15 # pragma once 16 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) 17 18 #include <boost/asio/detail/cstdint.hpp> 19 20 #include <boost/asio/detail/push_options.hpp> 21 22 namespace boost { 23 namespace asio { 24 namespace detail { 25 26 // Helper template to compute the greatest common divisor. 27 template <int64_t v1, int64_t v2> 28 struct gcd { enum { value = gcd<v2, v1 % v2>::value }; }; 29 30 template <int64_t v1> 31 struct gcd<v1, 0> { enum { value = v1 }; }; 32 33 // Adapts std::chrono clocks for use with a deadline timer. 34 template <typename Clock, typename WaitTraits> 35 struct chrono_time_traits 36 { 37 // The clock type. 38 typedef Clock clock_type; 39 40 // The duration type of the clock. 41 typedef typename clock_type::duration duration_type; 42 43 // The time point type of the clock. 44 typedef typename clock_type::time_point time_type; 45 46 // The period of the clock. 47 typedef typename duration_type::period period_type; 48 49 // Get the current time. nowboost::asio::detail::chrono_time_traits50 static time_type now() 51 { 52 return clock_type::now(); 53 } 54 55 // Add a duration to a time. addboost::asio::detail::chrono_time_traits56 static time_type add(const time_type& t, const duration_type& d) 57 { 58 const time_type epoch; 59 if (t >= epoch) 60 { 61 if ((time_type::max)() - t < d) 62 return (time_type::max)(); 63 } 64 else // t < epoch 65 { 66 if (-(t - (time_type::min)()) > d) 67 return (time_type::min)(); 68 } 69 70 return t + d; 71 } 72 73 // Subtract one time from another. subtractboost::asio::detail::chrono_time_traits74 static duration_type subtract(const time_type& t1, const time_type& t2) 75 { 76 const time_type epoch; 77 if (t1 >= epoch) 78 { 79 if (t2 >= epoch) 80 { 81 return t1 - t2; 82 } 83 else if (t2 == (time_type::min)()) 84 { 85 return (duration_type::max)(); 86 } 87 else if ((time_type::max)() - t1 < epoch - t2) 88 { 89 return (duration_type::max)(); 90 } 91 else 92 { 93 return t1 - t2; 94 } 95 } 96 else // t1 < epoch 97 { 98 if (t2 < epoch) 99 { 100 return t1 - t2; 101 } 102 else if (t1 == (time_type::min)()) 103 { 104 return (duration_type::min)(); 105 } 106 else if ((time_type::max)() - t2 < epoch - t1) 107 { 108 return (duration_type::min)(); 109 } 110 else 111 { 112 return -(t2 - t1); 113 } 114 } 115 } 116 117 // Test whether one time is less than another. less_thanboost::asio::detail::chrono_time_traits118 static bool less_than(const time_type& t1, const time_type& t2) 119 { 120 return t1 < t2; 121 } 122 123 // Implement just enough of the posix_time::time_duration interface to supply 124 // what the timer_queue requires. 125 class posix_time_duration 126 { 127 public: posix_time_duration(const duration_type & d)128 explicit posix_time_duration(const duration_type& d) 129 : d_(d) 130 { 131 } 132 ticks() const133 int64_t ticks() const 134 { 135 return d_.count(); 136 } 137 total_seconds() const138 int64_t total_seconds() const 139 { 140 return duration_cast<1, 1>(); 141 } 142 total_milliseconds() const143 int64_t total_milliseconds() const 144 { 145 return duration_cast<1, 1000>(); 146 } 147 total_microseconds() const148 int64_t total_microseconds() const 149 { 150 return duration_cast<1, 1000000>(); 151 } 152 153 private: 154 template <int64_t Num, int64_t Den> duration_cast() const155 int64_t duration_cast() const 156 { 157 const int64_t num1 = period_type::num / gcd<period_type::num, Num>::value; 158 const int64_t num2 = Num / gcd<period_type::num, Num>::value; 159 160 const int64_t den1 = period_type::den / gcd<period_type::den, Den>::value; 161 const int64_t den2 = Den / gcd<period_type::den, Den>::value; 162 163 const int64_t num = num1 * den2; 164 const int64_t den = num2 * den1; 165 166 if (num == 1 && den == 1) 167 return ticks(); 168 else if (num != 1 && den == 1) 169 return ticks() * num; 170 else if (num == 1 && period_type::den != 1) 171 return ticks() / den; 172 else 173 return ticks() * num / den; 174 } 175 176 duration_type d_; 177 }; 178 179 // Convert to POSIX duration type. to_posix_durationboost::asio::detail::chrono_time_traits180 static posix_time_duration to_posix_duration(const duration_type& d) 181 { 182 return posix_time_duration(WaitTraits::to_wait_duration(d)); 183 } 184 }; 185 186 } // namespace detail 187 } // namespace asio 188 } // namespace boost 189 190 #include <boost/asio/detail/pop_options.hpp> 191 192 #endif // BOOST_ASIO_DETAIL_CHRONO_TIME_TRAITS_HPP 193