diff options
Diffstat (limited to 'src/third_party/boost-1.69.0/boost/thread/detail/platform_time.hpp')
-rw-r--r-- | src/third_party/boost-1.69.0/boost/thread/detail/platform_time.hpp | 478 |
1 files changed, 478 insertions, 0 deletions
diff --git a/src/third_party/boost-1.69.0/boost/thread/detail/platform_time.hpp b/src/third_party/boost-1.69.0/boost/thread/detail/platform_time.hpp new file mode 100644 index 00000000000..2180f13c056 --- /dev/null +++ b/src/third_party/boost-1.69.0/boost/thread/detail/platform_time.hpp @@ -0,0 +1,478 @@ +#ifndef BOOST_THREAD_DETAIL_PLATFORM_TIME_HPP +#define BOOST_THREAD_DETAIL_PLATFORM_TIME_HPP +// (C) Copyright 2007-8 Anthony Williams +// (C) Copyright 2012 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include <boost/thread/detail/config.hpp> +#include <boost/thread/thread_time.hpp> +#if defined BOOST_THREAD_USES_DATETIME +#include <boost/date_time/posix_time/conversion.hpp> +#endif +#ifndef _WIN32 +#include <unistd.h> +#endif +#ifdef BOOST_THREAD_USES_CHRONO +#include <boost/chrono/duration.hpp> +#include <boost/chrono/system_clocks.hpp> +#include <boost/chrono/ceil.hpp> +#endif + +#if defined(BOOST_THREAD_CHRONO_WINDOWS_API) +#include <boost/detail/winapi/time.hpp> +#include <boost/detail/winapi/timers.hpp> +#include <boost/thread/win32/thread_primitives.hpp> +#elif defined(BOOST_THREAD_CHRONO_MAC_API) +#include <sys/time.h> //for gettimeofday and timeval +#include <mach/mach_time.h> // mach_absolute_time, mach_timebase_info_data_t + +#else +#include <time.h> // for clock_gettime +#endif + +#include <limits> + +#include <boost/config/abi_prefix.hpp> + +namespace boost +{ +//typedef boost::int_least64_t time_max_t; +typedef boost::intmax_t time_max_t; + +#if defined BOOST_THREAD_CHRONO_MAC_API +namespace threads +{ + +namespace chrono_details +{ + +// steady_clock + +// Note, in this implementation steady_clock and high_resolution_clock +// are the same clock. They are both based on mach_absolute_time(). +// mach_absolute_time() * MachInfo.numer / MachInfo.denom is the number of +// nanoseconds since the computer booted up. MachInfo.numer and MachInfo.denom +// are run time constants supplied by the OS. This clock has no relationship +// to the Gregorian calendar. It's main use is as a high resolution timer. + +// MachInfo.numer / MachInfo.denom is often 1 on the latest equipment. Specialize +// for that case as an optimization. + +inline time_max_t +steady_simplified() +{ + return mach_absolute_time(); +} + +inline double compute_steady_factor(kern_return_t& err) +{ + mach_timebase_info_data_t MachInfo; + err = mach_timebase_info(&MachInfo); + if ( err != 0 ) { + return 0; + } + return static_cast<double>(MachInfo.numer) / MachInfo.denom; +} + +inline time_max_t steady_full() +{ + kern_return_t err; + const double factor = chrono_details::compute_steady_factor(err); + if (err != 0) + { + BOOST_ASSERT(0 && "Boost::Chrono - Internal Error"); + } + return static_cast<time_max_t>(mach_absolute_time() * factor); +} + + +typedef time_max_t (*FP)(); + +inline FP init_steady_clock(kern_return_t & err) +{ + mach_timebase_info_data_t MachInfo; + err = mach_timebase_info(&MachInfo); + if ( err != 0 ) + { + return 0; + } + + if (MachInfo.numer == MachInfo.denom) + { + return &chrono_details::steady_simplified; + } + return &chrono_details::steady_full; +} + +} +} +#endif + + namespace detail + { +#if defined BOOST_THREAD_CHRONO_POSIX_API || defined BOOST_THREAD_CHRONO_MAC_API + inline timespec ns_to_timespec(boost::time_max_t const& ns) + { + boost::time_max_t s = ns / 1000000000l; + timespec ts; + ts.tv_sec = static_cast<long> (s); + ts.tv_nsec = static_cast<long> (ns - s * 1000000000l); + return ts; + } + inline boost::time_max_t timespec_to_ns(timespec const& ts) + { + return static_cast<boost::time_max_t>(ts.tv_sec) * 1000000000l + ts.tv_nsec; + } +#endif + + struct platform_duration + { +#if defined BOOST_THREAD_CHRONO_POSIX_API || defined BOOST_THREAD_CHRONO_MAC_API + explicit platform_duration(timespec const& v) : ts_val(v) {} + timespec const& getTs() const { return ts_val; } + + explicit platform_duration(boost::time_max_t const& ns = 0) : ts_val(ns_to_timespec(ns)) {} + boost::time_max_t getNs() const { return timespec_to_ns(ts_val); } +#else + explicit platform_duration(boost::time_max_t const& ns = 0) : ns_val(ns) {} + boost::time_max_t getNs() const { return ns_val; } +#endif + +#if defined BOOST_THREAD_USES_DATETIME + platform_duration(boost::posix_time::time_duration const& rel_time) + { +#if defined BOOST_THREAD_CHRONO_POSIX_API || defined BOOST_THREAD_CHRONO_MAC_API + ts_val.tv_sec = rel_time.total_seconds(); + ts_val.tv_nsec = static_cast<long>(rel_time.fractional_seconds() * (1000000000l / rel_time.ticks_per_second())); +#else + ns_val = static_cast<boost::time_max_t>(rel_time.total_seconds()) * 1000000000l; + ns_val += rel_time.fractional_seconds() * (1000000000l / rel_time.ticks_per_second()); +#endif + } +#endif + +#if defined BOOST_THREAD_USES_CHRONO + template <class Rep, class Period> + platform_duration(chrono::duration<Rep, Period> const& d) + { +#if defined BOOST_THREAD_CHRONO_POSIX_API || defined BOOST_THREAD_CHRONO_MAC_API + ts_val = ns_to_timespec(chrono::ceil<chrono::nanoseconds>(d).count()); +#else + ns_val = chrono::ceil<chrono::nanoseconds>(d).count(); +#endif + } +#endif + + boost::time_max_t getMs() const + { + const boost::time_max_t ns = getNs(); + // ceil/floor away from zero + if (ns >= 0) + { + // return ceiling of positive numbers + return (ns + 999999) / 1000000; + } + else + { + // return floor of negative numbers + return (ns - 999999) / 1000000; + } + } + + static platform_duration zero() + { + return platform_duration(0); + } + + private: +#if defined BOOST_THREAD_CHRONO_POSIX_API || defined BOOST_THREAD_CHRONO_MAC_API + timespec ts_val; +#else + boost::time_max_t ns_val; +#endif + }; + + inline bool operator==(platform_duration const& lhs, platform_duration const& rhs) + { + return lhs.getNs() == rhs.getNs(); + } + inline bool operator!=(platform_duration const& lhs, platform_duration const& rhs) + { + return lhs.getNs() != rhs.getNs(); + } + inline bool operator<(platform_duration const& lhs, platform_duration const& rhs) + { + return lhs.getNs() < rhs.getNs(); + } + inline bool operator<=(platform_duration const& lhs, platform_duration const& rhs) + { + return lhs.getNs() <= rhs.getNs(); + } + inline bool operator>(platform_duration const& lhs, platform_duration const& rhs) + { + return lhs.getNs() > rhs.getNs(); + } + inline bool operator>=(platform_duration const& lhs, platform_duration const& rhs) + { + return lhs.getNs() >= rhs.getNs(); + } + + static inline platform_duration platform_milliseconds(long const& ms) + { + return platform_duration(ms * 1000000l); + } + + struct real_platform_timepoint + { +#if defined BOOST_THREAD_CHRONO_POSIX_API || defined BOOST_THREAD_CHRONO_MAC_API + explicit real_platform_timepoint(timespec const& v) : dur(v) {} + timespec const& getTs() const { return dur.getTs(); } +#endif + + explicit real_platform_timepoint(boost::time_max_t const& ns) : dur(ns) {} + boost::time_max_t getNs() const { return dur.getNs(); } + +#if defined BOOST_THREAD_USES_DATETIME + real_platform_timepoint(boost::system_time const& abs_time) + : dur(abs_time - boost::posix_time::from_time_t(0)) {} +#endif + +#if defined BOOST_THREAD_USES_CHRONO + template <class Duration> + real_platform_timepoint(chrono::time_point<chrono::system_clock, Duration> const& abs_time) + : dur(abs_time.time_since_epoch()) {} +#endif + + private: + platform_duration dur; + }; + + inline bool operator==(real_platform_timepoint const& lhs, real_platform_timepoint const& rhs) + { + return lhs.getNs() == rhs.getNs(); + } + inline bool operator!=(real_platform_timepoint const& lhs, real_platform_timepoint const& rhs) + { + return lhs.getNs() != rhs.getNs(); + } + inline bool operator<(real_platform_timepoint const& lhs, real_platform_timepoint const& rhs) + { + return lhs.getNs() < rhs.getNs(); + } + inline bool operator<=(real_platform_timepoint const& lhs, real_platform_timepoint const& rhs) + { + return lhs.getNs() <= rhs.getNs(); + } + inline bool operator>(real_platform_timepoint const& lhs, real_platform_timepoint const& rhs) + { + return lhs.getNs() > rhs.getNs(); + } + inline bool operator>=(real_platform_timepoint const& lhs, real_platform_timepoint const& rhs) + { + return lhs.getNs() >= rhs.getNs(); + } + + inline real_platform_timepoint operator+(real_platform_timepoint const& lhs, platform_duration const& rhs) + { + return real_platform_timepoint(lhs.getNs() + rhs.getNs()); + } + inline real_platform_timepoint operator+(platform_duration const& lhs, real_platform_timepoint const& rhs) + { + return real_platform_timepoint(lhs.getNs() + rhs.getNs()); + } + inline platform_duration operator-(real_platform_timepoint const& lhs, real_platform_timepoint const& rhs) + { + return platform_duration(lhs.getNs() - rhs.getNs()); + } + + struct real_platform_clock + { + static real_platform_timepoint now() + { +#if defined(BOOST_THREAD_CHRONO_WINDOWS_API) + boost::detail::winapi::FILETIME_ ft; + boost::detail::winapi::GetSystemTimeAsFileTime(&ft); // never fails + boost::time_max_t ns = ((((static_cast<boost::time_max_t>(ft.dwHighDateTime) << 32) | ft.dwLowDateTime) - 116444736000000000LL) * 100LL); + return real_platform_timepoint(ns); +#elif defined(BOOST_THREAD_CHRONO_MAC_API) + timeval tv; + ::gettimeofday(&tv, 0); + timespec ts; + ts.tv_sec = tv.tv_sec; + ts.tv_nsec = tv.tv_usec * 1000; + return real_platform_timepoint(ts); +#else + timespec ts; + if ( ::clock_gettime( CLOCK_REALTIME, &ts ) ) + { + BOOST_ASSERT(0 && "Boost::Thread - clock_gettime(CLOCK_REALTIME) Internal Error"); + return real_platform_timepoint(0); + } + return real_platform_timepoint(ts); +#endif + } + }; + +#if defined(BOOST_THREAD_HAS_MONO_CLOCK) + + struct mono_platform_timepoint + { +#if defined BOOST_THREAD_CHRONO_POSIX_API || defined BOOST_THREAD_CHRONO_MAC_API + + explicit mono_platform_timepoint(timespec const& v) : dur(v) {} + timespec const& getTs() const { return dur.getTs(); } +#endif + + explicit mono_platform_timepoint(boost::time_max_t const& ns) : dur(ns) {} + boost::time_max_t getNs() const { return dur.getNs(); } + +#if defined BOOST_THREAD_USES_CHRONO + // This conversion assumes that chrono::steady_clock::time_point and mono_platform_timepoint share the same epoch. + template <class Duration> + mono_platform_timepoint(chrono::time_point<chrono::steady_clock, Duration> const& abs_time) + : dur(abs_time.time_since_epoch()) {} +#endif + + // can't name this max() since that is a macro on some Windows systems + static mono_platform_timepoint getMax() + { +#if defined BOOST_THREAD_CHRONO_POSIX_API || defined BOOST_THREAD_CHRONO_MAC_API + timespec ts; + ts.tv_sec = (std::numeric_limits<time_t>::max)(); + ts.tv_nsec = 999999999; + return mono_platform_timepoint(ts); +#else + boost::time_max_t ns = (std::numeric_limits<boost::time_max_t>::max)(); + return mono_platform_timepoint(ns); +#endif + } + + private: + platform_duration dur; + }; + + inline bool operator==(mono_platform_timepoint const& lhs, mono_platform_timepoint const& rhs) + { + return lhs.getNs() == rhs.getNs(); + } + inline bool operator!=(mono_platform_timepoint const& lhs, mono_platform_timepoint const& rhs) + { + return lhs.getNs() != rhs.getNs(); + } + inline bool operator<(mono_platform_timepoint const& lhs, mono_platform_timepoint const& rhs) + { + return lhs.getNs() < rhs.getNs(); + } + inline bool operator<=(mono_platform_timepoint const& lhs, mono_platform_timepoint const& rhs) + { + return lhs.getNs() <= rhs.getNs(); + } + inline bool operator>(mono_platform_timepoint const& lhs, mono_platform_timepoint const& rhs) + { + return lhs.getNs() > rhs.getNs(); + } + inline bool operator>=(mono_platform_timepoint const& lhs, mono_platform_timepoint const& rhs) + { + return lhs.getNs() >= rhs.getNs(); + } + + inline mono_platform_timepoint operator+(mono_platform_timepoint const& lhs, platform_duration const& rhs) + { + return mono_platform_timepoint(lhs.getNs() + rhs.getNs()); + } + inline mono_platform_timepoint operator+(platform_duration const& lhs, mono_platform_timepoint const& rhs) + { + return mono_platform_timepoint(lhs.getNs() + rhs.getNs()); + } + inline platform_duration operator-(mono_platform_timepoint const& lhs, mono_platform_timepoint const& rhs) + { + return platform_duration(lhs.getNs() - rhs.getNs()); + } + + struct mono_platform_clock + { + static mono_platform_timepoint now() + { +#if defined(BOOST_THREAD_CHRONO_WINDOWS_API) +#if defined(BOOST_THREAD_USES_CHRONO) + // Use QueryPerformanceCounter() to match the implementation in Boost + // Chrono so that chrono::steady_clock::now() and this function share the + // same epoch and so can be converted between each other. + boost::detail::winapi::LARGE_INTEGER_ freq; + if ( !boost::detail::winapi::QueryPerformanceFrequency( &freq ) ) + { + BOOST_ASSERT(0 && "Boost::Thread - QueryPerformanceFrequency Internal Error"); + return mono_platform_timepoint(0); + } + if ( freq.QuadPart <= 0 ) + { + BOOST_ASSERT(0 && "Boost::Thread - QueryPerformanceFrequency Internal Error"); + return mono_platform_timepoint(0); + } + + boost::detail::winapi::LARGE_INTEGER_ pcount; + unsigned times=0; + while ( ! boost::detail::winapi::QueryPerformanceCounter( &pcount ) ) + { + if ( ++times > 3 ) + { + BOOST_ASSERT(0 && "Boost::Thread - QueryPerformanceCounter Internal Error"); + return mono_platform_timepoint(0); + } + } + + long double ns = 1000000000.0L * pcount.QuadPart / freq.QuadPart; + return mono_platform_timepoint(static_cast<boost::time_max_t>(ns)); +#else + // Use GetTickCount64() because it's more reliable on older + // systems like Windows XP and Windows Server 2003. + win32::ticks_type msec = win32::gettickcount64(); + return mono_platform_timepoint(msec * 1000000); +#endif +#elif defined(BOOST_THREAD_CHRONO_MAC_API) + kern_return_t err; + threads::chrono_details::FP fp = threads::chrono_details::init_steady_clock(err); + if ( err != 0 ) + { + BOOST_ASSERT(0 && "Boost::Chrono - Internal Error"); + } + return mono_platform_timepoint(fp()); +#else + timespec ts; + if ( ::clock_gettime( CLOCK_MONOTONIC, &ts ) ) + { + BOOST_ASSERT(0 && "Boost::Thread - clock_gettime(CLOCK_MONOTONIC) Internal Error"); + return mono_platform_timepoint(0); + } + return mono_platform_timepoint(ts); +#endif + } + }; + +#endif + +#if defined(BOOST_THREAD_INTERNAL_CLOCK_IS_MONO) + typedef mono_platform_clock internal_platform_clock; + typedef mono_platform_timepoint internal_platform_timepoint; +#else + typedef real_platform_clock internal_platform_clock; + typedef real_platform_timepoint internal_platform_timepoint; +#endif + +#ifdef BOOST_THREAD_USES_CHRONO +#ifdef BOOST_THREAD_INTERNAL_CLOCK_IS_MONO + typedef chrono::steady_clock internal_chrono_clock; +#else + typedef chrono::system_clock internal_chrono_clock; +#endif +#endif + + } +} + +#include <boost/config/abi_suffix.hpp> + +#endif |