fork(4) download
  1. #include <iostream>
  2. #include <vector>
  3.  
  4. class BaseReceiever
  5. {
  6. protected:
  7.  
  8. static size_t nextId;
  9. };
  10.  
  11. size_t BaseReceiever::nextId = 0;
  12.  
  13. // if you inherit from this class,
  14. // you are required to implement
  15. // void recieve(const TEventData& eventData)
  16. // where TEventData is an Event (see further down)
  17. template <typename TEventData>
  18. class Receiver
  19. : public BaseReceiever
  20. {
  21. public:
  22.  
  23. virtual void receive(const TEventData&) = 0;
  24.  
  25. static size_t GetId()
  26. { return _id; }
  27.  
  28. private:
  29.  
  30. // used for internal storage
  31. // identification
  32. static size_t _id;
  33. };
  34.  
  35. template<typename T>
  36. size_t Receiver<T>::_id = BaseReceiever::nextId++;
  37.  
  38. struct BaseEvent
  39. {
  40. protected:
  41.  
  42. static size_t nextId;
  43. };
  44.  
  45. size_t BaseEvent::nextId = 0;
  46.  
  47. template <typename T>
  48. struct Event
  49. : public BaseEvent
  50. {
  51. static size_t GetId()
  52. { return _id; }
  53.  
  54. private:
  55.  
  56. static size_t _id;
  57. };
  58.  
  59. template <typename T>
  60. size_t Event<T>::_id = BaseEvent::nextId++;
  61.  
  62. class EventHandler
  63. {
  64. // note:
  65. // could use one vector for better performance
  66. // but I doubt it's noticeable
  67.  
  68. typedef std::vector<BaseReceiever*> ReceiverArray;
  69. typedef std::vector<ReceiverArray> ImplSubscriberArray;
  70.  
  71. public:
  72.  
  73. template <typename TEvent>
  74. void emit(const TEvent& event)
  75. {
  76. ReceiverArray& receivers = _subscribers[TEvent::GetId()];
  77. for(ReceiverArray::iterator i = receivers.begin(); i != receivers.end(); ++i)
  78. {
  79. static_cast<Receiver<TEvent>&>(*(*i)).receive(event);
  80. }
  81. }
  82.  
  83. template <typename TEvent, typename TReciever>
  84. void subscribe(TReciever* receiver)
  85. {
  86. size_t eventId = TEvent::GetId();
  87. size_t receiverId = TReciever::GetId();
  88.  
  89. if(_subscribers.size() <= eventId)
  90. {
  91. _subscribers.resize(eventId + 1);
  92. }
  93.  
  94. ReceiverArray& receivers = _subscribers[eventId];
  95.  
  96. if(receivers.size() <= receiverId)
  97. {
  98. receivers.resize(receiverId + 1);
  99. }
  100.  
  101. receivers[receiverId] = receiver;
  102. }
  103.  
  104. template <typename TEvent, typename TReciever>
  105. void unsubscribe(TReciever* reciever)
  106. {
  107. _subscribers[TEvent::GetId()][TReciever::GetId()] = NULL;
  108. }
  109.  
  110. private:
  111.  
  112. ImplSubscriberArray _subscribers;
  113. };
  114.  
  115.  
  116. // collision event information
  117. struct Collision
  118. : Event<Collision>
  119. {
  120. typedef int Entity; // (for this examples sake)
  121.  
  122. Collision(Entity E1, Entity E2)
  123. : e1(E1),
  124. e2(E2)
  125. {
  126. }
  127.  
  128. Entity e1;
  129. Entity e2;
  130. };
  131.  
  132. class MyReciever
  133. : public Receiver<Collision>
  134. {
  135. public:
  136.  
  137. virtual void receive(const Collision& collision) /*override*/
  138. {
  139. std::cout << "Collision event occured with " << collision.e1 << " and " << collision.e2 << '\n';
  140. }
  141. };
  142.  
  143. int main(int argc, const char * argv[])
  144. {
  145. MyReciever collisionReciever;
  146. EventHandler handler;
  147.  
  148. // subscribe the reciever for events that fire Collision data
  149. handler.subscribe<Collision>(&collisionReciever);
  150.  
  151. // make a collision object to send
  152. Collision collision(5, 4);
  153.  
  154. // emit the event
  155. handler.emit(collision);
  156.  
  157. return 0;
  158. }
Success #stdin #stdout 0.01s 2860KB
stdin
Standard input is empty
stdout
Collision event occured with 5 and 4