File indexing completed on 2026-05-02 07:57:07
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 ">#
0021 #if defined(BOOST_HAS_PRAGMA_ONCE)
0022 # pragma once
0023 #endif
0024
0025 #include <boost/interprocess/detail/config_begin.hpp>
0026 #include <boost/interprocess/detail/workaround.hpp>
0027 #include <boost/interprocess/detail/mpl.hpp>
0028 #include <boost/interprocess/detail/type_traits.hpp>
0029 #include <boost/intrusive/detail/mpl.hpp>
0030
0031 #include <ctime>
0032 #include <boost/cstdint.hpp>
0033
0034
0035 #ifdef BOOST_HAS_GETTIMEOFDAY
0036 #include <sys/time.h>
0037 #endif
0038
0039 #ifdef BOOST_HAS_FTIME
0040 #include <time.h>
0041 #include <boost/winapi/time.hpp>
0042 #endif
0043
0044 namespace boost {
0045 namespace interprocess {
0046
0047 class ustime;
0048 class usduration;
0049
0050 namespace ipcdetail {
0051
0052 BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(time_duration_type)
0053 BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(clock)
0054 BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(rep_type)
0055 BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(rep)
0056
0057 template<class T>
0058 struct enable_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 disable_if_ptime
0064 : enable_if_c< ! BOOST_INTRUSIVE_HAS_TYPE(boost::interprocess::ipcdetail::, T, time_duration_type) >
0065 {};
0066
0067 template<class T>
0068 struct enable_if_ptime_duration
0069 : enable_if_c< BOOST_INTRUSIVE_HAS_TYPE(boost::interprocess::ipcdetail::, T, rep_type) >
0070 {};
0071
0072 template<class T>
0073 struct enable_if_time_point
0074 : enable_if_c< BOOST_INTRUSIVE_HAS_TYPE(boost::interprocess::ipcdetail::, T, clock) >
0075 {};
0076
0077 template<class T>
0078 struct enable_if_duration
0079 : enable_if_c< BOOST_INTRUSIVE_HAS_TYPE(boost::interprocess::ipcdetail::, T, rep) >
0080 {};
0081
0082 template<class T>
0083 struct enable_if_ustime
0084 : enable_if_c< is_same<T, ustime>::value >
0085 {};
0086
0087 template<class T>
0088 struct enable_if_usduration
0089 : enable_if_c< is_same<T, usduration>::value >
0090 {};
0091
0092 #if defined(BOOST_INTERPROCESS_HAS_REENTRANT_STD_FUNCTIONS)
0093
0094 inline std::tm* interprocess_gmtime(const std::time_t* t, std::tm* result)
0095 {
0096
0097 #if defined(__VMS) && __INITIAL_POINTER_SIZE == 64
0098 std::tm tmp;
0099 if(!gmtime_r(t,&tmp))
0100 result = 0;
0101 else
0102 *result = tmp;
0103 #else
0104 result = gmtime_r(t, result);
0105 #endif
0106 return result;
0107 }
0108
0109 #else
0110
0111 #if defined(__clang__)
0112 # pragma clang diagnostic push
0113 # pragma clang diagnostic ignored "-Wdeprecated-declarations"
0114 #elif (defined(_MSC_VER) && (_MSC_VER >= 1400))
0115 # pragma warning(push)
0116 # pragma warning(disable : 4996)
0117 #endif
0118
0119 inline std::tm* interprocess_gmtime(const std::time_t* t, std::tm* result)
0120 {
0121 result = std::gmtime(t);
0122 return result;
0123 }
0124
0125 #if defined(__clang__)
0126 # pragma clang diagnostic pop
0127 #elif (defined(_MSC_VER) && (_MSC_VER >= 1400))
0128 # pragma warning(pop)
0129 #endif
0130
0131 #endif
0132
0133 #if defined(BOOST_HAS_FTIME)
0134
0135
0136
0137
0138
0139 inline boost::uint64_t file_time_to_microseconds(const boost::winapi::FILETIME_ & ft)
0140 {
0141
0142
0143 const boost::uint64_t shift = 116444736000000000ULL;
0144
0145
0146 boost::uint64_t ft_as_integer = (static_cast< boost::uint64_t >(ft.dwHighDateTime) << 32) | static_cast< boost::uint64_t >(ft.dwLowDateTime);
0147
0148 ft_as_integer -= shift;
0149 return (ft_as_integer / 10U);
0150 }
0151 #endif
0152
0153 inline boost::uint64_t universal_time_u64_us()
0154 {
0155 #ifdef BOOST_HAS_GETTIMEOFDAY
0156 timeval tv;
0157 gettimeofday(&tv, 0);
0158 boost::uint64_t micros = boost::uint64_t(tv.tv_sec)*1000000u;
0159 micros += (boost::uint64_t)tv.tv_usec;
0160 #elif defined(BOOST_HAS_FTIME)
0161 boost::winapi::FILETIME_ ft;
0162 boost::winapi::GetSystemTimeAsFileTime(&ft);
0163 boost::uint64_t micros = file_time_to_microseconds(ft);
0164
0165 #else
0166 #error "Unsupported date-time error: neither gettimeofday nor FILETIME support is detected"
0167 #endif
0168 return micros;
0169 }
0170
0171
0172 template<class TimeType, class Enable = void>
0173 class microsec_clock;
0174
0175 template<class TimeType>
0176 class microsec_clock<TimeType, typename enable_if_ptime<TimeType>::type>
0177 {
0178 private:
0179 typedef typename TimeType::date_type date_type;
0180 typedef typename TimeType::time_duration_type time_duration_type;
0181 typedef typename time_duration_type::rep_type resolution_traits_type;
0182
0183 public:
0184 typedef TimeType time_point;
0185
0186 static time_point universal_time()
0187 {
0188 #ifdef BOOST_HAS_GETTIMEOFDAY
0189 timeval tv;
0190 gettimeofday(&tv, 0);
0191 std::time_t t = tv.tv_sec;
0192 boost::uint32_t sub_sec = static_cast<boost::uint32_t>(tv.tv_usec);
0193 #elif defined(BOOST_HAS_FTIME)
0194 boost::winapi::FILETIME_ ft;
0195 boost::winapi::GetSystemTimeAsFileTime(&ft);
0196 boost::uint64_t micros = file_time_to_microseconds(ft);
0197
0198 std::time_t t = static_cast<std::time_t>(micros / 1000000UL);
0199
0200 boost::uint32_t sub_sec = static_cast<boost::uint32_t>(micros % 1000000UL);
0201 #else
0202 #error "Unsupported date-time error: neither gettimeofday nor FILETIME support is detected"
0203 #endif
0204
0205 std::tm curr;
0206 std::tm* curr_ptr = interprocess_gmtime(&t, &curr);
0207 date_type d(static_cast< typename date_type::year_type::value_type >(curr_ptr->tm_year + 1900),
0208 static_cast< typename date_type::month_type::value_type >(curr_ptr->tm_mon + 1),
0209 static_cast< typename date_type::day_type::value_type >(curr_ptr->tm_mday));
0210
0211
0212
0213
0214
0215 unsigned adjust = static_cast< unsigned >(resolution_traits_type::res_adjust() / 1000000);
0216
0217 time_duration_type td(static_cast< typename time_duration_type::hour_type >(curr_ptr->tm_hour),
0218 static_cast< typename time_duration_type::min_type >(curr_ptr->tm_min),
0219 static_cast< typename time_duration_type::sec_type >(curr_ptr->tm_sec),
0220 static_cast< typename time_duration_type::fractional_seconds_type >(sub_sec * adjust)
0221 );
0222 return time_point(d,td);
0223 }
0224 };
0225
0226 template<class TimePoint>
0227 class microsec_clock<TimePoint, typename enable_if_time_point<TimePoint>::type>
0228 {
0229 public:
0230 typedef typename TimePoint::clock::time_point time_point;
0231
0232 static time_point universal_time()
0233 { return TimePoint::clock::now(); }
0234 };
0235
0236
0237 template<class TimePoint>
0238 inline bool is_pos_infinity(const TimePoint &abs_time, typename enable_if_ptime<TimePoint>::type* = 0)
0239 {
0240 return abs_time.is_pos_infinity();
0241 }
0242
0243 template<class TimePoint>
0244 inline bool is_pos_infinity(const TimePoint &, typename disable_if_ptime<TimePoint>::type* = 0)
0245 {
0246 return false;
0247 }
0248
0249
0250
0251 template<class Duration>
0252 inline boost::uint64_t duration_to_milliseconds(const Duration &abs_time, typename enable_if_ptime_duration<Duration>::type* = 0)
0253 {
0254 return static_cast<boost::uint64_t>(abs_time.total_milliseconds());
0255 }
0256
0257 template<class Duration>
0258 inline boost::uint64_t duration_to_milliseconds(const Duration &d, typename enable_if_duration<Duration>::type* = 0)
0259 {
0260 const double factor = double(Duration::period::num)*1000.0/double(Duration::period::den);
0261 return static_cast<boost::uint64_t>(double(d.count())*factor);
0262 }
0263
0264 template<class Duration>
0265 inline boost::uint64_t duration_to_milliseconds(const Duration&d, typename enable_if_usduration<Duration>::type* = 0)
0266 {
0267 return d.get_microsecs()/1000u;
0268 }
0269
0270 }
0271 }
0272 }
0273
0274 #include <boost/interprocess/detail/config_end.hpp>
0275
0276 #endif
0277