123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224 |
- // 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 <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 <boost/winapi/time.hpp>
- #include <boost/winapi/timers.hpp>
- #include <boost/winapi/get_last_error.hpp>
- #include <boost/winapi/error_codes.hpp>
- #include <boost/assert.hpp>
- #include <boost/core/ignore_unused.hpp>
- namespace boost { namespace move_detail {
- template<int Dummy>
- struct QPFHolder
- {
- static inline double get_nsec_per_tic()
- {
- boost::winapi::LARGE_INTEGER_ freq;
- boost::winapi::BOOL_ r = boost::winapi::QueryPerformanceFrequency( &freq );
- boost::ignore_unused(r);
- BOOST_ASSERT(r != 0 && "Boost::Move - get_nanosecs_per_tic Internal Error");
- return double(1000000000.0L / freq.QuadPart);
- }
- 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;
-
- boost::winapi::LARGE_INTEGER_ pcount;
- unsigned times=0;
- while ( !boost::winapi::QueryPerformanceCounter( &pcount ) )
- {
- if ( ++times > 3 )
- {
- BOOST_ASSERT("Boost::Move - QueryPerformanceCounter Internal Error");
- return 0u;
- }
- }
- return static_cast<boost::uint64_t>((nanosecs_per_tic) * pcount.QuadPart);
- }
- }} //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 = count.tv_sec;
- r *= 1000000000U;
- r += 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; }
- };
- 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
|