Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:38:27

0001 //////////////////////////////////////////////////////////////////////////////
0002 //
0003 // (C) Copyright Ion Gaztanaga 2021-2021.
0004 //
0005 // Distributed under the Boost Software License, Version 1.0.
0006 // (See accompanying file LICENSE_1_0.txt or copy at
0007 // http://www.boost.org/LICENSE_1_0.txt)
0008 //
0009 // See http://www.boost.org/libs/interprocess for documentation.
0010 //
0011 //////////////////////////////////////////////////////////////////////////////
0012 
0013 #ifndef BOOST_INTERPROCESS_DETAIL_TIMED_UTILS_HPP
0014 #define BOOST_INTERPROCESS_DETAIL_TIMED_UTILS_HPP
0015 
0016 #ifndef BOOST_CONFIG_HPP
0017 #  include <boost/config.hpp>
0018 #endif
0019 #
0020 #if defined(BOOST_HAS_PRAGMA_ONCE)
0021 #  pragma once
0022 #endif
0023 
0024 #include <boost/interprocess/detail/config_begin.hpp>
0025 #include <boost/interprocess/detail/workaround.hpp>
0026 #include <boost/interprocess/detail/mpl.hpp>
0027 #include <boost/interprocess/detail/type_traits.hpp>
0028 #include <boost/intrusive/detail/mpl.hpp>
0029 
0030 #include <ctime>
0031 #include <boost/cstdint.hpp>
0032 
0033 //The following is used to support high precision time clocks
0034 #ifdef BOOST_HAS_GETTIMEOFDAY
0035 #include <sys/time.h>
0036 #endif
0037 
0038 #ifdef BOOST_HAS_FTIME
0039 #include <time.h>
0040 #include <boost/winapi/time.hpp>
0041 #endif
0042 
0043 namespace boost {
0044 namespace interprocess {
0045 namespace ipcdetail {
0046 
0047 BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(time_duration_type)
0048 BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(clock)
0049 BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(rep_type)
0050 BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(rep)
0051 
0052 template<class T>
0053 struct enable_if_ptime
0054    : enable_if_c< BOOST_INTRUSIVE_HAS_TYPE(boost::interprocess::ipcdetail::, T, time_duration_type) >
0055 {};
0056 
0057 template<class T>
0058 struct disable_if_ptime
0059    : enable_if_c< ! BOOST_INTRUSIVE_HAS_TYPE(boost::interprocess::ipcdetail::, T, time_duration_type) >
0060 {};
0061 
0062 template<class T>
0063 struct enable_if_ptime_duration
0064    : enable_if_c< BOOST_INTRUSIVE_HAS_TYPE(boost::interprocess::ipcdetail::, T, rep_type) >
0065 {};
0066 
0067 template<class T>
0068 struct enable_if_time_point
0069    : enable_if_c< BOOST_INTRUSIVE_HAS_TYPE(boost::interprocess::ipcdetail::, T, clock) >
0070 {};
0071 
0072 template<class T>
0073 struct enable_if_duration
0074    : enable_if_c< BOOST_INTRUSIVE_HAS_TYPE(boost::interprocess::ipcdetail::, T, rep) >
0075 {};
0076 
0077 #if defined(BOOST_INTERPROCESS_HAS_REENTRANT_STD_FUNCTIONS)
0078 
0079    inline std::tm* interprocess_gmtime(const std::time_t* t, std::tm* result)
0080    {
0081       // gmtime_r() not in namespace std???
0082       #if defined(__VMS) && __INITIAL_POINTER_SIZE == 64
0083          std::tm tmp;
0084          if(!gmtime_r(t,&tmp))
0085             result = 0;
0086          else
0087             *result = tmp;
0088       #else
0089          result = gmtime_r(t, result);
0090       #endif
0091       return result;
0092    }
0093 
0094 #else // BOOST_DATE_TIME_HAS_REENTRANT_STD_FUNCTIONS
0095 
0096    #if defined(__clang__) // Clang has to be checked before MSVC
0097    #  pragma clang diagnostic push
0098    #  pragma clang diagnostic ignored "-Wdeprecated-declarations"
0099    #elif (defined(_MSC_VER) && (_MSC_VER >= 1400))
0100    #  pragma warning(push) // preserve warning settings
0101    #  pragma warning(disable : 4996) // disable depricated localtime/gmtime warning on vc8
0102    #endif
0103 
0104    inline std::tm* interprocess_gmtime(const std::time_t* t, std::tm* result)
0105    {
0106       result = std::gmtime(t);
0107       return result;
0108    }
0109 
0110    #if defined(__clang__) // Clang has to be checked before MSVC
0111    #  pragma clang diagnostic pop
0112    #elif (defined(_MSC_VER) && (_MSC_VER >= 1400))
0113    #  pragma warning(pop) // restore warnings to previous state
0114    #endif
0115 
0116 #endif // BOOST_DATE_TIME_HAS_REENTRANT_STD_FUNCTIONS
0117 
0118 #if defined(BOOST_HAS_FTIME)
0119 /*!
0120 * The function converts file_time into number of microseconds elapsed since 1970-Jan-01
0121 *
0122 * \note Only dates after 1970-Jan-01 are supported. Dates before will be wrapped.
0123 */
0124 inline boost::uint64_t file_time_to_microseconds(const boost::winapi::FILETIME_ & ft)
0125 {
0126    // shift is difference between 1970-Jan-01 & 1601-Jan-01
0127    // in 100-nanosecond units
0128    const boost::uint64_t shift = 116444736000000000ULL; // (27111902 << 32) + 3577643008
0129 
0130    // 100-nanos since 1601-Jan-01
0131    boost::uint64_t ft_as_integer = (static_cast< boost::uint64_t >(ft.dwHighDateTime) << 32) | static_cast< boost::uint64_t >(ft.dwLowDateTime);
0132 
0133    ft_as_integer -= shift; // filetime is now 100-nanos since 1970-Jan-01
0134    return (ft_as_integer / 10U); // truncate to microseconds
0135 }
0136 #endif
0137 
0138 class ustime;
0139 
0140 class usduration
0141 {
0142    public:
0143    friend class ustime;
0144 
0145    explicit usduration(boost::uint64_t microsecs)
0146       : m_microsecs(microsecs)
0147    {}
0148 
0149    boost::uint64_t get_microsecs() const
0150    {  return m_microsecs;  }
0151 
0152    bool operator < (const usduration &other) const
0153    {  return m_microsecs < other.m_microsecs; }
0154 
0155    bool operator > (const usduration &other) const
0156    {  return m_microsecs > other.m_microsecs; }
0157 
0158    bool operator <= (const usduration &other) const
0159    {  return m_microsecs <= other.m_microsecs; }
0160 
0161    bool operator >= (const usduration &other) const
0162    {  return m_microsecs >= other.m_microsecs; }
0163 
0164    private:
0165    boost::uint64_t m_microsecs;
0166 };
0167 
0168 class ustime
0169 {
0170    public:
0171    explicit ustime(boost::uint64_t microsecs)
0172       : m_microsecs(microsecs)
0173    {}
0174 
0175    ustime &operator += (const usduration &other)
0176    {  m_microsecs += other.m_microsecs; return *this; }
0177 
0178    ustime operator + (const usduration &other)
0179    {  ustime r(*this); r += other; return r; }
0180 
0181    ustime &operator -= (const usduration &other)
0182    {  m_microsecs -= other.m_microsecs; return *this; }
0183 
0184    ustime operator - (const usduration &other)
0185    {  ustime r(*this); r -= other; return r; }
0186 
0187    friend usduration operator - (const ustime &l, const ustime &r)
0188    {  return usduration(l.m_microsecs - r.m_microsecs); }
0189 
0190    bool operator < (const ustime &other) const
0191    {  return m_microsecs < other.m_microsecs; }
0192 
0193    bool operator > (const ustime &other) const
0194    {  return m_microsecs > other.m_microsecs; }
0195 
0196    bool operator <= (const ustime &other) const
0197    {  return m_microsecs <= other.m_microsecs; }
0198 
0199    bool operator >= (const ustime &other) const
0200    {  return m_microsecs >= other.m_microsecs; }
0201 
0202    boost::uint64_t get_microsecs() const
0203    {  return m_microsecs;  }
0204 
0205    private:
0206    boost::uint64_t m_microsecs;
0207 };
0208 
0209 inline usduration usduration_milliseconds(boost::uint64_t millisec)
0210 {  return usduration(millisec*1000u);   }
0211 
0212 inline usduration usduration_seconds(boost::uint64_t sec)
0213 {  return usduration(sec*uint64_t(1000000u));   }
0214 
0215 template<class TimeType, class Enable = void>
0216 class microsec_clock;
0217 
0218 template<class TimeType>
0219 class microsec_clock<TimeType, typename enable_if_ptime<TimeType>::type>
0220 {
0221    private:
0222    typedef typename TimeType::date_type date_type;
0223    typedef typename TimeType::time_duration_type time_duration_type;
0224    typedef typename time_duration_type::rep_type resolution_traits_type;
0225    public:
0226 
0227    static TimeType universal_time()
0228    {
0229       #ifdef BOOST_HAS_GETTIMEOFDAY
0230          timeval tv;
0231          gettimeofday(&tv, 0); //gettimeofday does not support TZ adjust on Linux.
0232          std::time_t t = tv.tv_sec;
0233          boost::uint32_t sub_sec = static_cast<boost::uint32_t>(tv.tv_usec);
0234       #elif defined(BOOST_HAS_FTIME)
0235          boost::winapi::FILETIME_ ft;
0236          boost::winapi::GetSystemTimeAsFileTime(&ft);
0237          boost::uint64_t micros = file_time_to_microseconds(ft); // it will not wrap, since ft is the current time
0238                                                                   // and cannot be before 1970-Jan-01
0239          std::time_t t = static_cast<std::time_t>(micros / 1000000UL); // seconds since epoch
0240          // microseconds -- static casts suppress warnings
0241          boost::uint32_t sub_sec = static_cast<boost::uint32_t>(micros % 1000000UL);
0242       #else
0243          #error "Unsupported date-time error: neither gettimeofday nor FILETIME support is detected"
0244       #endif
0245 
0246       std::tm curr;
0247       std::tm* curr_ptr = interprocess_gmtime(&t, &curr);
0248       date_type d(static_cast< typename date_type::year_type::value_type >(curr_ptr->tm_year + 1900),
0249                   static_cast< typename date_type::month_type::value_type >(curr_ptr->tm_mon + 1),
0250                   static_cast< typename date_type::day_type::value_type >(curr_ptr->tm_mday));
0251 
0252       //The following line will adjust the fractional second tick in terms
0253       //of the current time system.  For example, if the time system
0254       //doesn't support fractional seconds then res_adjust returns 0
0255       //and all the fractional seconds return 0.
0256       unsigned adjust = static_cast< unsigned >(resolution_traits_type::res_adjust() / 1000000);
0257 
0258       time_duration_type td(static_cast< typename time_duration_type::hour_type >(curr_ptr->tm_hour),
0259                               static_cast< typename time_duration_type::min_type >(curr_ptr->tm_min),
0260                               static_cast< typename time_duration_type::sec_type >(curr_ptr->tm_sec),
0261                               static_cast< typename time_duration_type::fractional_seconds_type >(sub_sec * adjust)
0262                            );
0263       return TimeType(d,td);
0264    }
0265 };
0266 
0267 template<>
0268 class microsec_clock<ustime>
0269 {
0270    public:
0271    static ustime universal_time()
0272    {
0273       #ifdef BOOST_HAS_GETTIMEOFDAY
0274          timeval tv;
0275          gettimeofday(&tv, 0); //gettimeofday does not support TZ adjust on Linux.
0276          boost::uint64_t micros = boost::uint64_t(tv.tv_sec)*1000000;
0277          micros += (boost::uint64_t)tv.tv_usec;
0278       #elif defined(BOOST_HAS_FTIME)
0279          boost::winapi::FILETIME_ ft;
0280          boost::winapi::GetSystemTimeAsFileTime(&ft);
0281          boost::uint64_t micros = file_time_to_microseconds(ft); // it will not wrap, since ft is the current time
0282                                                                   // and cannot be before 1970-Jan-01
0283       #else
0284          #error "Unsupported date-time error: neither gettimeofday nor FILETIME support is detected"
0285       #endif
0286       return ustime(micros);
0287    }
0288 };
0289 
0290 template<class TimePoint>
0291 class microsec_clock<TimePoint, typename enable_if_time_point<TimePoint>::type>
0292 {
0293    public:
0294    static TimePoint universal_time()
0295    {  return TimePoint::clock::now();  }
0296 };
0297 
0298 
0299 template<class TimePoint>
0300 inline TimePoint delay_ms(unsigned msecs, typename enable_if_ptime<TimePoint>::type* = 0)
0301 {
0302    typedef typename TimePoint::time_duration_type time_duration_type;
0303    typedef typename time_duration_type::rep_type resolution_traits_type;
0304 
0305    time_duration_type td(msecs*1000*resolution_traits_type::res_adjust());
0306 
0307    TimePoint tp(microsec_clock<TimePoint>::universal_time());
0308    return (tp += td);
0309 }
0310 
0311 template<class TimePoint>
0312 inline bool is_pos_infinity(const TimePoint &abs_time, typename enable_if_ptime<TimePoint>::type* = 0)
0313 {
0314    return abs_time.is_pos_infinity();
0315 }
0316 
0317 template<class TimePoint>
0318 inline bool is_pos_infinity(const TimePoint &, typename disable_if_ptime<TimePoint>::type* = 0)
0319 {
0320    return false;
0321 }
0322 
0323 /*
0324 template<class Duration>
0325 inline ustime duration_to_timepoint(const Duration &dur, typename enable_if_ptime<Duration>::type* = 0)
0326 {
0327    return dur.is_pos_infinity();
0328 }
0329 
0330 template<class Duration>
0331 inline bool duration_to_timepoint(const Duration &, typename disable_if_ptime<Duration>::type* = 0)
0332 {
0333    return false;
0334 }
0335 */
0336 
0337 // duration_to_milliseconds
0338 
0339 template<class Duration>
0340 inline boost::uint64_t duration_to_milliseconds(const Duration &abs_time, typename enable_if_ptime_duration<Duration>::type* = 0)
0341 {
0342    return static_cast<boost::uint64_t>(abs_time.total_milliseconds());
0343 }
0344 
0345 template<class Duration>
0346 inline boost::uint64_t duration_to_milliseconds(const Duration &d, typename enable_if_duration<Duration>::type* = 0)
0347 {
0348    const double factor = double(Duration::period::num)*1000.0/double(Duration::period::den);
0349    return static_cast<boost::uint64_t>(double(d.count())*factor);
0350 }
0351 
0352 inline boost::uint64_t duration_to_milliseconds(const usduration &d)
0353 {
0354    return d.get_microsecs()/1000;
0355 }
0356 
0357 // duration_to_usduration
0358 
0359 template<class Duration>
0360 inline usduration duration_to_usduration(const Duration &d, typename enable_if_ptime_duration<Duration>::type* = 0)
0361 {
0362    return usduration(static_cast<boost::uint64_t>(d.total_microseconds()));
0363 }
0364 
0365 template<class Duration>
0366 inline usduration duration_to_usduration(const Duration &d, typename enable_if_duration<Duration>::type* = 0)
0367 {
0368    const double factor = double(Duration::period::num)*1000000.0/double(Duration::period::den);
0369    return usduration(static_cast<boost::uint64_t>(double(d.count())*factor));
0370 }
0371 
0372 // duration_to_ustime
0373 
0374 template<class Duration>
0375 inline ustime duration_to_ustime(const Duration &d)
0376 {
0377    return microsec_clock<ustime>::universal_time() + (duration_to_usduration)(d);
0378 }
0379 
0380 
0381 }  //namespace ipcdetail {
0382 }  //namespace interprocess {
0383 }  //namespace boost {
0384 
0385 #include <boost/interprocess/detail/config_end.hpp>
0386 
0387 #endif   //#ifndef BOOST_INTERPROCESS_DETAIL_TIMED_UTILS_HPP
0388