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