-
Notifications
You must be signed in to change notification settings - Fork 7
/
Copy pathnanotime.hpp
183 lines (152 loc) · 6.57 KB
/
nanotime.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
// solid/system/nanotime.hpp
//
// Copyright (c) 2007, 2008 Valentin Palade (vipalade @ gmail . com)
//
// This file is part of SolidFrame framework.
//
// Distributed under the Boost Software License, Version 1.0.
// See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt.
//
#pragma once
#include "convertors.hpp"
#include <chrono>
#include <time.h>
namespace solid {
//! A timespec wrapper
/*!
Basicaly it is a pair of seconds and nanoseconds.
*/
struct NanoTime : public timespec {
using SecondT = decltype(timespec::tv_sec);
using NanoSecondT = decltype(timespec::tv_nsec);
static NanoTime max()
{
return NanoTime{std::numeric_limits<SecondT>::max(), std::numeric_limits<NanoSecondT>::max()};
}
template <class Rep, class Period>
NanoTime(const std::chrono::duration<Rep, Period>& _duration)
{
tv_sec = std::chrono::duration_cast<std::chrono::seconds>(_duration).count();
tv_nsec = std::chrono::duration_cast<std::chrono::nanoseconds>(_duration).count() % 1000000000L;
}
template <class Clock, class Duration>
NanoTime(const std::chrono::time_point<Clock, Duration>& _time_point)
{
const auto duration = _time_point.time_since_epoch();
tv_sec = std::chrono::duration_cast<std::chrono::seconds>(duration).count();
tv_nsec = std::chrono::duration_cast<std::chrono::nanoseconds>(duration).count() % 1000000000L;
}
NanoTime(const SecondT _sec = 0, const NanoSecondT _nsec = 0)
{
tv_sec = _sec;
tv_nsec = _nsec;
}
static NanoTime nowSystem()
{
return NanoTime(std::chrono::system_clock::now());
}
static NanoTime nowSteady()
{
return NanoTime(std::chrono::steady_clock::now());
}
explicit operator bool() const noexcept
{
return tv_sec == 0 && tv_nsec == 0;
}
template <class TimePoint>
TimePoint timePointCast() const
{
const typename TimePoint::duration dur = std::chrono::duration_cast<typename TimePoint::duration>(std::chrono::seconds(tv_sec) + std::chrono::nanoseconds(tv_nsec));
return TimePoint() + dur;
}
template <class TimePoint, class MyClock>
TimePoint timePointClockCast() const
{
using MyTimePoint = std::chrono::time_point<MyClock, typename TimePoint::duration>;
const MyTimePoint my_time;
TimePoint re_time;
doClockCast(re_time, my_time);
return re_time;
}
template <class Duration>
Duration durationCast() const
{
return std::chrono::duration_cast<Duration>(std::chrono::seconds(tv_sec)) + std::chrono::duration_cast<Duration>(std::chrono::nanoseconds(tv_nsec));
}
template <class Rep, class Period>
NanoTime& operator=(const std::chrono::duration<Rep, Period>& _duration)
{
tv_sec = std::chrono::duration_cast<std::chrono::seconds>(_duration).count();
tv_nsec = std::chrono::duration_cast<std::chrono::nanoseconds>(_duration).count() % 1000000000L;
return *this;
}
template <class Clock, class Duration>
NanoTime& operator=(const std::chrono::time_point<Clock, Duration>& _time_point)
{
const auto duration = _time_point.time_since_epoch();
tv_sec = std::chrono::duration_cast<std::chrono::seconds>(duration).count();
tv_nsec = std::chrono::duration_cast<std::chrono::nanoseconds>(duration).count() % 1000000000L;
return *this;
}
auto seconds() const { return tv_sec; }
auto nanoSeconds() const { return tv_nsec; }
bool isMax() const;
bool operator!=(const NanoTime& _ts) const;
bool operator==(const NanoTime& _ts) const;
bool operator>=(const NanoTime& _ts) const;
bool operator>(const NanoTime& _ts) const;
bool operator<=(const NanoTime& _ts) const;
bool operator<(const NanoTime& _ts) const;
private:
template <class Clock, class Duration>
void doClockCast(std::chrono::time_point<Clock, Duration>& _rtp, const std::chrono::time_point<Clock, Duration>& /*_rmytp*/) const
{
_rtp = timePointCast<std::chrono::time_point<Clock, Duration>>();
}
template <class Clock, class MyClock, class Duration>
void doClockCast(std::chrono::time_point<Clock, Duration>& _rtp, const std::chrono::time_point<MyClock, Duration>& /*_rmytp*/) const
{
const typename Clock::time_point other_now = Clock::now();
const typename MyClock::time_point my_now = MyClock::now();
const typename MyClock::time_point my_tp = timePointCast<typename MyClock::time_point>();
const auto delta = my_tp - my_now;
_rtp = std::chrono::time_point_cast<Duration>(other_now + delta);
}
};
template <class Rep, class Period>
NanoTime operator+(NanoTime _first, const std::chrono::duration<Rep, Period>& _duration)
{
_first.tv_sec += std::chrono::duration_cast<std::chrono::seconds>(_duration).count();
_first.tv_nsec += std::chrono::duration_cast<std::chrono::nanoseconds>(_duration).count() % 1000000000L;
_first.tv_sec += (_first.tv_nsec / 1000000000L);
_first.tv_nsec = (_first.tv_nsec % 1000000000L);
return _first;
}
namespace detail {
template <class Clock, class RetDuration, class Duration>
void time_point_clock_cast(std::chrono::time_point<Clock, RetDuration>& _rret_tp, const std::chrono::time_point<Clock, Duration>& _rtp)
{
_rret_tp = std::chrono::time_point_cast<Duration>(_rtp);
}
template <class RetClock, class RetDuration, class Clock, class Duration>
void time_point_clock_cast(std::chrono::time_point<RetClock, RetDuration>& /*_rret_tp*/, const std::chrono::time_point<Clock, Duration>& _rtp)
{
const typename RetClock::time_point ret_now = RetClock::now();
const typename Clock::time_point my_now = Clock::now();
const typename Clock::time_point my_tp = std::chrono::time_point_cast<typename Clock::duration>(_rtp);
const auto delta = my_tp - my_now;
_rtp = std::chrono::time_point_cast<typename RetClock::duration>(ret_now + delta);
}
} // namespace detail
template <class RetClock, class Clock, class Duration>
typename RetClock::time_point time_point_clock_cast(const std::chrono::time_point<Clock, Duration>& _rtp)
{
typename RetClock::time_point ret_tp;
detail::time_point_clock_cast(ret_tp, _rtp);
return ret_tp;
}
std::ostream& operator<<(std::ostream& _ros, const NanoTime& _ntime);
#ifndef SOLID_HAS_NO_INLINES
#include "solid/system/nanotime.ipp"
#endif
} // namespace solid