Changeset View
Changeset View
Standalone View
Standalone View
src/chrono.cpp
//===------------------------- chrono.cpp ---------------------------------===// | //===------------------------- chrono.cpp ---------------------------------===// | ||||
// | // | ||||
// The LLVM Compiler Infrastructure | // The LLVM Compiler Infrastructure | ||||
// | // | ||||
// This file is dual licensed under the MIT and the University of Illinois Open | // This file is dual licensed under the MIT and the University of Illinois Open | ||||
// Source Licenses. See LICENSE.TXT for details. | // Source Licenses. See LICENSE.TXT for details. | ||||
// | // | ||||
//===----------------------------------------------------------------------===// | //===----------------------------------------------------------------------===// | ||||
#include "chrono" | #include "chrono" | ||||
#include "cerrno" // errno | #include "cerrno" // errno | ||||
#include "system_error" // __throw_system_error | #include "system_error" // __throw_system_error | ||||
#include <time.h> // clock_gettime, CLOCK_MONOTONIC and CLOCK_REALTIME | #include <time.h> // clock_gettime, CLOCK_MONOTONIC and CLOCK_REALTIME | ||||
#if (__APPLE__) | |||||
#if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) | |||||
#if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 101200 | |||||
#define _LIBCXX_USE_CLOCK_GETTIME | |||||
#endif | |||||
#elif defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) | |||||
#if __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ >= 100000 | |||||
#define _LIBCXX_USE_CLOCK_GETTIME | |||||
#endif | |||||
#elif defined(__ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__) | |||||
#if __ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__ >= 100000 | |||||
#define _LIBCXX_USE_CLOCK_GETTIME | |||||
#endif | |||||
#elif defined(__ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__) | |||||
#if __ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__ >= 30000 | |||||
#define _LIBCXX_USE_CLOCK_GETTIME | |||||
#endif | |||||
#endif // __ENVIRONMENT_.*_VERSION_MIN_REQUIRED__ | |||||
#else | |||||
#define _LIBCXX_USE_CLOCK_GETTIME | |||||
#endif // __APPLE__ | |||||
#if defined(_LIBCPP_WIN32API) | #if defined(_LIBCPP_WIN32API) | ||||
#define WIN32_LEAN_AND_MEAN | #define WIN32_LEAN_AND_MEAN | ||||
#define VC_EXTRA_LEAN | #define VC_EXTRA_LEAN | ||||
#include <Windows.h> | #include <Windows.h> | ||||
#if _WIN32_WINNT >= _WIN32_WINNT_WIN8 | #if _WIN32_WINNT >= _WIN32_WINNT_WIN8 | ||||
#include <winapifamily.h> | #include <winapifamily.h> | ||||
#endif | #endif | ||||
#else | #else | ||||
▲ Show 20 Lines • Show All 42 Lines • ▼ Show 20 Lines | |||||
#else | #else | ||||
GetSystemTimeAsFileTime(&ft); | GetSystemTimeAsFileTime(&ft); | ||||
#endif | #endif | ||||
filetime_duration d{(static_cast<__int64>(ft.dwHighDateTime) << 32) | | filetime_duration d{(static_cast<__int64>(ft.dwHighDateTime) << 32) | | ||||
static_cast<__int64>(ft.dwLowDateTime)}; | static_cast<__int64>(ft.dwLowDateTime)}; | ||||
return time_point(duration_cast<duration>(d - nt_to_unix_epoch)); | return time_point(duration_cast<duration>(d - nt_to_unix_epoch)); | ||||
#else | #else | ||||
#ifdef CLOCK_REALTIME | #if defined(_LIBCXX_USE_CLOCK_GETTIME) && defined(CLOCK_REALTIME) | ||||
struct timespec tp; | struct timespec tp; | ||||
if (0 != clock_gettime(CLOCK_REALTIME, &tp)) | if (0 != clock_gettime(CLOCK_REALTIME, &tp)) | ||||
__throw_system_error(errno, "clock_gettime(CLOCK_REALTIME) failed"); | __throw_system_error(errno, "clock_gettime(CLOCK_REALTIME) failed"); | ||||
return time_point(seconds(tp.tv_sec) + microseconds(tp.tv_nsec / 1000)); | return time_point(seconds(tp.tv_sec) + microseconds(tp.tv_nsec / 1000)); | ||||
#else // !CLOCK_REALTIME | #else | ||||
timeval tv; | timeval tv; | ||||
gettimeofday(&tv, 0); | gettimeofday(&tv, 0); | ||||
return time_point(seconds(tv.tv_sec) + microseconds(tv.tv_usec)); | return time_point(seconds(tv.tv_sec) + microseconds(tv.tv_usec)); | ||||
#endif // CLOCK_REALTIME | #endif // _LIBCXX_USE_CLOCK_GETTIME && CLOCK_REALTIME | ||||
#endif | #endif | ||||
} | } | ||||
time_t | time_t | ||||
system_clock::to_time_t(const time_point& t) _NOEXCEPT | system_clock::to_time_t(const time_point& t) _NOEXCEPT | ||||
{ | { | ||||
return time_t(duration_cast<seconds>(t.time_since_epoch()).count()); | return time_t(duration_cast<seconds>(t.time_since_epoch()).count()); | ||||
} | } | ||||
Show All 10 Lines | |||||
// Warning: If this is not truly steady, then it is non-conforming. It is | // Warning: If this is not truly steady, then it is non-conforming. It is | ||||
// better for it to not exist and have the rest of libc++ use system_clock | // better for it to not exist and have the rest of libc++ use system_clock | ||||
// instead. | // instead. | ||||
const bool steady_clock::is_steady; | const bool steady_clock::is_steady; | ||||
#if defined(__APPLE__) | #if defined(__APPLE__) | ||||
// Darwin libc versions >= 1133 provide ns precision via CLOCK_UPTIME_RAW | |||||
#if defined(_LIBCXX_USE_CLOCK_GETTIME) && defined(CLOCK_UPTIME_RAW) | |||||
steady_clock::time_point | |||||
steady_clock::now() _NOEXCEPT | |||||
{ | |||||
struct timespec tp; | |||||
if (0 != clock_gettime(CLOCK_UPTIME_RAW, &tp)) | |||||
__throw_system_error(errno, "clock_gettime(CLOCK_UPTIME_RAW) failed"); | |||||
return time_point(seconds(tp.tv_sec) + nanoseconds(tp.tv_nsec)); | |||||
} | |||||
#else | |||||
// mach_absolute_time() * MachInfo.numer / MachInfo.denom is the number of | // mach_absolute_time() * MachInfo.numer / MachInfo.denom is the number of | ||||
// nanoseconds since the computer booted up. MachInfo.numer and MachInfo.denom | // nanoseconds since the computer booted up. MachInfo.numer and MachInfo.denom | ||||
// are run time constants supplied by the OS. This clock has no relationship | // are run time constants supplied by the OS. This clock has no relationship | ||||
// to the Gregorian calendar. It's main use is as a high resolution timer. | // to the Gregorian calendar. It's main use is as a high resolution timer. | ||||
// MachInfo.numer / MachInfo.denom is often 1 on the latest equipment. Specialize | // MachInfo.numer / MachInfo.denom is often 1 on the latest equipment. Specialize | ||||
// for that case as an optimization. | // for that case as an optimization. | ||||
Show All 35 Lines | |||||
} | } | ||||
steady_clock::time_point | steady_clock::time_point | ||||
steady_clock::now() _NOEXCEPT | steady_clock::now() _NOEXCEPT | ||||
{ | { | ||||
static FP fp = init_steady_clock(); | static FP fp = init_steady_clock(); | ||||
return time_point(duration(fp())); | return time_point(duration(fp())); | ||||
} | } | ||||
#endif // defined(_LIBCXX_USE_CLOCK_GETTIME) && defined(CLOCK_UPTIME_RAW) | |||||
#elif defined(_LIBCPP_WIN32API) | #elif defined(_LIBCPP_WIN32API) | ||||
steady_clock::time_point | steady_clock::time_point | ||||
steady_clock::now() _NOEXCEPT | steady_clock::now() _NOEXCEPT | ||||
{ | { | ||||
static LARGE_INTEGER freq; | static LARGE_INTEGER freq; | ||||
static BOOL initialized = FALSE; | static BOOL initialized = FALSE; | ||||
if (!initialized) | if (!initialized) | ||||
initialized = QueryPerformanceFrequency(&freq); // always succceeds | initialized = QueryPerformanceFrequency(&freq); // always succceeds | ||||
LARGE_INTEGER counter; | LARGE_INTEGER counter; | ||||
QueryPerformanceCounter(&counter); | QueryPerformanceCounter(&counter); | ||||
return time_point(duration(counter.QuadPart * nano::den / freq.QuadPart)); | return time_point(duration(counter.QuadPart * nano::den / freq.QuadPart)); | ||||
} | } | ||||
#elif defined(CLOCK_MONOTONIC) | #elif defined(CLOCK_MONOTONIC) | ||||
// On Apple platforms only CLOCK_UPTIME_RAW or mach_absolute_time are able to | |||||
// time functions in the nanosecond range. Thus, they are the only acceptable | |||||
// implementations of steady_clock. | |||||
#ifdef __APPLE__ | |||||
#error "Never use CLOCK_MONOTONIC for steady_clock::now on Apple platforms" | |||||
#endif | |||||
howard.hinnant: Nice, thanks! | |||||
EricWFUnsubmitted Not Done ReplyInline ActionsThis code is currently dead due to the structure of the #ifdefs. However I think it's great documentation and great future proofing! EricWF: This code is currently dead due to the structure of the `#ifdef`s. However I think it's great… | |||||
steady_clock::time_point | steady_clock::time_point | ||||
steady_clock::now() _NOEXCEPT | steady_clock::now() _NOEXCEPT | ||||
{ | { | ||||
struct timespec tp; | struct timespec tp; | ||||
if (0 != clock_gettime(CLOCK_MONOTONIC, &tp)) | if (0 != clock_gettime(CLOCK_MONOTONIC, &tp)) | ||||
__throw_system_error(errno, "clock_gettime(CLOCK_MONOTONIC) failed"); | __throw_system_error(errno, "clock_gettime(CLOCK_MONOTONIC) failed"); | ||||
return time_point(seconds(tp.tv_sec) + nanoseconds(tp.tv_nsec)); | return time_point(seconds(tp.tv_sec) + nanoseconds(tp.tv_nsec)); | ||||
} | } | ||||
Show All 10 Lines |
Nice, thanks!