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