8fe4f152a2134dc2435b2526fa57995c76970874
[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
37 #include "Utils/MicroTime.hh"
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         /** \brief Callback type for timer events */
96         typedef boost::function<void ()> TimerCallback;
97
98         ///////////////////////////////////////////////////////////////////////////
99         ///\name Structors and default members
100         ///@{
101
102         // private default constructor
103         // no copy constructor
104         // no copy assignment
105         // default destructor
106         // no conversion constructors
107
108         /** \brief Return Scheduler instance
109
110             This static member is used to access the singleton instance. This member is save to
111             return a correctly initialized Scheduler instance even if called at global construction
112             time
113
114             \implementation This static member just defines the Scheduler as a static method
115                 variable. The C++ standard then provides above guarantee. The instance will be
116                 initialized the first time, the code flow passes the variable declaration found in
117                 the instance() body.
118          */
119         static Scheduler & instance();
120
121         ///@}
122         ///////////////////////////////////////////////////////////////////////////
123
124         template <class Handle>
125         void add(Handle const & handle,
126                  typename GenericCallback<Handle>::Callback const & cb,
127                  int eventMask = EV_ALL); ///< Add file handle event callback
128                                         /**< add() will add a callback to the Scheduler. The
129                                              callback will be called for the given type of event on
130                                              the given  arbitrary file-descriptor or
131                                              handle-like object. If there already is a Callback
132                                              registered for one of the events requested, the new
133                                              handler will replace the old one.
134                                              \param[in] handle file descriptor or handle providing
135                                                  the Handle interface defined above.
136                                              \param[in] cb callback
137                                              \param[in] eventMask arbitrary combination via '|'
138                                                  operator of EventId designators. */
139         template <class Handle>
140         void remove(Handle const & handle, int eventMask = EV_ALL); ///< Remove event callback
141                                         /**< remove() will remove any callback registered for any of
142                                              the given events on the given file descriptor or handle
143                                              like object.
144                                              \param[in] handle file descriptor or handle providing
145                                                  the Handle interface defined above.
146                                              \param[in] eventMask arbitrary combination via '|'
147                                                  operator of EventId designators. */
148
149         void timeout(unsigned long timeout, TimerCallback const & cb); ///< Add timeout event
150                                         /**< \param[in] timeout timeout in milliseconds
151                                              \param[in] cb callback to call after \a timeout
152                                                  milliseconds
153                                              \todo Return some kind of handle/pointer and add
154                                                  support to update or revoke a timeout */
155
156         void process();                 ///< Event handler main loop
157                                         /**< This member must be called at some time to enter the
158                                              event handler main loop. Only while this function is
159                                              running any events are handled. The call will return
160                                              only, if any callback calls terminate(). */
161         void terminate();               ///< Called by callbacks to terminate the main loop
162                                         /**< This member may be called by any callback to tell the
163                                              main loop to terminate. The main loop will return to
164                                              it's caller after the currently running callback
165                                              returns. */
166
167     protected:
168
169     private:
170         typedef boost::function<void (EventId)> SimpleCallback;
171
172         Scheduler();
173
174         void do_add(int fd, SimpleCallback const & cb, int eventMask = EV_ALL);
175         void do_remove(int fd, int eventMask = EV_ALL);
176
177         /** \brief Descriptor event specification
178             \internal */
179         struct EventSpec
180         {
181             SimpleCallback cb_read;
182             SimpleCallback cb_prio;
183             SimpleCallback cb_write;
184
185             int epollMask() const;
186         };
187
188         /** \brief Timer event specification
189             \internal */
190         struct TimerSpec
191         {
192             TimerSpec() : timeout(), cb() {}
193             TimerSpec(unsigned long long timeout_, TimerCallback cb_)
194                 : timeout(timeout_), cb(cb_) {}
195
196             bool operator< (TimerSpec const & other) const
197                 { return timeout > other.timeout; }
198
199             unsigned long long timeout;
200             TimerCallback cb;
201         };
202
203         typedef std::map<int,EventSpec> FdTable;
204         typedef std::priority_queue<TimerSpec> TimerQueue;
205
206         FdTable fdTable_;
207         TimerQueue timerQueue_;
208         int epollFd_;
209         bool terminate_;
210     };
211
212     /** \brief Default file descriptor accessor
213
214         retrieve_filehandle() provides the Scheduler with support for explicit file descriptors as
215         file handle argument.
216
217         \relates Scheduler
218      */
219     int retrieve_filehandle(int fd);
220
221 }
222
223 ///////////////////////////////hh.e////////////////////////////////////////
224 #include "Scheduler.cci"
225 //#include "Scheduler.ct"
226 #include "Scheduler.cti"
227 #endif
228
229 \f
230 // Local Variables:
231 // mode: c++
232 // fill-column: 100
233 // c-file-style: "senf"
234 // indent-tabs-mode: nil
235 // ispell-local-dictionary: "american"
236 // End: