switch to new MPL based Fraunhofer FOKUS Public License
[senf.git] / senf / PPI / Events.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 Events public header */
30
31 #ifndef HH_SENF_PPI_Events_
32 #define HH_SENF_PPI_Events_ 1
33
34 // Custom includes
35 #include <vector>
36 #include <senf/Scheduler/ClockService.hh>
37 #include "predecl.hh"
38
39 //#include "Events.mpp"
40 //-/////////////////////////////////////////////////////////////////////////////////////////////////
41
42 namespace senf {
43 namespace ppi {
44
45     namespace detail { class EventBindingBase; }
46
47     /** \defgroup event_group Events
48
49         Events provide notification of events outside the PPI framework: I/O activity, Timers
50         etc. Events are very important since they drive the PPI: Without events, nothing will
51         happen.
52
53         \section event_impl Implementing Events
54
55         All events are derived from EventImplementation which is based on EventDescriptor.
56         \see EventImplementation \n
57             \ref ppi_events
58      */
59
60     // Implementation: The concrete EventDescriptor implementation will need to set things up so
61     // some callback (within the EventDescriptor implementation) will be called when the event
62     // happens. This setup happens in 'v_enable()'. This internal handler sets up an EventType
63     // instance if needed and calls 'callback()'.
64     //
65     // 'callback()' will access the EventBinding wrapper to find the user-callback to signal. It
66     // will do any needed internal processing, call that user callback and clean up afterwards.
67
68     /** \brief Generic event interface base-class
69
70         The EventDescriptor base-class provides an interface to control events.
71
72         \see \ref ppi_events
73      */
74     class EventDescriptor
75     {
76     public:
77         virtual ~EventDescriptor();
78
79         bool enabled() const; ///< Check, whether the event is currently enabled
80         void enabled(bool v); ///< Enable or disable the event
81
82     protected:
83         EventDescriptor();
84
85     private:
86         virtual void v_enable() = 0;    ///< Called to enable the event delivery
87         virtual void v_disable() = 0;   ///< Called to disable the event delivery
88
89         virtual bool v_isRegistered() = 0;
90
91         void notifyThrottle();
92         void notifyUnthrottle();
93
94         void registerRoute(ForwardingRoute & route);
95         void unregisterRoute(ForwardingRoute & route);
96
97         bool enabled_;
98         bool throttled_;
99
100         typedef std::vector<ForwardingRoute*> Routes;
101         Routes routes_;
102
103         detail::EventBindingBase * binding_;
104
105         friend class ForwardingRoute;
106         friend class detail::EventBindingBase;
107     };
108
109     /** \brief Internal: Callback forwarders
110      */
111     template <class EventType, class Self>
112     class EventImplementationHelper
113     {
114     protected:
115         typedef typename detail::EventArgType<EventType>::type EventArg;
116
117         void callback(EventArg event, ClockService::clock_type time);
118                                         ///< Forward event to user callback
119                                         /**< \param[in] event Event argument to pass to the user
120                                              callback
121                                              \param[in] time Expected time of the event */
122         void callback(EventArg event);  ///< Forward event to user callback
123                                         /**< \param[in] event Event argument to pass to the user
124                                              callback. */
125
126     private:
127         detail::EventBinding<EventType> & binding();
128     };
129
130 #ifndef DOXYGEN
131
132     template <class Self>
133     class EventImplementationHelper<void,Self>
134     {
135     protected:
136         void callback(ClockService::clock_type time);
137         void callback();
138
139     private:
140         detail::EventBinding<void> & binding();
141     };
142
143 #endif
144
145     /** \brief Event implementation base class
146
147         EventImplementation provides the base-class for all Event implementations.
148         \code
149         class SomeEvent : public EventImplementation<SomeEventArg>
150         {
151         public:
152             SomeEvent() {}
153
154         private:
155             virtual void v_enable() {
156                 // register cb() to be called when the event occurs
157             }
158
159             virtual void v_disable() {
160                 // unregister cb()
161             }
162
163             void cb() {
164                 // Build event argument
165                 SomeEventArg arg (...);
166                 // Call the event callback
167                 callback(arg);
168             }
169         };
170         \endcode
171
172         Every event needs to implement v_enable() and v_disable(). v_enable() should register some
173         member (in the example \c cb() ) to be called whenever the event occurs, while v_disable()
174         should unregister it.
175
176         The \a EventType argument to EventImplementation defines the type of argument passed to the
177         user callback. It defaults to \c void. . This user callback is called from within the
178         registered member (e.g. \c cb() ) by calling the inherited callback() member. This member
179         takes an \a EventType reference as argument which will be forwarded to the user callback. If
180         available, you should also provide the \e expected event time as a second argument.
181      */
182     template <class EventType>
183     class EventImplementation
184         : public EventDescriptor,
185           public EventImplementationHelper< EventType, EventImplementation<EventType> >
186     {
187     public:
188         typedef EventType Event;
189         typedef typename detail::EventArgType<EventType>::type EventArg;
190
191         module::Module & module() const; ///< Module in which the event is registered
192         EventManager & manager() const; ///< EventManager of the event
193
194     protected:
195         EventImplementation();
196
197     private:
198         virtual bool v_isRegistered();
199         void setBinding(detail::EventBinding<Event> & binding);
200
201         detail::EventBinding<Event> * binding_;
202
203         friend class EventManager;
204         friend class EventImplementationHelper< EventType, EventImplementation<EventType> >;
205     };
206
207 }}
208
209 //-/////////////////////////////////////////////////////////////////////////////////////////////////
210 #include "Events.cci"
211 //#include "Events.ct"
212 #include "Events.cti"
213 #endif
214
215 \f
216 // Local Variables:
217 // mode: c++
218 // fill-column: 100
219 // c-file-style: "senf"
220 // indent-tabs-mode: nil
221 // ispell-local-dictionary: "american"
222 // compile-command: "scons -u test"
223 // comment-column: 40
224 // End: