1 /* 2 * Copyright Andrey Semashev 2013. 3 * Distributed under the Boost Software License, Version 1.0. 4 * (See accompanying file LICENSE_1_0.txt or copy at 5 * http://www.boost.org/LICENSE_1_0.txt) 6 */ 7 /*! 8 * \file time_units.hpp 9 * 10 * \brief This header is the Boost.Sync library implementation, see the library documentation 11 * at http://www.boost.org/doc/libs/release/libs/sync/doc/html/index.html. 12 */ 13 14 #ifndef BOOST_SYNC_DETAIL_TIME_UNITS_HPP_INCLUDED_ 15 #define BOOST_SYNC_DETAIL_TIME_UNITS_HPP_INCLUDED_ 16 17 #include <time.h> 18 #include <boost/cstdint.hpp> 19 #include <boost/sync/detail/config.hpp> 20 21 #if defined(BOOST_SYNC_DETAIL_PLATFORM_WINAPI) 22 #include <boost/detail/winapi/time.hpp> 23 #elif defined(BOOST_SYNC_DETAIL_PLATFORM_MACH) 24 #include <sys/time.h> // gettimeofday, timeval 25 #endif 26 27 #include <boost/sync/detail/header.hpp> 28 29 #ifdef BOOST_HAS_PRAGMA_ONCE 30 #pragma once 31 #endif 32 33 namespace boost { 34 35 namespace sync { 36 37 namespace detail { 38 39 class system_duration 40 { 41 public: 42 typedef int64_t native_type; 43 44 #if defined(BOOST_SYNC_DETAIL_PLATFORM_WINAPI) 45 // The native duration is in milliseconds 46 static BOOST_CONSTEXPR_OR_CONST uint64_t subsecond_fraction = 1000u; 47 #else 48 // The native duration is in nanoseconds 49 static BOOST_CONSTEXPR_OR_CONST uint64_t subsecond_fraction = 1000000000u; 50 #endif 51 52 private: 53 native_type m_value; 54 55 public: system_duration()56 BOOST_CONSTEXPR system_duration() BOOST_NOEXCEPT : m_value(0) {} system_duration(native_type value)57 explicit system_duration(native_type value) BOOST_NOEXCEPT : m_value(value) {} 58 get() const59 native_type get() const BOOST_NOEXCEPT { return m_value; } 60 operator +=(system_duration const & that)61 system_duration& operator+= (system_duration const& that) BOOST_NOEXCEPT 62 { 63 m_value += that.m_value; 64 return *this; 65 } operator -=(system_duration const & that)66 system_duration& operator-= (system_duration const& that) BOOST_NOEXCEPT 67 { 68 m_value -= that.m_value; 69 return *this; 70 } operator -() const71 system_duration operator- () const BOOST_NOEXCEPT 72 { 73 return system_duration(-m_value); 74 } 75 operator +(system_duration left,system_duration const & right)76 friend system_duration operator+ (system_duration left, system_duration const& right) BOOST_NOEXCEPT 77 { 78 left += right; 79 return left; 80 } operator -(system_duration left,system_duration const & right)81 friend system_duration operator- (system_duration left, system_duration const& right) BOOST_NOEXCEPT 82 { 83 left -= right; 84 return left; 85 } 86 }; 87 88 #if defined(BOOST_SYNC_DETAIL_PLATFORM_WINAPI) 89 90 class system_time_point 91 { 92 public: 93 typedef uint64_t native_type; 94 // The native subsecond precision is 100 nanoseconds 95 static BOOST_CONSTEXPR_OR_CONST uint64_t subsecond_fraction = 10000000u; 96 97 private: 98 //! 100 nanosecond units since 1601-Jan-01 (i.e. equivalent to FILETIME) 99 uint64_t m_value; 100 101 public: system_time_point()102 BOOST_CONSTEXPR system_time_point() BOOST_NOEXCEPT : m_value(0) {} system_time_point(time_t t,unsigned int subsecond=0)103 explicit system_time_point(time_t t, unsigned int subsecond = 0) BOOST_NOEXCEPT : 104 m_value(static_cast< uint64_t >(t) * subsecond_fraction + subsecond + 116444736000000000ull) 105 { 106 } 107 108 //! Creates time point from duration since 1970-Jan-01 system_time_point(system_duration dur)109 explicit system_time_point(system_duration dur) BOOST_NOEXCEPT : 110 m_value(dur.get() * 10000u + 116444736000000000ull) 111 { 112 } 113 get() const114 native_type const& get() const BOOST_NOEXCEPT { return m_value; } 115 now()116 static system_time_point now() BOOST_NOEXCEPT 117 { 118 system_time_point res; 119 boost::detail::winapi::GetSystemTimeAsFileTime(reinterpret_cast< boost::detail::winapi::FILETIME_* >(&res.m_value)); 120 return res; 121 } 122 operator +=(system_duration const & dur)123 system_time_point& operator+= (system_duration const& dur) BOOST_NOEXCEPT 124 { 125 m_value += dur.get() * 10000u; 126 return *this; 127 } operator -=(system_duration const & dur)128 system_time_point& operator-= (system_duration const& dur) BOOST_NOEXCEPT 129 { 130 m_value -= dur.get() * 10000u; 131 return *this; 132 } 133 operator +(system_time_point left,system_duration const & right)134 friend system_time_point operator+ (system_time_point left, system_duration const& right) BOOST_NOEXCEPT 135 { 136 left += right; 137 return left; 138 } operator -(system_time_point left,system_duration const & right)139 friend system_time_point operator- (system_time_point left, system_duration const& right) BOOST_NOEXCEPT 140 { 141 left -= right; 142 return left; 143 } 144 operator -(system_time_point const & left,system_time_point const & right)145 friend system_duration operator- (system_time_point const& left, system_time_point const& right) BOOST_NOEXCEPT 146 { 147 return system_duration(static_cast< system_duration::native_type >(left.m_value - right.m_value) / 10000u); 148 } 149 }; 150 151 #else 152 153 class system_time_point 154 { 155 public: 156 typedef struct ::timespec native_type; 157 // The native subsecond precision is nanoseconds 158 static BOOST_CONSTEXPR_OR_CONST uint64_t subsecond_fraction = system_duration::subsecond_fraction; 159 160 private: 161 //! Time, since 1970-Jan-01 162 native_type m_value; 163 164 public: system_time_point()165 BOOST_CONSTEXPR system_time_point() BOOST_NOEXCEPT : m_value() {} system_time_point(time_t t,unsigned int subsecond=0)166 explicit system_time_point(time_t t, unsigned int subsecond = 0) BOOST_NOEXCEPT 167 { 168 m_value.tv_sec = t; 169 m_value.tv_nsec = subsecond; 170 } 171 172 //! Creates time point from duration since 1970-Jan-01 system_time_point(system_duration dur)173 explicit system_time_point(system_duration dur) BOOST_NOEXCEPT 174 { 175 m_value.tv_sec = dur.get() / subsecond_fraction; 176 m_value.tv_nsec = dur.get() % subsecond_fraction; 177 } 178 get() const179 native_type const& get() const BOOST_NOEXCEPT { return m_value; } 180 now()181 static system_time_point now() BOOST_NOEXCEPT 182 { 183 #if defined(BOOST_HAS_CLOCK_GETTIME) 184 system_time_point t; 185 ::clock_gettime(CLOCK_REALTIME, &t.m_value); 186 return t; 187 #elif defined(BOOST_SYNC_DETAIL_PLATFORM_MACH) 188 ::timeval tv; 189 ::gettimeofday(&tv, 0); 190 return system_time_point(tv.tv_sec, tv.tv_usec * (subsecond_fraction / 1000000u)); 191 #else 192 return system_time_point(::time(0)); 193 #endif 194 } 195 operator +=(system_duration const & dur)196 system_time_point& operator+= (system_duration const& dur) BOOST_NOEXCEPT 197 { 198 int64_t nsec = static_cast< int64_t >(m_value.tv_nsec) + dur.get(); 199 int64_t tv_nsec = nsec % system_duration::subsecond_fraction; 200 if (tv_nsec < 0) 201 { 202 tv_nsec += subsecond_fraction; 203 --m_value.tv_sec; 204 } 205 m_value.tv_nsec = tv_nsec; 206 m_value.tv_sec += nsec / system_duration::subsecond_fraction; 207 208 return *this; 209 } operator -=(system_duration const & dur)210 system_time_point& operator-= (system_duration const& dur) BOOST_NOEXCEPT 211 { 212 return operator+= (-dur); 213 } 214 operator +(system_time_point left,system_duration const & right)215 friend system_time_point operator+ (system_time_point left, system_duration const& right) BOOST_NOEXCEPT 216 { 217 left += right; 218 return left; 219 } operator -(system_time_point left,system_duration const & right)220 friend system_time_point operator- (system_time_point left, system_duration const& right) BOOST_NOEXCEPT 221 { 222 left -= right; 223 return left; 224 } 225 operator -(system_time_point const & left,system_time_point const & right)226 friend system_duration operator- (system_time_point const& left, system_time_point const& right) BOOST_NOEXCEPT 227 { 228 int64_t seconds = static_cast< int64_t >(left.m_value.tv_sec) - static_cast< int64_t >(right.m_value.tv_sec); 229 int64_t nseconds = static_cast< int64_t >(left.m_value.tv_nsec) - static_cast< int64_t >(right.m_value.tv_nsec); 230 return system_duration(seconds * system_duration::subsecond_fraction + nseconds); 231 } 232 }; 233 234 #endif 235 236 template< typename TimePoint > 237 class chrono_time_point : 238 public TimePoint 239 { 240 public: 241 typedef TimePoint time_point; 242 typedef typename time_point::clock clock; 243 typedef typename time_point::duration duration; 244 245 private: 246 time_point m_value; 247 248 public: chrono_time_point()249 BOOST_DEFAULTED_FUNCTION(chrono_time_point(), : m_value() {}) 250 BOOST_DEFAULTED_FUNCTION(chrono_time_point(chrono_time_point const& that), : m_value(that.m_value) {}) 251 252 explicit chrono_time_point(time_point const& that) : m_value(that) 253 { 254 } 255 256 template< typename T > chrono_time_point(T const & arg)257 explicit chrono_time_point(T const& arg) : m_value(arg) 258 { 259 } 260 get() const261 time_point const& get() const { return m_value; } 262 now()263 static chrono_time_point now() { return chrono_time_point(clock::now()); } 264 operator +=(duration const & dur)265 chrono_time_point& operator+= (duration const& dur) 266 { 267 m_value += dur; 268 return *this; 269 } operator -=(duration const & dur)270 chrono_time_point& operator-= (duration const& dur) 271 { 272 m_value -= dur; 273 return *this; 274 } 275 operator +(chrono_time_point left,duration const & right)276 friend chrono_time_point operator+ (chrono_time_point left, duration const& right) 277 { 278 left.m_value += right; 279 return left; 280 } operator -(chrono_time_point left,duration const & right)281 friend chrono_time_point operator- (chrono_time_point left, duration const& right) 282 { 283 left.m_value -= right; 284 return left; 285 } 286 operator -(chrono_time_point const & left,chrono_time_point const & right)287 friend duration operator- (chrono_time_point const& left, chrono_time_point const& right) 288 { 289 return left.m_value - right.m_value; 290 } 291 }; 292 293 } // namespace detail 294 295 } // namespace sync 296 297 } // namespace boost 298 299 #include <boost/sync/detail/footer.hpp> 300 301 #endif // BOOST_SYNC_DETAIL_TIME_UNITS_HPP_INCLUDED_ 302