CFugue
EventHandler.h
1 #ifndef __EVENTHANDLER_H_105D52D8_13EC_4ea3_A86B_076B726541EB_
2 #define __EVENTHANDLER_H_105D52D8_13EC_4ea3_A86B_076B726541EB_
3 
4 #include <map>
5 #include <memory>
6 #include <vector>
7 #include <cassert>
8 #include <algorithm>
9 
10 namespace OIL /// C++ Object Introspection Library, by Cenacle Research
11 {
12  class CEventSource; //Forward declaration
13 
14  /// <Summary>
15  /// Class that is used to pass arguments to the event handler procedures.
16  /// <para> See CEventT for sample usage.</para>
17  /// </Summary>
19  {
20  public:
22  virtual ~CEventHandlerArgs() { }
23  };
24 
25  /// <Summary>
26  /// For Class-based Event Subscriptions, a class can receive
27  /// events only if it is derived from CEventReceiver.
28  /// <para> See CEventT for sample usage.</para>
29  /// </Summary>
31  {
32  protected:
33  // Protected constructor. CEventReceiver objects cannot be created directly.
34  // This Class should be inherited.
35  CEventReceiver() {}
36 
37  // Protected destructor.
38  // No need to declare as virtual because delete can't be applied on CEventReceiver pointers.
39  ~CEventReceiver() { }
40  };
41 
42  /// <Summary>
43  /// Class for Event Subscription Function Objects.
44  /// </Summary>
46  {
47  public:
48  virtual ~IEventFunctor() { }
49  virtual void operator()(CEventReceiver* pReceiver, CEventSource* pSender, CEventHandlerArgs* pArgs) = 0;
50  };
51 
52  /// <Summary>
53  /// A Receiver can Subscribe for an Event only once.
54  /// If a Receiver requests a second subscription for the same Event,
55  /// its previous subscription would be replaced with the new subscription.
56  ///
57  /// A Receiver can subscribe for as many different events as it wants.
58  /// But for each, only once.
59  ///
60  /// And an Event can have as many Receivers as it likes.
61  ///
62  /// CEventT take template arguments that indicate the prototype of the
63  /// handler proc that should used to subscribe to that event. By default,
64  /// CEvent uses the handlers of the form
65  /// <code>void EventReceptionFunc(const CEventSource* pSrc, CEventHandlerArgs* pArgs)</code>
66  /// You can use different prototypes by simply defining the sender and handler
67  /// args in the template definition for CEventT.
68  ///
69  /// For example, CEventT<Sender, HandlerArgs> expects its subscriber functions
70  /// to be of the form
71  /// <code>void EventReceptionFunc(Sender* pSrc, HandlerArgs* pArgs)</code>
72  /// </Summary>
73  /// Following Snippet demonstrates sample usage.
74  /** <code><pre>
75  \#include "EventHandler.h"
76  using namespace OIL;
77 
78  struct MyEventHandlerArgs : public CEventHandlerArgs
79  {
80  int m_nVal;
81  };
82 
83  class MySender : public CEventSource
84  {
85  public:
86 
87  CEvent m_Event; // Default handler prototype
88 
89  CEventT < const MySender, MyEventHandlerArgs > m_Event2; // Custom handler prototype
90 
91  void MyFunction()
92  {
93  RaiseEvent(&m_Event, &CEventHandlerArgs()); // Invoke the Event
94 
95  RaiseEvent(&m_Event2, &MyEventHandlerArgs()); // Invoke the Event with custom prototype
96  }
97  };
98 
99  class MyReceiver: public CEventReceiver
100  {
101  MySender* m_pMySenderObject;
102 
103  public:
104 
105  MyReceiver(MySender* pSender) : m_pMySenderObject(pSender) // Subscribe for the Events
106  {
107  m_pMySenderObject->m_Event.Subscribe(this, & MyReceiver::EventReceptionFunc);
108 
109  m_pMySenderObject->m_Event2.Subscribe(this, & MyReceiver::MyEventReceptionFunc2);
110  }
111 
112  void EventReceptionFunc(const CEventSource* pSrc, CEventHandlerArgs* pArgs)
113  {
114  printf("\n Event Received\n"); // Code for Handling the Event
115  }
116 
117  void MyEventReceptionFunc2(const MySender* pSrc, const MyEventHandlerArgs* pArgs)
118  {
119  printf("\nEvent2 Received"); // Code for Handling the Event
120  }
121  };
122 
123  void main()
124  {
125  MySender senderObj;
126 
127  MyReceiver receiverObj(senderObj);
128 
129  senderObj.MyFunction(); // Do something on Sender that will Raise the Events to be received on Receiver
130  }
131  </pre></code> */
132  template<typename TEventSource = const CEventSource, typename TEventHandlerArgs = CEventHandlerArgs>
133  class CEventT
134  {
135  /// <Summary>
136  /// Implements IEventFunctor for Handling Class-based Subscriptions.
137  /// </Summary>
138  template<typename TEventReceiver>
139  class CClassFunctor : public IEventFunctor
140  {
141  typedef void (TEventReceiver::*FuncType)(TEventSource* pSender, TEventHandlerArgs* pArgs);
142 
143  FuncType m_pFunc;
144 
145  CClassFunctor(FuncType pFunc) : m_pFunc(pFunc) { }
146 
147  inline void operator()(CEventReceiver* pReceiver, CEventSource* pSender, CEventHandlerArgs* pArgs)
148  {
149  (((TEventReceiver*)pReceiver)->*m_pFunc)((TEventSource*)pSender, (TEventHandlerArgs*)pArgs);
150  }
151 
152  friend class CEventT; // Only CEventT Objects can use the CClassFunctor Objects
153  };
154 
155  //typedef std::shared_ptr<IEventFunctor> FUNCTOR_SMARTPTR;
156  typedef std::shared_ptr<IEventFunctor> IEventFunctorPtr;
157  //typedef ATL::CMapToAutoPtr<CEventReceiver*, IEventFunctor> CLASS_HANDLER_MAP;
158  typedef std::map<CEventReceiver*, IEventFunctorPtr> CLASS_HANDLER_MAP;
159  typedef void (*STATICHANDLER)(TEventSource*, TEventHandlerArgs*);
160  //typedef ATL::CAtlList<STATICHANDLER> STATIC_HANDLER_LIST;
161  typedef std::vector<STATICHANDLER> STATIC_HANDLER_LIST;
162  //typedef ATL::CAutoPtr<IEventFunctor> FUNCTOR_AUTOPTR;
163 
164  CLASS_HANDLER_MAP m_ClassSubscribers;
165  STATIC_HANDLER_LIST m_StaticSubscribers;
166 
167  /// <Summary>
168  /// Events can be Invoked only through CEventSource::RaiseEvent()
169  /// </Summary>
170  void Invoke(TEventSource* pSender, TEventHandlerArgs* pArgs)
171  {
172  // Invoke operator() on each of the CClassFunctor Objects
173  typedef typename CLASS_HANDLER_MAP::value_type ClassSubIterT;
174  std::for_each(m_ClassSubscribers.begin(), m_ClassSubscribers.end(), [&](ClassSubIterT& iter)
175  {
176  (*iter.second)(iter.first, (CEventSource*)pSender, (CEventHandlerArgs*)pArgs);
177  });
178 
179  // Invoke operator() on each of the function pointer Objects
180  typedef typename STATIC_HANDLER_LIST::value_type StaticSubIterT;
181  std::for_each(m_StaticSubscribers.begin(), m_StaticSubscribers.end(), [&](StaticSubIterT& iter)
182  {
183  (*iter)(pSender, pArgs);
184  });
185  }
186 
187  /// <Summary>
188  /// Takes ownership of the supplied IEventFunctor pointer.
189  /// Assumes that it is allocated with new, and calls delete
190  /// automatically upon it when going out of scope.
191  /// Duplicate or Multiple Subscriptions are not allowed.
192  /// If the Receiver object already has a subscription for this event,
193  /// the old subscription is removed before adding the new subcription.
194  /// </Summary>
195  template<typename TReceiverClass>
196  inline void Subscribe(TReceiverClass* pReceiver, IEventFunctorPtr spFunctor)
197  {
198  assert(pReceiver != NULL && spFunctor.get() != NULL);
199 
200  m_ClassSubscribers[pReceiver] = spFunctor;
201  }
202 
203  friend class CEventSource;
204 
205  CEventT& operator = (const CEventT& ); // Prohibit Assignment
206 
207  CEventT(const CEventT& ); // Prohibit Copy Constructor
208 
209  public:
210  inline CEventT() { }
211 
212  inline ~CEventT() { }
213 
214 
215  /// <Summary>
216  /// Creates an IEventFunctor object for the given function and
217  /// subcribes it to be called upon the given object whenever the event
218  /// is raised.
219  /// Duplicates or Multiple Subscriptions are not allowed.
220  /// If the Receiver object already has a subscription for this event,
221  /// the old subscription is removed before adding the new subcription.
222  /// </Summary>
223  template<typename TEventReceiver>
224  inline void Subscribe(TEventReceiver* pReceiver, void (TEventReceiver::*lpfnHandler)(TEventSource*, TEventHandlerArgs* ))
225  {
226  assert(pReceiver != NULL);
227 
228  Subscribe(pReceiver, IEventFunctorPtr(new CClassFunctor<TEventReceiver>(lpfnHandler)));
229  }
230 
231  /// <Summary>
232  /// Subscribes the given Function to be called whenever the event is raised.
233  /// Duplicates are not Allowed.
234  /// If the given Function is already a subscriber, it would not be added again.
235  /// </Summary>
236  inline void Subscribe(void (*lpfnHandler)(TEventSource*, TEventHandlerArgs*))
237  {
238  assert(NULL != lpfnHandler);
239 
240  if(m_StaticSubscribers.end() == std::find(m_StaticSubscribers.cbegin(), m_StaticSubscribers.cend(), lpfnHandler)) // Do not Add if Already Exists
241  m_StaticSubscribers.push_back( lpfnHandler );
242  }
243 
244  /// <Summary>
245  /// UnSubscribes the given Function from being called.
246  /// Nothing Happens if the given Function is not a Subscriber.
247  /// </Summary>
248  inline void UnSubscribe(void (*lpfnHandler)(TEventSource*, TEventHandlerArgs*))
249  {
250  typename STATIC_HANDLER_LIST::const_iterator iter = std::find(m_StaticSubscribers.cbegin(), m_StaticSubscribers.cend(), lpfnHandler);
251 
252  if(iter != m_StaticSubscribers.end())
253  m_StaticSubscribers.erase(iter);
254  }
255 
256  /// <Summary>
257  /// UnSubscribes the pReceiver from the Subscription.
258  /// Nothing Happens if the supplied pReceiver object is not a Subscriber.
259  /// </Summary>
260  template<typename TReceiverClass>
261  inline void UnSubscribe(TReceiverClass* pReceiver)
262  {
263  m_ClassSubscribers.erase(pReceiver);
264  }
265 
266  /// <Summary>
267  /// UnSubscribes all receivers. SubscriberCount() would become Zero.
268  /// </Summary>
269  inline void UnSubscribeAll()
270  {
271  // Remove Static Subscribers
272  m_StaticSubscribers.clear();
273  // Remove Class-based Subscribers
274  m_ClassSubscribers.clear();
275  }
276 
277  /// <Summary>
278  /// Gives the number of active Subcriptions for this event.
279  /// It includes the Class-based Subscriptions as well the Function-based ones.
280  /// </Summary>
281  inline size_t SubscriberCount() const
282  {
283  return m_ClassSubscribers.size() + m_StaticSubscribers.size();
284  }
285  };
286 
287  ///<Summary>
288  /// Default form of CEventT that uses
289  /// <code>void EventReceptionFunc(const CEventSource* pSrc, CEventHandlerArgs* pArgs)</code>
290  /// as the Event handler procedure
291  ///</Summary>
292  typedef CEventT<> CEvent;
293 
294  /// <Summary>
295  /// Only CEventSource derived classes can raise events.
296  /// So to raise events from your class, declare CEventT
297  /// variables in your class and derive it from CEventSource. Use
298  /// CEventSource::RaiseEvent() method when required to raise
299  /// the event.
300  ///
301  /// <para>See CEventT for sample usage.</para>
302  ///
303  /// If you want to use events outside classes, then use the CInvokableEventT class.
304  /// </Summary>
306  {
307  protected:
308  // CEventSource objects cannot be created directly due to the protected constructor.
309  // This class can Only be Inherited.
310  CEventSource() {}
311 
312  // Protected destructor.
313  // No need to declare as virtual because delete can not be applied on CEventSource pointers.
314  ~CEventSource() { }
315 
316  /// <Summary>
317  /// Invokes the Event.
318  /// </Summary>
319  template<typename TEventSource, typename TEventHandlerArgs>
320  inline void RaiseEvent(CEventT<TEventSource, TEventHandlerArgs>* pEvent, TEventHandlerArgs* pArgs)
321  {
322  assert(pEvent != NULL);
323 
324  pEvent->Invoke((TEventSource *)this, (TEventHandlerArgs *)pArgs);
325  }
326 
327  /// <Summary>
328  /// Invokes the Event.
329  /// </Summary>
330  template<typename TEventSource, typename TEventHandlerArgs>
331  inline void RaiseEvent(CEventT<TEventSource, const TEventHandlerArgs>* pEvent, const TEventHandlerArgs* pArgs)
332  {
333  assert(pEvent != NULL);
334 
335  pEvent->Invoke((TEventSource *)this, (const TEventHandlerArgs *)pArgs);
336  }
337 
338  };
339 
340  /// <Summary>
341  /// An event that can be invoked by itself.
342  ///
343  /// A CEventT event can only be used from within a class. To use events
344  /// outside classes, you need to use CInvokableEventT.
345  ///
346  /// Just declare the variable of CInvokableEventT anywhere in your code,
347  /// and use its RaiseEvent() method to invoke it.
348  ///
349  /// Use its subscribe() methods to subscribe either static metods or
350  /// class based methods.
351  ///
352  /// Note that in this case the EventSource is same as the event object
353  /// itself, which means the handler prototype will be always of the form
354  /// <code> void EventHandlerProc(const CEventSource* pSender, T* pArgs) </code>
355  /// where T is the template argument passed while declaring the CInvokableEventT variable.
356  /// </Summary>
357  /// Following Snippet demonstrates sample usage.
358  /** <code><pre>
359  struct MyEventHandlerArgs : public CEventHandlerArgs
360  {
361  int m_nVal;
362  };
363 
364  CInvokableEventT <MyEventHandlerArgs> Event;
365 
366  class MyPseudoClass
367  {
368  public:
369  MyPseudoClass()
370  {
371  Event.RaiseEvent(&MyEventHandlerArgs());
372  }
373  };
374 
375  void EventHandlerProc(const CEventSource* pSender, MyEventHandlerArgs* pArgs)
376  {
377  printf("\nEvent Received");
378  }
379 
380  class MyListener : public CEventReceiver
381  {
382  public:
383  void EventHandlerProc(const CEventSource* pSender, MyEventHandlerArgs* pArgs)
384  {
385  printf("\nListener Received the Event");
386  }
387  };
388 
389  int _tmain(int argc, _TCHAR* argv[])
390  {
391  Event.Subscribe(&EventHandlerProc); // Subscribe a non-class method
392 
393  MyListener listener;
394  Event.Subscribe(&listener, &MyListener::EventHandlerProc); // Subscribe a class method
395 
396  MyPseudoClass Obj; // Raise the Event in the constructor
397 
398  Event.RaiseEvent(&MyEventHandlerArgs()); // Event can be raised explicitly with from anywhere !!
399 
400  return 0;
401  }
402  </pre></code>*/
403  template<typename TEventHandlerArgs = CEventHandlerArgs>
404  class CInvokableEventT : protected CEventSource, public CEventT<const CEventSource, TEventHandlerArgs>
405  {
406  public:
407  inline void RaiseEvent(TEventHandlerArgs* pArgs)
408  {
409  CEventSource::RaiseEvent(this, pArgs);
410  }
411  };
412 
413  ///<Summary>
414  /// Default form of CInvokableEventT that uses
415  /// <code>void EventReceptionFunc(const CEventSource* pSrc, CEventHandlerArgs* pArgs)</code>
416  /// as the Event handler procedure
417  ///</Summary>
419 
420 } // namespace OIL
421 
422 #endif // __EVENTHANDLER_H_105D52D8_13EC_4ea3_A86B_076B726541EB_
void UnSubscribe(void(*lpfnHandler)(TEventSource *, TEventHandlerArgs *))
Definition: EventHandler.h:248
void RaiseEvent(CEventT< TEventSource, const TEventHandlerArgs > *pEvent, const TEventHandlerArgs *pArgs)
Definition: EventHandler.h:331
void UnSubscribeAll()
Definition: EventHandler.h:269
void Subscribe(void(*lpfnHandler)(TEventSource *, TEventHandlerArgs *))
Definition: EventHandler.h:236
size_t SubscriberCount() const
Definition: EventHandler.h:281
void Subscribe(TEventReceiver *pReceiver, void(TEventReceiver::*lpfnHandler)(TEventSource *, TEventHandlerArgs *))
Definition: EventHandler.h:224
void UnSubscribe(TReceiverClass *pReceiver)
Definition: EventHandler.h:261
void RaiseEvent(CEventT< TEventSource, TEventHandlerArgs > *pEvent, TEventHandlerArgs *pArgs)
Definition: EventHandler.h:320

CFugue, the C++ Music Programming Library © Copyright 2009 Cenacle Research India Private Limited Gopalakrishna Palem