40ea765b953e1c87eb724c37b625aa844a7b9d93
[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 #include <senf/Utils/RestrictedInt.hh>
44
45 //#include "ClockService.mpp"
46 //-/////////////////////////////////////////////////////////////////////////////////////////////////
47
48 namespace senf {
49
50 #ifndef DOXYGEN
51     namespace detail { class ClockServiceTest; }
52 #endif
53
54     // Implementation note: The clock value is represented as a 64bit unsigned integer number of
55     // nanoseconds based on the CLOCK_MONOTONIC POSIX clock.
56     //
57     // To allow conversion between clock value and absolute time, the ClockService samples the
58     // absolute current time and the clock value when the conversion is performed. This is done at
59     // most once per second on a if-needed basis.
60
61     /** \brief Reliable high precision monotonous clock source
62
63         The ClockService provides a highly accurate monotonous clock source based on
64         gettimeofday(). However, it takes additional precautions to detect clock skew.
65
66         \implementation The funny mixture of static and non-static members stems from the old
67             implementation based on interval timers and gettimeofday(). The current implementation
68             uses POSIX clocks and is much simpler and more precise.
69       */
70     class ClockService
71         : singleton<ClockService>
72     {
73     public:
74         //-////////////////////////////////////////////////////////////////////////
75         // Types
76
77         /** \brief ClockService timer data type
78
79             Unsigned integer type representing scheduler time. Scheduler time is measured in
80             nanoseconds relative to some implementation defined reference time.
81          */
82 #ifdef SENF_DEBUG
83         struct ClockTypeTag {};
84         typedef senf::RestrictedInt<config::time_type, ClockTypeTag> clock_type;
85 #else
86         typedef config::time_type clock_type;
87 #endif
88         /** \brief Supplementary integer type
89
90             This type is used to represent varies supplementary values (e.g. number of microseconds)
91          */
92
93         typedef boost::int_fast64_t int64_type;
94
95         /** \brief Absolute time data type
96
97             <a href="http://www.boost.org/doc/libs/release/libs/date_time/index.html">Boost.DateTime</a>
98             datatype used to represent absolute date/time values.
99          */
100         typedef boost::posix_time::ptime abstime_type;
101
102         /** \brief Relative time data type
103
104             <a href="http://www.boost.org/doc/libs/release/libs/date_time/index.html">Boost.DateTime</a>
105             datatype used to represent time intervals
106          */
107         typedef boost::posix_time::time_duration reltime_type;
108
109         //-////////////////////////////////////////////////////////////////////////
110
111         static clock_type now();  ///< Return current clock value
112
113         static abstime_type abstime(clock_type clock); ///< Convert clock to absolute time
114                                         /**< This member converts a clock value into an absolute
115                                              <a href="http://www.boost.org/doc/libs/release/libs/date_time/index.html">Boost.DateTime</a>
116                                              value.
117                                              \note You should not base timeout calculations on this
118                                                  absolute time value. Clock time is guaranteed to be
119                                                  monotonous, absolute time may be non-monotonous if
120                                                  the system date/time is changed. */
121
122         static reltime_type reltime(clock_type clock); ///< Convert clock to relative time
123                                         /**< This member converts a clock value into a relative
124                                              <a href="http://www.boost.org/doc/libs/release/libs/date_time/index.html">Boost.DateTime</a>
125                                              time interval
126                                              \note The resolution of reltime_type might be smaller
127                                                  than the clock_type resolution */
128
129         static clock_type clock(abstime_type time); ///< Convert absolute time to clock value
130                                         /**< This member convert an absolute time value into the
131                                              corresponding clock value.
132                                              \see abstime */
133
134         static clock_type from_time_t(time_t const & time);
135                                         ///< Convert legacy time_t to clock value
136                                         /**< This member converts an absolute time value
137                                              represented as a time_t value into a clock value */
138
139         static clock_type from_timeval(timeval const & time);
140                                         ///< Convert legacy timeval to clock value
141                                         /**< This member converts an absolute time value
142                                              represented as a timeval value into a clock value */
143
144         static clock_type nanoseconds(int64_type v); ///< Convert \a v nanoseconds to clock_type
145         static clock_type microseconds(int64_type v); ///< Convert \a v microseconds to clock_type
146         static clock_type milliseconds(int64_type v); ///< Convert \a v milliseconds to clock_type
147         static clock_type seconds(int64_type v); ///< Convert \a v seconds to clock_type
148         static clock_type minutes(int64_type v); ///< Convert \a v minutes to clock_type
149         static clock_type hours(int64_type v); ///< Convert \a v hours to clock_type
150         static clock_type days(int64_type v); ///< Convert \a v days to clock_type
151
152         static int64_type in_nanoseconds(clock_type v); ///< Convert \a v to nanoseconds
153         static int64_type in_microseconds(clock_type v); ///< Convert \a v to microseconds
154         static int64_type in_milliseconds(clock_type v); ///< Convert \a v to milliseconds
155         static int64_type in_seconds(clock_type v); ///< Convert \a v to seconds
156         static int64_type in_minutes(clock_type v); ///< Convert \a v to minutes
157         static int64_type in_hours(clock_type v); ///< Convert \a v to hours
158         static int64_type in_days(clock_type v); ///< Convert \a v to days
159
160         static void restart(); ///< Force re-synchronization of abstime and clock
161                                         /**< Calling the member should never be necessary since
162                                              abstime() / clock() automatically call restart() if
163                                              needed */
164
165     private:
166         ClockService();
167
168         abstime_type abstime_m(clock_type clock);
169         clock_type clock_m(abstime_type time);
170         void restart_m();
171
172         boost::posix_time::ptime baseAbstime_;
173         clock_type baseClock_;
174
175         /// Internal: ClockService private data (PIMPL idiom)
176
177 #ifndef DOXYGEN
178         friend class singleton<ClockService>;
179 #endif
180     };
181
182     /** \brief Console argument parser to parse value as time interval
183
184         This parser will parse a time interval specification into a ClockService::clock_type
185         value. The following units are supported:
186
187         <table class="senf fixedcolumn">
188         <tr><td>\c d</td><td>days</td></tr>
189         <tr><td>\c h</td><td>hours</td></tr>
190         <tr><td>\c m</td><td>minutes</td></tr>
191         <tr><td>\c s</td><td>seconds</td></tr>
192         </table>
193
194         Additionally, the unit may be prefixed by an SI scale:
195
196         <table class="senf fixedcolumn">
197         <tr><td>\c m</td><td>milli</td></tr>
198         <tr><td>\c u</td><td>micro</td></tr>
199         <tr><td>\c n</td><td>nano</td></tr>
200         </table>
201
202         An optional decimal point is also supported. A single timer interval may combine any number
203         of these specifications. The following are all valid intervals:
204
205         <table class="senf fixedcolumn">
206         <tr><td><code>10d</code></td><td>10 days</td></tr>
207         <tr><td><code>5d5d</code></td><td>10 days</td></tr>
208         <tr><td><code>1d2h100m3.5s</code></td><td>27 hours, 30 minutes and 3.5 seconds</td></tr>
209         <tr><td><code>1s100ms</code></td><td>1.1 seconds</td></tr>
210         <tr><td><code>1.1s</code></td><td>1.1 seconds</td></tr>
211         <tr><td><code>123.456us</code></td><td>123.456 microseconds</td></tr>
212         <tr><td><code>2md</code></td><td>(very unusual) 2 milli-days</td></tr>
213         </table>
214      */
215     void parseClockServiceInterval(console::ParseCommandInfo::TokensRange const & tokens,
216                                    ClockService::clock_type & out);
217
218     void formatClockServiceInterval(ClockService::clock_type interval, std::ostream & os);
219 }
220
221 //-/////////////////////////////////////////////////////////////////////////////////////////////////
222 #include "ClockService.cci"
223 //#include "ClockService.ct"
224 //#include "ClockService.cti"
225 #endif
226
227 \f
228 // Local Variables:
229 // mode: c++
230 // fill-column: 100
231 // comment-column: 40
232 // c-file-style: "senf"
233 // indent-tabs-mode: nil
234 // ispell-local-dictionary: "american"
235 // compile-command: "scons -u test"
236 // End: