123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244 |
- // runtime_resolution.cpp ----------------------------------------------------------//
- // Copyright 2008 Howard Hinnant
- // Copyright 2008 Beman Dawes
- // Copyright 2009 Vicente J. Botet Escriba
- // Copyright (c) Microsoft Corporation 2014
- // Distributed under the Boost Software License, Version 1.0.
- // See http://www.boost.org/LICENSE_1_0.txt
- /*
- This code was extracted by Vicente J. Botet Escriba from Beman Dawes time2_demo.cpp which
- was derived by Beman Dawes from Howard Hinnant's time2_demo prototype.
- Many thanks to Howard for making his code available under the Boost license.
- The original code was modified to conform to Boost conventions and to section
- 20.9 Time utilities [time] of the C++ committee's working paper N2798.
- See http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2798.pdf.
- time2_demo contained this comment:
- Much thanks to Andrei Alexandrescu,
- Walter Brown,
- Peter Dimov,
- Jeff Garland,
- Terry Golubiewski,
- Daniel Krugler,
- Anthony Williams.
- */
- #define _CRT_SECURE_NO_WARNINGS // disable VC++ foolishness
- #include <boost/chrono/chrono.hpp>
- #include <boost/type_traits.hpp>
- #include <iostream>
- #if defined(BOOST_CHRONO_MAC_API)
- #include <sys/time.h> //for gettimeofday and timeval
- #include <mach/mach_time.h> // mach_absolute_time, mach_timebase_info_data_t
- #endif
- #if defined(BOOST_CHRONO_WINDOWS_API)
- #include <windows.h>
- namespace
- {
- #if defined UNDER_CE || BOOST_PLAT_WINDOWS_RUNTIME
- // Windows CE and Windows store does not define timeval
- struct timeval {
- long tv_sec; /* seconds */
- long tv_usec; /* and microseconds */
- };
- #endif
- int gettimeofday(struct timeval * tp, void *)
- {
- FILETIME ft;
- #if defined(UNDER_CE)
- // Windows CE does not define GetSystemTimeAsFileTime so we do it in two steps.
- SYSTEMTIME st;
- ::GetSystemTime( &st );
- ::SystemTimeToFileTime( &st, &ft );
- #else
- ::GetSystemTimeAsFileTime( &ft ); // never fails
- #endif
- long long t = (static_cast<long long>(ft.dwHighDateTime) << 32) | ft.dwLowDateTime;
- # if !defined( BOOST_MSVC ) || BOOST_MSVC > 1300 // > VC++ 7.0
- t -= 116444736000000000LL;
- # else
- t -= 116444736000000000;
- # endif
- t /= 10; // microseconds
- tp->tv_sec = static_cast<long>( t / 1000000UL);
- tp->tv_usec = static_cast<long>( t % 1000000UL);
- return 0;
- }
- } // unnamed namespace
- #endif
- // Handle duration with resolution not known until run time
- using namespace boost::chrono;
- namespace runtime_resolution
- {
- class duration
- {
- public:
- typedef long long rep;
- private:
- rep rep_;
- static const double ticks_per_nanosecond;
- public:
- typedef boost::chrono::duration<double, boost::nano> tonanosec;
- duration() {} // = default;
- explicit duration(const rep& r) : rep_(r) {}
- // conversions
- explicit duration(const tonanosec& d)
- : rep_(static_cast<rep>(d.count() * ticks_per_nanosecond)) {}
- // explicit
- tonanosec convert_to_nanosec() const {return tonanosec(rep_/ticks_per_nanosecond);}
- // observer
- rep count() const {return rep_;}
- // arithmetic
- duration& operator+=(const duration& d) {rep_ += d.rep_; return *this;}
- duration& operator-=(const duration& d) {rep_ += d.rep_; return *this;}
- duration& operator*=(rep rhs) {rep_ *= rhs; return *this;}
- duration& operator/=(rep rhs) {rep_ /= rhs; return *this;}
- duration operator+() const {return *this;}
- duration operator-() const {return duration(-rep_);}
- duration& operator++() {++rep_; return *this;}
- duration operator++(int) {return duration(rep_++);}
- duration& operator--() {--rep_; return *this;}
- duration operator--(int) {return duration(rep_--);}
- friend duration operator+(duration x, duration y) {return x += y;}
- friend duration operator-(duration x, duration y) {return x -= y;}
- friend duration operator*(duration x, rep y) {return x *= y;}
- friend duration operator*(rep x, duration y) {return y *= x;}
- friend duration operator/(duration x, rep y) {return x /= y;}
- friend bool operator==(duration x, duration y) {return x.rep_ == y.rep_;}
- friend bool operator!=(duration x, duration y) {return !(x == y);}
- friend bool operator< (duration x, duration y) {return x.rep_ < y.rep_;}
- friend bool operator<=(duration x, duration y) {return !(y < x);}
- friend bool operator> (duration x, duration y) {return y < x;}
- friend bool operator>=(duration x, duration y) {return !(x < y);}
- };
- static
- double
- init_duration()
- {
- #if defined(BOOST_CHRONO_WINDOWS_API)
- return static_cast<double>(1) / 1000; // Windows FILETIME is 1 per microsec
- #elif defined(BOOST_CHRONO_MAC_API)
- mach_timebase_info_data_t MachInfo;
- mach_timebase_info(&MachInfo);
- return static_cast<double>(MachInfo.denom) / MachInfo.numer;
- #elif defined(BOOST_CHRONO_POSIX_API)
- return static_cast<double>(1) / 1000;
- #endif
- }
- const double duration::ticks_per_nanosecond = init_duration();
- class clock;
- class time_point
- {
- public:
- typedef runtime_resolution::clock clock;
- typedef long long rep;
- private:
- rep rep_;
- rep count() const {return rep_;}
- public:
- time_point() : rep_(0) {}
- explicit time_point(const duration& d)
- : rep_(d.count()) {}
- // arithmetic
- time_point& operator+=(const duration& d) {rep_ += d.count(); return *this;}
- time_point& operator-=(const duration& d) {rep_ -= d.count(); return *this;}
- friend time_point operator+(time_point x, duration y) {return x += y;}
- friend time_point operator+(duration x, time_point y) {return y += x;}
- friend time_point operator-(time_point x, duration y) {return x -= y;}
- friend duration operator-(time_point x, time_point y) {return duration(x.rep_ - y.rep_);}
- };
- class clock
- {
- public:
- typedef runtime_resolution::duration::rep rep;
- typedef runtime_resolution::duration duration;
- typedef runtime_resolution::time_point time_point;
- static time_point now()
- {
- #if defined(BOOST_CHRONO_WINDOWS_API)
- timeval tv;
- gettimeofday( &tv, 0 );
- return time_point(duration((static_cast<rep>(tv.tv_sec)<<32) | tv.tv_usec));
- #elif defined(BOOST_CHRONO_MAC_API)
- timeval tv;
- gettimeofday( &tv, 0 );
- return time_point(duration((static_cast<rep>(tv.tv_sec)<<32) | tv.tv_usec));
- #elif defined(BOOST_CHRONO_POSIX_API)
- timespec ts;
- ::clock_gettime( CLOCK_REALTIME, &ts );
- return time_point(duration((static_cast<rep>(ts.tv_sec)<<32) | ts.tv_nsec/1000));
- #endif // POSIX
- }
- };
- void test()
- {
- std::cout << "runtime_resolution test\n";
- clock::duration delay(boost::chrono::milliseconds(5));
- clock::time_point start = clock::now();
- while (clock::now() - start <= delay)
- ;
- clock::time_point stop = clock::now();
- clock::duration elapsed = stop - start;
- std::cout << "paused " <<
- boost::chrono::nanoseconds(
- boost::chrono::duration_cast<boost::chrono::nanoseconds>( elapsed.convert_to_nanosec() )).count()
- << " nanoseconds\n";
- }
- } // runtime_resolution
- int main()
- {
- runtime_resolution::test();
- return 0;
- }
|