123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276 |
- //////////////////////////////////////////////////////////////////////////////
- //
- // (C) Copyright Ion Gaztanaga 2021-2021.
- //
- // 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)
- //
- // See http://www.boost.org/libs/interprocess for documentation.
- //
- //////////////////////////////////////////////////////////////////////////////
- #ifndef BOOST_INTERPROCESS_DETAIL_TIMED_UTILS_HPP
- #define BOOST_INTERPROCESS_DETAIL_TIMED_UTILS_HPP
- #ifndef BOOST_CONFIG_HPP
- # include <boost/config.hpp>
- #endif
- #
- #if defined(BOOST_HAS_PRAGMA_ONCE)
- # pragma once
- #endif
- #include <boost/interprocess/detail/config_begin.hpp>
- #include <boost/interprocess/detail/workaround.hpp>
- #include <boost/interprocess/detail/mpl.hpp>
- #include <boost/interprocess/detail/type_traits.hpp>
- #include <boost/intrusive/detail/mpl.hpp>
- #include <ctime>
- #include <boost/cstdint.hpp>
- //The following is used to support high precision time clocks
- #ifdef BOOST_HAS_GETTIMEOFDAY
- #include <sys/time.h>
- #endif
- #ifdef BOOST_HAS_FTIME
- #include <time.h>
- #include <boost/winapi/time.hpp>
- #endif
- namespace boost {
- namespace interprocess {
- class ustime;
- class usduration;
- namespace ipcdetail {
- BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(time_duration_type)
- BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(clock)
- BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(rep_type)
- BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(rep)
- template<class T>
- struct enable_if_ptime
- : enable_if_c< BOOST_INTRUSIVE_HAS_TYPE(boost::interprocess::ipcdetail::, T, time_duration_type) >
- {};
- template<class T>
- struct disable_if_ptime
- : enable_if_c< ! BOOST_INTRUSIVE_HAS_TYPE(boost::interprocess::ipcdetail::, T, time_duration_type) >
- {};
- template<class T>
- struct enable_if_ptime_duration
- : enable_if_c< BOOST_INTRUSIVE_HAS_TYPE(boost::interprocess::ipcdetail::, T, rep_type) >
- {};
- template<class T>
- struct enable_if_time_point
- : enable_if_c< BOOST_INTRUSIVE_HAS_TYPE(boost::interprocess::ipcdetail::, T, clock) >
- {};
- template<class T>
- struct enable_if_duration
- : enable_if_c< BOOST_INTRUSIVE_HAS_TYPE(boost::interprocess::ipcdetail::, T, rep) >
- {};
- template<class T>
- struct enable_if_ustime
- : enable_if_c< is_same<T, ustime>::value >
- {};
- template<class T>
- struct enable_if_usduration
- : enable_if_c< is_same<T, usduration>::value >
- {};
- #if defined(BOOST_INTERPROCESS_HAS_REENTRANT_STD_FUNCTIONS)
- inline std::tm* interprocess_gmtime(const std::time_t* t, std::tm* result)
- {
- // gmtime_r() not in namespace std???
- #if defined(__VMS) && __INITIAL_POINTER_SIZE == 64
- std::tm tmp;
- if(!gmtime_r(t,&tmp))
- result = 0;
- else
- *result = tmp;
- #else
- result = gmtime_r(t, result);
- #endif
- return result;
- }
- #else // BOOST_DATE_TIME_HAS_REENTRANT_STD_FUNCTIONS
- #if defined(__clang__) // Clang has to be checked before MSVC
- # pragma clang diagnostic push
- # pragma clang diagnostic ignored "-Wdeprecated-declarations"
- #elif (defined(_MSC_VER) && (_MSC_VER >= 1400))
- # pragma warning(push) // preserve warning settings
- # pragma warning(disable : 4996) // disable depricated localtime/gmtime warning on vc8
- #endif
- inline std::tm* interprocess_gmtime(const std::time_t* t, std::tm* result)
- {
- result = std::gmtime(t);
- return result;
- }
- #if defined(__clang__) // Clang has to be checked before MSVC
- # pragma clang diagnostic pop
- #elif (defined(_MSC_VER) && (_MSC_VER >= 1400))
- # pragma warning(pop) // restore warnings to previous state
- #endif
- #endif // BOOST_DATE_TIME_HAS_REENTRANT_STD_FUNCTIONS
- #if defined(BOOST_HAS_FTIME)
- /*!
- * The function converts file_time into number of microseconds elapsed since 1970-Jan-01
- *
- * \note Only dates after 1970-Jan-01 are supported. Dates before will be wrapped.
- */
- inline boost::uint64_t file_time_to_microseconds(const boost::winapi::FILETIME_ & ft)
- {
- // shift is difference between 1970-Jan-01 & 1601-Jan-01
- // in 100-nanosecond units
- const boost::uint64_t shift = 116444736000000000ULL; // (27111902 << 32) + 3577643008
- // 100-nanos since 1601-Jan-01
- boost::uint64_t ft_as_integer = (static_cast< boost::uint64_t >(ft.dwHighDateTime) << 32) | static_cast< boost::uint64_t >(ft.dwLowDateTime);
- ft_as_integer -= shift; // filetime is now 100-nanos since 1970-Jan-01
- return (ft_as_integer / 10U); // truncate to microseconds
- }
- #endif
- inline boost::uint64_t universal_time_u64_us()
- {
- #ifdef BOOST_HAS_GETTIMEOFDAY
- timeval tv;
- gettimeofday(&tv, 0); //gettimeofday does not support TZ adjust on Linux.
- boost::uint64_t micros = boost::uint64_t(tv.tv_sec)*1000000u;
- micros += (boost::uint64_t)tv.tv_usec;
- #elif defined(BOOST_HAS_FTIME)
- boost::winapi::FILETIME_ ft;
- boost::winapi::GetSystemTimeAsFileTime(&ft);
- boost::uint64_t micros = file_time_to_microseconds(ft); // it will not wrap, since ft is the current time
- // and cannot be before 1970-Jan-01
- #else
- #error "Unsupported date-time error: neither gettimeofday nor FILETIME support is detected"
- #endif
- return micros;
- }
- template<class TimeType, class Enable = void>
- class microsec_clock;
- template<class TimeType>
- class microsec_clock<TimeType, typename enable_if_ptime<TimeType>::type>
- {
- private:
- typedef typename TimeType::date_type date_type;
- typedef typename TimeType::time_duration_type time_duration_type;
- typedef typename time_duration_type::rep_type resolution_traits_type;
- public:
- typedef TimeType time_point;
- static time_point universal_time()
- {
- #ifdef BOOST_HAS_GETTIMEOFDAY
- timeval tv;
- gettimeofday(&tv, 0); //gettimeofday does not support TZ adjust on Linux.
- std::time_t t = tv.tv_sec;
- boost::uint32_t sub_sec = static_cast<boost::uint32_t>(tv.tv_usec);
- #elif defined(BOOST_HAS_FTIME)
- boost::winapi::FILETIME_ ft;
- boost::winapi::GetSystemTimeAsFileTime(&ft);
- boost::uint64_t micros = file_time_to_microseconds(ft); // it will not wrap, since ft is the current time
- // and cannot be before 1970-Jan-01
- std::time_t t = static_cast<std::time_t>(micros / 1000000UL); // seconds since epoch
- // microseconds -- static casts suppress warnings
- boost::uint32_t sub_sec = static_cast<boost::uint32_t>(micros % 1000000UL);
- #else
- #error "Unsupported date-time error: neither gettimeofday nor FILETIME support is detected"
- #endif
- std::tm curr;
- std::tm* curr_ptr = interprocess_gmtime(&t, &curr);
- date_type d(static_cast< typename date_type::year_type::value_type >(curr_ptr->tm_year + 1900),
- static_cast< typename date_type::month_type::value_type >(curr_ptr->tm_mon + 1),
- static_cast< typename date_type::day_type::value_type >(curr_ptr->tm_mday));
- //The following line will adjust the fractional second tick in terms
- //of the current time system. For example, if the time system
- //doesn't support fractional seconds then res_adjust returns 0
- //and all the fractional seconds return 0.
- unsigned adjust = static_cast< unsigned >(resolution_traits_type::res_adjust() / 1000000);
- time_duration_type td(static_cast< typename time_duration_type::hour_type >(curr_ptr->tm_hour),
- static_cast< typename time_duration_type::min_type >(curr_ptr->tm_min),
- static_cast< typename time_duration_type::sec_type >(curr_ptr->tm_sec),
- static_cast< typename time_duration_type::fractional_seconds_type >(sub_sec * adjust)
- );
- return time_point(d,td);
- }
- };
- template<class TimePoint>
- class microsec_clock<TimePoint, typename enable_if_time_point<TimePoint>::type>
- {
- public:
- typedef typename TimePoint::clock::time_point time_point;
- static time_point universal_time()
- { return TimePoint::clock::now(); }
- };
- template<class TimePoint>
- inline bool is_pos_infinity(const TimePoint &abs_time, typename enable_if_ptime<TimePoint>::type* = 0)
- {
- return abs_time.is_pos_infinity();
- }
- template<class TimePoint>
- inline bool is_pos_infinity(const TimePoint &, typename disable_if_ptime<TimePoint>::type* = 0)
- {
- return false;
- }
- // duration_to_milliseconds
- template<class Duration>
- inline boost::uint64_t duration_to_milliseconds(const Duration &abs_time, typename enable_if_ptime_duration<Duration>::type* = 0)
- {
- return static_cast<boost::uint64_t>(abs_time.total_milliseconds());
- }
- template<class Duration>
- inline boost::uint64_t duration_to_milliseconds(const Duration &d, typename enable_if_duration<Duration>::type* = 0)
- {
- const double factor = double(Duration::period::num)*1000.0/double(Duration::period::den);
- return static_cast<boost::uint64_t>(double(d.count())*factor);
- }
- template<class Duration>
- inline boost::uint64_t duration_to_milliseconds(const Duration&d, typename enable_if_usduration<Duration>::type* = 0)
- {
- return d.get_microsecs()/1000u;
- }
- } //namespace ipcdetail {
- } //namespace interprocess {
- } //namespace boost {
- #include <boost/interprocess/detail/config_end.hpp>
- #endif //#ifndef BOOST_INTERPROCESS_DETAIL_TIMED_UTILS_HPP
|