chrono.cpp revision 246468
134229Speter//===------------------------- chrono.cpp ---------------------------------===// 251408Sobrien// 334229Speter// The LLVM Compiler Infrastructure 434229Speter// 551408Sobrien// This file is dual licensed under the MIT and the University of Illinois Open 634229Speter// Source Licenses. See LICENSE.TXT for details. 752112Sobrien// 818334Speter//===----------------------------------------------------------------------===// 918334Speter 1018334Speter#include "chrono" 1118334Speter#include <sys/time.h> //for gettimeofday and timeval 1218334Speter#if __APPLE__ 1318334Speter#include <mach/mach_time.h> // mach_absolute_time, mach_timebase_info_data_t 1418334Speter#else /* !__APPLE__ */ 1518334Speter#include <cerrno> // errno 1618334Speter#include <system_error> // __throw_system_error 1718334Speter#include <time.h> // clock_gettime, CLOCK_MONOTONIC 1818334Speter#endif // __APPLE__ 1918334Speter 2018334Speter_LIBCPP_BEGIN_NAMESPACE_STD 2118334Speter 2218334Speternamespace chrono 2318334Speter{ 2418334Speter 2518334Speter// system_clock 2651408Sobrien 2718334Speterconst bool system_clock::is_steady; 2851408Sobrien 2951408Sobriensystem_clock::time_point 3051408Sobriensystem_clock::now() _NOEXCEPT 3151408Sobrien{ 3234229Speter timeval tv; 3334229Speter gettimeofday(&tv, 0); 3434229Speter return time_point(seconds(tv.tv_sec) + microseconds(tv.tv_usec)); 3518349Speter} 3634229Speter 3734229Spetertime_t 3834229Spetersystem_clock::to_time_t(const time_point& t) _NOEXCEPT 3934229Speter{ 4018349Speter return time_t(duration_cast<seconds>(t.time_since_epoch()).count()); 4134229Speter} 4252112Sobrien 4352112Sobriensystem_clock::time_point 4452112Sobriensystem_clock::from_time_t(time_t t) _NOEXCEPT 4552112Sobrien{ 4652112Sobrien return system_clock::time_point(seconds(t)); 4752112Sobrien} 4834229Speter 4918349Speter// steady_clock 5034229Speter 5134229Speterconst bool steady_clock::is_steady; 5234229Speter 5334229Speter#if __APPLE__ 5434229Speter// mach_absolute_time() * MachInfo.numer / MachInfo.denom is the number of 5518349Speter// nanoseconds since the computer booted up. MachInfo.numer and MachInfo.denom 5634229Speter// are run time constants supplied by the OS. This clock has no relationship 5734229Speter// to the Gregorian calendar. It's main use is as a high resolution timer. 5834229Speter 5918349Speter// MachInfo.numer / MachInfo.denom is often 1 on the latest equipment. Specialize 6034229Speter// for that case as an optimization. 6134229Speter 6218349Speter#pragma GCC visibility push(hidden) 6334229Speter 6434229Speterstatic 6518349Spetersteady_clock::rep 6652112Sobriensteady_simplified() 6751408Sobrien{ 6851408Sobrien return static_cast<steady_clock::rep>(mach_absolute_time()); 6934229Speter} 7034229Speter 7118349Speterstatic 7234229Speterdouble 7334229Spetercompute_steady_factor() 7434229Speter{ 7552112Sobrien mach_timebase_info_data_t MachInfo; 7634229Speter mach_timebase_info(&MachInfo); 7752112Sobrien return static_cast<double>(MachInfo.numer) / MachInfo.denom; 7834229Speter} 7918349Speter 8034285Speterstatic 8134285Spetersteady_clock::rep 8234285Spetersteady_full() 8334285Speter{ 8434285Speter static const double factor = compute_steady_factor(); 8534285Speter return static_cast<steady_clock::rep>(mach_absolute_time() * factor); 8634285Speter} 8734285Speter 8834285Spetertypedef steady_clock::rep (*FP)(); 8934285Speter 9034229Speterstatic 9134229SpeterFP 9234229Speterinit_steady_clock() 9334229Speter{ 9434229Speter mach_timebase_info_data_t MachInfo; 9534229Speter mach_timebase_info(&MachInfo); 9634229Speter if (MachInfo.numer == MachInfo.denom) 9734229Speter return &steady_simplified; 9818349Speter return &steady_full; 9934229Speter} 10034229Speter 10134229Speter#pragma GCC visibility pop 10234229Speter 10352112Sobriensteady_clock::time_point 10452112Sobriensteady_clock::now() _NOEXCEPT 10518334Speter{ 10634229Speter static FP fp = init_steady_clock(); 10734229Speter return time_point(duration(fp())); 10852112Sobrien} 10952112Sobrien 11018349Speter#else // __APPLE__ 11118334Speter// FIXME: We assume that clock_gettime(CLOCK_MONOTONIC) works on 11234229Speter// non-apple systems. Instead, we should check _POSIX_TIMERS and 11334229Speter// _POSIX_MONOTONIC_CLOCK and fall back to something else if those 11434229Speter// don't exist. 11534229Speter 11651408Sobrien// Warning: If this is not truly steady, then it is non-conforming. It is 11752112Sobrien// better for it to not exist and have the rest of libc++ use system_clock 11818349Speter// instead. 11934229Speter 12052112Sobriensteady_clock::time_point 12151408Sobriensteady_clock::now() _NOEXCEPT 12251408Sobrien{ 12351408Sobrien struct timespec tp; 12451408Sobrien if (0 != clock_gettime(CLOCK_MONOTONIC, &tp)) 12551408Sobrien __throw_system_error(errno, "clock_gettime(CLOCK_MONOTONIC) failed"); 12651408Sobrien return time_point(seconds(tp.tv_sec) + nanoseconds(tp.tv_nsec)); 12718349Speter} 12834229Speter#endif // __APPLE__ 12934229Speter 13034229Speter} 13118334Speter 13251408Sobrien_LIBCPP_END_NAMESPACE_STD 13352112Sobrien