X-Git-Url: http://g0dil.de/git?a=blobdiff_plain;f=Scheduler%2FClockService.cci;h=791a403f63c5e2e9d6decae715abfbd2abcc58f2;hb=5443435c4c2b6e4386c5334b5b8358273f2bae93;hp=f5369314462f01da5aba2555b3e2c5631f44c5e9;hpb=091048ffd94ceff5b8b415d1c7487c7893287b42;p=senf.git diff --git a/Scheduler/ClockService.cci b/Scheduler/ClockService.cci index f536931..791a403 100644 --- a/Scheduler/ClockService.cci +++ b/Scheduler/ClockService.cci @@ -24,7 +24,9 @@ \brief ClockService inline non-template implementation */ // Custom includes +#include #include +#include "../Utils/Exception.hh" #define prefix_ inline ///////////////////////////////cci.p/////////////////////////////////////// @@ -34,14 +36,62 @@ prefix_ senf::ClockService::clock_type senf::ClockService::now() { - return instance().now_m(); + struct timespec spec; + if (clock_gettime(CLOCK_MONOTONIC, &spec) < 0) + SENF_THROW_SYSTEM_EXCEPTION("clock_gettime()"); + return spec.tv_sec * 1000000000LL + spec.tv_nsec; } +//////////////////////////////////////// +// private members + +prefix_ senf::ClockService::clock_type senf::ClockService::clock_m(abstime_type time) +{ + if (now() - baseClock_ > 1000000000ll) + restart_m(); + boost::posix_time::time_duration delta (time - baseAbstime_); + return baseClock_ + clock_type( delta.ticks() ) + * clock_type( 1000000000UL / boost::posix_time::time_duration::ticks_per_second() ); +} + +prefix_ senf::ClockService::abstime_type senf::ClockService::abstime_m(clock_type clock) +{ + if (now() - baseClock_ > 1000000000ll) + restart_m(); +#ifdef BOOST_DATE_TIME_POSIX_TIME_STD_CONFIG + return baseAbstime_ + boost::posix_time::nanoseconds(clock-baseClock_); +#else + return baseAbstime_ + boost::posix_time::microseconds((clock-baseClock_+500)/1000); +#endif +} + +prefix_ senf::ClockService::ClockService() +{ + restart_m(); +} + +prefix_ void senf::ClockService::restart_m() +{ + baseAbstime_ = boost::posix_time::microsec_clock::universal_time(); + baseClock_ = now(); +} + +// public members + prefix_ senf::ClockService::abstime_type senf::ClockService::abstime(clock_type clock) { return instance().abstime_m(clock); } +prefix_ senf::ClockService::reltime_type senf::ClockService::reltime(clock_type clock) +{ +#ifdef BOOST_DATE_TIME_POSIX_TIME_STD_CONFIG + return boost::posix_time::nanoseconds(clock); +#else + return boost::posix_time::microseconds((clock+500)/1000); +#endif +} + prefix_ senf::ClockService::clock_type senf::ClockService::clock(abstime_type time) { return instance().clock_m(time); @@ -52,11 +102,6 @@ prefix_ senf::ClockService::clock_type senf::ClockService::from_time_t(time_t co return clock( boost::posix_time::from_time_t(time) ); } -prefix_ senf::ClockService::clock_type senf::ClockService::from_timeval(timeval const & time) -{ - return from_time_t(time.tv_sec) + ClockService::microseconds(time.tv_usec); -} - prefix_ senf::ClockService::clock_type senf::ClockService::nanoseconds(int64_type v) { return v; @@ -127,64 +172,14 @@ prefix_ senf::ClockService::clock_type senf::ClockService::in_days(int64_type v) return v / hours(24); } -prefix_ void senf::ClockService::restart() -{ - instance().restart_m(); -} - -//////////////////////////////////////// -// private members - -prefix_ senf::ClockService::clock_type senf::ClockService::now_m() -{ - // We want to make the normal case (no skew) really fast. This first 'checkSkew' *might* - // transiently fail if a SIGALRM is delivered in the midst of the test. updateSkew will - // therefore block signals and do the check again to make sure. - // - // The opposite case (the test returns 'false' even though it should return 'true') is so highly - // improbable that it is treated as academic. (it will be catched by the next SIGALRM) - - boost::posix_time::ptime time (boost::posix_time::microsec_clock::universal_time()); - if (checkSkew(time)) - updateSkew(time); - - // 'clock' will pick up the corrected base_ value if needed. - return clock_m(time); -} - -prefix_ senf::ClockService::abstime_type senf::ClockService::abstime_m(clock_type clock) -{ -#ifdef BOOST_DATE_TIME_POSIX_TIME_STD_CONFIG - return base_ + boost::posix_time::nanoseconds(clock); -#else - return base_ + boost::posix_time::microseconds((clock+500)/1000); -#endif -} - -prefix_ senf::ClockService::clock_type senf::ClockService::clock_m(abstime_type time) -{ - ///\fixme What happens, if base_ is changed in SIGALRM while reading it here ? - - // Idea: Have *two* base values: one is written by the SIGALRM handler, the other is only - // Written by synchronous code. If they differ, we block signals, copy over and continue. If - // they transiently differ because we are reading the SIGALRM value while it is being changed - // this does not matter: We will then still copy it over. - - boost::posix_time::time_duration delta (time - base_); - return clock_type( delta.ticks() ) - * clock_type( 1000000000UL / boost::posix_time::time_duration::ticks_per_second() ); -} - -prefix_ bool senf::ClockService::checkSkew(boost::posix_time::ptime time) +prefix_ senf::ClockService::clock_type senf::ClockService::from_timeval(timeval const & time) { - boost::posix_time::ptime h (heartbeat_); // reduce chance for race condition - return time < h || (time - h) > boost::posix_time::seconds(2*CheckInterval); + return from_time_t(time.tv_sec) + ClockService::microseconds(time.tv_usec); } -prefix_ void senf::ClockService::clockSkew(boost::posix_time::ptime time, - boost::posix_time::ptime expected) +prefix_ void senf::ClockService::restart() { - base_ += (time - expected); + instance().restart_m(); } ///////////////////////////////cci.e///////////////////////////////////////