diff --git a/projects/libcxx/src/chrono.cpp b/projects/libcxx/src/chrono.cpp index f0a5d50..c7fbd90 100644 --- a/projects/libcxx/src/chrono.cpp +++ b/projects/libcxx/src/chrono.cpp @@ -33,6 +33,11 @@ # endif // !defined(CLOCK_REALTIME) #endif // defined(_LIBCPP_WIN32API) + // restore previous libcxx fallback +#if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 101200 +#include +#endif + #if defined(__ELF__) && defined(_LIBCPP_LINK_RT_LIB) # pragma comment(lib, "rt") #endif @@ -110,6 +115,8 @@ const bool steady_clock::is_steady; #if defined(__APPLE__) +#if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 101200 + #if !defined(CLOCK_MONOTONIC_RAW) # error "Building libc++ on Apple platforms requires CLOCK_MONOTONIC_RAW" #endif @@ -127,6 +134,61 @@ steady_clock::now() _NOEXCEPT __throw_system_error(errno, "clock_gettime(CLOCK_MONOTONIC_RAW) failed"); return time_point(seconds(tp.tv_sec) + nanoseconds(tp.tv_nsec)); } +#else + // restore previous libcxx fallback + // + // mach_absolute_time() * MachInfo.numer / MachInfo.denom is the number of + // nanoseconds since the computer booted up. MachInfo.numer and MachInfo.denom + // 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. + + // MachInfo.numer / MachInfo.denom is often 1 on the latest equipment. Specialize + // for that case as an optimization. + + static + steady_clock::rep + steady_simplified() + { + return static_cast(mach_absolute_time()); + } + + static + double + compute_steady_factor() + { + mach_timebase_info_data_t MachInfo; + mach_timebase_info(&MachInfo); + return static_cast(MachInfo.numer) / MachInfo.denom; + } + + static + steady_clock::rep + steady_full() + { + static const double factor = compute_steady_factor(); + return static_cast(mach_absolute_time() * factor); + } + + typedef steady_clock::rep (*FP)(); + + static + FP + init_steady_clock() + { + mach_timebase_info_data_t MachInfo; + mach_timebase_info(&MachInfo); + if (MachInfo.numer == MachInfo.denom) + return &steady_simplified; + return &steady_full; + } + + steady_clock::time_point + steady_clock::now() _NOEXCEPT + { + static FP fp = init_steady_clock(); + return time_point(duration(fp())); + } +#endif // restore previous libcxx fallback #elif defined(_LIBCPP_WIN32API)