X-Git-Url: http://g0dil.de/git?a=blobdiff_plain;f=Scheduler%2FClockService.hh;h=8fb1341a12d8d56bd24d20c7a205135b782dcbc8;hb=fd3a0e8ac95d1158e9ea661ddf9187b67c70169f;hp=6ad51b5be9ca7395b3e2365bd1ae42c072fe1479;hpb=dd9cab12c8a33e57da1dd1104b530e8ea1591c53;p=senf.git diff --git a/Scheduler/ClockService.hh b/Scheduler/ClockService.hh index 6ad51b5..8fb1341 100644 --- a/Scheduler/ClockService.hh +++ b/Scheduler/ClockService.hh @@ -1,8 +1,8 @@ // $Id$ // -// Copyright (C) 2007 -// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) -// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Copyright (C) 2007 +// Fraunhofer Institute for Open Communication Systems (FOKUS) +// Competence Center NETwork research (NET), St. Augustin, GERMANY // Stefan Bund // // This program is free software; you can redistribute it and/or modify @@ -23,60 +23,46 @@ /** \file \brief ClockService public header */ -#ifndef HH_ClockService_ -#define HH_ClockService_ 1 +#ifndef HH_SENF_Scheduler_ClockService_ +#define HH_SENF_Scheduler_ClockService_ 1 // Custom includes +#include #include -#include +#include +#include +#include +#include "../config.hh" +#include "../Utils/singleton.hh" +#include "../Utils/Console/Parse.hh" //#include "ClockService.mpp" ///////////////////////////////hh.p//////////////////////////////////////// namespace senf { - // Implementation note: - // - // The clock value is represented as a 64bit unsigned integer number of nanosecods elapsed since - // the construction of the ClockService object. - // - // The implementation must provide two features: - // a) It must reliably detect clock changes - // b) In case of a clock change a reasonably accurate fallback clock value must be provided - // - // We do this using setitimer/getitimer. We setup an interval timer sending SIGALRM whenever - // CheckInverval seconds have elapsed. - // - // On every SIGALRM signal we save the current value of gettimeofday(). If this new value is - // substantially different from the currently saved value + CheckInterval, the clock has been - // changed. - // - // Whenever the current clock value is requested using now(), the current gettimeofday() value - // is compared with the saved value. If the difference is substantially more than CheckInterval, - // the clock has been changed. - // - // This provides clock skew detection. If clock skew is detected, we need to move base_ by the - // amount the time has been changed. To do this we need an as accurate as possible approximation - // of the expected current time value. We need to differentiate two cases: - // - // a) Clock skew detected in within now() - // - // In this case, we use getitimer() to find the time remaining in the timer. Using this value and - // an the saved gettimeofday() value we can adjust base_ accordingly. - // - // b) Clock skew detected in the signal handler +#ifndef DOXYGEN + namespace detail { class ClockServiceTest; } +#endif + + // Implementation note: The clock value is represented as a 64bit unsigned integer number of + // nanosecods based on the CLOCK_MONOTONIC POSIX clock. // - // In this case we use the save gettimeofday() value + CheckInterval to adjust base_. + // To allow conversion between clock value and absolute time, the ClockService samples the + // absolute current time and the clock value when the conversion is performed. This is done at + // most once per second on a if-needed basis. /** \brief Reliable high precision monotonous clock source The ClockService provides a highly accurate monotonous clock source based on gettimeofday(). However, it takes additional precautions to detect clock skew. - \fixme Implement the clock-skew detection + \implementation The funny mixture of static and non-static members stems from the old + implementation based on interval timers and gettimeofday(). The current implementation + usses POSIX clocks and is much simpler and more precise. */ class ClockService - : boost::noncopyable + : singleton { public: /////////////////////////////////////////////////////////////////////////// @@ -87,7 +73,13 @@ namespace senf { Unsigned integer type representing scheduler time. Scheduler time is measured in nanoseconds relative to some implementation defined reference time. */ - typedef boost::uint_fast64_t clock_type; + typedef config::time_type clock_type; + + /** \brief Supplementary integer type + + This type is used to represent varies supplementary values (e.g. number of microseconds) + */ + typedef boost::int_fast64_t int64_type; /** \brief Absolute time data type @@ -95,15 +87,12 @@ namespace senf { */ typedef boost::posix_time::ptime abstime_type; - static unsigned const CheckInterval = 1; - - /////////////////////////////////////////////////////////////////////////// - ///\name Structors and default members - ///@{ + /** \brief Relative time data type - ~ClockService(); + Boost.DateTime datatype used to represent time intervals + */ + typedef boost::posix_time::time_duration reltime_type; - ///@} /////////////////////////////////////////////////////////////////////////// static clock_type now(); ///< Return current clock value @@ -116,22 +105,102 @@ namespace senf { monotonous, absolute time may be non-monotonous if the system date/time is changed. */ + static reltime_type reltime(clock_type clock); ///< Convert clock to relative time + /**< This member converts a clock value into a relative + Boost.DateTime time interval + \note The resolution of reltime_type might be smaller + than the clock_type resolution */ + static clock_type clock(abstime_type time); ///< Convert absolute time to clock value /**< This member converst an absolute time value into the corresponding clock value. \see abstime */ - protected: + static clock_type from_time_t(time_t const & time); + ///< Convert legacy time_t to clock value + /**< This member converts an absolute time value + represented as a time_t value into a clock value */ + + static clock_type from_timeval(timeval const & time); + ///< Convert legacy timeval to clock value + /**< This member converts an absolute time value + represented as a timeval value into a clock value */ + + static clock_type nanoseconds(int64_type v); ///< Convert \a v nanoseconds to clock_type + static clock_type microseconds(int64_type v); ///< Convert \a v microseconds to clock_type + static clock_type milliseconds(int64_type v); ///< Convert \a v milliseconds to clock_type + static clock_type seconds(int64_type v); ///< Convert \a v seconds to clock_type + static clock_type minutes(int64_type v); ///< Convert \a v minutes to clock_type + static clock_type hours(int64_type v); ///< Convert \a v hours to clock_type + static clock_type days(int64_type v); ///< Convert \a v days to clock_type + + static int64_type in_nanoseconds(clock_type v); ///< Convert \a v to nanoseconds + static int64_type in_microseconds(clock_type v); ///< Convert \a v to microseconds + static int64_type in_milliseconds(clock_type v); ///< Convert \a v to milliseconds + static int64_type in_seconds(clock_type v); ///< Convert \a v to seconds + static int64_type in_minutes(clock_type v); ///< Convert \a v to minutes + static int64_type in_hours(clock_type v); ///< Convert \a v to hours + static int64_type in_days(clock_type v); ///< Convert \a v to days + + static void restart(); ///< Force re-syncronisation of abstime and clock + /**< Calling the member should never be necessary since + abstime() / clock() automatically call restart() if + needed */ private: ClockService(); - static ClockService & instance(); - - boost::posix_time::ptime base_; - }; + abstime_type abstime_m(clock_type clock); + clock_type clock_m(abstime_type time); + void restart_m(); + + boost::posix_time::ptime baseAbstime_; + clock_type baseClock_; + + /// Internal: ClockService private data (PIMPL idiom) +#ifndef DOXYGEN + friend class singleton; +#endif + }; + /** \brief Console argument parser to parse value as time interval + + This parser will parse a time interval specification into a ClockService::clock_type + value. The following units are supported: + + + + + + +
\c ddays
\c hhours
\c mminutes
\c sseconds
+ + Additionally, the unit may be prefixed by an SI scale: + + + + + +
\c mmilli
\c umicro
\c nnano
+ + An optional decimal point is also supported. A single timer interval may combine any number + of these specifications. The following are all valid intervals: + + + + + + + + + +
10d10 days
5d5d10 days
1d2h100m3.5s27 hours, 30 minutes and 3.5 seconds
1s100ms1.1 seconds
1.1s1.1 seconds
123.456us123.456 microseconds
2md(very unusual) 2 milli-days
+ */ + void parseClockServiceInterval(console::ParseCommandInfo::TokensRange const & tokens, + ClockService::clock_type & out); + + void formatClockServiceInterval(ClockService::clock_type interval, std::ostream & os); } ///////////////////////////////hh.e////////////////////////////////////////