ba077e4ce25758b7c86a762ce2e7e4c1546c7b87
[senf.git] / Scheduler / Scheduler.hh
1 // $Id$
2 //
3 // Copyright (C) 2006
4 // Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS)
5 // Kompetenzzentrum fuer Satelitenkommunikation (SatCom)
6 //     Stefan Bund <stefan.bund@fokus.fraunhofer.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 Scheduler public header
25  */
26
27 #ifndef HH_Scheduler_
28 #define HH_Scheduler_ 1
29
30 // Custom includes
31 #include <map>
32 #include <queue>
33 #include <boost/function.hpp>
34 #include <boost/utility.hpp>
35 #include <boost/call_traits.hpp>
36 #include <boost/integer.hpp>
37 #include <boost/date_time/posix_time/posix_time_types.hpp>
38
39 //#include "scheduler.mpp"
40 ///////////////////////////////hh.p////////////////////////////////////////
41
42 /** \brief SENF Project namespace */
43 namespace senf {
44
45     /** \brief Singleton class to manage the event loop
46
47         This class manages a single select() type event loop. A customer of this class may register
48         any number of file descriptors with this class and pass callback functions to be called on
49         input, output or error. This functions are specified using boost::function objects (See <a
50         href="http://www.boost.org/doc/html/function.html">Boost.Function</a>)
51
52         The Scheduler is based on a generic handle representation. The only information needed from
53         a handle, is the intrinsic file descriptor. Any object for which the statement
54         \code
55           int fd = retrieve_filehandle(object);
56         \endcode
57         is valid and places the relevant file descriptor into fd can be used as a Handle type. There
58         is an implementation of retrieve_filehandle(int) within the library to handle explicit file
59         descriptors. The <a href="../../../Socket/doc/html/index.html">Socket library</a> provides an
60         implementation of <tt>retrieve_filehandle(FileHandle handle)</tt>. If you want to support
61         some other handle type, just define an appropriate \c retrieve_filehandle function <em>in
62         that types namespace</em>.
63
64         It is important to note, that for every combination of file descriptor and event, only a \e
65         single handler may be installed. Installing more handlers does not make sense. If you need
66         to distribute data to several interested parties, you must take care of this yourself.
67
68         \todo Fix EventId parameter (probably to int) to allow |-ing without casting ...
69       */
70     class Scheduler
71         : boost::noncopyable
72     {
73     public:
74         ///////////////////////////////////////////////////////////////////////////
75         // Types
76
77         /** \brief Types of file descriptor events */
78         enum EventId { EV_NONE=0,
79                        EV_READ=1, EV_PRIO=2, EV_WRITE=4, 
80                        EV_ALL=7,
81                        EV_HUP=8, EV_ERR=16 };
82
83         /** \brief Template typedef for Callback type
84
85             This is a template typedef (which does not exist in C++) that is, a template class whose
86             sole member is a typedef symbol defining the callback type given the handle type.
87
88             The Callback is any callable object taking a \c Handle and an \c EventId as argument.
89          */
90         template <class Handle>
91         struct GenericCallback {
92             typedef boost::function<void (typename boost::call_traits<Handle>::param_type,
93                                           EventId) > Callback;
94         };
95
96         /** \brief Scheduler time data type
97             
98             Unsigned integer type representing scheduler time. Scheduler time is measured in
99             nanoseconds relative to some implementation defined reference time.
100          */
101         typedef boost::uint_fast64_t sched_time;
102
103         /** \brief Absolute time data type
104
105             Boost.DateTime datatype used to represent absolute date/time values.
106          */
107         typedef boost::posix_time::ptime abs_time;
108
109         /** \brief Callback type for timer events */
110         typedef boost::function<void ()> TimerCallback;
111
112         ///////////////////////////////////////////////////////////////////////////
113         ///\name Structors and default members
114         ///@{
115
116         // private default constructor
117         // no copy constructor
118         // no copy assignment
119         // default destructor
120         // no conversion constructors
121
122         /** \brief Return Scheduler instance
123
124             This static member is used to access the singleton instance. This member is save to
125             return a correctly initialized Scheduler instance even if called at global construction
126             time
127
128             \implementation This static member just defines the Scheduler as a static method
129                 variable. The C++ standard then provides above guarantee. The instance will be
130                 initialized the first time, the code flow passes the variable declaration found in
131                 the instance() body.
132          */
133         static Scheduler & instance();
134
135         ///@}
136         ///////////////////////////////////////////////////////////////////////////
137
138         template <class Handle>
139         void add(Handle const & handle,
140                  typename GenericCallback<Handle>::Callback const & cb,
141                  int eventMask = EV_ALL); ///< Add file handle event callback
142                                         /**< add() will add a callback to the Scheduler. The
143                                              callback will be called for the given type of event on
144                                              the given  arbitrary file-descriptor or
145                                              handle-like object. If there already is a Callback
146                                              registered for one of the events requested, the new
147                                              handler will replace the old one.
148                                              \param[in] handle file descriptor or handle providing
149                                                  the Handle interface defined above.
150                                              \param[in] cb callback
151                                              \param[in] eventMask arbitrary combination via '|'
152                                                  operator of EventId designators. */
153         template <class Handle>
154         void remove(Handle const & handle, int eventMask = EV_ALL); ///< Remove event callback
155                                         /**< remove() will remove any callback registered for any of
156                                              the given events on the given file descriptor or handle
157                                              like object.
158                                              \param[in] handle file descriptor or handle providing
159                                                  the Handle interface defined above.
160                                              \param[in] eventMask arbitrary combination via '|'
161                                                  operator of EventId designators. */
162
163         void timeout(sched_time timeout, TimerCallback const & cb); ///< Add timeout event
164                                         /**< \param[in] timeout timeout in nanoseconds
165                                              \param[in] cb callback to call after \a timeout
166                                                  milliseconds
167                                              \todo Return some kind of handle/pointer and add
168                                                  support to update or revoke a timeout */
169
170         void process();                 ///< Event handler main loop
171                                         /**< This member must be called at some time to enter the
172                                              event handler main loop. Only while this function is
173                                              running any events are handled. The call will return
174                                              only, if any callback calls terminate(). */
175         void terminate();               ///< Called by callbacks to terminate the main loop
176                                         /**< This member may be called by any callback to tell the
177                                              main loop to terminate. The main loop will return to
178                                              it's caller after the currently running callback
179                                              returns. */
180         
181         abs_time abstime(sched_time time) const; ///< Convert scheduler time to absolute time
182                                         /**< This member converts a scheduler time value into an
183                                              absolute Boost.DateTime value. 
184                                              \note You should not base timeout calculations on this
185                                                  absolute time value. Scheduler time is guaranteed
186                                                  to be monotonous, absolute time may be
187                                                  non-monotonous if the system date/time is
188                                                  changed. */
189
190         sched_time schedtime(abs_time time) const; ///< Convert absolute time to scheduler time
191                                         /**< This member converst an absolute time value into the
192                                              corresponding scheduler time.
193                                              \see abstime */
194
195         sched_time now() const;         ///< Return current date/time
196                                         /**< The return value represents the current date/time in
197                                              scheduler time representation */
198
199         sched_time eventTime() const;   ///< Return date/time of last event
200
201     protected:
202
203     private:
204         typedef boost::function<void (EventId)> SimpleCallback;
205
206         static unsigned const MinTimeout = 1000;
207
208         Scheduler();
209
210         void do_add(int fd, SimpleCallback const & cb, int eventMask = EV_ALL);
211         void do_remove(int fd, int eventMask = EV_ALL);
212
213         /** \brief Descriptor event specification
214             \internal */
215         struct EventSpec
216         {
217             SimpleCallback cb_read;
218             SimpleCallback cb_prio;
219             SimpleCallback cb_write;
220
221             int epollMask() const;
222         };
223
224         /** \brief Timer event specification
225             \internal */
226         struct TimerSpec
227         {
228             TimerSpec() : timeout(), cb() {}
229             TimerSpec(sched_time timeout_, TimerCallback cb_)
230                 : timeout(timeout_), cb(cb_) {}
231
232             bool operator< (TimerSpec const & other) const
233                 { return timeout > other.timeout; }
234
235             sched_time timeout;
236             TimerCallback cb;
237         };
238
239         typedef std::map<int,EventSpec> FdTable;
240         typedef std::priority_queue<TimerSpec> TimerQueue;
241
242         FdTable fdTable_;
243         TimerQueue timerQueue_;
244         int epollFd_;
245         bool terminate_;
246         abs_time epoch_;
247     };
248
249     /** \brief Default file descriptor accessor
250
251         retrieve_filehandle() provides the Scheduler with support for explicit file descriptors as
252         file handle argument.
253
254         \relates Scheduler
255      */
256     int retrieve_filehandle(int fd);
257
258 }
259
260 ///////////////////////////////hh.e////////////////////////////////////////
261 #include "Scheduler.cci"
262 //#include "Scheduler.ct"
263 #include "Scheduler.cti"
264 #endif
265
266 \f
267 // Local Variables:
268 // mode: c++
269 // fill-column: 100
270 // c-file-style: "senf"
271 // indent-tabs-mode: nil
272 // ispell-local-dictionary: "american"
273 // compile-command: "scons -u test"
274 // comment-column: 40
275 // End: