// $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 <g0dil@berlios.de>
//
// This program is free software; you can redistribute it and/or modify
// Custom includes
#include <boost/utility.hpp>
-#include <boost/date_time/posix_time/posix_time_types.hpp>
+#include <boost/date_time/posix_time/posix_time.hpp>
+#include <boost/scoped_ptr.hpp>
+#include "../Utils/singleton.hh"
//#include "ClockService.mpp"
///////////////////////////////hh.p////////////////////////////////////////
namespace senf {
+#ifndef DOXYGEN
+ namespace detail { class ClockServiceTest; }
+#endif
+
// Implementation note:
//
// The clock value is represented as a 64bit unsigned integer number of nanosecods elapsed since
// 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()
+ // a) Clock skew detected 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.
+ // In this case, we use getitimer() to find the time remaining in the timer. Using this value
+ // and the saved gettimeofday() value we can adjust base_ accordingly.
//
// b) Clock skew detected in the signal handler
//
- // In this case we use the save gettimeofday() value + CheckInterval to adjust base_.
+ // In this case we use the saved gettimeofday() value + CheckInterval to adjust base_.
/** \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 We use a mix of static and non-static members to achieve high performance
+ in the normal case (no clock skew) and still encapsulate the dependency on legacy C
+ headers. Using the senf::singleton mixin ensures, that the instance is constructed
+ before main even when instance() is not called.
*/
class ClockService
- : boost::noncopyable
+ : singleton<ClockService>
{
public:
///////////////////////////////////////////////////////////////////////////
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 boost::int_fast64_t clock_type;
/** \brief Absolute time data type
*/
typedef boost::posix_time::ptime abstime_type;
- static unsigned const CheckInterval = 1;
+ static unsigned const CheckInterval = 10;
///////////////////////////////////////////////////////////////////////////
///\name Structors and default members
corresponding clock value.
\see abstime */
- protected:
+ static clock_type nanoseconds(clock_type v);
+ static clock_type microseconds(clock_type v);
+ static clock_type milliseconds(clock_type v);
+ static clock_type seconds(clock_type v);
+ static clock_type minutes(clock_type v);
+ static clock_type hours(clock_type v);
+ static clock_type days(clock_type v);
+
+ static void restart();
private:
ClockService();
- static ClockService & instance();
-
+ void timer();
+
+ clock_type now_m();
+ abstime_type abstime_m(clock_type clock);
+ clock_type clock_m(abstime_type time);
+ void restart_m(bool restart = true);
+
+ bool checkSkew(boost::posix_time::ptime time);
+ void updateSkew(boost::posix_time::ptime time);
+ void clockSkew(boost::posix_time::ptime time, boost::posix_time::ptime expected);
+
+ void restartTimer(bool restart = true);
+
boost::posix_time::ptime base_;
- };
+ boost::posix_time::ptime heartbeat_;
+ // I don't want this header to depend on the legacy C headers.
+ /// Internal: ClockService private data (PIMPL idiom)
+ struct Impl;
+ boost::scoped_ptr<Impl> impl_;
+
+ friend class Impl;
+#ifndef DOXYGEN
+ friend class senf::detail::ClockServiceTest;
+ friend class singleton<ClockService>;
+#endif
+ };
}