191 lines
		
	
	
		
			4.3 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			191 lines
		
	
	
		
			4.3 KiB
		
	
	
	
		
			C++
		
	
	
	
| //
 | |
| // detail/chrono_time_traits.hpp
 | |
| // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 | |
| //
 | |
| // Copyright (c) 2003-2023 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
 |