chrono.cpp revision 276792
177298Sobrien//===------------------------- chrono.cpp ---------------------------------===// 277298Sobrien// 377298Sobrien// The LLVM Compiler Infrastructure 477298Sobrien// 577298Sobrien// This file is dual licensed under the MIT and the University of Illinois Open 677298Sobrien// Source Licenses. See LICENSE.TXT for details. 777298Sobrien// 877298Sobrien//===----------------------------------------------------------------------===// 977298Sobrien 1077298Sobrien#include "chrono" 1177298Sobrien#include <sys/time.h> //for gettimeofday and timeval 1277298Sobrien#ifdef __APPLE__ 1377298Sobrien#include <mach/mach_time.h> // mach_absolute_time, mach_timebase_info_data_t 1477298Sobrien#else /* !__APPLE__ */ 1577298Sobrien#include <cerrno> // errno 1677298Sobrien#include <system_error> // __throw_system_error 1777298Sobrien#include <time.h> // clock_gettime, CLOCK_MONOTONIC 1877298Sobrien#endif // __APPLE__ 1977298Sobrien 2077298Sobrien_LIBCPP_BEGIN_NAMESPACE_STD 2177298Sobrien 2277298Sobriennamespace chrono 2377298Sobrien{ 2477298Sobrien 2577298Sobrien// system_clock 2677298Sobrien 2777298Sobrienconst bool system_clock::is_steady; 2877298Sobrien 2977298Sobriensystem_clock::time_point 3077298Sobriensystem_clock::now() _NOEXCEPT 3177298Sobrien{ 3277298Sobrien timeval tv; 3377298Sobrien gettimeofday(&tv, 0); 3477298Sobrien return time_point(seconds(tv.tv_sec) + microseconds(tv.tv_usec)); 3577298Sobrien} 3677298Sobrien 3777298Sobrientime_t 3877298Sobriensystem_clock::to_time_t(const time_point& t) _NOEXCEPT 3977298Sobrien{ 4077298Sobrien return time_t(duration_cast<seconds>(t.time_since_epoch()).count()); 4177298Sobrien} 4277298Sobrien 4377298Sobriensystem_clock::time_point 4477298Sobriensystem_clock::from_time_t(time_t t) _NOEXCEPT 4577298Sobrien{ 4677298Sobrien return system_clock::time_point(seconds(t)); 4777298Sobrien} 4877298Sobrien 4977298Sobrien#ifndef _LIBCPP_HAS_NO_MONOTONIC_CLOCK 5077298Sobrien// steady_clock 5177298Sobrien 5277298Sobrienconst bool steady_clock::is_steady; 5377298Sobrien 5477298Sobrien#ifdef __APPLE__ 5577298Sobrien// mach_absolute_time() * MachInfo.numer / MachInfo.denom is the number of 5677298Sobrien// nanoseconds since the computer booted up. MachInfo.numer and MachInfo.denom 5777298Sobrien// are run time constants supplied by the OS. This clock has no relationship 5877298Sobrien// to the Gregorian calendar. It's main use is as a high resolution timer. 5977298Sobrien 6077298Sobrien// MachInfo.numer / MachInfo.denom is often 1 on the latest equipment. Specialize 6177298Sobrien// for that case as an optimization. 6277298Sobrien 6377298Sobrien#pragma GCC visibility push(hidden) 6477298Sobrien 6577298Sobrienstatic 6677298Sobriensteady_clock::rep 6777298Sobriensteady_simplified() 6877298Sobrien{ 6977298Sobrien return static_cast<steady_clock::rep>(mach_absolute_time()); 7077298Sobrien} 7177298Sobrien 7277298Sobrienstatic 7377298Sobriendouble 7477298Sobriencompute_steady_factor() 7577298Sobrien{ 7677298Sobrien mach_timebase_info_data_t MachInfo; 7777298Sobrien mach_timebase_info(&MachInfo); 7877298Sobrien return static_cast<double>(MachInfo.numer) / MachInfo.denom; 7977298Sobrien} 8077298Sobrien 8177298Sobrienstatic 8277298Sobriensteady_clock::rep 8377298Sobriensteady_full() 8477298Sobrien{ 8577298Sobrien static const double factor = compute_steady_factor(); 8677298Sobrien return static_cast<steady_clock::rep>(mach_absolute_time() * factor); 8777298Sobrien} 8877298Sobrien 8977298Sobrientypedef steady_clock::rep (*FP)(); 9077298Sobrien 9177298Sobrienstatic 9277298SobrienFP 9377298Sobrieninit_steady_clock() 9477298Sobrien{ 9577298Sobrien mach_timebase_info_data_t MachInfo; 9677298Sobrien mach_timebase_info(&MachInfo); 9777298Sobrien if (MachInfo.numer == MachInfo.denom) 9877298Sobrien return &steady_simplified; 9977298Sobrien return &steady_full; 10077298Sobrien} 10177298Sobrien 10277298Sobrien#pragma GCC visibility pop 10377298Sobrien 10477298Sobriensteady_clock::time_point 10577298Sobriensteady_clock::now() _NOEXCEPT 10677298Sobrien{ 10777298Sobrien static FP fp = init_steady_clock(); 10877298Sobrien return time_point(duration(fp())); 10977298Sobrien} 11077298Sobrien 11177298Sobrien#else // __APPLE__ 11277298Sobrien// FIXME: if _LIBCPP_HAS_NO_MONOTONIC_CLOCK, then clock_gettime isn't going to 11377298Sobrien// work. It may be possible to fall back on something else, depending on the system. 11477298Sobrien 11577298Sobrien// Warning: If this is not truly steady, then it is non-conforming. It is 11677298Sobrien// better for it to not exist and have the rest of libc++ use system_clock 11777298Sobrien// instead. 11877298Sobrien 11977298Sobriensteady_clock::time_point 12077298Sobriensteady_clock::now() _NOEXCEPT 12177298Sobrien{ 12277298Sobrien struct timespec tp; 12377298Sobrien if (0 != clock_gettime(CLOCK_MONOTONIC, &tp)) 12477298Sobrien __throw_system_error(errno, "clock_gettime(CLOCK_MONOTONIC) failed"); 12577298Sobrien return time_point(seconds(tp.tv_sec) + nanoseconds(tp.tv_nsec)); 12677298Sobrien} 12777298Sobrien#endif // __APPLE__ 12877298Sobrien 12977298Sobrien#endif // !_LIBCPP_HAS_NO_MONOTONIC_CLOCK 13077298Sobrien 13177298Sobrien} 13277298Sobrien 13377298Sobrien_LIBCPP_END_NAMESPACE_STD 13477298Sobrien