chrono.cpp revision 227825
150027Speter//===------------------------- chrono.cpp ---------------------------------===//
272376Sjake//
372376Sjake//                     The LLVM Compiler Infrastructure
450027Speter//
550027Speter// This file is dual licensed under the MIT and the University of Illinois Open
650027Speter// Source Licenses. See LICENSE.TXT for details.
750027Speter//
850027Speter//===----------------------------------------------------------------------===//
950027Speter
1050027Speter#include "chrono"
1150027Speter#include <sys/time.h>        //for gettimeofday and timeval
1250027Speter#if __APPLE__
1350027Speter#include <mach/mach_time.h>  // mach_absolute_time, mach_timebase_info_data_t
1450027Speter#else  /* !__APPLE__ */
1550027Speter#include <cerrno>  // errno
1650027Speter#include <system_error>  // __throw_system_error
1750027Speter#include <time.h>  // clock_gettime, CLOCK_MONOTONIC
1850027Speter#endif  // __APPLE__
1950027Speter
2050027Speter_LIBCPP_BEGIN_NAMESPACE_STD
2150027Speter
2250027Speternamespace chrono
2350027Speter{
2450027Speter
2550027Speter// system_clock
2650027Speter
2750027Spetersystem_clock::time_point
2850027Spetersystem_clock::now() _NOEXCEPT
2999072Sjulian{
3099072Sjulian    timeval tv;
3199072Sjulian    gettimeofday(&tv, 0);
3299072Sjulian    return time_point(seconds(tv.tv_sec) + microseconds(tv.tv_usec));
3399072Sjulian}
3499072Sjulian
3599072Sjuliantime_t
3699072Sjuliansystem_clock::to_time_t(const time_point& t) _NOEXCEPT
3799072Sjulian{
3899072Sjulian    return time_t(duration_cast<seconds>(t.time_since_epoch()).count());
3999072Sjulian}
4099072Sjulian
4199072Sjuliansystem_clock::time_point
4299072Sjuliansystem_clock::from_time_t(time_t t) _NOEXCEPT
4399072Sjulian{
4499072Sjulian    return system_clock::time_point(seconds(t));
4599072Sjulian}
4699072Sjulian
4799072Sjulian// steady_clock
4899072Sjulian
4999072Sjulian#if __APPLE__
5099072Sjulian//   mach_absolute_time() * MachInfo.numer / MachInfo.denom is the number of
5199072Sjulian//   nanoseconds since the computer booted up.  MachInfo.numer and MachInfo.denom
5299072Sjulian//   are run time constants supplied by the OS.  This clock has no relationship
5399072Sjulian//   to the Gregorian calendar.  It's main use is as a high resolution timer.
5499072Sjulian
5599072Sjulian// MachInfo.numer / MachInfo.denom is often 1 on the latest equipment.  Specialize
5699072Sjulian//   for that case as an optimization.
5799072Sjulian
5899072Sjulian#pragma GCC visibility push(hidden)
5999072Sjulian
6099072Sjulianstatic
6199072Sjuliansteady_clock::rep
6299072Sjuliansteady_simplified()
6399072Sjulian{
6499072Sjulian    return mach_absolute_time();
6599072Sjulian}
6699072Sjulian
6799072Sjulianstatic
6899072Sjuliandouble
6999072Sjuliancompute_steady_factor()
7099072Sjulian{
7199072Sjulian    mach_timebase_info_data_t MachInfo;
7299072Sjulian    mach_timebase_info(&MachInfo);
7399072Sjulian    return static_cast<double>(MachInfo.numer) / MachInfo.denom;
7499072Sjulian}
7599072Sjulian
7699072Sjulianstatic
7799072Sjuliansteady_clock::rep
7899072Sjuliansteady_full()
7999072Sjulian{
8099072Sjulian    static const double factor = compute_steady_factor();
8199072Sjulian    return static_cast<steady_clock::rep>(mach_absolute_time() * factor);
8299072Sjulian}
8399072Sjulian
8499072Sjuliantypedef steady_clock::rep (*FP)();
8599072Sjulian
8699072Sjulianstatic
8799072SjulianFP
8899072Sjulianinit_steady_clock()
8999072Sjulian{
9099072Sjulian    mach_timebase_info_data_t MachInfo;
9199072Sjulian    mach_timebase_info(&MachInfo);
9250027Speter    if (MachInfo.numer == MachInfo.denom)
9350027Speter        return &steady_simplified;
9450027Speter    return &steady_full;
9565557Sjasone}
9674914Sjhb
9767365Sjhb#pragma GCC visibility pop
9850027Speter
9950027Spetersteady_clock::time_point
10093607Sdillonsteady_clock::now() _NOEXCEPT
10150027Speter{
10297261Sjake    static FP fp = init_steady_clock();
10397261Sjake    return time_point(duration(fp()));
10450027Speter}
10572376Sjake
10650027Speter#else  // __APPLE__
10772376Sjake// FIXME: We assume that clock_gettime(CLOCK_MONOTONIC) works on
10872376Sjake// non-apple systems.  Instead, we should check _POSIX_TIMERS and
10950027Speter// _POSIX_MONOTONIC_CLOCK and fall back to something else if those
11099072Sjulian// don't exist.
11199072Sjulian
11299072Sjulian// Warning:  If this is not truly steady, then it is non-conforming.  It is
11399072Sjulian//  better for it to not exist and have the rest of libc++ use system_clock
11499072Sjulian//  instead.
11550027Speter
11699072Sjuliansteady_clock::time_point
11799072Sjuliansteady_clock::now() _NOEXCEPT
11899072Sjulian{
11950027Speter    struct timespec tp;
12083366Sjulian    if (0 != clock_gettime(CLOCK_MONOTONIC, &tp))
12183366Sjulian        __throw_system_error(errno, "clock_gettime(CLOCK_MONOTONIC) failed");
12250027Speter    return time_point(seconds(tp.tv_sec) + nanoseconds(tp.tv_nsec));
12399072Sjulian}
12499072Sjulian#endif  // __APPLE__
12599072Sjulian
12699072Sjulian}
12799072Sjulian
12899072Sjulian_LIBCPP_END_NAMESPACE_STD
12999072Sjulian