14684ddb6SLionel Sambuc //===------------------------- chrono.cpp ---------------------------------===// 24684ddb6SLionel Sambuc // 34684ddb6SLionel Sambuc // The LLVM Compiler Infrastructure 44684ddb6SLionel Sambuc // 54684ddb6SLionel Sambuc // This file is dual licensed under the MIT and the University of Illinois Open 64684ddb6SLionel Sambuc // Source Licenses. See LICENSE.TXT for details. 74684ddb6SLionel Sambuc // 84684ddb6SLionel Sambuc //===----------------------------------------------------------------------===// 94684ddb6SLionel Sambuc 104684ddb6SLionel Sambuc #include "chrono" 11*0a6a1f1dSLionel Sambuc #include "cerrno" // errno 12*0a6a1f1dSLionel Sambuc #include "system_error" // __throw_system_error 13*0a6a1f1dSLionel Sambuc #include <time.h> // clock_gettime, CLOCK_MONOTONIC and CLOCK_REALTIME 14*0a6a1f1dSLionel Sambuc 15*0a6a1f1dSLionel Sambuc #if !defined(CLOCK_REALTIME) 164684ddb6SLionel Sambuc #include <sys/time.h> // for gettimeofday and timeval 17*0a6a1f1dSLionel Sambuc #endif 18*0a6a1f1dSLionel Sambuc 19*0a6a1f1dSLionel Sambuc #if !defined(_LIBCPP_HAS_NO_MONOTONIC_CLOCK) && !defined(CLOCK_MONOTONIC) 20*0a6a1f1dSLionel Sambuc #if __APPLE__ 214684ddb6SLionel Sambuc #include <mach/mach_time.h> // mach_absolute_time, mach_timebase_info_data_t 22*0a6a1f1dSLionel Sambuc #else 23*0a6a1f1dSLionel Sambuc #error "Monotonic clock not implemented" 24*0a6a1f1dSLionel Sambuc #endif 25*0a6a1f1dSLionel Sambuc #endif 264684ddb6SLionel Sambuc 274684ddb6SLionel Sambuc _LIBCPP_BEGIN_NAMESPACE_STD 284684ddb6SLionel Sambuc 294684ddb6SLionel Sambuc namespace chrono 304684ddb6SLionel Sambuc { 314684ddb6SLionel Sambuc 324684ddb6SLionel Sambuc // system_clock 334684ddb6SLionel Sambuc 344684ddb6SLionel Sambuc const bool system_clock::is_steady; 354684ddb6SLionel Sambuc 364684ddb6SLionel Sambuc system_clock::time_point now()374684ddb6SLionel Sambucsystem_clock::now() _NOEXCEPT 384684ddb6SLionel Sambuc { 39*0a6a1f1dSLionel Sambuc #ifdef CLOCK_REALTIME 40*0a6a1f1dSLionel Sambuc struct timespec tp; 41*0a6a1f1dSLionel Sambuc if (0 != clock_gettime(CLOCK_REALTIME, &tp)) 42*0a6a1f1dSLionel Sambuc __throw_system_error(errno, "clock_gettime(CLOCK_REALTIME) failed"); 43*0a6a1f1dSLionel Sambuc return time_point(seconds(tp.tv_sec) + microseconds(tp.tv_nsec / 1000)); 44*0a6a1f1dSLionel Sambuc #else // !CLOCK_REALTIME 454684ddb6SLionel Sambuc timeval tv; 464684ddb6SLionel Sambuc gettimeofday(&tv, 0); 474684ddb6SLionel Sambuc return time_point(seconds(tv.tv_sec) + microseconds(tv.tv_usec)); 48*0a6a1f1dSLionel Sambuc #endif // CLOCK_REALTIME 494684ddb6SLionel Sambuc } 504684ddb6SLionel Sambuc 514684ddb6SLionel Sambuc time_t to_time_t(const time_point & t)524684ddb6SLionel Sambucsystem_clock::to_time_t(const time_point& t) _NOEXCEPT 534684ddb6SLionel Sambuc { 544684ddb6SLionel Sambuc return time_t(duration_cast<seconds>(t.time_since_epoch()).count()); 554684ddb6SLionel Sambuc } 564684ddb6SLionel Sambuc 574684ddb6SLionel Sambuc system_clock::time_point from_time_t(time_t t)584684ddb6SLionel Sambucsystem_clock::from_time_t(time_t t) _NOEXCEPT 594684ddb6SLionel Sambuc { 604684ddb6SLionel Sambuc return system_clock::time_point(seconds(t)); 614684ddb6SLionel Sambuc } 624684ddb6SLionel Sambuc 63*0a6a1f1dSLionel Sambuc #ifndef _LIBCPP_HAS_NO_MONOTONIC_CLOCK 644684ddb6SLionel Sambuc // steady_clock 65*0a6a1f1dSLionel Sambuc // 66*0a6a1f1dSLionel Sambuc // Warning: If this is not truly steady, then it is non-conforming. It is 67*0a6a1f1dSLionel Sambuc // better for it to not exist and have the rest of libc++ use system_clock 68*0a6a1f1dSLionel Sambuc // instead. 694684ddb6SLionel Sambuc 704684ddb6SLionel Sambuc const bool steady_clock::is_steady; 714684ddb6SLionel Sambuc 72*0a6a1f1dSLionel Sambuc #ifdef CLOCK_MONOTONIC 73*0a6a1f1dSLionel Sambuc 74*0a6a1f1dSLionel Sambuc steady_clock::time_point now()75*0a6a1f1dSLionel Sambucsteady_clock::now() _NOEXCEPT 76*0a6a1f1dSLionel Sambuc { 77*0a6a1f1dSLionel Sambuc struct timespec tp; 78*0a6a1f1dSLionel Sambuc if (0 != clock_gettime(CLOCK_MONOTONIC, &tp)) 79*0a6a1f1dSLionel Sambuc __throw_system_error(errno, "clock_gettime(CLOCK_MONOTONIC) failed"); 80*0a6a1f1dSLionel Sambuc return time_point(seconds(tp.tv_sec) + nanoseconds(tp.tv_nsec)); 81*0a6a1f1dSLionel Sambuc } 82*0a6a1f1dSLionel Sambuc 83*0a6a1f1dSLionel Sambuc #elif defined(__APPLE__) 84*0a6a1f1dSLionel Sambuc 854684ddb6SLionel Sambuc // mach_absolute_time() * MachInfo.numer / MachInfo.denom is the number of 864684ddb6SLionel Sambuc // nanoseconds since the computer booted up. MachInfo.numer and MachInfo.denom 874684ddb6SLionel Sambuc // are run time constants supplied by the OS. This clock has no relationship 884684ddb6SLionel Sambuc // to the Gregorian calendar. It's main use is as a high resolution timer. 894684ddb6SLionel Sambuc 904684ddb6SLionel Sambuc // MachInfo.numer / MachInfo.denom is often 1 on the latest equipment. Specialize 914684ddb6SLionel Sambuc // for that case as an optimization. 924684ddb6SLionel Sambuc 934684ddb6SLionel Sambuc #pragma GCC visibility push(hidden) 944684ddb6SLionel Sambuc 954684ddb6SLionel Sambuc static 964684ddb6SLionel Sambuc steady_clock::rep steady_simplified()974684ddb6SLionel Sambucsteady_simplified() 984684ddb6SLionel Sambuc { 994684ddb6SLionel Sambuc return static_cast<steady_clock::rep>(mach_absolute_time()); 1004684ddb6SLionel Sambuc } 1014684ddb6SLionel Sambuc 1024684ddb6SLionel Sambuc static 1034684ddb6SLionel Sambuc double compute_steady_factor()1044684ddb6SLionel Sambuccompute_steady_factor() 1054684ddb6SLionel Sambuc { 1064684ddb6SLionel Sambuc mach_timebase_info_data_t MachInfo; 1074684ddb6SLionel Sambuc mach_timebase_info(&MachInfo); 1084684ddb6SLionel Sambuc return static_cast<double>(MachInfo.numer) / MachInfo.denom; 1094684ddb6SLionel Sambuc } 1104684ddb6SLionel Sambuc 1114684ddb6SLionel Sambuc static 1124684ddb6SLionel Sambuc steady_clock::rep steady_full()1134684ddb6SLionel Sambucsteady_full() 1144684ddb6SLionel Sambuc { 1154684ddb6SLionel Sambuc static const double factor = compute_steady_factor(); 1164684ddb6SLionel Sambuc return static_cast<steady_clock::rep>(mach_absolute_time() * factor); 1174684ddb6SLionel Sambuc } 1184684ddb6SLionel Sambuc 1194684ddb6SLionel Sambuc typedef steady_clock::rep (*FP)(); 1204684ddb6SLionel Sambuc 1214684ddb6SLionel Sambuc static 1224684ddb6SLionel Sambuc FP init_steady_clock()1234684ddb6SLionel Sambucinit_steady_clock() 1244684ddb6SLionel Sambuc { 1254684ddb6SLionel Sambuc mach_timebase_info_data_t MachInfo; 1264684ddb6SLionel Sambuc mach_timebase_info(&MachInfo); 1274684ddb6SLionel Sambuc if (MachInfo.numer == MachInfo.denom) 1284684ddb6SLionel Sambuc return &steady_simplified; 1294684ddb6SLionel Sambuc return &steady_full; 1304684ddb6SLionel Sambuc } 1314684ddb6SLionel Sambuc 1324684ddb6SLionel Sambuc #pragma GCC visibility pop 1334684ddb6SLionel Sambuc 1344684ddb6SLionel Sambuc steady_clock::time_point now()1354684ddb6SLionel Sambucsteady_clock::now() _NOEXCEPT 1364684ddb6SLionel Sambuc { 1374684ddb6SLionel Sambuc static FP fp = init_steady_clock(); 1384684ddb6SLionel Sambuc return time_point(duration(fp())); 1394684ddb6SLionel Sambuc } 1404684ddb6SLionel Sambuc 141*0a6a1f1dSLionel Sambuc #else 142*0a6a1f1dSLionel Sambuc #error "Monotonic clock not implemented" 143*0a6a1f1dSLionel Sambuc #endif 1444684ddb6SLionel Sambuc 145*0a6a1f1dSLionel Sambuc #endif // !_LIBCPP_HAS_NO_MONOTONIC_CLOCK 1464684ddb6SLionel Sambuc 1474684ddb6SLionel Sambuc } 1484684ddb6SLionel Sambuc 1494684ddb6SLionel Sambuc _LIBCPP_END_NAMESPACE_STD 150