chrono.hpp 3.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. /*
  2. * Distributed under the Boost Software License, Version 1.0.
  3. * (See accompanying file LICENSE_1_0.txt or copy at
  4. * http://www.boost.org/LICENSE_1_0.txt)
  5. *
  6. * Copyright (c) 2025 Andrey Semashev
  7. */
  8. /*!
  9. * \file atomic/detail/chrono.hpp
  10. *
  11. * This header contains \c std::chrono utilities.
  12. */
  13. #ifndef BOOST_ATOMIC_DETAIL_CHRONO_HPP_INCLUDED_
  14. #define BOOST_ATOMIC_DETAIL_CHRONO_HPP_INCLUDED_
  15. #include <time.h>
  16. #include <chrono>
  17. #if !defined(__cpp_lib_chrono) || (__cpp_lib_chrono < 201510l)
  18. #include <ratio>
  19. #include <type_traits>
  20. #endif // !defined(__cpp_lib_chrono) || (__cpp_lib_chrono < 201510l)
  21. #if defined(CLOCK_REALTIME)
  22. #include <boost/atomic/posix_clock_traits_fwd.hpp>
  23. #endif // defined(CLOCK_REALTIME)
  24. #include <boost/atomic/detail/config.hpp>
  25. #include <boost/atomic/detail/header.hpp>
  26. #ifdef BOOST_HAS_PRAGMA_ONCE
  27. #pragma once
  28. #endif
  29. namespace boost {
  30. namespace atomics {
  31. namespace detail {
  32. namespace chrono {
  33. #if defined(__cpp_lib_chrono) && (__cpp_lib_chrono >= 201510l)
  34. using std::chrono::ceil;
  35. #else // defined(__cpp_lib_chrono) && (__cpp_lib_chrono >= 201510l)
  36. template< typename To, typename Rep, typename Period >
  37. inline constexpr To ceil(std::chrono::duration< Rep, Period > from) noexcept
  38. {
  39. using conv_ratio = std::ratio_divide< Period, typename To::period >;
  40. using common_rep = typename std::common_type< Rep, typename To::rep, decltype(conv_ratio::num) >::type;
  41. return To(static_cast< typename To::rep >((static_cast< common_rep >(from.count()) * conv_ratio::num) / conv_ratio::den +
  42. static_cast< common_rep >(((static_cast< common_rep >(from.count()) * conv_ratio::num) % conv_ratio::den) != static_cast< common_rep >(0))));
  43. }
  44. #endif // defined(__cpp_lib_chrono) && (__cpp_lib_chrono >= 201510l)
  45. } // namespace chrono
  46. } // namespace detail
  47. #if defined(CLOCK_REALTIME)
  48. //! Integrate `std::chrono::system_clock` with POSIX clocks
  49. template< >
  50. struct posix_clock_traits< std::chrono::system_clock >
  51. {
  52. //! POSIX clock identifier
  53. static constexpr clockid_t clock_id = CLOCK_REALTIME;
  54. //! Function that converts a time point to a timespec structure
  55. static timespec to_timespec(std::chrono::system_clock::time_point time_point) noexcept
  56. {
  57. timespec ts{};
  58. std::chrono::nanoseconds::rep time_ns = std::chrono::duration_cast< std::chrono::nanoseconds >(time_point.time_since_epoch()).count();
  59. // Note: The standard doesn't require that std::chrono::system_clock epoch matches the POSIX CLOCK_REALTIME epoch. Also, std::chrono::system_clock::to_time_t
  60. // is allowed to round or truncate the time point when converting to time_t resolution, which means to_time_t may return a time before or after time_point.
  61. ts.tv_sec = std::chrono::system_clock::to_time_t(std::chrono::system_clock::time_point()) + static_cast< decltype(ts.tv_sec) >(time_ns / 1000000000);
  62. time_ns %= 1000000000;
  63. if (BOOST_UNLIKELY(time_ns < 0))
  64. {
  65. --ts.tv_sec;
  66. time_ns += 1000000000;
  67. }
  68. ts.tv_nsec = static_cast< decltype(ts.tv_nsec) >(time_ns);
  69. return ts;
  70. }
  71. };
  72. #endif // defined(CLOCK_REALTIME)
  73. } // namespace atomics
  74. } // namespace boost
  75. #include <boost/atomic/detail/footer.hpp>
  76. #endif // BOOST_ATOMIC_DETAIL_CHRONO_HPP_INCLUDED_