| // 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 |