Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
wine-mirror
GitHub Repository: wine-mirror/wine
Path: blob/master/libs/c++/src/chrono.cpp
12346 views
1
//===------------------------- chrono.cpp ---------------------------------===//
2
//
3
// The LLVM Compiler Infrastructure
4
//
5
// This file is dual licensed under the MIT and the University of Illinois Open
6
// Source Licenses. See LICENSE.TXT for details.
7
//
8
//===----------------------------------------------------------------------===//
9
10
#include "chrono"
11
#include "cerrno" // errno
12
#include "system_error" // __throw_system_error
13
#include <time.h> // clock_gettime, CLOCK_MONOTONIC and CLOCK_REALTIME
14
#include "include/apple_availability.h"
15
16
#if !defined(__APPLE__)
17
#define _LIBCPP_USE_CLOCK_GETTIME
18
#endif // __APPLE__
19
20
#if defined(_LIBCPP_WIN32API)
21
#define WIN32_LEAN_AND_MEAN
22
#define VC_EXTRA_LEAN
23
#include <windows.h>
24
#if _WIN32_WINNT >= _WIN32_WINNT_WIN8
25
#include <winapifamily.h>
26
#endif
27
#else
28
#if !defined(CLOCK_REALTIME) || !defined(_LIBCPP_USE_CLOCK_GETTIME)
29
#include <sys/time.h> // for gettimeofday and timeval
30
#endif // !defined(CLOCK_REALTIME)
31
#endif // defined(_LIBCPP_WIN32API)
32
33
#if !defined(_LIBCPP_HAS_NO_MONOTONIC_CLOCK)
34
#if __APPLE__
35
#include <mach/mach_time.h> // mach_absolute_time, mach_timebase_info_data_t
36
#elif !defined(_LIBCPP_WIN32API) && !defined(CLOCK_MONOTONIC)
37
#error "Monotonic clock not implemented"
38
#endif
39
#endif
40
41
_LIBCPP_BEGIN_NAMESPACE_STD
42
43
namespace chrono
44
{
45
46
// system_clock
47
48
const bool system_clock::is_steady;
49
50
system_clock::time_point
51
system_clock::now() _NOEXCEPT
52
{
53
#if defined(_LIBCPP_WIN32API)
54
// FILETIME is in 100ns units
55
using filetime_duration =
56
_VSTD::chrono::duration<__int64,
57
_VSTD::ratio_multiply<_VSTD::ratio<100, 1>,
58
nanoseconds::period>>;
59
60
// The Windows epoch is Jan 1 1601, the Unix epoch Jan 1 1970.
61
static _LIBCPP_CONSTEXPR const seconds nt_to_unix_epoch{11644473600};
62
63
FILETIME ft;
64
#if _WIN32_WINNT >= _WIN32_WINNT_WIN8
65
#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
66
GetSystemTimePreciseAsFileTime(&ft);
67
#else
68
GetSystemTimeAsFileTime(&ft);
69
#endif
70
#else
71
GetSystemTimeAsFileTime(&ft);
72
#endif
73
74
filetime_duration d{(static_cast<__int64>(ft.dwHighDateTime) << 32) |
75
static_cast<__int64>(ft.dwLowDateTime)};
76
return time_point(duration_cast<duration>(d - nt_to_unix_epoch));
77
#else
78
#if defined(_LIBCPP_USE_CLOCK_GETTIME) && defined(CLOCK_REALTIME)
79
struct timespec tp;
80
if (0 != clock_gettime(CLOCK_REALTIME, &tp))
81
__throw_system_error(errno, "clock_gettime(CLOCK_REALTIME) failed");
82
return time_point(seconds(tp.tv_sec) + microseconds(tp.tv_nsec / 1000));
83
#else
84
timeval tv;
85
gettimeofday(&tv, 0);
86
return time_point(seconds(tv.tv_sec) + microseconds(tv.tv_usec));
87
#endif // _LIBCPP_USE_CLOCK_GETTIME && CLOCK_REALTIME
88
#endif
89
}
90
91
time_t
92
system_clock::to_time_t(const time_point& t) _NOEXCEPT
93
{
94
return time_t(duration_cast<seconds>(t.time_since_epoch()).count());
95
}
96
97
system_clock::time_point
98
system_clock::from_time_t(time_t t) _NOEXCEPT
99
{
100
return system_clock::time_point(seconds(t));
101
}
102
103
#ifndef _LIBCPP_HAS_NO_MONOTONIC_CLOCK
104
// steady_clock
105
//
106
// Warning: If this is not truly steady, then it is non-conforming. It is
107
// better for it to not exist and have the rest of libc++ use system_clock
108
// instead.
109
110
const bool steady_clock::is_steady;
111
112
#if defined(__APPLE__)
113
114
// Darwin libc versions >= 1133 provide ns precision via CLOCK_UPTIME_RAW
115
#if defined(_LIBCPP_USE_CLOCK_GETTIME) && defined(CLOCK_UPTIME_RAW)
116
steady_clock::time_point
117
steady_clock::now() _NOEXCEPT
118
{
119
struct timespec tp;
120
if (0 != clock_gettime(CLOCK_UPTIME_RAW, &tp))
121
__throw_system_error(errno, "clock_gettime(CLOCK_UPTIME_RAW) failed");
122
return time_point(seconds(tp.tv_sec) + nanoseconds(tp.tv_nsec));
123
}
124
125
#else
126
// mach_absolute_time() * MachInfo.numer / MachInfo.denom is the number of
127
// nanoseconds since the computer booted up. MachInfo.numer and MachInfo.denom
128
// are run time constants supplied by the OS. This clock has no relationship
129
// to the Gregorian calendar. It's main use is as a high resolution timer.
130
131
// MachInfo.numer / MachInfo.denom is often 1 on the latest equipment. Specialize
132
// for that case as an optimization.
133
134
static
135
steady_clock::rep
136
steady_simplified()
137
{
138
return static_cast<steady_clock::rep>(mach_absolute_time());
139
}
140
141
static
142
double
143
compute_steady_factor()
144
{
145
mach_timebase_info_data_t MachInfo;
146
mach_timebase_info(&MachInfo);
147
return static_cast<double>(MachInfo.numer) / MachInfo.denom;
148
}
149
150
static
151
steady_clock::rep
152
steady_full()
153
{
154
static const double factor = compute_steady_factor();
155
return static_cast<steady_clock::rep>(mach_absolute_time() * factor);
156
}
157
158
typedef steady_clock::rep (*FP)();
159
160
static
161
FP
162
init_steady_clock()
163
{
164
mach_timebase_info_data_t MachInfo;
165
mach_timebase_info(&MachInfo);
166
if (MachInfo.numer == MachInfo.denom)
167
return &steady_simplified;
168
return &steady_full;
169
}
170
171
steady_clock::time_point
172
steady_clock::now() _NOEXCEPT
173
{
174
static FP fp = init_steady_clock();
175
return time_point(duration(fp()));
176
}
177
#endif // defined(_LIBCPP_USE_CLOCK_GETTIME) && defined(CLOCK_UPTIME_RAW)
178
179
#elif defined(_LIBCPP_WIN32API)
180
181
steady_clock::time_point
182
steady_clock::now() _NOEXCEPT
183
{
184
static LARGE_INTEGER freq;
185
static BOOL initialized = FALSE;
186
if (!initialized)
187
initialized = QueryPerformanceFrequency(&freq); // always succceeds
188
189
LARGE_INTEGER counter;
190
QueryPerformanceCounter(&counter);
191
return time_point(duration(counter.QuadPart * nano::den / freq.QuadPart));
192
}
193
194
#elif defined(CLOCK_MONOTONIC)
195
196
// On Apple platforms only CLOCK_UPTIME_RAW or mach_absolute_time are able to
197
// time functions in the nanosecond range. Thus, they are the only acceptable
198
// implementations of steady_clock.
199
#ifdef __APPLE__
200
#error "Never use CLOCK_MONOTONIC for steady_clock::now on Apple platforms"
201
#endif
202
203
steady_clock::time_point
204
steady_clock::now() _NOEXCEPT
205
{
206
struct timespec tp;
207
if (0 != clock_gettime(CLOCK_MONOTONIC, &tp))
208
__throw_system_error(errno, "clock_gettime(CLOCK_MONOTONIC) failed");
209
return time_point(seconds(tp.tv_sec) + nanoseconds(tp.tv_nsec));
210
}
211
212
#else
213
#error "Monotonic clock not implemented"
214
#endif
215
216
#endif // !_LIBCPP_HAS_NO_MONOTONIC_CLOCK
217
218
}
219
220
_LIBCPP_END_NAMESPACE_STD
221
222