chrono.cpp revision 227825
150027Speter//===------------------------- chrono.cpp ---------------------------------===// 272376Sjake// 372376Sjake// The LLVM Compiler Infrastructure 450027Speter// 550027Speter// This file is dual licensed under the MIT and the University of Illinois Open 650027Speter// Source Licenses. See LICENSE.TXT for details. 750027Speter// 850027Speter//===----------------------------------------------------------------------===// 950027Speter 1050027Speter#include "chrono" 1150027Speter#include <sys/time.h> //for gettimeofday and timeval 1250027Speter#if __APPLE__ 1350027Speter#include <mach/mach_time.h> // mach_absolute_time, mach_timebase_info_data_t 1450027Speter#else /* !__APPLE__ */ 1550027Speter#include <cerrno> // errno 1650027Speter#include <system_error> // __throw_system_error 1750027Speter#include <time.h> // clock_gettime, CLOCK_MONOTONIC 1850027Speter#endif // __APPLE__ 1950027Speter 2050027Speter_LIBCPP_BEGIN_NAMESPACE_STD 2150027Speter 2250027Speternamespace chrono 2350027Speter{ 2450027Speter 2550027Speter// system_clock 2650027Speter 2750027Spetersystem_clock::time_point 2850027Spetersystem_clock::now() _NOEXCEPT 2999072Sjulian{ 3099072Sjulian timeval tv; 3199072Sjulian gettimeofday(&tv, 0); 3299072Sjulian return time_point(seconds(tv.tv_sec) + microseconds(tv.tv_usec)); 3399072Sjulian} 3499072Sjulian 3599072Sjuliantime_t 3699072Sjuliansystem_clock::to_time_t(const time_point& t) _NOEXCEPT 3799072Sjulian{ 3899072Sjulian return time_t(duration_cast<seconds>(t.time_since_epoch()).count()); 3999072Sjulian} 4099072Sjulian 4199072Sjuliansystem_clock::time_point 4299072Sjuliansystem_clock::from_time_t(time_t t) _NOEXCEPT 4399072Sjulian{ 4499072Sjulian return system_clock::time_point(seconds(t)); 4599072Sjulian} 4699072Sjulian 4799072Sjulian// steady_clock 4899072Sjulian 4999072Sjulian#if __APPLE__ 5099072Sjulian// mach_absolute_time() * MachInfo.numer / MachInfo.denom is the number of 5199072Sjulian// nanoseconds since the computer booted up. MachInfo.numer and MachInfo.denom 5299072Sjulian// are run time constants supplied by the OS. This clock has no relationship 5399072Sjulian// to the Gregorian calendar. It's main use is as a high resolution timer. 5499072Sjulian 5599072Sjulian// MachInfo.numer / MachInfo.denom is often 1 on the latest equipment. Specialize 5699072Sjulian// for that case as an optimization. 5799072Sjulian 5899072Sjulian#pragma GCC visibility push(hidden) 5999072Sjulian 6099072Sjulianstatic 6199072Sjuliansteady_clock::rep 6299072Sjuliansteady_simplified() 6399072Sjulian{ 6499072Sjulian return mach_absolute_time(); 6599072Sjulian} 6699072Sjulian 6799072Sjulianstatic 6899072Sjuliandouble 6999072Sjuliancompute_steady_factor() 7099072Sjulian{ 7199072Sjulian mach_timebase_info_data_t MachInfo; 7299072Sjulian mach_timebase_info(&MachInfo); 7399072Sjulian return static_cast<double>(MachInfo.numer) / MachInfo.denom; 7499072Sjulian} 7599072Sjulian 7699072Sjulianstatic 7799072Sjuliansteady_clock::rep 7899072Sjuliansteady_full() 7999072Sjulian{ 8099072Sjulian static const double factor = compute_steady_factor(); 8199072Sjulian return static_cast<steady_clock::rep>(mach_absolute_time() * factor); 8299072Sjulian} 8399072Sjulian 8499072Sjuliantypedef steady_clock::rep (*FP)(); 8599072Sjulian 8699072Sjulianstatic 8799072SjulianFP 8899072Sjulianinit_steady_clock() 8999072Sjulian{ 9099072Sjulian mach_timebase_info_data_t MachInfo; 9199072Sjulian mach_timebase_info(&MachInfo); 9250027Speter if (MachInfo.numer == MachInfo.denom) 9350027Speter return &steady_simplified; 9450027Speter return &steady_full; 9565557Sjasone} 9674914Sjhb 9767365Sjhb#pragma GCC visibility pop 9850027Speter 9950027Spetersteady_clock::time_point 10093607Sdillonsteady_clock::now() _NOEXCEPT 10150027Speter{ 10297261Sjake static FP fp = init_steady_clock(); 10397261Sjake return time_point(duration(fp())); 10450027Speter} 10572376Sjake 10650027Speter#else // __APPLE__ 10772376Sjake// FIXME: We assume that clock_gettime(CLOCK_MONOTONIC) works on 10872376Sjake// non-apple systems. Instead, we should check _POSIX_TIMERS and 10950027Speter// _POSIX_MONOTONIC_CLOCK and fall back to something else if those 11099072Sjulian// don't exist. 11199072Sjulian 11299072Sjulian// Warning: If this is not truly steady, then it is non-conforming. It is 11399072Sjulian// better for it to not exist and have the rest of libc++ use system_clock 11499072Sjulian// instead. 11550027Speter 11699072Sjuliansteady_clock::time_point 11799072Sjuliansteady_clock::now() _NOEXCEPT 11899072Sjulian{ 11950027Speter struct timespec tp; 12083366Sjulian if (0 != clock_gettime(CLOCK_MONOTONIC, &tp)) 12183366Sjulian __throw_system_error(errno, "clock_gettime(CLOCK_MONOTONIC) failed"); 12250027Speter return time_point(seconds(tp.tv_sec) + nanoseconds(tp.tv_nsec)); 12399072Sjulian} 12499072Sjulian#endif // __APPLE__ 12599072Sjulian 12699072Sjulian} 12799072Sjulian 12899072Sjulian_LIBCPP_END_NAMESPACE_STD 12999072Sjulian