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