chrono.cpp revision 249998
1227825Stheraven//===------------------------- chrono.cpp ---------------------------------===// 2227825Stheraven// 3227825Stheraven// The LLVM Compiler Infrastructure 4227825Stheraven// 5227825Stheraven// This file is dual licensed under the MIT and the University of Illinois Open 6227825Stheraven// Source Licenses. See LICENSE.TXT for details. 7227825Stheraven// 8227825Stheraven//===----------------------------------------------------------------------===// 9227825Stheraven 10227825Stheraven#include "chrono" 11227825Stheraven#include <sys/time.h> //for gettimeofday and timeval 12249998Sdim#ifdef __APPLE__ 13227825Stheraven#include <mach/mach_time.h> // mach_absolute_time, mach_timebase_info_data_t 14227825Stheraven#else /* !__APPLE__ */ 15227825Stheraven#include <cerrno> // errno 16227825Stheraven#include <system_error> // __throw_system_error 17227825Stheraven#include <time.h> // clock_gettime, CLOCK_MONOTONIC 18227825Stheraven#endif // __APPLE__ 19227825Stheraven 20227825Stheraven_LIBCPP_BEGIN_NAMESPACE_STD 21227825Stheraven 22227825Stheravennamespace chrono 23227825Stheraven{ 24227825Stheraven 25227825Stheraven// system_clock 26227825Stheraven 27246487Stheravenconst bool system_clock::is_steady; 28246487Stheraven 29227825Stheravensystem_clock::time_point 30227825Stheravensystem_clock::now() _NOEXCEPT 31227825Stheraven{ 32227825Stheraven timeval tv; 33227825Stheraven gettimeofday(&tv, 0); 34227825Stheraven return time_point(seconds(tv.tv_sec) + microseconds(tv.tv_usec)); 35227825Stheraven} 36227825Stheraven 37227825Stheraventime_t 38227825Stheravensystem_clock::to_time_t(const time_point& t) _NOEXCEPT 39227825Stheraven{ 40227825Stheraven return time_t(duration_cast<seconds>(t.time_since_epoch()).count()); 41227825Stheraven} 42227825Stheraven 43227825Stheravensystem_clock::time_point 44227825Stheravensystem_clock::from_time_t(time_t t) _NOEXCEPT 45227825Stheraven{ 46227825Stheraven return system_clock::time_point(seconds(t)); 47227825Stheraven} 48227825Stheraven 49227825Stheraven// steady_clock 50227825Stheraven 51246487Stheravenconst bool steady_clock::is_steady; 52246487Stheraven 53249998Sdim#ifdef __APPLE__ 54227825Stheraven// mach_absolute_time() * MachInfo.numer / MachInfo.denom is the number of 55227825Stheraven// nanoseconds since the computer booted up. MachInfo.numer and MachInfo.denom 56227825Stheraven// are run time constants supplied by the OS. This clock has no relationship 57227825Stheraven// to the Gregorian calendar. It's main use is as a high resolution timer. 58227825Stheraven 59227825Stheraven// MachInfo.numer / MachInfo.denom is often 1 on the latest equipment. Specialize 60227825Stheraven// for that case as an optimization. 61227825Stheraven 62227825Stheraven#pragma GCC visibility push(hidden) 63227825Stheraven 64227825Stheravenstatic 65227825Stheravensteady_clock::rep 66227825Stheravensteady_simplified() 67227825Stheraven{ 68232950Stheraven return static_cast<steady_clock::rep>(mach_absolute_time()); 69227825Stheraven} 70227825Stheraven 71227825Stheravenstatic 72227825Stheravendouble 73227825Stheravencompute_steady_factor() 74227825Stheraven{ 75227825Stheraven mach_timebase_info_data_t MachInfo; 76227825Stheraven mach_timebase_info(&MachInfo); 77227825Stheraven return static_cast<double>(MachInfo.numer) / MachInfo.denom; 78227825Stheraven} 79227825Stheraven 80227825Stheravenstatic 81227825Stheravensteady_clock::rep 82227825Stheravensteady_full() 83227825Stheraven{ 84227825Stheraven static const double factor = compute_steady_factor(); 85227825Stheraven return static_cast<steady_clock::rep>(mach_absolute_time() * factor); 86227825Stheraven} 87227825Stheraven 88227825Stheraventypedef steady_clock::rep (*FP)(); 89227825Stheraven 90227825Stheravenstatic 91227825StheravenFP 92227825Stheraveninit_steady_clock() 93227825Stheraven{ 94227825Stheraven mach_timebase_info_data_t MachInfo; 95227825Stheraven mach_timebase_info(&MachInfo); 96227825Stheraven if (MachInfo.numer == MachInfo.denom) 97227825Stheraven return &steady_simplified; 98227825Stheraven return &steady_full; 99227825Stheraven} 100227825Stheraven 101227825Stheraven#pragma GCC visibility pop 102227825Stheraven 103227825Stheravensteady_clock::time_point 104227825Stheravensteady_clock::now() _NOEXCEPT 105227825Stheraven{ 106227825Stheraven static FP fp = init_steady_clock(); 107227825Stheraven return time_point(duration(fp())); 108227825Stheraven} 109227825Stheraven 110227825Stheraven#else // __APPLE__ 111227825Stheraven// FIXME: We assume that clock_gettime(CLOCK_MONOTONIC) works on 112227825Stheraven// non-apple systems. Instead, we should check _POSIX_TIMERS and 113227825Stheraven// _POSIX_MONOTONIC_CLOCK and fall back to something else if those 114227825Stheraven// don't exist. 115227825Stheraven 116227825Stheraven// Warning: If this is not truly steady, then it is non-conforming. It is 117227825Stheraven// better for it to not exist and have the rest of libc++ use system_clock 118227825Stheraven// instead. 119227825Stheraven 120227825Stheravensteady_clock::time_point 121227825Stheravensteady_clock::now() _NOEXCEPT 122227825Stheraven{ 123227825Stheraven struct timespec tp; 124227825Stheraven if (0 != clock_gettime(CLOCK_MONOTONIC, &tp)) 125227825Stheraven __throw_system_error(errno, "clock_gettime(CLOCK_MONOTONIC) failed"); 126227825Stheraven return time_point(seconds(tp.tv_sec) + nanoseconds(tp.tv_nsec)); 127227825Stheraven} 128227825Stheraven#endif // __APPLE__ 129227825Stheraven 130227825Stheraven} 131227825Stheraven 132227825Stheraven_LIBCPP_END_NAMESPACE_STD 133