mirror of
				https://github.com/fmtlib/fmt.git
				synced 2025-11-04 08:01:40 +01:00 
			
		
		
		
	
		
			
	
	
		
			475 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
		
		
			
		
	
	
			475 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| 
								 | 
							
								//  Copyright (c) 2005-2010 Hartmut Kaiser
							 | 
						||
| 
								 | 
							
								//  Copyright (c) 2009      Edward Grace
							 | 
						||
| 
								 | 
							
								// 
							 | 
						||
| 
								 | 
							
								//  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)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#if !defined(HIGH_RESOLUTION_TIMER_MAR_24_2008_1222PM)
							 | 
						||
| 
								 | 
							
								#define HIGH_RESOLUTION_TIMER_MAR_24_2008_1222PM
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include <boost/config.hpp>
							 | 
						||
| 
								 | 
							
								#include <boost/throw_exception.hpp>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#if defined(BOOST_HAS_UNISTD_H)
							 | 
						||
| 
								 | 
							
								#include <unistd.h>
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								#include <time.h>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#if defined(BOOST_WINDOWS)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include <stdexcept>
							 | 
						||
| 
								 | 
							
								#include <limits>
							 | 
						||
| 
								 | 
							
								#include <windows.h>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								namespace util 
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    ///////////////////////////////////////////////////////////////////////////////
							 | 
						||
| 
								 | 
							
								    //
							 | 
						||
| 
								 | 
							
								    //  high_resolution_timer 
							 | 
						||
| 
								 | 
							
								    //      A timer object measures elapsed time.
							 | 
						||
| 
								 | 
							
								    //      CAUTION: Windows only!
							 | 
						||
| 
								 | 
							
								    //
							 | 
						||
| 
								 | 
							
								    ///////////////////////////////////////////////////////////////////////////////
							 | 
						||
| 
								 | 
							
								    class high_resolution_timer
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								    public:
							 | 
						||
| 
								 | 
							
								        high_resolution_timer() 
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								            restart(); 
							 | 
						||
| 
								 | 
							
								        } 
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        high_resolution_timer(double t) 
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								            LARGE_INTEGER frequency;
							 | 
						||
| 
								 | 
							
								            if (!QueryPerformanceFrequency(&frequency))
							 | 
						||
| 
								 | 
							
								                boost::throw_exception(std::runtime_error("Couldn't acquire frequency"));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            start_time.QuadPart = (LONGLONG)(t * frequency.QuadPart); 
							 | 
						||
| 
								 | 
							
								        } 
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        high_resolution_timer(high_resolution_timer const& rhs) 
							 | 
						||
| 
								 | 
							
								          : start_time(rhs.start_time)
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								        } 
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        static double now()
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								            SYSTEMTIME st;
							 | 
						||
| 
								 | 
							
								            GetSystemTime(&st);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            FILETIME ft;
							 | 
						||
| 
								 | 
							
								            SystemTimeToFileTime(&st, &ft);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            LARGE_INTEGER now;
							 | 
						||
| 
								 | 
							
								            now.LowPart = ft.dwLowDateTime;
							 | 
						||
| 
								 | 
							
								            now.HighPart = ft.dwHighDateTime;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            // FileTime is in 100ns increments, result needs to be in [s]
							 | 
						||
| 
								 | 
							
								            return now.QuadPart * 1e-7;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        void restart() 
							 | 
						||
| 
								 | 
							
								        { 
							 | 
						||
| 
								 | 
							
								            if (!QueryPerformanceCounter(&start_time))
							 | 
						||
| 
								 | 
							
								                boost::throw_exception(std::runtime_error("Couldn't initialize start_time"));
							 | 
						||
| 
								 | 
							
								        } 
							 | 
						||
| 
								 | 
							
								        double elapsed() const                  // return elapsed time in seconds
							 | 
						||
| 
								 | 
							
								        { 
							 | 
						||
| 
								 | 
							
								            LARGE_INTEGER now;
							 | 
						||
| 
								 | 
							
								            if (!QueryPerformanceCounter(&now))
							 | 
						||
| 
								 | 
							
								                boost::throw_exception(std::runtime_error("Couldn't get current time"));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            LARGE_INTEGER frequency;
							 | 
						||
| 
								 | 
							
								            if (!QueryPerformanceFrequency(&frequency))
							 | 
						||
| 
								 | 
							
								                boost::throw_exception(std::runtime_error("Couldn't acquire frequency"));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            return double(now.QuadPart - start_time.QuadPart) / frequency.QuadPart;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        double elapsed_max() const   // return estimated maximum value for elapsed()
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								            LARGE_INTEGER frequency;
							 | 
						||
| 
								 | 
							
								            if (!QueryPerformanceFrequency(&frequency))
							 | 
						||
| 
								 | 
							
								                boost::throw_exception(std::runtime_error("Couldn't acquire frequency"));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            return double((std::numeric_limits<LONGLONG>::max)() - start_time.QuadPart) / 
							 | 
						||
| 
								 | 
							
								                double(frequency.QuadPart); 
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        double elapsed_min() const            // return minimum value for elapsed()
							 | 
						||
| 
								 | 
							
								        { 
							 | 
						||
| 
								 | 
							
								            LARGE_INTEGER frequency;
							 | 
						||
| 
								 | 
							
								            if (!QueryPerformanceFrequency(&frequency))
							 | 
						||
| 
								 | 
							
								                boost::throw_exception(std::runtime_error("Couldn't acquire frequency"));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            return 1.0 / frequency.QuadPart; 
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    private:
							 | 
						||
| 
								 | 
							
								        LARGE_INTEGER start_time;
							 | 
						||
| 
								 | 
							
								    }; 
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								} // namespace util
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#elif defined(_POSIX_TIMERS) && _POSIX_TIMERS > 0 && defined(_POSIX_THREAD_CPUTIME)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#if _POSIX_THREAD_CPUTIME > 0   // timer always supported
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								namespace util
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    ///////////////////////////////////////////////////////////////////////////////
							 | 
						||
| 
								 | 
							
								    //
							 | 
						||
| 
								 | 
							
								    //  high_resolution_timer 
							 | 
						||
| 
								 | 
							
								    //      A timer object measures elapsed time.
							 | 
						||
| 
								 | 
							
								    //
							 | 
						||
| 
								 | 
							
								    ///////////////////////////////////////////////////////////////////////////////
							 | 
						||
| 
								 | 
							
								    class high_resolution_timer
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								    public:
							 | 
						||
| 
								 | 
							
								        high_resolution_timer() 
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								            start_time.tv_sec = 0;
							 | 
						||
| 
								 | 
							
								            start_time.tv_nsec = 0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            restart(); 
							 | 
						||
| 
								 | 
							
								        } 
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        high_resolution_timer(double t) 
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								            start_time.tv_sec = time_t(t);
							 | 
						||
| 
								 | 
							
								            start_time.tv_nsec = (t - start_time.tv_sec) * 1e9;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        high_resolution_timer(high_resolution_timer const& rhs) 
							 | 
						||
| 
								 | 
							
								          : start_time(rhs.start_time)
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								        } 
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        static double now()
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								            timespec now;
							 | 
						||
| 
								 | 
							
								            if (-1 == clock_gettime(CLOCK_REALTIME, &now))
							 | 
						||
| 
								 | 
							
								                boost::throw_exception(std::runtime_error("Couldn't get current time"));
							 | 
						||
| 
								 | 
							
								            return double(now.tv_sec) + double(now.tv_nsec) * 1e-9;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        void restart() 
							 | 
						||
| 
								 | 
							
								        { 
							 | 
						||
| 
								 | 
							
								            if (-1 == clock_gettime(CLOCK_REALTIME, &start_time))
							 | 
						||
| 
								 | 
							
								                boost::throw_exception(std::runtime_error("Couldn't initialize start_time"));
							 | 
						||
| 
								 | 
							
								        } 
							 | 
						||
| 
								 | 
							
								        double elapsed() const                  // return elapsed time in seconds
							 | 
						||
| 
								 | 
							
								        { 
							 | 
						||
| 
								 | 
							
								            timespec now;
							 | 
						||
| 
								 | 
							
								            if (-1 == clock_gettime(CLOCK_REALTIME, &now))
							 | 
						||
| 
								 | 
							
								                boost::throw_exception(std::runtime_error("Couldn't get current time"));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            if (now.tv_sec == start_time.tv_sec)
							 | 
						||
| 
								 | 
							
								                return double(now.tv_nsec - start_time.tv_nsec) * 1e-9;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            return double(now.tv_sec - start_time.tv_sec) + 
							 | 
						||
| 
								 | 
							
								                (double(now.tv_nsec - start_time.tv_nsec) * 1e-9);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        double elapsed_max() const   // return estimated maximum value for elapsed()
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								            return double((std::numeric_limits<time_t>::max)() - start_time.tv_sec); 
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        double elapsed_min() const            // return minimum value for elapsed()
							 | 
						||
| 
								 | 
							
								        { 
							 | 
						||
| 
								 | 
							
								            timespec resolution;
							 | 
						||
| 
								 | 
							
								            if (-1 == clock_getres(CLOCK_REALTIME, &resolution))
							 | 
						||
| 
								 | 
							
								                boost::throw_exception(std::runtime_error("Couldn't get resolution"));
							 | 
						||
| 
								 | 
							
								            return double(resolution.tv_sec + resolution.tv_nsec * 1e-9); 
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    private:
							 | 
						||
| 
								 | 
							
								        timespec start_time;
							 | 
						||
| 
								 | 
							
								    }; 
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								} // namespace util
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#else   // _POSIX_THREAD_CPUTIME > 0
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include <boost/timer.hpp>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// availability of high performance timers must be checked at runtime
							 | 
						||
| 
								 | 
							
								namespace util
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    ///////////////////////////////////////////////////////////////////////////////
							 | 
						||
| 
								 | 
							
								    //
							 | 
						||
| 
								 | 
							
								    //  high_resolution_timer 
							 | 
						||
| 
								 | 
							
								    //      A timer object measures elapsed time.
							 | 
						||
| 
								 | 
							
								    //
							 | 
						||
| 
								 | 
							
								    ///////////////////////////////////////////////////////////////////////////////
							 | 
						||
| 
								 | 
							
								    class high_resolution_timer
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								    public:
							 | 
						||
| 
								 | 
							
								        high_resolution_timer() 
							 | 
						||
| 
								 | 
							
								          : use_backup(sysconf(_SC_THREAD_CPUTIME) <= 0)
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								            if (!use_backup) {
							 | 
						||
| 
								 | 
							
								                start_time.tv_sec = 0;
							 | 
						||
| 
								 | 
							
								                start_time.tv_nsec = 0;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								            restart(); 
							 | 
						||
| 
								 | 
							
								        } 
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        high_resolution_timer(double t) 
							 | 
						||
| 
								 | 
							
								          : use_backup(sysconf(_SC_THREAD_CPUTIME) <= 0)
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								            if (!use_backup) {
							 | 
						||
| 
								 | 
							
								                start_time.tv_sec = time_t(t);
							 | 
						||
| 
								 | 
							
								                start_time.tv_nsec = (t - start_time.tv_sec) * 1e9;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        
							 | 
						||
| 
								 | 
							
								        high_resolution_timer(high_resolution_timer const& rhs) 
							 | 
						||
| 
								 | 
							
								          : use_backup(sysconf(_SC_THREAD_CPUTIME) <= 0),
							 | 
						||
| 
								 | 
							
								            start_time(rhs.start_time)
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								        } 
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        static double now()
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								            if (sysconf(_SC_THREAD_CPUTIME) <= 0)
							 | 
						||
| 
								 | 
							
								                return double(std::clock());
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            timespec now;
							 | 
						||
| 
								 | 
							
								            if (-1 == clock_gettime(CLOCK_REALTIME, &now))
							 | 
						||
| 
								 | 
							
								                boost::throw_exception(std::runtime_error("Couldn't get current time"));
							 | 
						||
| 
								 | 
							
								            return double(now.tv_sec) + double(now.tv_nsec) * 1e-9;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        void restart() 
							 | 
						||
| 
								 | 
							
								        { 
							 | 
						||
| 
								 | 
							
								            if (use_backup)
							 | 
						||
| 
								 | 
							
								                start_time_backup.restart();
							 | 
						||
| 
								 | 
							
								            else if (-1 == clock_gettime(CLOCK_REALTIME, &start_time))
							 | 
						||
| 
								 | 
							
								                boost::throw_exception(std::runtime_error("Couldn't initialize start_time"));
							 | 
						||
| 
								 | 
							
								        } 
							 | 
						||
| 
								 | 
							
								        double elapsed() const                  // return elapsed time in seconds
							 | 
						||
| 
								 | 
							
								        { 
							 | 
						||
| 
								 | 
							
								            if (use_backup)
							 | 
						||
| 
								 | 
							
								                return start_time_backup.elapsed();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            timespec now;
							 | 
						||
| 
								 | 
							
								            if (-1 == clock_gettime(CLOCK_REALTIME, &now))
							 | 
						||
| 
								 | 
							
								                boost::throw_exception(std::runtime_error("Couldn't get current time"));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            if (now.tv_sec == start_time.tv_sec)
							 | 
						||
| 
								 | 
							
								                return double(now.tv_nsec - start_time.tv_nsec) * 1e-9;
							 | 
						||
| 
								 | 
							
								                
							 | 
						||
| 
								 | 
							
								            return double(now.tv_sec - start_time.tv_sec) + 
							 | 
						||
| 
								 | 
							
								                (double(now.tv_nsec - start_time.tv_nsec) * 1e-9);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        double elapsed_max() const   // return estimated maximum value for elapsed()
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								            if (use_backup)
							 | 
						||
| 
								 | 
							
								                start_time_backup.elapsed_max();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            return double((std::numeric_limits<time_t>::max)() - start_time.tv_sec); 
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        double elapsed_min() const            // return minimum value for elapsed()
							 | 
						||
| 
								 | 
							
								        { 
							 | 
						||
| 
								 | 
							
								            if (use_backup)
							 | 
						||
| 
								 | 
							
								                start_time_backup.elapsed_min();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            timespec resolution;
							 | 
						||
| 
								 | 
							
								            if (-1 == clock_getres(CLOCK_REALTIME, &resolution))
							 | 
						||
| 
								 | 
							
								                boost::throw_exception(std::runtime_error("Couldn't get resolution"));
							 | 
						||
| 
								 | 
							
								            return double(resolution.tv_sec + resolution.tv_nsec * 1e-9); 
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    private:
							 | 
						||
| 
								 | 
							
								        bool use_backup;
							 | 
						||
| 
								 | 
							
								        timespec start_time;
							 | 
						||
| 
								 | 
							
								        boost::timer start_time_backup;
							 | 
						||
| 
								 | 
							
								    }; 
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								} // namespace util
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#endif  // _POSIX_THREAD_CPUTIME > 0
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#else   //  !defined(BOOST_WINDOWS) && (!defined(_POSIX_TIMERS)
							 | 
						||
| 
								 | 
							
								        //      || _POSIX_TIMERS <= 0
							 | 
						||
| 
								 | 
							
								        //      || !defined(_POSIX_THREAD_CPUTIME)
							 | 
						||
| 
								 | 
							
								        //      || _POSIX_THREAD_CPUTIME <= 0)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#if defined(BOOST_HAS_GETTIMEOFDAY)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// For platforms that do not support _POSIX_TIMERS but do have
							 | 
						||
| 
								 | 
							
								// GETTIMEOFDAY, which is still preferable to std::clock()
							 | 
						||
| 
								 | 
							
								#include <stdexcept>
							 | 
						||
| 
								 | 
							
								#include <limits>
							 | 
						||
| 
								 | 
							
								#include <sys/time.h>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								namespace util
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    ///////////////////////////////////////////////////////////////////////////
							 | 
						||
| 
								 | 
							
								    //
							 | 
						||
| 
								 | 
							
								    //  high_resolution_timer 
							 | 
						||
| 
								 | 
							
								    //      A timer object measures elapsed time.
							 | 
						||
| 
								 | 
							
								    //
							 | 
						||
| 
								 | 
							
								    //  Implemented with gettimeofday() for platforms that support it,
							 | 
						||
| 
								 | 
							
								    //  such as Darwin (OS X) but do not support the previous options.
							 | 
						||
| 
								 | 
							
								    //
							 | 
						||
| 
								 | 
							
								    //  Copyright (c) 2009 Edward Grace
							 | 
						||
| 
								 | 
							
								    //
							 | 
						||
| 
								 | 
							
								    ///////////////////////////////////////////////////////////////////////////
							 | 
						||
| 
								 | 
							
								    class high_resolution_timer
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								    private:
							 | 
						||
| 
								 | 
							
								        template <typename U>
							 | 
						||
| 
								 | 
							
								        static inline double unsigned_diff(const U &a, const U &b)
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								            if (a > b)
							 | 
						||
| 
								 | 
							
								                return static_cast<double>(a-b);
							 | 
						||
| 
								 | 
							
								            return -static_cast<double>(b-a);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        // @brief Return the difference between two timeval types.
							 | 
						||
| 
								 | 
							
								        // 
							 | 
						||
| 
								 | 
							
								        // @param t1 The most recent timeval.
							 | 
						||
| 
								 | 
							
								        // @param t0 The historical timeval.
							 | 
						||
| 
								 | 
							
								        // 
							 | 
						||
| 
								 | 
							
								        // @return The difference between the two in seconds.
							 | 
						||
| 
								 | 
							
								        double elapsed(const timeval &t1, const timeval &t0) const
							 | 
						||
| 
								 | 
							
								        { 
							 | 
						||
| 
								 | 
							
								            if (t1.tv_sec == t0.tv_sec)
							 | 
						||
| 
								 | 
							
								                return unsigned_diff(t1.tv_usec,t0.tv_usec) * 1e-6;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            // We do it this way as the result of the difference of the
							 | 
						||
| 
								 | 
							
								            // microseconds can be negative if the clock is implemented so
							 | 
						||
| 
								 | 
							
								            // that the seconds timer increases in large steps.
							 | 
						||
| 
								 | 
							
								            //
							 | 
						||
| 
								 | 
							
								            // Naive subtraction of the unsigned types and conversion to
							 | 
						||
| 
								 | 
							
								            // double can wreak havoc!
							 | 
						||
| 
								 | 
							
								            return unsigned_diff(t1.tv_sec,t0.tv_sec) + 
							 | 
						||
| 
								 | 
							
								                unsigned_diff(t1.tv_usec,t0.tv_usec) * 1e-6; 
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    public:
							 | 
						||
| 
								 | 
							
								        high_resolution_timer() 
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								            start_time.tv_sec = 0;
							 | 
						||
| 
								 | 
							
								            start_time.tv_usec = 0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            restart(); 
							 | 
						||
| 
								 | 
							
								        } 
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        high_resolution_timer(double t) 
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								            start_time.tv_sec = time_t(t);
							 | 
						||
| 
								 | 
							
								            start_time.tv_usec = (t - start_time.tv_sec) * 1e6;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        high_resolution_timer(high_resolution_timer const& rhs) 
							 | 
						||
| 
								 | 
							
								          : start_time(rhs.start_time)
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								        } 
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        static double now()
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								            // Under some implementations gettimeofday() will always
							 | 
						||
| 
								 | 
							
								            // return zero. If it returns anything else however then
							 | 
						||
| 
								 | 
							
								            // we accept this as evidence of an error.  Note we are
							 | 
						||
| 
								 | 
							
								            // not assuming that -1 explicitly indicates the error
							 | 
						||
| 
								 | 
							
								            // condition, just that non zero is indicative of the
							 | 
						||
| 
								 | 
							
								            // error.
							 | 
						||
| 
								 | 
							
								            timeval now;
							 | 
						||
| 
								 | 
							
								            if (gettimeofday(&now, NULL))
							 | 
						||
| 
								 | 
							
								                boost::throw_exception(std::runtime_error("Couldn't get current time"));
							 | 
						||
| 
								 | 
							
								            return double(now.tv_sec) + double(now.tv_usec) * 1e-6;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        void restart() 
							 | 
						||
| 
								 | 
							
								        { 
							 | 
						||
| 
								 | 
							
								            if (gettimeofday(&start_time, NULL))
							 | 
						||
| 
								 | 
							
								                boost::throw_exception(std::runtime_error("Couldn't initialize start_time"));
							 | 
						||
| 
								 | 
							
								        } 
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        double elapsed() const                  // return elapsed time in seconds
							 | 
						||
| 
								 | 
							
								        { 
							 | 
						||
| 
								 | 
							
								            timeval now;
							 | 
						||
| 
								 | 
							
								            if (gettimeofday(&now, NULL))
							 | 
						||
| 
								 | 
							
								                boost::throw_exception(std::runtime_error("Couldn't get current time"));
							 | 
						||
| 
								 | 
							
								            return elapsed(now,start_time);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        double elapsed_max() const   // return estimated maximum value for elapsed()
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								            return double((std::numeric_limits<time_t>::max)() - start_time.tv_sec); 
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        double elapsed_min() const            // return minimum value for elapsed()
							 | 
						||
| 
								 | 
							
								        { 
							 | 
						||
| 
								 | 
							
								            // On systems without an explicit clock_getres or similar
							 | 
						||
| 
								 | 
							
								            // we can only estimate an upper bound on the resolution
							 | 
						||
| 
								 | 
							
								            // by repeatedly calling the gettimeofday function.  This
							 | 
						||
| 
								 | 
							
								            // is often likely to be indicative of the true
							 | 
						||
| 
								 | 
							
								            // resolution.
							 | 
						||
| 
								 | 
							
								            timeval t0, t1;
							 | 
						||
| 
								 | 
							
								            double delta(0);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            if (gettimeofday(&t0, NULL)) 
							 | 
						||
| 
								 | 
							
								                boost::throw_exception(std::runtime_error("Couldn't get resolution."));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            // Spin around in a tight loop until we observe a change
							 | 
						||
| 
								 | 
							
								            // in the reported timer value.
							 | 
						||
| 
								 | 
							
								            do {
							 | 
						||
| 
								 | 
							
								                if (gettimeofday(&t1, NULL)) 
							 | 
						||
| 
								 | 
							
								                    boost::throw_exception(std::runtime_error("Couldn't get resolution."));
							 | 
						||
| 
								 | 
							
								                delta = elapsed(t1, t0);
							 | 
						||
| 
								 | 
							
								            } while (delta <= 0.0);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            return delta;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    private:
							 | 
						||
| 
								 | 
							
								        timeval start_time;
							 | 
						||
| 
								 | 
							
								    }; 
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								} 
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#else // BOOST_HAS_GETTIMEOFDAY
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								//  For platforms other than Windows or Linux, or not implementing gettimeofday
							 | 
						||
| 
								 | 
							
								//  simply fall back to boost::timer
							 | 
						||
| 
								 | 
							
								#include <boost/timer.hpp>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								namespace util
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    struct high_resolution_timer
							 | 
						||
| 
								 | 
							
								        : boost::timer
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        static double now()
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								            return double(std::clock());
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    };
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#endif  // HIGH_RESOLUTION_TIMER_AUG_14_2009_0425PM
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								// $Log: high_resolution_timer.hpp,v $
							 | 
						||
| 
								 | 
							
								// Revision 1.4  2009/08/14 15:28:10  graceej
							 | 
						||
| 
								 | 
							
								// * It is entirely possible for the updating clock to increment the
							 | 
						||
| 
								 | 
							
								// * seconds and *decrement* the microseconds field.  Consequently
							 | 
						||
| 
								 | 
							
								// * when subtracting these unsigned microseconds fields a wrap-around
							 | 
						||
| 
								 | 
							
								// * error can occur.  For this reason elapsed(t1, t0) is used in a
							 | 
						||
| 
								 | 
							
								// * similar maner to cycle.h this preserves the sign of the
							 | 
						||
| 
								 | 
							
								// * difference.
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								
							 |