2 * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 * @file event_delivery.h
18 * @author Przemyslaw Dobrowolski (p.dobrowolsk@samsung.com)
20 * @brief This file is the header file of event delivery class
22 #ifndef DPL_EVENT_DELIVERY_H
23 #define DPL_EVENT_DELIVERY_H
25 #include <dpl/event/event_delivery_detail.h>
26 #include <dpl/event/event_delivery_messages.h>
27 #include <dpl/event/event_support.h>
28 #include <dpl/noncopyable.h>
29 #include <dpl/shared_ptr.h>
30 #include <dpl/exception.h>
31 #include <dpl/assert.h>
32 #include <dpl/foreach.h>
39 * Event delivery system
43 * I. Listening for standard predefined notifications
46 * : public EventListener<EventMessages::RoamingChanged>
48 * void OnEventReceived(const EventMessages::RoamingChanged& event)
50 * std::cout << "Roaming is now " << event.GetRoamingEnabled() ? "ENABLED" : "DISABLED" << std::endl;
56 * EventDeliverySystem::AddListener<EventMessages::RoamingChanged>(this);
61 * EventDeliverySystem::RemoveListener<EventMessages::RoamingChanged>(this);
64 * void SendSampleSignal()
66 * EventMessages::RoamingChanged roamingMessage(true);
67 * EventDeliverySystem::Publish(roamingMessage);
71 * II. Creation of custom generic events, and listening for them
73 * EVENT_DELIVERY_DECLARE_EVENT_MESSAGE_2(MyEvent, int, float);
76 * : public EventListener<MyEvent>
78 * void OnEventReceived(const MyEvent &event)
80 * std::cout << "Event contents: " << event.GetArg0() << ", " << event.GetArg1() << std::endl;
86 * EventDeliverySystem::AddListener<MyEvent>(this);
91 * EventDeliverySystem::RemoveListener<MyEvent>(this);
94 * void SendSampleSignal()
96 * MyEvent myEvent(5, 3.14f);
97 * EventDeliverySystem::Publish(myEvent);
101 * In source file, one must add implementation of event delivery message:
103 * EVENT_DELIVERY_IMPLEMENT_EVENT_MESSAGE(MyEvent)
111 class AbstractEventDeliverySystemPublisher
114 virtual ~AbstractEventDeliverySystemPublisher() = 0;
117 template<typename EventType>
118 class EventDeliverySystemPublisher
119 : private EventSupport<EventType>
120 , public AbstractEventDeliverySystemPublisher
123 typedef typename EventSupport<EventType>::EventListenerType EventListenerType;
126 friend class EventDeliverySystem;
128 EventDeliverySystemPublisher(EventListenerType *eventListener)
129 : m_eventListener(eventListener)
131 EventSupport<EventType>::AddListener(m_eventListener);
134 EventListenerType *m_eventListener;
137 ~EventDeliverySystemPublisher()
139 EventSupport<EventType>::RemoveListener(m_eventListener);
142 void PublishEvent(const EventType &event)
144 EmitEvent(event, EmitMode::Queued);
147 EventListenerType *GetListener() const
149 return m_eventListener;
153 template<typename Type>
154 class EventDeliverySystemTraits
157 typedef Type EventType;
158 typedef EventDeliverySystemPublisher<EventType> PublisherType;
159 typedef typename PublisherType::EventListenerType EventListenerType;
160 typedef SharedPtr<PublisherType> PublisherPtrType;
161 typedef std::list<PublisherPtrType> PublisherPtrContainerType;
164 class EventDeliverySystem
165 : private Noncopyable
168 typedef SharedPtr<AbstractEventDeliverySystemPublisher> AbstractPublisherPtrType;
169 typedef std::list<AbstractPublisherPtrType> AbstractPublisherPtrContainerType;
170 typedef AbstractPublisherPtrContainerType::const_iterator AbstractPublisherPtrContainerTypeConstIterator;
171 typedef AbstractPublisherPtrContainerType::iterator AbstractPublisherPtrContainerTypeIterator;
172 typedef std::map<std::string, AbstractPublisherPtrContainerType> AbstractPublisherPtrContainerMapType;
174 template<class EventType>
178 const AbstractPublisherPtrContainerType &m_publisherContainer;
181 CrtDeleteCheck(const AbstractPublisherPtrContainerType &publisherContainer)
182 : m_publisherContainer(publisherContainer)
186 virtual ~CrtDeleteCheck()
188 Assert(m_publisherContainer.empty() && "All event delivery listeners must be removed before exit!");
192 // Map containing publishers for all registered events
193 static AbstractPublisherPtrContainerMapType m_publishers;
195 // Detail implementation: lazy initialized
196 static EventDeliverySystemDetail m_detailSystem;
198 EventDeliverySystem()
202 template<typename EventType>
203 static AbstractPublisherPtrContainerType &GetPublisherContainerRef()
205 std::string typeId = typeid(EventType).name();
207 //FIXME: problem with linking per compilation unit won't hurt this check?
208 static CrtDeleteCheck<EventType> crtDeleteCheck(m_publishers[typeId]);
209 (void)crtDeleteCheck;
211 return m_publishers[typeId];
214 template<typename EventType>
215 static typename EventDeliverySystemTraits<EventType>::PublisherPtrContainerType GetPublisherContainer()
217 std::string typeId = typeid(EventType).name();
218 typedef typename EventDeliverySystemTraits<EventType>::PublisherPtrContainerType PublisherContainerType;
219 typedef typename EventDeliverySystemTraits<EventType>::PublisherType PublisherType;
220 typedef typename EventDeliverySystemTraits<EventType>::PublisherPtrType PublisherPtrType;
222 AbstractPublisherPtrContainerType eventPublishers = m_publishers[typeId];
223 PublisherContainerType publisherContainer;
225 FOREACH(iterator, eventPublishers)
227 PublisherPtrType publisher =
228 StaticPointerCast<PublisherType>(*iterator);
229 publisherContainer.push_back(publisher);
232 return publisherContainer;
236 template<typename EventType>
237 static void Inject(const EventType &event)
239 typedef typename EventDeliverySystemTraits<EventType>::PublisherPtrContainerType PublisherContainerType;
240 typedef typename EventDeliverySystemTraits<EventType>::PublisherPtrType PublisherPtrType;
242 PublisherContainerType publisherContainer = GetPublisherContainer<EventType>();
243 typename PublisherContainerType::iterator iterator;
245 for (iterator = publisherContainer.begin(); iterator != publisherContainer.end(); ++iterator)
247 PublisherPtrType &publisher = *iterator;
248 publisher->PublishEvent(event);
252 template<typename EventType>
253 class PublisherPtrContainerListenerPredicate
256 typedef EventListener<EventType> EventListenerType;
259 EventListenerType *m_listener;
262 PublisherPtrContainerListenerPredicate(EventListenerType *listener)
263 : m_listener(listener)
267 bool operator()(const AbstractPublisherPtrType &publisher) const
269 return StaticPointerCast<typename EventDeliverySystemTraits<EventType>::PublisherType>(publisher)->GetListener() == m_listener;
273 friend class EventDeliverySystemInjector;
276 virtual ~EventDeliverySystem()
280 template<typename EventType>
281 static void AddListener(EventListener<EventType> *listener)
283 typedef typename EventDeliverySystemTraits<EventType>::PublisherType PublisherType;
284 typedef typename EventDeliverySystemTraits<EventType>::PublisherPtrType PublisherPtrType;
285 typedef typename EventDeliverySystemTraits<EventType>::PublisherPtrContainerType PublisherPtrContainerType;
287 typedef PublisherPtrContainerListenerPredicate<EventType> PublisherPtrContainerListenerPredicateType;
289 AbstractPublisherPtrContainerType &publisherContainer = GetPublisherContainerRef<EventType>();
290 AbstractPublisherPtrContainerTypeConstIterator iterator =
291 std::find_if(publisherContainer.begin(), publisherContainer.end(), PublisherPtrContainerListenerPredicateType(listener));
293 Assert(iterator == publisherContainer.end() && "Listener already exists");
296 publisherContainer.push_back(AbstractPublisherPtrType(new PublisherType(listener)));
298 // When first listener is inserted, start to listen for events
299 if (publisherContainer.size() == 1) {
300 m_detailSystem.Listen(EventType());
304 template<typename EventType>
305 static void RemoveListener(EventListener<EventType> *listener)
307 typedef typename EventDeliverySystemTraits<EventType>::PublisherType PublisherType;
308 typedef typename EventDeliverySystemTraits<EventType>::PublisherPtrType PublisherPtrType;
309 typedef typename EventDeliverySystemTraits<EventType>::PublisherPtrContainerType PublisherPtrContainerType;
311 typedef PublisherPtrContainerListenerPredicate<EventType> PublisherPtrContainerListenerPredicateType;
313 AbstractPublisherPtrContainerType &publisherContainer = GetPublisherContainerRef<EventType>();
315 AbstractPublisherPtrContainerTypeIterator iterator =
316 std::find_if(publisherContainer.begin(), publisherContainer.end(), PublisherPtrContainerListenerPredicateType(listener));
318 Assert(iterator != publisherContainer.end() && "Listener does not exist");
321 publisherContainer.erase(iterator);
323 // When last listener was removed, stop to listen for events
324 if (publisherContainer.empty())
325 m_detailSystem.Unlisten(EventType());
328 template<typename EventType>
329 static void Publish(const EventType &event)
331 m_detailSystem.Publish(event);
338 #endif // DPL_EVENT_DELIVERY_H