123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268 |
- // This code is based on Timer and Chrono code. Thanks to authors:
- //
- // Boost.Timer:
- // Copyright Beman Dawes 1994-2007, 2011
- //
- // Boost.Chrono:
- // Copyright Beman Dawes 2008
- // Copyright 2009-2010 Vicente J. Botet Escriba
- //
- // Simplified and modified to be able to support exceptionless (-fno-exceptions).
- // Boost.Timer depends on Boost.Chorno wich uses boost::throw_exception.
- // And Boost.Chrono DLLs don't build in Win32 as there is no
- // boost::throw_exception(std::exception const&) implementation
- // in Boost.Chrono:
- //
- // Copyright 2020 Ion Gaztanaga
- //
- // Distributed under the Boost Software License, Version 1.0.
- // See http://www.boost.org/LICENSE_1_0.txt
- //----------------------------------------------------------------------------//
- // Windows //
- //----------------------------------------------------------------------------//
- #ifndef BOOST_MOVE_DETAIL_NSEC_CLOCK_HPP
- #define BOOST_MOVE_DETAIL_NSEC_CLOCK_HPP
- #include <boost/config.hpp>
- #include <boost/cstdint.hpp>
- #include <boost/move/detail/workaround.hpp>
- #include <cstdlib>
- # if (defined(_WIN32) || defined(__WIN32__) || defined(WIN32))
- # define BOOST_MOVE_DETAIL_WINDOWS_API
- # elif defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)
- # define BOOST_MOVE_DETAIL_MAC_API
- # else
- # define BOOST_MOVE_DETAIL_POSIX_API
- # endif
- #if defined(BOOST_MOVE_DETAIL_WINDOWS_API)
- #include <cassert>
- #if defined( BOOST_USE_WINDOWS_H )
- #include <Windows.h>
- #else
- #if defined (WIN32_PLATFORM_PSPC)
- #define BOOST_MOVE_WINAPI_IMPORT BOOST_SYMBOL_IMPORT
- #define BOOST_MOVE_WINAPI_IMPORT_EXCEPT_WM
- #elif defined (_WIN32_WCE)
- #define BOOST_MOVE_WINAPI_IMPORT
- #define BOOST_MOVE_WINAPI_IMPORT_EXCEPT_WM
- #else
- #define BOOST_MOVE_WINAPI_IMPORT BOOST_SYMBOL_IMPORT
- #define BOOST_MOVE_WINAPI_IMPORT_EXCEPT_WM BOOST_SYMBOL_IMPORT
- #endif
- #if defined(WINAPI)
- #define BOOST_MOVE_WINAPI_CC WINAPI
- #else
- #if defined(_M_IX86) || defined(__i386__)
- #define BOOST_MOVE_WINAPI_CC __stdcall
- #else
- // On architectures other than 32-bit x86 __stdcall is ignored. Clang also issues a warning.
- #define BOOST_MOVE_WINAPI_CC
- #endif
- #endif
- extern "C" {
- union _LARGE_INTEGER;
- typedef long long QuadPart;
- BOOST_MOVE_WINAPI_IMPORT_EXCEPT_WM int BOOST_MOVE_WINAPI_CC
- QueryPerformanceCounter(::_LARGE_INTEGER* lpPerformanceCount);
- BOOST_MOVE_WINAPI_IMPORT_EXCEPT_WM int BOOST_MOVE_WINAPI_CC
- QueryPerformanceFrequency(::_LARGE_INTEGER* lpFrequency);
- } // extern "C"
- #endif
- namespace boost { namespace move_detail {
- BOOST_FORCEINLINE int QueryPerformanceCounter(long long* lpPerformanceCount)
- {
- return ::QueryPerformanceCounter(reinterpret_cast< ::_LARGE_INTEGER* >(lpPerformanceCount));
- }
- BOOST_FORCEINLINE int QueryPerformanceFrequency(long long* lpFrequency)
- {
- return ::QueryPerformanceFrequency(reinterpret_cast< ::_LARGE_INTEGER* >(lpFrequency));
- }
- template<int Dummy>
- struct QPFHolder
- {
- static inline double get_nsec_per_tic()
- {
- long long freq;
- //According to MS documentation:
- //"On systems that run Windows XP or later, the function will always succeed and will thus never return zero"
- (void)boost::move_detail::QueryPerformanceFrequency(&freq);
- return double(1000000000.0L / double(freq));
- }
- static const double nanosecs_per_tic;
- };
- template<int Dummy>
- const double QPFHolder<Dummy>::nanosecs_per_tic = get_nsec_per_tic();
- inline boost::uint64_t nsec_clock() BOOST_NOEXCEPT
- {
- double nanosecs_per_tic = QPFHolder<0>::nanosecs_per_tic;
-
- long long pcount;
- //According to MS documentation:
- //"On systems that run Windows XP or later, the function will always succeed and will thus never return zero"
- (void)boost::move_detail::QueryPerformanceCounter( &pcount );
- return static_cast<boost::uint64_t>(nanosecs_per_tic * double(pcount));
- }
- }} //namespace boost { namespace move_detail {
- #elif defined(BOOST_MOVE_DETAIL_MAC_API)
- #include <mach/mach_time.h> // mach_absolute_time, mach_timebase_info_data_t
- inline boost::uint64_t nsec_clock() BOOST_NOEXCEPT
- {
- boost::uint64_t count = ::mach_absolute_time();
- mach_timebase_info_data_t info;
- mach_timebase_info(&info);
- return static_cast<boost::uint64_t>
- ( static_cast<double>(count)*(static_cast<double>(info.numer) / info.denom) );
- }
- #elif defined(BOOST_MOVE_DETAIL_POSIX_API)
- #include <time.h>
- # if defined(CLOCK_MONOTONIC_PRECISE) //BSD
- # define BOOST_MOVE_DETAIL_CLOCK_MONOTONIC CLOCK_MONOTONIC_PRECISE
- # elif defined(CLOCK_MONOTONIC_RAW) //Linux
- # define BOOST_MOVE_DETAIL_CLOCK_MONOTONIC CLOCK_MONOTONIC_RAW
- # elif defined(CLOCK_HIGHRES) //Solaris
- # define BOOST_MOVE_DETAIL_CLOCK_MONOTONIC CLOCK_HIGHRES
- # elif defined(CLOCK_MONOTONIC) //POSIX (AIX, BSD, Linux, Solaris)
- # define BOOST_MOVE_DETAIL_CLOCK_MONOTONIC CLOCK_MONOTONIC
- # else
- # error "No high resolution steady clock in your system, please provide a patch"
- # endif
- inline boost::uint64_t nsec_clock() BOOST_NOEXCEPT
- {
- struct timespec count;
- ::clock_gettime(BOOST_MOVE_DETAIL_CLOCK_MONOTONIC, &count);
- boost::uint64_t r = static_cast<boost::uint64_t>(count.tv_sec);
- r *= 1000000000U;
- r += static_cast<boost::uint64_t>(count.tv_nsec);
- return r;
- }
- #endif // POSIX
- namespace boost { namespace move_detail {
- typedef boost::uint64_t nanosecond_type;
- struct cpu_times
- {
- nanosecond_type wall;
- nanosecond_type user;
- nanosecond_type system;
- void clear() { wall = user = system = 0; }
- cpu_times()
- { this->clear(); }
- };
- inline void get_cpu_times(boost::move_detail::cpu_times& current)
- {
- current.wall = nsec_clock();
- }
- class cpu_timer
- {
- public:
- // constructor
- cpu_timer() BOOST_NOEXCEPT { start(); }
- // observers
- bool is_stopped() const BOOST_NOEXCEPT { return m_is_stopped; }
- cpu_times elapsed() const BOOST_NOEXCEPT; // does not stop()
- // actions
- void start() BOOST_NOEXCEPT;
- void stop() BOOST_NOEXCEPT;
- void resume() BOOST_NOEXCEPT;
- private:
- cpu_times m_times;
- bool m_is_stopped;
- };
- // cpu_timer ---------------------------------------------------------------------//
- inline void cpu_timer::start() BOOST_NOEXCEPT
- {
- m_is_stopped = false;
- get_cpu_times(m_times);
- }
- inline void cpu_timer::stop() BOOST_NOEXCEPT
- {
- if (is_stopped())
- return;
- m_is_stopped = true;
-
- cpu_times current;
- get_cpu_times(current);
- m_times.wall = (current.wall - m_times.wall);
- m_times.user = (current.user - m_times.user);
- m_times.system = (current.system - m_times.system);
- }
- inline cpu_times cpu_timer::elapsed() const BOOST_NOEXCEPT
- {
- if (is_stopped())
- return m_times;
- cpu_times current;
- get_cpu_times(current);
- current.wall -= m_times.wall;
- current.user -= m_times.user;
- current.system -= m_times.system;
- return current;
- }
- inline void cpu_timer::resume() BOOST_NOEXCEPT
- {
- if (is_stopped())
- {
- cpu_times current (m_times);
- start();
- m_times.wall -= current.wall;
- m_times.user -= current.user;
- m_times.system -= current.system;
- }
- }
- } // namespace move_detail
- } // namespace boost
- #endif //BOOST_MOVE_DETAIL_NSEC_CLOCK_HPP
|