chrono.cpp revision 287679
1230557Sjimharris//===------------------------- chrono.cpp ---------------------------------===// 2230557Sjimharris// 3230557Sjimharris// The LLVM Compiler Infrastructure 4230557Sjimharris// 5230557Sjimharris// This file is dual licensed under the MIT and the University of Illinois Open 6230557Sjimharris// Source Licenses. See LICENSE.TXT for details. 7230557Sjimharris// 8230557Sjimharris//===----------------------------------------------------------------------===// 9230557Sjimharris 10230557Sjimharris#include "chrono" 11230557Sjimharris#include <sys/time.h> //for gettimeofday and timeval 12230557Sjimharris#ifdef __APPLE__ 13230557Sjimharris#include <mach/mach_time.h> // mach_absolute_time, mach_timebase_info_data_t 14230557Sjimharris#else /* !__APPLE__ */ 15230557Sjimharris#include <cerrno> // errno 16230557Sjimharris#include <system_error> // __throw_system_error 17230557Sjimharris#include <time.h> // clock_gettime, CLOCK_MONOTONIC 18230557Sjimharris#endif // __APPLE__ 19230557Sjimharris 20230557Sjimharris_LIBCPP_BEGIN_NAMESPACE_STD 21230557Sjimharris 22230557Sjimharrisnamespace chrono 23230557Sjimharris{ 24230557Sjimharris 25230557Sjimharris// system_clock 26230557Sjimharris 27230557Sjimharrisconst bool system_clock::is_steady; 28230557Sjimharris 29230557Sjimharrissystem_clock::time_point 30230557Sjimharrissystem_clock::now() _NOEXCEPT 31230557Sjimharris{ 32230557Sjimharris timeval tv; 33230557Sjimharris gettimeofday(&tv, 0); 34230557Sjimharris return time_point(seconds(tv.tv_sec) + microseconds(tv.tv_usec)); 35230557Sjimharris} 36230557Sjimharris 37230557Sjimharristime_t 38230557Sjimharrissystem_clock::to_time_t(const time_point& t) _NOEXCEPT 39230557Sjimharris{ 40230557Sjimharris return time_t(duration_cast<seconds>(t.time_since_epoch()).count()); 41230557Sjimharris} 42230557Sjimharris 43230557Sjimharrissystem_clock::time_point 44230557Sjimharrissystem_clock::from_time_t(time_t t) _NOEXCEPT 45230557Sjimharris{ 46230557Sjimharris return system_clock::time_point(seconds(t)); 47230557Sjimharris} 48230557Sjimharris 49230557Sjimharris#ifndef _LIBCPP_HAS_NO_MONOTONIC_CLOCK 50230557Sjimharris// steady_clock 51230557Sjimharris 52230557Sjimharrisconst bool steady_clock::is_steady; 53230557Sjimharris 54230557Sjimharris#ifdef __APPLE__ 55230557Sjimharris// mach_absolute_time() * MachInfo.numer / MachInfo.denom is the number of 56230557Sjimharris// nanoseconds since the computer booted up. MachInfo.numer and MachInfo.denom 57230557Sjimharris// are run time constants supplied by the OS. This clock has no relationship 58230557Sjimharris// to the Gregorian calendar. It's main use is as a high resolution timer. 59230557Sjimharris 60230557Sjimharris// MachInfo.numer / MachInfo.denom is often 1 on the latest equipment. Specialize 61230557Sjimharris// for that case as an optimization. 62230557Sjimharris 63230557Sjimharris#pragma GCC visibility push(hidden) 64230557Sjimharris 65230557Sjimharrisstatic 66230557Sjimharrissteady_clock::rep 67230557Sjimharrissteady_simplified() 68230557Sjimharris{ 69230557Sjimharris return static_cast<steady_clock::rep>(mach_absolute_time()); 70230557Sjimharris} 71230557Sjimharris 72230557Sjimharrisstatic 73230557Sjimharrisdouble 74230557Sjimharriscompute_steady_factor() 75230557Sjimharris{ 76230557Sjimharris mach_timebase_info_data_t MachInfo; 77230557Sjimharris mach_timebase_info(&MachInfo); 78230557Sjimharris return static_cast<double>(MachInfo.numer) / MachInfo.denom; 79230557Sjimharris} 80230557Sjimharris 81230557Sjimharrisstatic 82230557Sjimharrissteady_clock::rep 83230557Sjimharrissteady_full() 84230557Sjimharris{ 85230557Sjimharris static const double factor = compute_steady_factor(); 86230557Sjimharris return static_cast<steady_clock::rep>(mach_absolute_time() * factor); 87230557Sjimharris} 88230557Sjimharris 89230557Sjimharristypedef steady_clock::rep (*FP)(); 90230557Sjimharris 91230557Sjimharrisstatic 92230557SjimharrisFP 93230557Sjimharrisinit_steady_clock() 94230557Sjimharris{ 95230557Sjimharris mach_timebase_info_data_t MachInfo; 96230557Sjimharris mach_timebase_info(&MachInfo); 97298955Spfg if (MachInfo.numer == MachInfo.denom) 98230557Sjimharris return &steady_simplified; 99230557Sjimharris return &steady_full; 100230557Sjimharris} 101230557Sjimharris 102230557Sjimharris#pragma GCC visibility pop 103230557Sjimharris 104230557Sjimharrissteady_clock::time_point 105230557Sjimharrissteady_clock::now() _NOEXCEPT 106230557Sjimharris{ 107230557Sjimharris static FP fp = init_steady_clock(); 108230557Sjimharris return time_point(duration(fp())); 109230557Sjimharris} 110230557Sjimharris 111230557Sjimharris#else // __APPLE__ 112230557Sjimharris// FIXME: if _LIBCPP_HAS_NO_MONOTONIC_CLOCK, then clock_gettime isn't going to 113230557Sjimharris// work. It may be possible to fall back on something else, depending on the system. 114230557Sjimharris 115230557Sjimharris// Warning: If this is not truly steady, then it is non-conforming. It is 116230557Sjimharris// better for it to not exist and have the rest of libc++ use system_clock 117230557Sjimharris// instead. 118230557Sjimharris 119230557Sjimharrissteady_clock::time_point 120230557Sjimharrissteady_clock::now() _NOEXCEPT 121230557Sjimharris{ 122230557Sjimharris struct timespec tp; 123230557Sjimharris if (0 != clock_gettime(CLOCK_MONOTONIC, &tp)) 124230557Sjimharris __throw_system_error(errno, "clock_gettime(CLOCK_MONOTONIC) failed"); 125230557Sjimharris return time_point(seconds(tp.tv_sec) + nanoseconds(tp.tv_nsec)); 126230557Sjimharris} 127230557Sjimharris#endif // __APPLE__ 128230557Sjimharris 129230557Sjimharris#endif // !_LIBCPP_HAS_NO_MONOTONIC_CLOCK 130230557Sjimharris 131230557Sjimharris} 132230557Sjimharris 133230557Sjimharris_LIBCPP_END_NAMESPACE_STD 134230557Sjimharris