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_support.h
18 * @author Przemyslaw Dobrowolski (p.dobrowolsk@samsung.com)
20 * @brief This file is the implementation file of MVC event support
22 #ifndef DPL_EVENT_SUPPORT_H
23 #define DPL_EVENT_SUPPORT_H
25 #include <dpl/event/event_listener.h>
26 #include <dpl/event/abstract_event_dispatcher.h>
27 #include <dpl/event/main_event_dispatcher.h>
28 #include <dpl/event/thread_event_dispatcher.h>
29 #include <dpl/event/generic_event_call.h>
30 #include <dpl/waitable_event.h>
31 #include <dpl/fast_delegate.h>
33 #include <dpl/exception.h>
34 #include <dpl/thread.h>
35 #include <dpl/assert.h>
36 #include <dpl/atomic.h>
37 #include <dpl/mutex.h>
38 #include <dpl/foreach.h>
39 #include <dpl/log/log.h>
52 Auto, ///< If calling thread is the same as receiver's use
53 ///< direct call, otherwise call is queued
55 Queued, ///< Call is always queued
57 Blocking, ///< If calling thread is the same as receiver's use
58 ///< direct call, otherwise call is queued and blocking
60 Deffered ///< Call is always queued for a period of time
62 } // namespace EmitMode
64 template<typename EventType>
69 typedef EventSupport<EventType> EventSupportType;
71 typedef EventListener<EventType> EventListenerType;
72 typedef FastDelegate1<const EventType &> DelegateType;
74 class EventSupportData; // Forward declaration
75 typedef EventSupportData *EventSupportDataPtr;
78 typedef typename GenericEventCall<EventType, EventSupportDataPtr>::
79 template Rebind<EventType, EventSupportDataPtr>::
80 Other GenericEventCallType;
82 // Event listener list
83 typedef std::map<EventListenerType *, Thread *> EventListenerList;
84 EventListenerList m_eventListenerList;
87 typedef std::map<DelegateType, Thread *> DelegateList;
88 DelegateList m_delegateList;
90 // Event support operation mutex
91 Mutex m_listenerDelegateMutex;
93 // Dedicated instance of thread event dispatcher
94 ThreadEventDispatcher m_threadEventDispatcher;
96 // Guard destruction of event support in event handler
97 Atomic m_guardedCallInProgress;
99 // Events created by this support
100 typedef std::list<GenericEventCallType *> EventCallList;
101 EventCallList m_eventsList;
104 Mutex m_eventListMutex;
107 class EventSupportData
110 typedef void (EventSupportType::*ReceiveAbstractEventCallMethod)(
111 const EventType &event,
112 EventListenerType *eventListener,
113 DelegateType delegate,
114 WaitableEvent *synchronization);
116 EventSupportType *m_eventSupport;
117 ReceiveAbstractEventCallMethod m_method;
118 typename EventCallList::iterator m_iterator;
120 //TODO: Add dispatcher iterator to remove events from
121 // framework/thread's event queue
122 WaitableEvent *m_synchronization;
127 EventSupportData(EventSupportType *support,
128 ReceiveAbstractEventCallMethod method,
129 WaitableEvent *synchronization)
130 : m_eventSupport(support),
132 m_synchronization(synchronization)
138 Mutex::ScopedLock lock(&m_dataMutex);
142 LogPedantic("EventSupport for this call does not exist");
146 m_eventSupport->RemoveEventCall(m_iterator);
149 // TODO: Make private and make EventSupport friend
150 void SetIterator(typename EventCallList::iterator iter)
155 // This method at the end destroys this as it will not be used anymore
156 void CallAndDestroy(const EventType &event,
157 EventListenerType *listener,
158 DelegateType delegate)
161 Mutex::ScopedLock lock(&m_dataMutex);
163 if (m_eventSupport != NULL)
165 (*m_eventSupport.*m_method)(event,
172 LogPedantic("EventSupport for this call does not "
173 "exist anymore. Ignored.");
176 // releasing mutex lock
179 // EventSupportData object is no more used.
180 // It can be safely destroyed now.
186 LogPedantic("Reseting my EventSupport");
188 Mutex::ScopedLock lock(&m_dataMutex);
189 m_eventSupport = NULL;
194 GenericEventCallType *RegisterEventCall(const EventType &event,
195 EventListenerType *eventListener,
196 DelegateType delegate,
197 WaitableEvent *waitableEvent)
199 LogPedantic("Create and Register EventCall in EventSupport");
201 Mutex::ScopedLock lock(&m_eventListMutex);
203 EventSupportDataPtr supportData =
204 new EventSupportData(
206 &EventSupportType::ReceiveAbstractEventCall,
209 GenericEventCallType *eventCall =
210 new GenericEventCallType(supportData, eventListener,
213 typename EventCallList::iterator eventCallIter =
214 m_eventsList.insert(m_eventsList.end(), eventCall);
216 supportData->SetIterator(eventCallIter);
221 void RemoveEventCall(typename EventCallList::iterator eventIterator)
223 Mutex::ScopedLock lock(&m_eventListMutex);
225 LogPedantic("Removing event call from EventSupport");
227 m_eventsList.erase(eventIterator);
230 // Note: Reentrant metod
231 void GuardedEventCall(const EventType &event,
232 EventListenerType *eventListener)
234 LogPedantic("Guarded event listener call...");
236 ++m_guardedCallInProgress;
238 UNHANDLED_EXCEPTION_HANDLER_BEGIN
240 eventListener->OnEventReceived(event);
242 UNHANDLED_EXCEPTION_HANDLER_END
244 --m_guardedCallInProgress;
246 LogPedantic("Guarded event listener finished");
249 // Note: Reentrant metod
250 void GuardedEventCall(const EventType &event,
251 DelegateType delegate)
253 LogPedantic("Guarded delegate call...");
255 ++m_guardedCallInProgress;
257 UNHANDLED_EXCEPTION_HANDLER_BEGIN
261 UNHANDLED_EXCEPTION_HANDLER_END
263 --m_guardedCallInProgress;
265 LogPedantic("Guarded delegate call finished");
268 void ReceiveAbstractEventCall(const EventType &event,
269 EventListenerType *eventListener,
270 DelegateType delegate,
271 WaitableEvent *synchronization)
273 LogPedantic("Received abstract event call method");
275 Thread *targetThread;
277 // Listener might have been removed, ensure that it still exits
278 if (eventListener != NULL)
280 Mutex::ScopedLock lock(&m_listenerDelegateMutex);
282 typename EventListenerList::iterator iterator =
283 m_eventListenerList.find(eventListener);
285 if (iterator == m_eventListenerList.end())
287 LogPedantic("Abstract event call listener disappeared."
290 // Even though, synchronize caller if needed
291 if (synchronization != NULL)
292 synchronization->Signal();
297 // Get target thread id
298 targetThread = iterator->second;
302 // Delegate might have been removed, ensure that it still exits
303 Mutex::ScopedLock lock(&m_listenerDelegateMutex);
305 typename DelegateList::iterator iterator =
306 m_delegateList.find(delegate);
308 if (iterator == m_delegateList.end())
310 LogPedantic("Abstract event call delegate disappeared."
313 // Even though, synchronize caller if needed
314 if (synchronization != NULL)
315 synchronization->Signal();
320 // Get target thread id
321 targetThread = iterator->second;
324 // Ensure that we are now in proper thread now
325 if (targetThread != Thread::GetCurrentThread())
327 LogPedantic("Detected event dispatching ping-pong scenario");
329 // Retry if it was not synchronized
330 if (synchronization == NULL)
332 // Cheat with event delivery
333 EmitEvent(event, EmitMode::Queued);
335 LogPedantic("Ping-Pong: Resent as queued event");
339 // There is a problem
340 // Developer did something nasty, and we will not clean up his mess
341 synchronization->Signal();
343 LogPedantic("### Ping-Pong: Failed to deliver synchronized"
344 "event in ping-pong scenario!");
350 // Guard listener code for exceptions
351 if (eventListener != NULL)
352 GuardedEventCall(event, eventListener);
354 GuardedEventCall(event, delegate);
356 // Release caller if synchronizing
357 if (synchronization != NULL)
358 synchronization->Signal();
362 void EmitEvent(const EventType &event,
363 EmitMode::Type mode = EmitMode::Queued,
364 double dueTime = 0.0)
366 // Emit event, and retrieve later in current context to dispatch
367 std::unique_ptr<Mutex::ScopedLock> lock(
368 new Mutex::ScopedLock(&m_listenerDelegateMutex));
374 LogPedantic("Emitting AUTO event...");
377 case EmitMode::Queued:
378 LogPedantic("Emitting QUEUED event...");
381 case EmitMode::Blocking:
382 LogPedantic("Emitting BLOCKING event...");
385 case EmitMode::Deffered:
386 LogPedantic("Emitting DEFFERED event...");
393 // In some configurations there is a barrier
394 std::vector<WaitableEvent *> synchronizationBarrier;
396 // Emit to all listeners
397 FOREACH(iterator, m_eventListenerList)
399 // Switch to proper dispatcher and emit event
400 AbstractEventDispatcher *dispatcher = NULL;
402 if (iterator->second == NULL)
404 // Send to main thread
405 LogPedantic("Sending event to main dispatcher");
406 dispatcher = &GetMainEventDispatcherInstance();
410 // Setup thread dispatcher, and send to proper thread
411 LogPedantic("Sending event to thread dispatcher");
412 m_threadEventDispatcher.SetThread(iterator->second);
413 dispatcher = &m_threadEventDispatcher;
416 // Dispatch event to abstract dispatcher
417 WaitableEvent *synchronization;
419 // TODO: Pool synchronization objects
424 if (iterator->second == Thread::GetCurrentThread())
426 // Guard listener code for exceptions
427 GuardedEventCall(event, iterator->first);
431 // Handle non-synchronized event
432 dispatcher->AddEventCall(
433 RegisterEventCall(event, iterator->first,
434 DelegateType(), NULL));
438 case EmitMode::Queued:
439 // Handle non-synchronized event
440 dispatcher->AddEventCall(
441 RegisterEventCall(event, iterator->first,
442 DelegateType(), NULL));
446 case EmitMode::Blocking:
448 if (iterator->second == Thread::GetCurrentThread())
450 // Guard listener code for exceptions
451 GuardedEventCall(event, iterator->first);
455 // New synchronization object is needed
456 synchronization = new WaitableEvent();
458 // Handle synchronized event
459 dispatcher->AddEventCall(
460 RegisterEventCall(event, iterator->first,
461 DelegateType(), synchronization));
464 synchronizationBarrier.push_back(synchronization);
468 case EmitMode::Deffered:
469 // Handle deffered events
470 Assert(dueTime >= 0.0 && "Due time must be non-negative");
472 dispatcher->AddTimedEventCall(
473 RegisterEventCall(event, iterator->first,
474 DelegateType(), NULL), dueTime);
479 Assert("Invalid emit mode");
483 LogPedantic("Added event to dispatchers");
485 // Emit to all delegates
486 FOREACH(iterator, m_delegateList)
488 // Switch to proper dispatcher and emit event
489 AbstractEventDispatcher *dispatcher = NULL;
491 if (iterator->second == NULL)
493 // Send to main thread
494 LogPedantic("Sending event to main dispatcher");
495 dispatcher = &GetMainEventDispatcherInstance();
499 // Setup thread dispatcher, and send to proper thread
500 LogPedantic("Sending event to thread dispatcher");
501 m_threadEventDispatcher.SetThread(iterator->second);
502 dispatcher = &m_threadEventDispatcher;
505 // Dispatch event to abstract dispatcher
506 WaitableEvent *synchronization;
508 // TODO: Pool synchronization objects
513 if (iterator->second == Thread::GetCurrentThread())
515 // Guard listener code for exceptions
516 GuardedEventCall(event, iterator->first);
520 // Handle non-synchronized event
521 dispatcher->AddEventCall(
522 RegisterEventCall(event,
529 case EmitMode::Queued:
530 // Handle non-synchronized event
531 dispatcher->AddEventCall(
532 RegisterEventCall(event,
539 case EmitMode::Blocking:
541 if (iterator->second == Thread::GetCurrentThread())
543 // Guard listener code for exceptions
544 GuardedEventCall(event, iterator->first);
548 // New synchronization object is needed
549 synchronization = new WaitableEvent();
551 // Handle synchronized event
552 dispatcher->AddEventCall(
553 RegisterEventCall(event,
559 synchronizationBarrier.push_back(synchronization);
563 case EmitMode::Deffered:
564 // Handle deffered events
565 Assert(dueTime >= 0.0 && "Due time must be non-negative");
567 dispatcher->AddTimedEventCall(
568 RegisterEventCall(event,
576 Assert("Invalid emit mode");
580 LogPedantic("Added event to dispatchers");
582 // Leave listeners lock in case of blocking call
583 if (!synchronizationBarrier.empty())
585 LogPedantic("Leaving lock due to existing barrier");
589 LogPedantic("Size of barrier: " << synchronizationBarrier.size());
591 // Synchronize with barrier
592 // TODO: Implement generic WaitForAllMultipleHandles call
593 while (!synchronizationBarrier.empty())
595 // Get barrier waitable handles
596 WaitableHandleList barrierHandles;
598 FOREACH(iterator, synchronizationBarrier)
599 barrierHandles.push_back((*iterator)->GetHandle());
602 WaitableHandleIndexList indexList =
603 WaitForMultipleHandles(barrierHandles);
605 // Remove all awaited handles
606 // TODO: Return handles to pool
607 FOREACH(iterator, indexList)
610 delete synchronizationBarrier[*iterator];
613 synchronizationBarrier[*iterator] = NULL;
617 std::vector<WaitableEvent *> clearedSynchronizationBarrier;
619 FOREACH(iterator, synchronizationBarrier)
621 if (*iterator == NULL)
624 clearedSynchronizationBarrier.push_back(*iterator);
627 synchronizationBarrier.swap(clearedSynchronizationBarrier);
629 LogPedantic("Reduced size of barrier: "
630 << synchronizationBarrier.size());
633 LogPedantic("Event emitted");
638 : m_guardedCallInProgress(false)
642 virtual ~EventSupport()
644 Assert(m_guardedCallInProgress == false);
646 m_eventListenerList.clear();
647 m_delegateList.clear();
649 Mutex::ScopedLock lock(&m_eventListMutex);
651 LogPedantic("Disabling events for EventSupport");
653 FOREACH(iterator, m_eventsList)
654 (*iterator)->DisableEvent();
657 void AddListener(EventListenerType *eventListener)
659 Mutex::ScopedLock lock(&m_listenerDelegateMutex);
661 // Listener must not be NULL
662 Assert(eventListener != NULL);
664 // Listener must not already exists
665 Assert(m_eventListenerList.find(eventListener)
666 == m_eventListenerList.end());
668 // Add new listener, inherit dispatcher from current context
669 m_eventListenerList.insert(
670 std::make_pair(eventListener, Thread::GetCurrentThread()));
673 LogPedantic("Listener registered");
676 void AddListener(DelegateType delegate)
678 Mutex::ScopedLock lock(&m_listenerDelegateMutex);
680 // Delegate must not be empty
681 Assert(!delegate.empty());
683 // Delegate must not already exists
684 Assert(m_delegateList.find(delegate) == m_delegateList.end());
686 // Add new delegate, inherit dispatcher from current context
687 m_delegateList.insert(
688 std::make_pair(delegate, Thread::GetCurrentThread()));
691 LogPedantic("Delegate registered");
694 void RemoveListener(EventListenerType *eventListener)
696 Mutex::ScopedLock lock(&m_listenerDelegateMutex);
698 // Listener must not be NULL
699 Assert(eventListener != NULL);
701 // Listener must exist
702 typename EventListenerList::iterator iterator =
703 m_eventListenerList.find(eventListener);
705 Assert(iterator != m_eventListenerList.end());
707 // Remove listener from list
708 m_eventListenerList.erase(iterator);
709 LogPedantic("Listener unregistered");
712 void RemoveListener(DelegateType delegate)
714 Mutex::ScopedLock lock(&m_listenerDelegateMutex);
716 // Delegate must not be empty
717 Assert(!delegate.empty());
719 // Delegate must exist
720 typename DelegateList::iterator iterator =
721 m_delegateList.find(delegate);
723 Assert(iterator != m_delegateList.end());
725 // Remove delegate from list
726 m_delegateList.erase(iterator);
727 LogPedantic("Delegate unregistered");
730 void SwitchListenerToThread(EventListenerType *eventListener,
733 Mutex::ScopedLock lock(&m_listenerDelegateMutex);
735 // Listener must not be NULL
736 Assert(eventListener != NULL);
738 // Listener must exist
739 typename EventListenerList::iterator iterator =
740 m_eventListenerList.find(eventListener);
742 Assert(iterator != m_eventListenerList.end());
744 // Set listener thread
745 iterator->second = thread;
747 LogPedantic("Listener switched");
750 void SwitchListenerToThread(DelegateType delegate,
753 Mutex::ScopedLock lock(&m_listenerDelegateMutex);
755 // Delegate must not be empty
756 Assert(!delegate.empty());
758 // Delegate must exist
759 typename EventListenerList::iterator iterator =
760 m_delegateList.find(delegate);
762 Assert(iterator != m_delegateList.end());
764 // Set delegate thread
765 iterator->second = thread;
767 LogPedantic("Delegate switched");
770 void SwitchAllListenersToThread(Thread *thread)
772 Mutex::ScopedLock lock(&m_listenerDelegateMutex);
774 // Switch all listeners and delegates
775 FOREACH(iterator, m_eventListenerList)
776 iterator->second = thread;
778 FOREACH(iterator, m_delegateList)
779 iterator->second = thread;
781 LogPedantic("All listeners and delegates switched");
788 #endif // DPL_EVENT_SUPPORT_H