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>
49 Auto, ///< If calling thread is the same as receiver's use
50 ///< direct call, otherwise call is queued
52 Queued, ///< Call is always queued
54 Blocking, ///< If calling thread is the same as receiver's use
55 ///< direct call, otherwise call is queued and blocking
57 Deffered ///< Call is always queued for a period of time
59 } // namespace EmitMode
61 template<typename EventType>
66 typedef EventSupport<EventType> EventSupportType;
68 typedef EventListener<EventType> EventListenerType;
69 typedef FastDelegate1<const EventType &> DelegateType;
71 class EventSupportData; // Forward declaration
72 typedef EventSupportData *EventSupportDataPtr;
75 typedef typename GenericEventCall<EventType, EventSupportDataPtr>::
76 template Rebind<EventType, EventSupportDataPtr>::
77 Other GenericEventCallType;
79 // Event listener list
80 typedef std::map<EventListenerType *, Thread *> EventListenerList;
81 EventListenerList m_eventListenerList;
84 typedef std::map<DelegateType, Thread *> DelegateList;
85 DelegateList m_delegateList;
87 // Event support operation mutex
88 Mutex m_listenerDelegateMutex;
90 // Dedicated instance of thread event dispatcher
91 ThreadEventDispatcher m_threadEventDispatcher;
93 // Guard destruction of event support in event handler
94 Atomic m_guardedCallInProgress;
96 // Events created by this support
97 typedef std::list<GenericEventCallType *> EventCallList;
98 EventCallList m_eventsList;
101 Mutex m_eventListMutex;
104 class EventSupportData
107 typedef void (EventSupportType::*ReceiveAbstractEventCallMethod)(
108 const EventType &event,
109 EventListenerType *eventListener,
110 DelegateType delegate,
111 WaitableEvent *synchronization);
113 EventSupportType *m_eventSupport;
114 ReceiveAbstractEventCallMethod m_method;
115 typename EventCallList::iterator m_iterator;
117 //TODO: Add dispatcher iterator to remove events from
118 // framework/thread's event queue
119 WaitableEvent *m_synchronization;
124 EventSupportData(EventSupportType *support,
125 ReceiveAbstractEventCallMethod method,
126 WaitableEvent *synchronization) :
127 m_eventSupport(support),
129 m_synchronization(synchronization)
134 Mutex::ScopedLock lock(&m_dataMutex);
136 if (!m_eventSupport) {
137 LogPedantic("EventSupport for this call does not exist");
141 m_eventSupport->RemoveEventCall(m_iterator);
144 // TODO: Make private and make EventSupport friend
145 void SetIterator(typename EventCallList::iterator iter)
150 // This method at the end destroys this as it will not be used anymore
151 void CallAndDestroy(const EventType &event,
152 EventListenerType *listener,
153 DelegateType delegate)
156 Mutex::ScopedLock lock(&m_dataMutex);
158 if (m_eventSupport != NULL) {
159 (*m_eventSupport.*m_method)(event,
164 LogPedantic("EventSupport for this call does not "
165 "exist anymore. Ignored.");
168 // releasing mutex lock
171 // EventSupportData object is no more used.
172 // It can be safely destroyed now.
178 LogPedantic("Reseting my EventSupport");
180 Mutex::ScopedLock lock(&m_dataMutex);
181 m_eventSupport = NULL;
186 GenericEventCallType *RegisterEventCall(const EventType &event,
187 EventListenerType *eventListener,
188 DelegateType delegate,
189 WaitableEvent *waitableEvent)
191 LogPedantic("Create and Register EventCall in EventSupport");
193 Mutex::ScopedLock lock(&m_eventListMutex);
195 EventSupportDataPtr supportData =
196 new EventSupportData(
198 &EventSupportType::ReceiveAbstractEventCall,
201 GenericEventCallType *eventCall =
202 new GenericEventCallType(supportData, eventListener,
205 typename EventCallList::iterator eventCallIter =
206 m_eventsList.insert(m_eventsList.end(), eventCall);
208 supportData->SetIterator(eventCallIter);
213 void RemoveEventCall(typename EventCallList::iterator eventIterator)
215 Mutex::ScopedLock lock(&m_eventListMutex);
217 LogPedantic("Removing event call from EventSupport");
219 m_eventsList.erase(eventIterator);
222 // Note: Reentrant metod
223 void GuardedEventCall(const EventType &event,
224 EventListenerType *eventListener)
226 LogPedantic("Guarded event listener call...");
228 ++m_guardedCallInProgress;
230 UNHANDLED_EXCEPTION_HANDLER_BEGIN
232 eventListener->OnEventReceived(event);
234 UNHANDLED_EXCEPTION_HANDLER_END
236 -- m_guardedCallInProgress;
238 LogPedantic("Guarded event listener finished");
241 // Note: Reentrant metod
242 void GuardedEventCall(const EventType &event,
243 DelegateType delegate)
245 LogPedantic("Guarded delegate call...");
247 ++m_guardedCallInProgress;
249 UNHANDLED_EXCEPTION_HANDLER_BEGIN
253 UNHANDLED_EXCEPTION_HANDLER_END
255 -- m_guardedCallInProgress;
257 LogPedantic("Guarded delegate call finished");
260 void ReceiveAbstractEventCall(const EventType &event,
261 EventListenerType *eventListener,
262 DelegateType delegate,
263 WaitableEvent *synchronization)
265 LogPedantic("Received abstract event call method");
267 Thread *targetThread;
269 // Listener might have been removed, ensure that it still exits
270 if (eventListener != NULL) {
271 Mutex::ScopedLock lock(&m_listenerDelegateMutex);
273 typename EventListenerList::iterator iterator =
274 m_eventListenerList.find(eventListener);
276 if (iterator == m_eventListenerList.end()) {
277 LogPedantic("Abstract event call listener disappeared."
280 // Even though, synchronize caller if needed
281 if (synchronization != NULL) {
282 synchronization->Signal();
288 // Get target thread id
289 targetThread = iterator->second;
291 // Delegate might have been removed, ensure that it still exits
292 Mutex::ScopedLock lock(&m_listenerDelegateMutex);
294 typename DelegateList::iterator iterator =
295 m_delegateList.find(delegate);
297 if (iterator == m_delegateList.end()) {
298 LogPedantic("Abstract event call delegate disappeared."
301 // Even though, synchronize caller if needed
302 if (synchronization != NULL) {
303 synchronization->Signal();
309 // Get target thread id
310 targetThread = iterator->second;
313 // Ensure that we are now in proper thread now
314 if (targetThread != Thread::GetCurrentThread()) {
315 LogPedantic("Detected event dispatching ping-pong scenario");
317 // Retry if it was not synchronized
318 if (synchronization == NULL) {
319 // Cheat with event delivery
320 EmitEvent(event, EmitMode::Queued);
322 LogPedantic("Ping-Pong: Resent as queued event");
324 // There is a problem
325 // Developer did something nasty, and we will not clean up his
327 synchronization->Signal();
329 LogPedantic("### Ping-Pong: Failed to deliver synchronized"
330 "event in ping-pong scenario!");
336 // Guard listener code for exceptions
337 if (eventListener != NULL) {
338 GuardedEventCall(event, eventListener);
340 GuardedEventCall(event, delegate);
343 // Release caller if synchronizing
344 if (synchronization != NULL) {
345 synchronization->Signal();
350 void EmitEvent(const EventType &event,
351 EmitMode::Type mode = EmitMode::Queued,
352 double dueTime = 0.0)
354 // Emit event, and retrieve later in current context to dispatch
355 std::unique_ptr<Mutex::ScopedLock> lock(
356 new Mutex::ScopedLock(&m_listenerDelegateMutex));
361 LogPedantic("Emitting AUTO event...");
364 case EmitMode::Queued:
365 LogPedantic("Emitting QUEUED event...");
368 case EmitMode::Blocking:
369 LogPedantic("Emitting BLOCKING event...");
372 case EmitMode::Deffered:
373 LogPedantic("Emitting DEFFERED event...");
380 // In some configurations there is a barrier
381 std::vector<WaitableEvent *> synchronizationBarrier;
383 // Emit to all listeners
384 FOREACH(iterator, m_eventListenerList)
386 // Switch to proper dispatcher and emit event
387 AbstractEventDispatcher *dispatcher = NULL;
389 if (iterator->second == NULL) {
390 // Send to main thread
391 LogPedantic("Sending event to main dispatcher");
392 dispatcher = &GetMainEventDispatcherInstance();
394 // Setup thread dispatcher, and send to proper thread
395 LogPedantic("Sending event to thread dispatcher");
396 m_threadEventDispatcher.SetThread(iterator->second);
397 dispatcher = &m_threadEventDispatcher;
400 // Dispatch event to abstract dispatcher
401 WaitableEvent *synchronization;
403 // TODO: Pool synchronization objects
407 if (iterator->second == Thread::GetCurrentThread()) {
408 // Guard listener code for exceptions
409 GuardedEventCall(event, iterator->first);
411 // Handle non-synchronized event
412 dispatcher->AddEventCall(
413 RegisterEventCall(event, iterator->first,
414 DelegateType(), NULL));
418 case EmitMode::Queued:
419 // Handle non-synchronized event
420 dispatcher->AddEventCall(
421 RegisterEventCall(event, iterator->first,
422 DelegateType(), NULL));
426 case EmitMode::Blocking:
428 if (iterator->second == Thread::GetCurrentThread()) {
429 // Guard listener code for exceptions
430 GuardedEventCall(event, iterator->first);
432 // New synchronization object is needed
433 synchronization = new WaitableEvent();
435 // Handle synchronized event
436 dispatcher->AddEventCall(
437 RegisterEventCall(event, iterator->first,
438 DelegateType(), synchronization));
441 synchronizationBarrier.push_back(synchronization);
445 case EmitMode::Deffered:
446 // Handle deffered events
447 Assert(dueTime >= 0.0 && "Due time must be non-negative");
449 dispatcher->AddTimedEventCall(
450 RegisterEventCall(event, iterator->first,
451 DelegateType(), NULL), dueTime);
456 Assert("Invalid emit mode");
460 LogPedantic("Added event to dispatchers");
462 // Emit to all delegates
463 FOREACH(iterator, m_delegateList)
465 // Switch to proper dispatcher and emit event
466 AbstractEventDispatcher *dispatcher = NULL;
468 if (iterator->second == NULL) {
469 // Send to main thread
470 LogPedantic("Sending event to main dispatcher");
471 dispatcher = &GetMainEventDispatcherInstance();
473 // Setup thread dispatcher, and send to proper thread
474 LogPedantic("Sending event to thread dispatcher");
475 m_threadEventDispatcher.SetThread(iterator->second);
476 dispatcher = &m_threadEventDispatcher;
479 // Dispatch event to abstract dispatcher
480 WaitableEvent *synchronization;
482 // TODO: Pool synchronization objects
486 if (iterator->second == Thread::GetCurrentThread()) {
487 // Guard listener code for exceptions
488 GuardedEventCall(event, iterator->first);
490 // Handle non-synchronized event
491 dispatcher->AddEventCall(
492 RegisterEventCall(event,
499 case EmitMode::Queued:
500 // Handle non-synchronized event
501 dispatcher->AddEventCall(
502 RegisterEventCall(event,
509 case EmitMode::Blocking:
511 if (iterator->second == Thread::GetCurrentThread()) {
512 // Guard listener code for exceptions
513 GuardedEventCall(event, iterator->first);
515 // New synchronization object is needed
516 synchronization = new WaitableEvent();
518 // Handle synchronized event
519 dispatcher->AddEventCall(
520 RegisterEventCall(event,
526 synchronizationBarrier.push_back(synchronization);
530 case EmitMode::Deffered:
531 // Handle deffered events
532 Assert(dueTime >= 0.0 && "Due time must be non-negative");
534 dispatcher->AddTimedEventCall(
535 RegisterEventCall(event,
543 Assert("Invalid emit mode");
547 LogPedantic("Added event to dispatchers");
549 // Leave listeners lock in case of blocking call
550 if (!synchronizationBarrier.empty()) {
551 LogPedantic("Leaving lock due to existing barrier");
555 LogPedantic("Size of barrier: " << synchronizationBarrier.size());
557 // Synchronize with barrier
558 // TODO: Implement generic WaitForAllMultipleHandles call
559 while (!synchronizationBarrier.empty()) {
560 // Get barrier waitable handles
561 WaitableHandleList barrierHandles;
563 FOREACH(iterator, synchronizationBarrier)
564 barrierHandles.push_back((*iterator)->GetHandle());
567 WaitableHandleIndexList indexList =
568 WaitForMultipleHandles(barrierHandles);
570 // Remove all awaited handles
571 // TODO: Return handles to pool
572 FOREACH(iterator, indexList)
575 delete synchronizationBarrier[*iterator];
578 synchronizationBarrier[*iterator] = NULL;
582 std::vector<WaitableEvent *> clearedSynchronizationBarrier;
584 FOREACH(iterator, synchronizationBarrier)
586 if (*iterator == NULL) {
590 clearedSynchronizationBarrier.push_back(*iterator);
593 synchronizationBarrier.swap(clearedSynchronizationBarrier);
595 LogPedantic("Reduced size of barrier: "
596 << synchronizationBarrier.size());
599 LogPedantic("Event emitted");
604 m_guardedCallInProgress(false)
607 virtual ~EventSupport()
609 Assert(m_guardedCallInProgress == false);
611 m_eventListenerList.clear();
612 m_delegateList.clear();
614 Mutex::ScopedLock lock(&m_eventListMutex);
616 LogPedantic("Disabling events for EventSupport");
618 FOREACH(iterator, m_eventsList)
619 (*iterator)->DisableEvent();
622 void AddListener(EventListenerType *eventListener)
624 Mutex::ScopedLock lock(&m_listenerDelegateMutex);
626 // Listener must not be NULL
627 Assert(eventListener != NULL);
629 // Listener must not already exists
630 Assert(m_eventListenerList.find(eventListener)
631 == m_eventListenerList.end());
633 // Add new listener, inherit dispatcher from current context
634 m_eventListenerList.insert(
635 std::make_pair(eventListener, Thread::GetCurrentThread()));
638 LogPedantic("Listener registered");
641 void AddListener(DelegateType delegate)
643 Mutex::ScopedLock lock(&m_listenerDelegateMutex);
645 // Delegate must not be empty
646 Assert(!delegate.empty());
648 // Delegate must not already exists
649 Assert(m_delegateList.find(delegate) == m_delegateList.end());
651 // Add new delegate, inherit dispatcher from current context
652 m_delegateList.insert(
653 std::make_pair(delegate, Thread::GetCurrentThread()));
656 LogPedantic("Delegate registered");
659 void RemoveListener(EventListenerType *eventListener)
661 Mutex::ScopedLock lock(&m_listenerDelegateMutex);
663 // Listener must not be NULL
664 Assert(eventListener != NULL);
666 // Listener must exist
667 typename EventListenerList::iterator iterator =
668 m_eventListenerList.find(eventListener);
670 Assert(iterator != m_eventListenerList.end());
672 // Remove listener from list
673 m_eventListenerList.erase(iterator);
674 LogPedantic("Listener unregistered");
677 void RemoveListener(DelegateType delegate)
679 Mutex::ScopedLock lock(&m_listenerDelegateMutex);
681 // Delegate must not be empty
682 Assert(!delegate.empty());
684 // Delegate must exist
685 typename DelegateList::iterator iterator =
686 m_delegateList.find(delegate);
688 Assert(iterator != m_delegateList.end());
690 // Remove delegate from list
691 m_delegateList.erase(iterator);
692 LogPedantic("Delegate unregistered");
695 void SwitchListenerToThread(EventListenerType *eventListener,
698 Mutex::ScopedLock lock(&m_listenerDelegateMutex);
700 // Listener must not be NULL
701 Assert(eventListener != NULL);
703 // Listener must exist
704 typename EventListenerList::iterator iterator =
705 m_eventListenerList.find(eventListener);
707 Assert(iterator != m_eventListenerList.end());
709 // Set listener thread
710 iterator->second = thread;
712 LogPedantic("Listener switched");
715 void SwitchListenerToThread(DelegateType delegate,
718 Mutex::ScopedLock lock(&m_listenerDelegateMutex);
720 // Delegate must not be empty
721 Assert(!delegate.empty());
723 // Delegate must exist
724 typename EventListenerList::iterator iterator =
725 m_delegateList.find(delegate);
727 Assert(iterator != m_delegateList.end());
729 // Set delegate thread
730 iterator->second = thread;
732 LogPedantic("Delegate switched");
735 void SwitchAllListenersToThread(Thread *thread)
737 Mutex::ScopedLock lock(&m_listenerDelegateMutex);
739 // Switch all listeners and delegates
740 FOREACH(iterator, m_eventListenerList)
741 iterator->second = thread;
743 FOREACH(iterator, m_delegateList)
744 iterator->second = thread;
746 LogPedantic("All listeners and delegates switched");
752 #endif // DPL_EVENT_SUPPORT_H