heap/tools/high_resolution_timer.hpp
2023-12-07 17:27:32 +08:00

207 lines
4.9 KiB
C++

/*=============================================================================
Copyright (c) 2005-2007 Hartmut Kaiser
2007, 2009 Tim Blechmann
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( BOOST_HIGH_RESOLUTION_TIMER_HPP )
# define BOOST_HIGH_RESOLUTION_TIMER_HPP
# include <boost/config.hpp>
# include <boost/throw_exception.hpp>
# if _POSIX_C_SOURCE >= 199309L
# include "time.h"
# include <limits>
# include <stdexcept>
namespace boost {
class high_resolution_timer
{
public:
high_resolution_timer()
{
restart();
}
void restart()
{
int status = clock_gettime( CLOCK_REALTIME, &start_time );
if ( status == -1 )
boost::throw_exception( std::runtime_error( "Couldn't initialize start_time" ) );
}
double elapsed() const // return elapsed time in seconds
{
struct timespec now;
int status = clock_gettime( CLOCK_REALTIME, &now );
if ( status == -1 )
boost::throw_exception( std::runtime_error( "Couldn't get current time" ) );
struct timespec diff;
double ret_sec = double( now.tv_sec - start_time.tv_sec );
double ret_nsec = double( now.tv_nsec - start_time.tv_nsec );
while ( ret_nsec < 0 ) {
ret_sec -= 1.0;
ret_nsec += 1e9;
}
double ret = ret_sec + ret_nsec / 1e9;
return ret;
}
double elapsed_max() const // return estimated maximum value for elapsed()
{
return double( ( std::numeric_limits< double >::max )() );
}
double elapsed_min() const // return minimum value for elapsed()
{
return 0.0;
}
private:
struct timespec start_time;
};
} // namespace boost
# elif defined( __APPLE__ )
# import <mach/mach_time.h>
namespace boost {
class high_resolution_timer
{
public:
high_resolution_timer( void )
{
mach_timebase_info_data_t info;
kern_return_t err = mach_timebase_info( &info );
if ( err )
throw std::runtime_error( "cannot create mach timebase info" );
conversion_factor = (double)info.numer / (double)info.denom;
restart();
}
void restart()
{
start = mach_absolute_time();
}
double elapsed() const // return elapsed time in seconds
{
uint64_t now = mach_absolute_time();
double duration = double( now - start ) * conversion_factor;
return duration
}
double elapsed_max() const // return estimated maximum value for elapsed()
{
return double( ( std::numeric_limits< double >::max )() );
}
double elapsed_min() const // return minimum value for elapsed()
{
return 0.0;
}
private:
uint64_t start;
double conversion_factor;
};
} // namespace boost
# elif defined( BOOST_WINDOWS )
# include <limits>
# include <stdexcept>
# include <windows.h>
namespace boost {
///////////////////////////////////////////////////////////////////////////////
//
// high_resolution_timer
// A timer object measures elapsed time.
// CAUTION: Windows only!
//
///////////////////////////////////////////////////////////////////////////////
class high_resolution_timer
{
public:
high_resolution_timer()
{
start_time.QuadPart = 0;
frequency.QuadPart = 0;
if ( !QueryPerformanceFrequency( &frequency ) )
boost::throw_exception( std::runtime_error( "Couldn't acquire frequency" ) );
restart();
}
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" ) );
return double( now.QuadPart - start_time.QuadPart ) / frequency.QuadPart;
}
double elapsed_max() const // return estimated maximum value for elapsed()
{
return ( double( ( std::numeric_limits< LONGLONG >::max )() ) - double( start_time.QuadPart ) )
/ double( frequency.QuadPart );
}
double elapsed_min() const // return minimum value for elapsed()
{
return 1.0 / frequency.QuadPart;
}
private:
LARGE_INTEGER start_time;
LARGE_INTEGER frequency;
};
} // namespace boost
# else
// For other platforms, simply fall back to boost::timer
# include <boost/throw_exception.hpp>
# include <boost/timer.hpp>
namespace boost {
typedef boost::timer high_resolution_timer;
} // namespace boost
# endif
#endif // !defined(BOOST_HIGH_RESOLUTION_TIMER_HPP)