Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:29:46

0001 //  mac/chrono.cpp  --------------------------------------------------------------//
0002 
0003 //  Copyright Beman Dawes 2008
0004 //  Copyright 2009-2010 Vicente J. Botet Escriba
0005 
0006 //  Distributed under the Boost Software License, Version 1.0.
0007 //  See http://www.boost.org/LICENSE_1_0.txt
0008 
0009 
0010 //----------------------------------------------------------------------------//
0011 //                                 Mac                                        //
0012 //----------------------------------------------------------------------------//
0013 
0014 #include <sys/time.h> //for gettimeofday and timeval
0015 #include <mach/mach_time.h>  // mach_absolute_time, mach_timebase_info_data_t
0016 #include <boost/assert.hpp>
0017 
0018 namespace boost
0019 {
0020 namespace chrono
0021 {
0022 
0023 // system_clock
0024 
0025 // gettimeofday is the most precise "system time" available on this platform.
0026 // It returns the number of microseconds since New Years 1970 in a struct called timeval
0027 // which has a field for seconds and a field for microseconds.
0028 //    Fill in the timeval and then convert that to the time_point
0029 system_clock::time_point
0030 system_clock::now() BOOST_NOEXCEPT
0031 {
0032     timeval tv;
0033     gettimeofday(&tv, BOOST_NULLPTR);
0034     return time_point(seconds(tv.tv_sec) + microseconds(tv.tv_usec));
0035 }
0036 
0037 #if !defined BOOST_CHRONO_DONT_PROVIDE_HYBRID_ERROR_HANDLING
0038 system_clock::time_point
0039 system_clock::now(system::error_code & ec)
0040 {
0041     timeval tv;
0042     gettimeofday(&tv, BOOST_NULLPTR);
0043     if (!::boost::chrono::is_throws(ec))
0044     {
0045         ec.clear();
0046     }
0047     return time_point(seconds(tv.tv_sec) + microseconds(tv.tv_usec));
0048 }
0049 #endif
0050 // Take advantage of the fact that on this platform time_t is nothing but
0051 //    an integral count of seconds since New Years 1970 (same epoch as timeval).
0052 //    Just get the duration out of the time_point and truncate it to seconds.
0053 time_t
0054 system_clock::to_time_t(const time_point& t) BOOST_NOEXCEPT
0055 {
0056     return time_t(duration_cast<seconds>(t.time_since_epoch()).count());
0057 }
0058 
0059 // Just turn the time_t into a count of seconds and construct a time_point with it.
0060 system_clock::time_point
0061 system_clock::from_time_t(time_t t) BOOST_NOEXCEPT
0062 {
0063     return system_clock::time_point(seconds(t));
0064 }
0065 
0066 namespace chrono_detail
0067 {
0068 
0069 // steady_clock
0070 
0071 // Note, in this implementation steady_clock and high_resolution_clock
0072 //   are the same clock.  They are both based on mach_absolute_time().
0073 //   mach_absolute_time() * MachInfo.numer / MachInfo.denom is the number of
0074 //   nanoseconds since the computer booted up.  MachInfo.numer and MachInfo.denom
0075 //   are run time constants supplied by the OS.  This clock has no relationship
0076 //   to the Gregorian calendar.  It's main use is as a high resolution timer.
0077 
0078 // MachInfo.numer / MachInfo.denom is often 1 on the latest equipment.  Specialize
0079 //   for that case as an optimization.
0080 BOOST_CHRONO_STATIC
0081 steady_clock::rep
0082 steady_simplified()
0083 {
0084     return mach_absolute_time();
0085 }
0086 
0087 #if !defined BOOST_CHRONO_DONT_PROVIDE_HYBRID_ERROR_HANDLING
0088 BOOST_CHRONO_STATIC
0089 steady_clock::rep
0090 steady_simplified_ec(system::error_code & ec)
0091 {
0092     if (!::boost::chrono::is_throws(ec))
0093     {
0094         ec.clear();
0095     }
0096     return mach_absolute_time();
0097 }
0098 #endif
0099 
0100 BOOST_CHRONO_STATIC
0101 double
0102 compute_steady_factor(kern_return_t& err)
0103 {
0104     mach_timebase_info_data_t MachInfo;
0105     err = mach_timebase_info(&MachInfo);
0106     if ( err != 0  ) {
0107         return 0;
0108     }
0109     return static_cast<double>(MachInfo.numer) / MachInfo.denom;
0110 }
0111 
0112 BOOST_CHRONO_STATIC
0113 steady_clock::rep
0114 steady_full()
0115 {
0116     kern_return_t err;
0117     const double factor = chrono_detail::compute_steady_factor(err);
0118     if (err != 0)
0119     {
0120       BOOST_ASSERT(0 && "Boost::Chrono - Internal Error");
0121     }
0122     return static_cast<steady_clock::rep>(mach_absolute_time() * factor);
0123 }
0124 
0125 #if !defined BOOST_CHRONO_DONT_PROVIDE_HYBRID_ERROR_HANDLING
0126 BOOST_CHRONO_STATIC
0127 steady_clock::rep
0128 steady_full_ec(system::error_code & ec)
0129 {
0130     kern_return_t err;
0131     const double factor = chrono_detail::compute_steady_factor(err);
0132     if (err != 0)
0133     {
0134         if (::boost::chrono::is_throws(ec))
0135         {
0136             boost::throw_exception(
0137                     system::system_error(
0138                             err,
0139                             ::boost::system::system_category(),
0140                             "chrono::steady_clock" ));
0141         }
0142         else
0143         {
0144             ec.assign( errno, ::boost::system::system_category() );
0145             return steady_clock::rep();
0146         }
0147     }
0148     if (!::boost::chrono::is_throws(ec))
0149     {
0150         ec.clear();
0151     }
0152     return static_cast<steady_clock::rep>(mach_absolute_time() * factor);
0153 }
0154 #endif
0155 
0156 typedef steady_clock::rep (*FP)();
0157 #if !defined BOOST_CHRONO_DONT_PROVIDE_HYBRID_ERROR_HANDLING
0158 typedef steady_clock::rep (*FP_ec)(system::error_code &);
0159 #endif
0160 
0161 BOOST_CHRONO_STATIC
0162 FP
0163 init_steady_clock(kern_return_t & err)
0164 {
0165     mach_timebase_info_data_t MachInfo;
0166     err = mach_timebase_info(&MachInfo);
0167     if ( err != 0  )
0168     {
0169         return BOOST_NULLPTR;
0170     }
0171 
0172     if (MachInfo.numer == MachInfo.denom)
0173     {
0174         return &chrono_detail::steady_simplified;
0175     }
0176     return &chrono_detail::steady_full;
0177 }
0178 
0179 #if !defined BOOST_CHRONO_DONT_PROVIDE_HYBRID_ERROR_HANDLING
0180 BOOST_CHRONO_STATIC
0181 FP_ec
0182 init_steady_clock_ec(kern_return_t & err)
0183 {
0184     mach_timebase_info_data_t MachInfo;
0185     err = mach_timebase_info(&MachInfo);
0186     if ( err != 0  )
0187     {
0188         return BOOST_NULLPTR;
0189     }
0190 
0191     if (MachInfo.numer == MachInfo.denom)
0192     {
0193         return &chrono_detail::steady_simplified_ec;
0194     }
0195     return &chrono_detail::steady_full_ec;
0196 }
0197 #endif
0198 }
0199 
0200 steady_clock::time_point
0201 steady_clock::now() BOOST_NOEXCEPT
0202 {
0203     kern_return_t err;
0204     chrono_detail::FP fp = chrono_detail::init_steady_clock(err);
0205     if ( err != 0  )
0206     {
0207       BOOST_ASSERT(0 && "Boost::Chrono - Internal Error");
0208     }
0209     return time_point(duration(fp()));
0210 }
0211 
0212 #if !defined BOOST_CHRONO_DONT_PROVIDE_HYBRID_ERROR_HANDLING
0213 steady_clock::time_point
0214 steady_clock::now(system::error_code & ec)
0215 {
0216     kern_return_t err;
0217     chrono_detail::FP_ec fp = chrono_detail::init_steady_clock_ec(err);
0218     if ( err != 0  )
0219     {
0220         if (::boost::chrono::is_throws(ec))
0221         {
0222             boost::throw_exception(
0223                     system::system_error(
0224                             err,
0225                             ::boost::system::system_category(),
0226                             "chrono::steady_clock" ));
0227         }
0228         else
0229         {
0230             ec.assign( err, ::boost::system::system_category() );
0231             return time_point();
0232         }
0233     }
0234     if (!::boost::chrono::is_throws(ec))
0235     {
0236         ec.clear();
0237     }
0238     return time_point(duration(fp(ec)));
0239 }
0240 #endif
0241 }  // namespace chrono
0242 }  // namespace boost