Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r49823 - in sandbox/chrono: boost/chrono libs/chrono/src libs/chrono/test
From: bdawes_at_[hidden]
Date: 2008-11-18 09:58:03


Author: bemandawes
Date: 2008-11-18 09:58:02 EST (Tue, 18 Nov 2008)
New Revision: 49823
URL: http://svn.boost.org/trac/boost/changeset/49823

Log:
Chrono: tests passing on VC++ 9.0 and Intel 11.0 on Windows, and GCC 4.2.4 on Ubuntu.
Text files modified:
   sandbox/chrono/boost/chrono/chrono.hpp | 36 ++++++-
   sandbox/chrono/libs/chrono/src/chrono.cpp | 6
   sandbox/chrono/libs/chrono/src/process_clock.cpp | 66 ++++++++----
   sandbox/chrono/libs/chrono/src/run_timer.cpp | 24 ----
   sandbox/chrono/libs/chrono/test/run_timer_test.cpp | 195 ++++++++++++++++++++++-----------------
   5 files changed, 187 insertions(+), 140 deletions(-)

Modified: sandbox/chrono/boost/chrono/chrono.hpp
==============================================================================
--- sandbox/chrono/boost/chrono/chrono.hpp (original)
+++ sandbox/chrono/boost/chrono/chrono.hpp 2008-11-18 09:58:02 EST (Tue, 18 Nov 2008)
@@ -118,12 +118,8 @@
 
   // duration_cast
 
- # if !BOOST_WORKAROUND( BOOST_MSVC, <= 1500 ) // VC++ 9.0 can't handle this
-
- template <class ToDuration, class Rep, class Period>
- ToDuration duration_cast(const duration<Rep, Period>& d);
-
- # endif
+ //template <class ToDuration, class Rep, class Period>
+ // ToDuration duration_cast(const duration<Rep, Period>& d);
 
   // convenience typedefs
   typedef duration<boost::int_least64_t, nano> nanoseconds; // at least 64 bits needed
@@ -407,7 +403,16 @@
                   || (ratio_divide<Period2, period>::type::den == 1
                     && !treat_as_floating_point<Rep2>::value)
>::type* = 0)
+#ifdef __GNUC__
+ // GCC 4.2.4 refused to accept a definition at this point,
+ // yet both VC++ 9.0 SP1 and Intel ia32 11.0 accepted the definition
+ // without complaint. VC++ 9.0 SP1 refused to accept a later definition,
+ // although that was fine with GCC 4.2.4 and Intel ia32 11.0. Thus we
+ // have to support both approaches.
+ ;
+#else
               : rep_(duration_cast<duration>(d).count()) {}
+#endif
 
       // observer
 
@@ -901,6 +906,25 @@
 // As permitted, monotonic_clock is a typedef for high_resolution_clock.
 // See synopsis.
 
+
+//----------------------------------------------------------------------------//
+// duration constructor implementation //
+//----------------------------------------------------------------------------//
+
+#ifdef __GNUC__
+ // see comment above in section 20.9.3 Class template duration [time.duration]
+ template <class Rep, class Period>
+ template <class Rep2, class Period2>
+ duration<Rep, Period>::duration(const duration<Rep2, Period2>& d,
+ typename boost::enable_if_c
+ <
+ treat_as_floating_point<rep>::value
+ || (ratio_divide<Period2, period>::type::den == 1
+ && !treat_as_floating_point<Rep2>::value)
+ >::type*)
+ : rep_(duration_cast<duration>(d).count()) {}
+#endif
+
 } // namespace chrono
 } // namespace boost
 

Modified: sandbox/chrono/libs/chrono/src/chrono.cpp
==============================================================================
--- sandbox/chrono/libs/chrono/src/chrono.cpp (original)
+++ sandbox/chrono/libs/chrono/src/chrono.cpp 2008-11-18 09:58:02 EST (Tue, 18 Nov 2008)
@@ -137,8 +137,7 @@
     timespec ts;
     if ( ::clock_gettime( CLOCK_REALTIME, &ts ) )
     {
- boost::throw_exception(
- std::runtime_error( "system_clock: clock_gettime failed" ));
+ throw std::runtime_error( "system_clock: clock_gettime failed" );
     }
 
     return time_point(duration(
@@ -164,8 +163,7 @@
     timespec ts;
     if ( ::clock_gettime( CLOCK_MONOTONIC, &ts ) )
     {
- boost::throw_exception(
- std::runtime_error( "monotonic_clock: clock_gettime failed" ));
+ throw std::runtime_error( "monotonic_clock: clock_gettime failed" );
     }
 
     return time_point(duration(

Modified: sandbox/chrono/libs/chrono/src/process_clock.cpp
==============================================================================
--- sandbox/chrono/libs/chrono/src/process_clock.cpp (original)
+++ sandbox/chrono/libs/chrono/src/process_clock.cpp 2008-11-18 09:58:02 EST (Tue, 18 Nov 2008)
@@ -21,6 +21,29 @@
 # include <windows.h>
 #elif defined(BOOST_CHRONO_POSIX_API)
 # include <sys/times.h>
+# include <unistd.h>
+
+namespace
+{
+ long tick_factor() // multiplier to convert ticks
+ // to nanoseconds; -1 if unknown
+ {
+ static long factor = 0;
+ if ( !factor )
+ {
+ if ( (factor = ::sysconf( _SC_CLK_TCK )) <= 0 )
+ factor = -1;
+ else
+ {
+ assert( factor <= 1000000l ); // doesn't handle large ticks
+ factor = 1000000l / factor; // compute factor
+ if ( !factor ) factor = -1;
+ }
+ }
+ return factor;
+ }
+}
+
 #else
 # error unknown API
 #endif
@@ -30,30 +53,24 @@
   namespace chrono
   {
 
- void process_clock::now( process_times & times, system::error_code & ec )
+ void process_clock::now( process_times & times_, system::error_code & ec )
     {
 
-# if defined(BOOST_WINDOWS_API)
+# if defined(BOOST_CHRONO_WINDOWS_API)
 
       // note that Windows uses 100 nanosecond ticks for FILETIME
       FILETIME creation, exit, user_time, system_time;
 
- //FILETIME stopwatch_time;
- //::GetSystemTimeAsFileTime( &stopwatch_time );
- //times.real = duration(
- // ((static_cast<time_point::rep>(stopwatch_time.dwHighDateTime) << 32)
- // | stopwatch_time.dwLowDateTime) * 100 );
-
- times.real = duration( monotonic_clock::now().time_since_epoch().count() );
+ times_.real = duration( monotonic_clock::now().time_since_epoch().count() );
 
       if ( ::GetProcessTimes( ::GetCurrentProcess(), &creation, &exit,
              &system_time, &user_time ) )
       {
- times.user = duration(
+ times_.user = duration(
           ((static_cast<time_point::rep>(user_time.dwHighDateTime) << 32)
             | user_time.dwLowDateTime) * 100 );
 
- times.system = duration(
+ times_.system = duration(
           ((static_cast<time_point::rep>(system_time.dwHighDateTime) << 32)
             | system_time.dwLowDateTime) * 100 );
       }
@@ -61,32 +78,35 @@
       {
         assert( 0 && "error handling not implemented yet" );
         //ec = error_code( ::GetLastError(), native_ecat );
- //current.wall = current.system = current.user = microsecond_t(-1);
+ //times_.real = times_.system = times_.user = nanoseconds(-1);
       }
 
-# else
+# else // BOOST_CHRONO_POSIX_API
       tms tm;
       clock_t c = ::times( &tm );
       if ( c == -1 ) // error
       {
- ec = error_code( errno, native_ecat );
- current.wall = current.system = current.user = microsecond_t(-1);
+ assert( 0 && "error handling not implemented yet" );
+
+ ec = system::error_code( errno, system::system_category );
+ times_.real = times_.system = times_.user = nanoseconds(-1);
       }
       else
       {
- current.wall = microsecond_t(c);
- current.system = microsecond_t(tm.tms_stime + tm.tms_cstime);
- current.user = microsecond_t(tm.tms_utime + tm.tms_cutime);
+ times_.real = microseconds(c);
+ times_.system = microseconds(tm.tms_stime + tm.tms_cstime);
+ times_.user = microseconds(tm.tms_utime + tm.tms_cutime);
         if ( tick_factor() != -1 )
         {
- current.wall *= tick_factor();
- current.user *= tick_factor();
- current.system *= tick_factor();
+ times_.real *= tick_factor();
+ times_.user *= tick_factor();
+ times_.system *= tick_factor();
         }
         else
         {
- ec = error_code( errno, native_ecat );
- current.wall = current.user = current.system = microsecond_t(-1);
+ assert( 0 && "error handling not implemented yet" );
+ ec = system::error_code( errno, system::system_category );
+ times_.real = times_.user = times_.system = nanoseconds(-1);
         }
       }
 # endif

Modified: sandbox/chrono/libs/chrono/src/run_timer.cpp
==============================================================================
--- sandbox/chrono/libs/chrono/src/run_timer.cpp (original)
+++ sandbox/chrono/libs/chrono/src/run_timer.cpp 2008-11-18 09:58:02 EST (Tue, 18 Nov 2008)
@@ -27,26 +27,6 @@
   const char * default_format =
     "\nreal %rs, cpu %cs (%p%), user %us, system %ss\n";
 
-//# if defined(BOOST_POSIX_API)
-// long tick_factor() // multiplier to convert ticks
-// // to nanoseconds; -1 if unknown
-// {
-// static long tick_factor = 0;
-// if ( !tick_factor )
-// {
-// if ( (tick_factor = ::sysconf( _SC_CLK_TCK )) <= 0 )
-// tick_factor = -1;
-// else
-// {
-// assert( tick_factor <= 1000000L ); // doesn't handle large ticks
-// tick_factor = 1000000L / tick_factor; // compute factor
-// if ( !tick_factor ) tick_factor = -1;
-// }
-// }
-// return tick_factor;
-// }
-//# endif
-
   void show_time( const boost::chrono::process_times & times,
                   const char * format, int places, std::ostream & os )
   // NOTE WELL: Will truncate least-significant digits to LDBL_DIG, which may
@@ -110,7 +90,7 @@
 {
   namespace chrono
   {
- // run_timer:: report --------------------------------------//
+ // run_timer::report --------------------------------------------------------//
 
     void run_timer::report( system::error_code & ec )
     {
@@ -140,6 +120,8 @@
       }
     }
 
+ // run_timer::test_report ---------------------------------------------------//
+
     void run_timer::test_report( duration real_, duration user_, duration system_ )
     {
       if ( m_format.empty() ) m_format = default_format;

Modified: sandbox/chrono/libs/chrono/test/run_timer_test.cpp
==============================================================================
--- sandbox/chrono/libs/chrono/test/run_timer_test.cpp (original)
+++ sandbox/chrono/libs/chrono/test/run_timer_test.cpp 2008-11-18 09:58:02 EST (Tue, 18 Nov 2008)
@@ -14,12 +14,15 @@
 #include <sstream>
 #include <locale>
 #include <ctime>
+#include <cmath> // for sqrt(), used to burn time
 
 using boost::chrono::run_timer;
 using boost::system::error_code;
 
 #include <boost/test/minimal.hpp>
 
+//#define BOOST_CHECK(expr) if (!(expr)) std::cout << "*****ERROR*****\n"
+
 #define CHECK_REPORT(Timer,String_Stream,R,U,S,Expected_String) \
   check_report(Timer, String_Stream, R, U, S, Expected_String, __LINE__)
 
@@ -78,117 +81,137 @@
     std::cout << "\n";
     std::cout << run_timer::default_places() << " default places\n";
     std::cout << pl << " explicitly coded places\n";
-
   }
-}
-
-int test_main( int argc, char * argv[] )
-{
- std::locale loc( "" ); // test with appropriate locale
- std::cout.imbue( loc );
 
+ // accuracy test
+ void accuracy_test( int argc, char * argv[] )
   {
- std::stringstream ss;
- run_timer t(ss);
- BOOST_CHECK( CHECK_REPORT(t, ss, ns(0), ns(0), ns(0),
- "\nreal 0.000s, cpu 0.000s (0.0%), user 0.000s, system 0.000s\n" ) );
- }
+ long timeout_in_secs = 1;
+ if ( argc > 1 ) timeout_in_secs = std::atol( argv[1] );
+ std::cout << "accuracy test for " << timeout_in_secs << " second(s)...";
+
+ std::clock_t timeout_in_clock_t = std::clock();
+ timeout_in_clock_t += (timeout_in_secs * CLOCKS_PER_SEC);
+
+ boost::chrono::system_timer sys;
+ boost::chrono::monotonic_timer mono;
+ boost::chrono::high_resolution_timer hires;
+ boost::chrono::process_timer process;
+
+ std::clock_t now;
+ do
+ {
+ now = std::clock();
+ } while ( now < timeout_in_clock_t );
 
- {
- std::stringstream ss;
- run_timer t(ss);
- BOOST_CHECK( CHECK_REPORT(t, ss, ns(3000000000), ns(2000000000), ns(1000000000),
- "\nreal 3.000s, cpu 3.000s (100.0%), user 2.000s, system 1.000s\n" ) );
- }
+ boost::chrono::system_timer::duration sys_dur = sys.elapsed();
+ boost::chrono::monotonic_timer::duration mono_dur = mono.elapsed();
+ boost::chrono::high_resolution_timer::duration hires_dur = hires.elapsed();
+ boost::chrono::process_times times;
+ process.elapsed( times );
 
- {
- std::stringstream ss;
- run_timer t( ss, "9 places: r %r, c %c, p %p, u %u, s %s", 9 );
- BOOST_CHECK( CHECK_REPORT(t, ss, ns(3000000003), ns(2000000002), ns(1000000001),
- "9 places: "
- "r 3.000000003, c 3.000000003, p 100.0, u 2.000000002, s 1.000000001" ) );
- }
+ std::cout << std::endl;
 
- run_timer_constructor_overload_test();
+ ns timeout_in_nanoseconds( static_cast<long long>(timeout_in_secs) * 1000000000LL );
 
- // accuracy test
+ // Allow 20% leeway. Particularly on Linux, there seems to be a large discrepancy
+ // between std::clock() and higher resolution clocks.
+ ns maximum_delta ( static_cast<long long>(timeout_in_nanoseconds.count() * 0.20 ) );
 
- long timeout_in_secs = 1;
- if ( argc > 1 ) timeout_in_secs = std::atol( argv[1] );
+ std::cout << timeout_in_nanoseconds.count() << " timeout_in_nanoseconds\n";
+ std::cout << maximum_delta.count() << " maximum_delta\n";
 
- std::clock_t timeout_in_clock_t = std::clock();
- timeout_in_clock_t += (timeout_in_secs * CLOCKS_PER_SEC);
+ std::cout << sys_dur.count() << " sys_dur\n";
 
- std::cout << "accuracy test for " << timeout_in_secs << " second(s)...";
+ BOOST_CHECK( sys_dur > timeout_in_nanoseconds - maximum_delta
+ && sys_dur < timeout_in_nanoseconds + maximum_delta );
 
- boost::chrono::system_timer sys;
- boost::chrono::monotonic_timer mono;
- boost::chrono::high_resolution_timer hires;
- boost::chrono::process_timer process;
-
- std::clock_t now;
- do
+ std::cout << mono_dur.count() << " mono_dur\n";
+
+ BOOST_CHECK( mono_dur > timeout_in_nanoseconds - maximum_delta
+ && mono_dur < timeout_in_nanoseconds + maximum_delta );
+
+ std::cout << hires_dur.count() << " hires_dur\n";
+
+ BOOST_CHECK( hires_dur > timeout_in_nanoseconds - maximum_delta
+ && hires_dur < timeout_in_nanoseconds + maximum_delta );
+
+ std::cout << times.real.count() << " times.real\n";
+
+ BOOST_CHECK( times.real > timeout_in_nanoseconds - maximum_delta
+ && times.real < timeout_in_nanoseconds + maximum_delta );
+ }
+
+ // report test
+
+ void report_test()
   {
- now = std::clock();
- } while ( now < timeout_in_clock_t );
+ {
+ std::stringstream ss;
+ run_timer t(ss);
+ BOOST_CHECK( CHECK_REPORT(t, ss, ns(0), ns(0), ns(0),
+ "\nreal 0.000s, cpu 0.000s (0.0%), user 0.000s, system 0.000s\n" ) );
+ }
 
- boost::chrono::system_timer::duration sys_dur = sys.elapsed();
- boost::chrono::monotonic_timer::duration mono_dur = mono.elapsed();
- boost::chrono::high_resolution_timer::duration hires_dur = hires.elapsed();
- boost::chrono::process_times times;
- process.elapsed( times );
+ {
+ std::stringstream ss;
+ run_timer t(ss);
+ BOOST_CHECK( CHECK_REPORT(t, ss, ns(3000000000LL), ns(2000000000LL), ns(1000000000LL),
+ "\nreal 3.000s, cpu 3.000s (100.0%), user 2.000s, system 1.000s\n" ) );
+ }
 
- std::cout << std::endl;
+ {
+ std::stringstream ss;
+ run_timer t( ss, "9 places: r %r, c %c, p %p, u %u, s %s", 9 );
+ BOOST_CHECK( CHECK_REPORT(t, ss, ns(3000000003LL), ns(2000000002LL), ns(1000000001LL),
+ "9 places: "
+ "r 3.000000003, c 3.000000003, p 100.0, u 2.000000002, s 1.000000001" ) );
+ }
+ }
 
- ns timeout_in_nanoseconds( static_cast<long long>(timeout_in_secs) * 1000000000LL );
- ns maximum_delta ( static_cast<long long>(timeout_in_nanoseconds.count() * 0.02 ) ); // 2% leeway
+ // process_timer_test
 
- std::cout << timeout_in_nanoseconds.count() << " timeout_in_nanoseconds\n";
- std::cout << maximum_delta.count() << " maximum_delta\n";
+ void process_timer_test()
+ {
+ std::cout << "process_timer_test..." << std::flush;
 
- std::cout << sys_dur.count() << " sys_dur\n";
+ boost::chrono::process_timer t;
 
- BOOST_CHECK( sys_dur > timeout_in_nanoseconds - maximum_delta
- && sys_dur < timeout_in_nanoseconds + maximum_delta );
+ for (long i = 0; i < 1000000L; ++i)
+ {
+ std::sqrt( static_cast<double>(i) );
+ }
 
- std::cout << mono_dur.count() << " mono_dur\n";
+ boost::chrono::process_times times;
+ times.real = times.system = times.user = ns(0);
 
- BOOST_CHECK( mono_dur > timeout_in_nanoseconds - maximum_delta
- && mono_dur < timeout_in_nanoseconds + maximum_delta );
+ BOOST_CHECK( times.real == ns(0) );
+ BOOST_CHECK( times.user == ns(0) );
+ BOOST_CHECK( times.system == ns(0) );
 
- std::cout << hires_dur.count() << " hires_dur\n";
+ t.elapsed( times );
+ std::cout << "\n";
 
- BOOST_CHECK( hires_dur > timeout_in_nanoseconds - maximum_delta
- && hires_dur < timeout_in_nanoseconds + maximum_delta );
+ std::cout << times.real.count() << " times.real\n";
+ BOOST_CHECK( times.real > ns(1) );
 
- std::cout << times.real.count() << " times.real\n";
+ std::cout << times.user.count() << " times.user\n";
+ BOOST_CHECK( times.user > ns(1) );
 
- BOOST_CHECK( times.real > timeout_in_nanoseconds - maximum_delta
- && times.real < timeout_in_nanoseconds + maximum_delta );
-
- //long count = 0;
- //times_t times;
- //times.real = 0;
- //microsecond_t timeout
- // = microsecond_t(500000); // default .5 seconds
-
- //if ( argc > 1 ) timeout = microsecond_t(std::atol( argv[1] ));
-
- //while ( times.real < timeout )
- //{
- // // The point of this code is to burn both kernal and user cpu time,
- // // with the total less than wall clock time.
- // ++count;
- // timer.elapsed( times );
- // // sleep(1);
- // std::cout << "iteration " << count << ", "
- // << times.real << " real, "
- // << times.user << " user, "
- // << times.system << " system microsecs"
- // << std::endl;
- //}
+ std::cout << "complete" << std::endl;
+ }
+}
 
- //std::cout << count << " iterations\n";
+int test_main( int argc, char * argv[] )
+{
+ std::locale loc( "" ); // test with appropriate locale
+ std::cout.imbue( loc );
+
+ accuracy_test( argc, argv );
+ run_timer_constructor_overload_test();
+ process_timer_test();
+ report_test();
+
   return 0;
 }
 


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk