| // |
| // detail/chrono_time_traits.hpp |
| // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| // |
| // Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) |
| // |
| // Distributed under the Boost Software License, Version 1.0. (See accompanying |
| // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) |
| // |
| |
| #ifndef ASIO_DETAIL_CHRONO_TIME_TRAITS_HPP |
| #define ASIO_DETAIL_CHRONO_TIME_TRAITS_HPP |
| |
| #if defined(_MSC_VER) && (_MSC_VER >= 1200) |
| # pragma once |
| #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) |
| |
| #include "asio/detail/cstdint.hpp" |
| |
| #include "asio/detail/push_options.hpp" |
| |
| namespace asio { |
| namespace detail { |
| |
| // Helper template to compute the greatest common divisor. |
| template <int64_t v1, int64_t v2> |
| struct gcd { enum { value = gcd<v2, v1 % v2>::value }; }; |
| |
| template <int64_t v1> |
| struct gcd<v1, 0> { enum { value = v1 }; }; |
| |
| // Adapts std::chrono clocks for use with a deadline timer. |
| template <typename Clock, typename WaitTraits> |
| struct chrono_time_traits |
| { |
| // The clock type. |
| typedef Clock clock_type; |
| |
| // The duration type of the clock. |
| typedef typename clock_type::duration duration_type; |
| |
| // The time point type of the clock. |
| typedef typename clock_type::time_point time_type; |
| |
| // The period of the clock. |
| typedef typename duration_type::period period_type; |
| |
| // Get the current time. |
| static time_type now() |
| { |
| return clock_type::now(); |
| } |
| |
| // Add a duration to a time. |
| static time_type add(const time_type& t, const duration_type& d) |
| { |
| const time_type epoch; |
| if (t >= epoch) |
| { |
| if ((time_type::max)() - t < d) |
| return (time_type::max)(); |
| } |
| else // t < epoch |
| { |
| if (-(t - (time_type::min)()) > d) |
| return (time_type::min)(); |
| } |
| |
| return t + d; |
| } |
| |
| // Subtract one time from another. |
| static duration_type subtract(const time_type& t1, const time_type& t2) |
| { |
| const time_type epoch; |
| if (t1 >= epoch) |
| { |
| if (t2 >= epoch) |
| { |
| return t1 - t2; |
| } |
| else if (t2 == (time_type::min)()) |
| { |
| return (duration_type::max)(); |
| } |
| else if ((time_type::max)() - t1 < epoch - t2) |
| { |
| return (duration_type::max)(); |
| } |
| else |
| { |
| return t1 - t2; |
| } |
| } |
| else // t1 < epoch |
| { |
| if (t2 < epoch) |
| { |
| return t1 - t2; |
| } |
| else if (t1 == (time_type::min)()) |
| { |
| return (duration_type::min)(); |
| } |
| else if ((time_type::max)() - t2 < epoch - t1) |
| { |
| return (duration_type::min)(); |
| } |
| else |
| { |
| return -(t2 - t1); |
| } |
| } |
| } |
| |
| // Test whether one time is less than another. |
| static bool less_than(const time_type& t1, const time_type& t2) |
| { |
| return t1 < t2; |
| } |
| |
| // Implement just enough of the posix_time::time_duration interface to supply |
| // what the timer_queue requires. |
| class posix_time_duration |
| { |
| public: |
| explicit posix_time_duration(const duration_type& d) |
| : d_(d) |
| { |
| } |
| |
| int64_t ticks() const |
| { |
| return d_.count(); |
| } |
| |
| int64_t total_seconds() const |
| { |
| return duration_cast<1, 1>(); |
| } |
| |
| int64_t total_milliseconds() const |
| { |
| return duration_cast<1, 1000>(); |
| } |
| |
| int64_t total_microseconds() const |
| { |
| return duration_cast<1, 1000000>(); |
| } |
| |
| private: |
| template <int64_t Num, int64_t Den> |
| int64_t duration_cast() const |
| { |
| const int64_t num1 = period_type::num / gcd<period_type::num, Num>::value; |
| const int64_t num2 = Num / gcd<period_type::num, Num>::value; |
| |
| const int64_t den1 = period_type::den / gcd<period_type::den, Den>::value; |
| const int64_t den2 = Den / gcd<period_type::den, Den>::value; |
| |
| const int64_t num = num1 * den2; |
| const int64_t den = num2 * den1; |
| |
| if (num == 1 && den == 1) |
| return ticks(); |
| else if (num != 1 && den == 1) |
| return ticks() * num; |
| else if (num == 1 && period_type::den != 1) |
| return ticks() / den; |
| else |
| return ticks() * num / den; |
| } |
| |
| duration_type d_; |
| }; |
| |
| // Convert to POSIX duration type. |
| static posix_time_duration to_posix_duration(const duration_type& d) |
| { |
| return posix_time_duration(WaitTraits::to_wait_duration(d)); |
| } |
| }; |
| |
| } // namespace detail |
| } // namespace asio |
| |
| #include "asio/detail/pop_options.hpp" |
| |
| #endif // ASIO_DETAIL_CHRONO_TIME_TRAITS_HPP |