File indexing completed on 2025-01-18 09:38:27
0001
0002
0003
0004
0005
0006
0007
0008
0009
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
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
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
0095
0096 #if defined(__clang__)
0097 # pragma clang diagnostic push
0098 # pragma clang diagnostic ignored "-Wdeprecated-declarations"
0099 #elif (defined(_MSC_VER) && (_MSC_VER >= 1400))
0100 # pragma warning(push)
0101 # pragma warning(disable : 4996)
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__)
0111 # pragma clang diagnostic pop
0112 #elif (defined(_MSC_VER) && (_MSC_VER >= 1400))
0113 # pragma warning(pop)
0114 #endif
0115
0116 #endif
0117
0118 #if defined(BOOST_HAS_FTIME)
0119
0120
0121
0122
0123
0124 inline boost::uint64_t file_time_to_microseconds(const boost::winapi::FILETIME_ & ft)
0125 {
0126
0127
0128 const boost::uint64_t shift = 116444736000000000ULL;
0129
0130
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;
0134 return (ft_as_integer / 10U);
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);
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);
0238
0239 std::time_t t = static_cast<std::time_t>(micros / 1000000UL);
0240
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
0253
0254
0255
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);
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);
0282
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
0325
0326
0327
0328
0329
0330
0331
0332
0333
0334
0335
0336
0337
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
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
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 }
0382 }
0383 }
0384
0385 #include <boost/interprocess/detail/config_end.hpp>
0386
0387 #endif
0388