Back to home page

EIC code displayed by LXR

 
 

    


Warning, file /include/boost/thread/detail/platform_time.hpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

0001 #ifndef BOOST_THREAD_DETAIL_PLATFORM_TIME_HPP
0002 #define BOOST_THREAD_DETAIL_PLATFORM_TIME_HPP
0003 //  (C) Copyright 2007-8 Anthony Williams
0004 //  (C) Copyright 2012 Vicente J. Botet Escriba
0005 //
0006 //  Distributed under the Boost Software License, Version 1.0. (See
0007 //  accompanying file LICENSE_1_0.txt or copy at
0008 //  http://www.boost.org/LICENSE_1_0.txt)
0009 
0010 #include <boost/thread/detail/config.hpp>
0011 #include <boost/thread/thread_time.hpp>
0012 #if defined BOOST_THREAD_USES_DATETIME
0013 #include <boost/date_time/posix_time/conversion.hpp>
0014 #endif
0015 #ifndef _WIN32
0016 #include <unistd.h>
0017 #endif
0018 #ifdef BOOST_THREAD_USES_CHRONO
0019 #include <boost/chrono/duration.hpp>
0020 #include <boost/chrono/system_clocks.hpp>
0021 #include <boost/chrono/ceil.hpp>
0022 #endif
0023 
0024 #if defined(BOOST_THREAD_CHRONO_WINDOWS_API)
0025 #include <boost/winapi/time.hpp>
0026 #include <boost/winapi/timers.hpp>
0027 #include <boost/thread/win32/thread_primitives.hpp>
0028 #elif defined(BOOST_THREAD_CHRONO_MAC_API)
0029 #include <sys/time.h> //for gettimeofday and timeval
0030 #include <mach/mach_time.h>  // mach_absolute_time, mach_timebase_info_data_t
0031 
0032 #else
0033 #include <time.h>  // for clock_gettime
0034 #endif
0035 
0036 #include <limits>
0037 
0038 #include <boost/config/abi_prefix.hpp>
0039 
0040 namespace boost
0041 {
0042 //typedef boost::int_least64_t time_max_t;
0043 typedef boost::intmax_t time_max_t;
0044 
0045 #if defined BOOST_THREAD_CHRONO_MAC_API
0046 namespace threads
0047 {
0048 
0049 namespace chrono_details
0050 {
0051 
0052 // steady_clock
0053 
0054 // Note, in this implementation steady_clock and high_resolution_clock
0055 //   are the same clock.  They are both based on mach_absolute_time().
0056 //   mach_absolute_time() * MachInfo.numer / MachInfo.denom is the number of
0057 //   nanoseconds since the computer booted up.  MachInfo.numer and MachInfo.denom
0058 //   are run time constants supplied by the OS.  This clock has no relationship
0059 //   to the Gregorian calendar.  It's main use is as a high resolution timer.
0060 
0061 // MachInfo.numer / MachInfo.denom is often 1 on the latest equipment.  Specialize
0062 //   for that case as an optimization.
0063 
0064 inline time_max_t
0065 steady_simplified()
0066 {
0067     return mach_absolute_time();
0068 }
0069 
0070 inline double compute_steady_factor(kern_return_t& err)
0071 {
0072     mach_timebase_info_data_t MachInfo;
0073     err = mach_timebase_info(&MachInfo);
0074     if ( err != 0  ) {
0075         return 0;
0076     }
0077     return static_cast<double>(MachInfo.numer) / MachInfo.denom;
0078 }
0079 
0080 inline time_max_t steady_full()
0081 {
0082     kern_return_t err;
0083     const double factor = chrono_details::compute_steady_factor(err);
0084     if (err != 0)
0085     {
0086       BOOST_ASSERT(0 && "Boost::Chrono - Internal Error");
0087     }
0088     return static_cast<time_max_t>(mach_absolute_time() * factor);
0089 }
0090 
0091 
0092 typedef time_max_t (*FP)();
0093 
0094 inline FP init_steady_clock(kern_return_t & err)
0095 {
0096     mach_timebase_info_data_t MachInfo;
0097     err = mach_timebase_info(&MachInfo);
0098     if ( err != 0  )
0099     {
0100         return 0;
0101     }
0102 
0103     if (MachInfo.numer == MachInfo.denom)
0104     {
0105         return &chrono_details::steady_simplified;
0106     }
0107     return &chrono_details::steady_full;
0108 }
0109 
0110 }
0111 }
0112 #endif
0113 
0114   namespace detail
0115   {
0116 #if defined BOOST_THREAD_CHRONO_POSIX_API || defined BOOST_THREAD_CHRONO_MAC_API
0117     inline timespec ns_to_timespec(boost::time_max_t const& ns)
0118     {
0119       boost::time_max_t s = ns / 1000000000l;
0120       timespec ts;
0121       ts.tv_sec = static_cast<long> (s);
0122       ts.tv_nsec = static_cast<long> (ns - s * 1000000000l);
0123       return ts;
0124     }
0125     inline boost::time_max_t timespec_to_ns(timespec const& ts)
0126     {
0127       return static_cast<boost::time_max_t>(ts.tv_sec) * 1000000000l + ts.tv_nsec;
0128     }
0129 #endif
0130 
0131     struct platform_duration
0132     {
0133 #if defined BOOST_THREAD_CHRONO_POSIX_API || defined BOOST_THREAD_CHRONO_MAC_API
0134       explicit platform_duration(timespec const& v) : ts_val(v) {}
0135       timespec const& getTs() const { return ts_val; }
0136 
0137       explicit platform_duration(boost::time_max_t const& ns = 0) : ts_val(ns_to_timespec(ns)) {}
0138       boost::time_max_t getNs() const { return timespec_to_ns(ts_val); }
0139 #else
0140       explicit platform_duration(boost::time_max_t const& ns = 0) : ns_val(ns) {}
0141       boost::time_max_t getNs() const { return ns_val; }
0142 #endif
0143 
0144 #if defined BOOST_THREAD_USES_DATETIME
0145       platform_duration(boost::posix_time::time_duration const& rel_time)
0146       {
0147 #if defined BOOST_THREAD_CHRONO_POSIX_API || defined BOOST_THREAD_CHRONO_MAC_API
0148         ts_val.tv_sec = rel_time.total_seconds();
0149         ts_val.tv_nsec = static_cast<long>(rel_time.fractional_seconds() * (1000000000l / rel_time.ticks_per_second()));
0150 #else
0151         ns_val = static_cast<boost::time_max_t>(rel_time.total_seconds()) * 1000000000l;
0152         ns_val += rel_time.fractional_seconds() * (1000000000l / rel_time.ticks_per_second());
0153 #endif
0154       }
0155 #endif
0156 
0157 #if defined BOOST_THREAD_USES_CHRONO
0158       template <class Rep, class Period>
0159       platform_duration(chrono::duration<Rep, Period> const& d)
0160       {
0161 #if defined BOOST_THREAD_CHRONO_POSIX_API || defined BOOST_THREAD_CHRONO_MAC_API
0162         ts_val = ns_to_timespec(chrono::ceil<chrono::nanoseconds>(d).count());
0163 #else
0164         ns_val = chrono::ceil<chrono::nanoseconds>(d).count();
0165 #endif
0166       }
0167 #endif
0168 
0169       boost::time_max_t getMs() const
0170       {
0171         const boost::time_max_t ns = getNs();
0172         // ceil/floor away from zero
0173         if (ns >= 0)
0174         {
0175           // return ceiling of positive numbers
0176           return (ns + 999999) / 1000000;
0177         }
0178         else
0179         {
0180           // return floor of negative numbers
0181           return (ns - 999999) / 1000000;
0182         }
0183       }
0184 
0185       static platform_duration zero()
0186       {
0187         return platform_duration(0);
0188       }
0189 
0190     private:
0191 #if defined BOOST_THREAD_CHRONO_POSIX_API || defined BOOST_THREAD_CHRONO_MAC_API
0192       timespec ts_val;
0193 #else
0194       boost::time_max_t ns_val;
0195 #endif
0196     };
0197 
0198     inline bool operator==(platform_duration const& lhs, platform_duration const& rhs)
0199     {
0200       return lhs.getNs() == rhs.getNs();
0201     }
0202     inline bool operator!=(platform_duration const& lhs, platform_duration const& rhs)
0203     {
0204       return lhs.getNs() != rhs.getNs();
0205     }
0206     inline bool operator<(platform_duration const& lhs, platform_duration const& rhs)
0207     {
0208       return lhs.getNs() < rhs.getNs();
0209     }
0210     inline bool operator<=(platform_duration const& lhs, platform_duration const& rhs)
0211     {
0212       return lhs.getNs() <= rhs.getNs();
0213     }
0214     inline bool operator>(platform_duration const& lhs, platform_duration const& rhs)
0215     {
0216       return lhs.getNs() > rhs.getNs();
0217     }
0218     inline bool operator>=(platform_duration const& lhs, platform_duration const& rhs)
0219     {
0220       return lhs.getNs() >= rhs.getNs();
0221     }
0222 
0223     static inline platform_duration platform_milliseconds(long const& ms)
0224     {
0225       return platform_duration(ms * 1000000l);
0226     }
0227 
0228     struct real_platform_timepoint
0229     {
0230 #if defined BOOST_THREAD_CHRONO_POSIX_API || defined BOOST_THREAD_CHRONO_MAC_API
0231       explicit real_platform_timepoint(timespec const& v) : dur(v) {}
0232       timespec const& getTs() const { return dur.getTs(); }
0233 #endif
0234 
0235       explicit real_platform_timepoint(boost::time_max_t const& ns) : dur(ns) {}
0236       boost::time_max_t getNs() const { return dur.getNs(); }
0237 
0238 #if defined BOOST_THREAD_USES_DATETIME
0239       real_platform_timepoint(boost::system_time const& abs_time)
0240         : dur(abs_time - boost::posix_time::from_time_t(0)) {}
0241 #endif
0242 
0243 #if defined BOOST_THREAD_USES_CHRONO
0244       template <class Duration>
0245       real_platform_timepoint(chrono::time_point<chrono::system_clock, Duration> const& abs_time)
0246         : dur(abs_time.time_since_epoch()) {}
0247 #endif
0248 
0249     private:
0250       platform_duration dur;
0251     };
0252 
0253     inline bool operator==(real_platform_timepoint const& lhs, real_platform_timepoint const& rhs)
0254     {
0255       return lhs.getNs() == rhs.getNs();
0256     }
0257     inline bool operator!=(real_platform_timepoint const& lhs, real_platform_timepoint const& rhs)
0258     {
0259       return lhs.getNs() != rhs.getNs();
0260     }
0261     inline bool operator<(real_platform_timepoint const& lhs, real_platform_timepoint const& rhs)
0262     {
0263       return lhs.getNs() < rhs.getNs();
0264     }
0265     inline bool operator<=(real_platform_timepoint const& lhs, real_platform_timepoint const& rhs)
0266     {
0267       return lhs.getNs() <= rhs.getNs();
0268     }
0269     inline bool operator>(real_platform_timepoint const& lhs, real_platform_timepoint const& rhs)
0270     {
0271       return lhs.getNs() > rhs.getNs();
0272     }
0273     inline bool operator>=(real_platform_timepoint const& lhs, real_platform_timepoint const& rhs)
0274     {
0275       return lhs.getNs() >= rhs.getNs();
0276     }
0277 
0278     inline real_platform_timepoint operator+(real_platform_timepoint const& lhs, platform_duration const& rhs)
0279     {
0280       return real_platform_timepoint(lhs.getNs() + rhs.getNs());
0281     }
0282     inline real_platform_timepoint operator+(platform_duration const& lhs, real_platform_timepoint const& rhs)
0283     {
0284       return real_platform_timepoint(lhs.getNs() + rhs.getNs());
0285     }
0286     inline platform_duration operator-(real_platform_timepoint const& lhs, real_platform_timepoint const& rhs)
0287     {
0288       return platform_duration(lhs.getNs() - rhs.getNs());
0289     }
0290 
0291     struct real_platform_clock
0292     {
0293       static real_platform_timepoint now()
0294       {
0295 #if defined(BOOST_THREAD_CHRONO_WINDOWS_API)
0296         boost::winapi::FILETIME_ ft;
0297         boost::winapi::GetSystemTimeAsFileTime(&ft);  // never fails
0298         boost::time_max_t ns = ((((static_cast<boost::time_max_t>(ft.dwHighDateTime) << 32) | ft.dwLowDateTime) - 116444736000000000LL) * 100LL);
0299         return real_platform_timepoint(ns);
0300 #elif defined(BOOST_THREAD_CHRONO_MAC_API)
0301         timeval tv;
0302         ::gettimeofday(&tv, 0);
0303         timespec ts;
0304         ts.tv_sec = tv.tv_sec;
0305         ts.tv_nsec = tv.tv_usec * 1000;
0306         return real_platform_timepoint(ts);
0307 #else
0308         timespec ts;
0309         if ( ::clock_gettime( CLOCK_REALTIME, &ts ) )
0310         {
0311           BOOST_ASSERT(0 && "Boost::Thread - clock_gettime(CLOCK_REALTIME) Internal Error");
0312           return real_platform_timepoint(0);
0313         }
0314         return real_platform_timepoint(ts);
0315 #endif
0316       }
0317     };
0318 
0319 #if defined(BOOST_THREAD_HAS_MONO_CLOCK)
0320 
0321   struct mono_platform_timepoint
0322   {
0323 #if defined BOOST_THREAD_CHRONO_POSIX_API || defined BOOST_THREAD_CHRONO_MAC_API
0324 
0325     explicit mono_platform_timepoint(timespec const& v) : dur(v) {}
0326     timespec const& getTs() const { return dur.getTs(); }
0327 #endif
0328 
0329     explicit mono_platform_timepoint(boost::time_max_t const& ns) : dur(ns) {}
0330     boost::time_max_t getNs() const { return dur.getNs(); }
0331 
0332 #if defined BOOST_THREAD_USES_CHRONO
0333     // This conversion assumes that chrono::steady_clock::time_point and mono_platform_timepoint share the same epoch.
0334     template <class Duration>
0335     mono_platform_timepoint(chrono::time_point<chrono::steady_clock, Duration> const& abs_time)
0336       : dur(abs_time.time_since_epoch()) {}
0337 #endif
0338 
0339     // can't name this max() since that is a macro on some Windows systems
0340     static mono_platform_timepoint getMax()
0341     {
0342 #if defined BOOST_THREAD_CHRONO_POSIX_API || defined BOOST_THREAD_CHRONO_MAC_API
0343       timespec ts;
0344       ts.tv_sec = (std::numeric_limits<time_t>::max)();
0345       ts.tv_nsec = 999999999;
0346       return mono_platform_timepoint(ts);
0347 #else
0348       boost::time_max_t ns = (std::numeric_limits<boost::time_max_t>::max)();
0349       return mono_platform_timepoint(ns);
0350 #endif
0351     }
0352 
0353   private:
0354     platform_duration dur;
0355   };
0356 
0357   inline bool operator==(mono_platform_timepoint const& lhs, mono_platform_timepoint const& rhs)
0358   {
0359     return lhs.getNs() == rhs.getNs();
0360   }
0361   inline bool operator!=(mono_platform_timepoint const& lhs, mono_platform_timepoint const& rhs)
0362   {
0363     return lhs.getNs() != rhs.getNs();
0364   }
0365   inline bool operator<(mono_platform_timepoint const& lhs, mono_platform_timepoint const& rhs)
0366   {
0367     return lhs.getNs() < rhs.getNs();
0368   }
0369   inline bool operator<=(mono_platform_timepoint const& lhs, mono_platform_timepoint const& rhs)
0370   {
0371     return lhs.getNs() <= rhs.getNs();
0372   }
0373   inline bool operator>(mono_platform_timepoint const& lhs, mono_platform_timepoint const& rhs)
0374   {
0375     return lhs.getNs() > rhs.getNs();
0376   }
0377   inline bool operator>=(mono_platform_timepoint const& lhs, mono_platform_timepoint const& rhs)
0378   {
0379     return lhs.getNs() >= rhs.getNs();
0380   }
0381 
0382   inline mono_platform_timepoint operator+(mono_platform_timepoint const& lhs, platform_duration const& rhs)
0383   {
0384     return mono_platform_timepoint(lhs.getNs() + rhs.getNs());
0385   }
0386   inline mono_platform_timepoint operator+(platform_duration const& lhs, mono_platform_timepoint const& rhs)
0387   {
0388     return mono_platform_timepoint(lhs.getNs() + rhs.getNs());
0389   }
0390   inline platform_duration operator-(mono_platform_timepoint const& lhs, mono_platform_timepoint const& rhs)
0391   {
0392     return platform_duration(lhs.getNs() - rhs.getNs());
0393   }
0394 
0395   struct mono_platform_clock
0396   {
0397     static mono_platform_timepoint now()
0398     {
0399 #if defined(BOOST_THREAD_CHRONO_WINDOWS_API)
0400 #if defined(BOOST_THREAD_USES_CHRONO)
0401       // Use QueryPerformanceCounter() to match the implementation in Boost
0402       // Chrono so that chrono::steady_clock::now() and this function share the
0403       // same epoch and so can be converted between each other.
0404       boost::winapi::LARGE_INTEGER_ freq;
0405       if ( !boost::winapi::QueryPerformanceFrequency( &freq ) )
0406       {
0407         BOOST_ASSERT(0 && "Boost::Thread - QueryPerformanceFrequency Internal Error");
0408         return mono_platform_timepoint(0);
0409       }
0410       if ( freq.QuadPart <= 0 )
0411       {
0412         BOOST_ASSERT(0 && "Boost::Thread - QueryPerformanceFrequency Internal Error");
0413         return mono_platform_timepoint(0);
0414       }
0415 
0416       boost::winapi::LARGE_INTEGER_ pcount;
0417       unsigned times=0;
0418       while ( ! boost::winapi::QueryPerformanceCounter( &pcount ) )
0419       {
0420         if ( ++times > 3 )
0421         {
0422           BOOST_ASSERT(0 && "Boost::Thread - QueryPerformanceCounter Internal Error");
0423           return mono_platform_timepoint(0);
0424         }
0425       }
0426 
0427       long double ns = 1000000000.0L * pcount.QuadPart / freq.QuadPart;
0428       return mono_platform_timepoint(static_cast<boost::time_max_t>(ns));
0429 #else
0430       // Use GetTickCount64() because it's more reliable on older
0431       // systems like Windows XP and Windows Server 2003.
0432       win32::ticks_type msec = win32::gettickcount64();
0433       return mono_platform_timepoint(msec * 1000000);
0434 #endif
0435 #elif defined(BOOST_THREAD_CHRONO_MAC_API)
0436       kern_return_t err;
0437       threads::chrono_details::FP fp = threads::chrono_details::init_steady_clock(err);
0438       if ( err != 0  )
0439       {
0440         BOOST_ASSERT(0 && "Boost::Chrono - Internal Error");
0441       }
0442       return mono_platform_timepoint(fp());
0443 #else
0444       timespec ts;
0445       if ( ::clock_gettime( CLOCK_MONOTONIC, &ts ) )
0446       {
0447         BOOST_ASSERT(0 && "Boost::Thread - clock_gettime(CLOCK_MONOTONIC) Internal Error");
0448         return mono_platform_timepoint(0);
0449       }
0450       return mono_platform_timepoint(ts);
0451 #endif
0452     }
0453   };
0454 
0455 #endif
0456 
0457 #if defined(BOOST_THREAD_INTERNAL_CLOCK_IS_MONO)
0458   typedef mono_platform_clock     internal_platform_clock;
0459   typedef mono_platform_timepoint internal_platform_timepoint;
0460 #else
0461   typedef real_platform_clock     internal_platform_clock;
0462   typedef real_platform_timepoint internal_platform_timepoint;
0463 #endif
0464 
0465 #ifdef BOOST_THREAD_USES_CHRONO
0466 #ifdef BOOST_THREAD_INTERNAL_CLOCK_IS_MONO
0467   typedef chrono::steady_clock internal_chrono_clock;
0468 #else
0469   typedef chrono::system_clock internal_chrono_clock;
0470 #endif
0471 #endif
0472 
0473   }
0474 }
0475 
0476 #include <boost/config/abi_suffix.hpp>
0477 
0478 #endif