44ad232d3c2085529a58e80e1a1cfde278d4d3e7
[senf.git] / senf / Scheduler / ClockService.hh
1 // $Id$
2 //
3 // Copyright (C) 2007
4 // Fraunhofer Institute for Open Communication Systems (FOKUS)
5 //
6 // The contents of this file are subject to the Fraunhofer FOKUS Public License
7 // Version 1.0 (the "License"); you may not use this file except in compliance
8 // with the License. You may obtain a copy of the License at 
9 // http://senf.berlios.de/license.html
10 //
11 // The Fraunhofer FOKUS Public License Version 1.0 is based on, 
12 // but modifies the Mozilla Public License Version 1.1.
13 // See the full license text for the amendments.
14 //
15 // Software distributed under the License is distributed on an "AS IS" basis, 
16 // WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 
17 // for the specific language governing rights and limitations under the License.
18 //
19 // The Original Code is Fraunhofer FOKUS code.
20 //
21 // The Initial Developer of the Original Code is Fraunhofer-Gesellschaft e.V. 
22 // (registered association), Hansastraße 27 c, 80686 Munich, Germany.
23 // All Rights Reserved.
24 //
25 // Contributor(s):
26 //   Stefan Bund <g0dil@berlios.de>
27
28 /** \file
29     \brief ClockService public header */
30
31 #ifndef HH_SENF_Scheduler_ClockService_
32 #define HH_SENF_Scheduler_ClockService_ 1
33
34 // Custom includes
35 #include <sys/time.h>
36 #include <boost/utility.hpp>
37 #include <boost/date_time/posix_time/posix_time.hpp>
38 #include <boost/scoped_ptr.hpp>
39 #include <boost/cstdint.hpp>
40 #include <senf/config.hh>
41 #include <senf/Utils/singleton.hh>
42 #include <senf/Utils/Console/Parse.hh>
43
44 //#include "ClockService.mpp"
45 //-/////////////////////////////////////////////////////////////////////////////////////////////////
46
47 namespace senf {
48
49 #ifndef DOXYGEN
50     namespace detail { class ClockServiceTest; }
51 #endif
52
53     // Implementation note: The clock value is represented as a 64bit unsigned integer number of
54     // nanoseconds based on the CLOCK_MONOTONIC POSIX clock.
55     //
56     // To allow conversion between clock value and absolute time, the ClockService samples the
57     // absolute current time and the clock value when the conversion is performed. This is done at
58     // most once per second on a if-needed basis.
59
60     /** \brief Reliable high precision monotonous clock source
61
62         The ClockService provides a highly accurate monotonous clock source based on
63         gettimeofday(). However, it takes additional precautions to detect clock skew.
64
65         \implementation The funny mixture of static and non-static members stems from the old
66             implementation based on interval timers and gettimeofday(). The current implementation
67             uses POSIX clocks and is much simpler and more precise.
68       */
69     class ClockService
70         : singleton<ClockService>
71     {
72     public:
73         //-////////////////////////////////////////////////////////////////////////
74         // Types
75
76         /** \brief ClockService timer data type
77
78             Unsigned integer type representing scheduler time. Scheduler time is measured in
79             nanoseconds relative to some implementation defined reference time.
80          */
81         typedef config::time_type clock_type;
82
83         /** \brief Supplementary integer type
84
85             This type is used to represent varies supplementary values (e.g. number of microseconds)
86          */
87         typedef boost::int_fast64_t int64_type;
88
89         /** \brief Absolute time data type
90
91             <a href="http://www.boost.org/doc/libs/release/libs/date_time/index.html">Boost.DateTime</a>
92             datatype used to represent absolute date/time values.
93          */
94         typedef boost::posix_time::ptime abstime_type;
95
96         /** \brief Relative time data type
97
98             <a href="http://www.boost.org/doc/libs/release/libs/date_time/index.html">Boost.DateTime</a>
99             datatype used to represent time intervals
100          */
101         typedef boost::posix_time::time_duration reltime_type;
102
103         //-////////////////////////////////////////////////////////////////////////
104
105         static clock_type now();  ///< Return current clock value
106
107         static abstime_type abstime(clock_type clock); ///< Convert clock to absolute time
108                                         /**< This member converts a clock value into an absolute
109                                              <a href="http://www.boost.org/doc/libs/release/libs/date_time/index.html">Boost.DateTime</a>
110                                              value.
111                                              \note You should not base timeout calculations on this
112                                                  absolute time value. Clock time is guaranteed to be
113                                                  monotonous, absolute time may be non-monotonous if
114                                                  the system date/time is changed. */
115
116         static reltime_type reltime(clock_type clock); ///< Convert clock to relative time
117                                         /**< This member converts a clock value into a relative
118                                              <a href="http://www.boost.org/doc/libs/release/libs/date_time/index.html">Boost.DateTime</a>
119                                              time interval
120                                              \note The resolution of reltime_type might be smaller
121                                                  than the clock_type resolution */
122
123         static clock_type clock(abstime_type time); ///< Convert absolute time to clock value
124                                         /**< This member convert an absolute time value into the
125                                              corresponding clock value.
126                                              \see abstime */
127
128         static clock_type from_time_t(time_t const & time);
129                                         ///< Convert legacy time_t to clock value
130                                         /**< This member converts an absolute time value
131                                              represented as a time_t value into a clock value */
132
133         static clock_type from_timeval(timeval const & time);
134                                         ///< Convert legacy timeval to clock value
135                                         /**< This member converts an absolute time value
136                                              represented as a timeval value into a clock value */
137
138         static clock_type nanoseconds(int64_type v); ///< Convert \a v nanoseconds to clock_type
139         static clock_type microseconds(int64_type v); ///< Convert \a v microseconds to clock_type
140         static clock_type milliseconds(int64_type v); ///< Convert \a v milliseconds to clock_type
141         static clock_type seconds(int64_type v); ///< Convert \a v seconds to clock_type
142         static clock_type minutes(int64_type v); ///< Convert \a v minutes to clock_type
143         static clock_type hours(int64_type v); ///< Convert \a v hours to clock_type
144         static clock_type days(int64_type v); ///< Convert \a v days to clock_type
145
146         static int64_type in_nanoseconds(clock_type v); ///< Convert \a v to nanoseconds
147         static int64_type in_microseconds(clock_type v); ///< Convert \a v to microseconds
148         static int64_type in_milliseconds(clock_type v); ///< Convert \a v to milliseconds
149         static int64_type in_seconds(clock_type v); ///< Convert \a v to seconds
150         static int64_type in_minutes(clock_type v); ///< Convert \a v to minutes
151         static int64_type in_hours(clock_type v); ///< Convert \a v to hours
152         static int64_type in_days(clock_type v); ///< Convert \a v to days
153
154         static void restart(); ///< Force re-synchronization of abstime and clock
155                                         /**< Calling the member should never be necessary since
156                                              abstime() / clock() automatically call restart() if
157                                              needed */
158
159     private:
160         ClockService();
161
162         abstime_type abstime_m(clock_type clock);
163         clock_type clock_m(abstime_type time);
164         void restart_m();
165
166         boost::posix_time::ptime baseAbstime_;
167         clock_type baseClock_;
168
169         /// Internal: ClockService private data (PIMPL idiom)
170
171 #ifndef DOXYGEN
172         friend class singleton<ClockService>;
173 #endif
174     };
175
176     /** \brief Console argument parser to parse value as time interval
177
178         This parser will parse a time interval specification into a ClockService::clock_type
179         value. The following units are supported:
180
181         <table class="senf fixedcolumn">
182         <tr><td>\c d</td><td>days</td></tr>
183         <tr><td>\c h</td><td>hours</td></tr>
184         <tr><td>\c m</td><td>minutes</td></tr>
185         <tr><td>\c s</td><td>seconds</td></tr>
186         </table>
187
188         Additionally, the unit may be prefixed by an SI scale:
189
190         <table class="senf fixedcolumn">
191         <tr><td>\c m</td><td>milli</td></tr>
192         <tr><td>\c u</td><td>micro</td></tr>
193         <tr><td>\c n</td><td>nano</td></tr>
194         </table>
195
196         An optional decimal point is also supported. A single timer interval may combine any number
197         of these specifications. The following are all valid intervals:
198
199         <table class="senf fixedcolumn">
200         <tr><td><code>10d</code></td><td>10 days</td></tr>
201         <tr><td><code>5d5d</code></td><td>10 days</td></tr>
202         <tr><td><code>1d2h100m3.5s</code></td><td>27 hours, 30 minutes and 3.5 seconds</td></tr>
203         <tr><td><code>1s100ms</code></td><td>1.1 seconds</td></tr>
204         <tr><td><code>1.1s</code></td><td>1.1 seconds</td></tr>
205         <tr><td><code>123.456us</code></td><td>123.456 microseconds</td></tr>
206         <tr><td><code>2md</code></td><td>(very unusual) 2 milli-days</td></tr>
207         </table>
208      */
209     void parseClockServiceInterval(console::ParseCommandInfo::TokensRange const & tokens,
210                                    ClockService::clock_type & out);
211
212     void formatClockServiceInterval(ClockService::clock_type interval, std::ostream & os);
213 }
214
215 //-/////////////////////////////////////////////////////////////////////////////////////////////////
216 #include "ClockService.cci"
217 //#include "ClockService.ct"
218 //#include "ClockService.cti"
219 #endif
220
221 \f
222 // Local Variables:
223 // mode: c++
224 // fill-column: 100
225 // comment-column: 40
226 // c-file-style: "senf"
227 // indent-tabs-mode: nil
228 // ispell-local-dictionary: "american"
229 // compile-command: "scons -u test"
230 // End: