Source code formating unification
[framework/web/wrt-commons.git] / modules / event / include / dpl / event / event_support.h
1 /*
2  * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
3  *
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
7  *
8  *        http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16 /*
17  * @file        event_support.h
18  * @author      Przemyslaw Dobrowolski (p.dobrowolsk@samsung.com)
19  * @version     1.0
20  * @brief       This file is the implementation file of MVC event support
21  */
22 #ifndef DPL_EVENT_SUPPORT_H
23 #define DPL_EVENT_SUPPORT_H
24
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>
32 #include <memory>
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>
40 #include <vector>
41 #include <map>
42 #include <list>
43
44 namespace DPL {
45 namespace Event {
46 namespace EmitMode {
47 enum Type
48 {
49     Auto,     ///< If calling thread is the same as receiver's use
50               ///< direct call, otherwise call is queued
51
52     Queued,   ///< Call is always queued
53
54     Blocking, ///< If calling thread is the same as receiver's use
55               ///< direct call, otherwise call is queued and blocking
56
57     Deffered  ///< Call is always queued for a period of time
58 };
59 } // namespace EmitMode
60
61 template<typename EventType>
62 class EventSupport :
63     private Noncopyable
64 {
65   public:
66     typedef EventSupport<EventType> EventSupportType;
67
68     typedef EventListener<EventType> EventListenerType;
69     typedef FastDelegate1<const EventType &> DelegateType;
70
71     class EventSupportData; // Forward declaration
72     typedef EventSupportData *EventSupportDataPtr;
73
74   private:
75     typedef typename GenericEventCall<EventType, EventSupportDataPtr>::
76         template Rebind<EventType, EventSupportDataPtr>::
77         Other GenericEventCallType;
78
79     // Event listener list
80     typedef std::map<EventListenerType *, Thread *> EventListenerList;
81     EventListenerList m_eventListenerList;
82
83     // Delegate list
84     typedef std::map<DelegateType, Thread *> DelegateList;
85     DelegateList m_delegateList;
86
87     // Event support operation mutex
88     Mutex m_listenerDelegateMutex;
89
90     // Dedicated instance of thread event dispatcher
91     ThreadEventDispatcher m_threadEventDispatcher;
92
93     // Guard destruction of event support in event handler
94     Atomic m_guardedCallInProgress;
95
96     // Events created by this support
97     typedef std::list<GenericEventCallType *> EventCallList;
98     EventCallList m_eventsList;
99
100     // Events list mutex
101     Mutex m_eventListMutex;
102
103   public:
104     class EventSupportData
105     {
106       private:
107         typedef void (EventSupportType::*ReceiveAbstractEventCallMethod)(
108             const EventType &event,
109             EventListenerType *eventListener,
110             DelegateType delegate,
111             WaitableEvent *synchronization);
112
113         EventSupportType *m_eventSupport;
114         ReceiveAbstractEventCallMethod m_method;
115         typename EventCallList::iterator m_iterator;
116
117         //TODO: Add dispatcher iterator to remove events from
118         //      framework/thread's event queue
119         WaitableEvent *m_synchronization;
120
121         Mutex m_dataMutex;
122
123       public:
124         EventSupportData(EventSupportType *support,
125                          ReceiveAbstractEventCallMethod method,
126                          WaitableEvent *synchronization) :
127             m_eventSupport(support),
128             m_method(method),
129             m_synchronization(synchronization)
130         {}
131
132         ~EventSupportData()
133         {
134             Mutex::ScopedLock lock(&m_dataMutex);
135
136             if (!m_eventSupport) {
137                 LogPedantic("EventSupport for this call does not exist");
138                 return;
139             }
140
141             m_eventSupport->RemoveEventCall(m_iterator);
142         }
143
144         // TODO: Make private and make EventSupport friend
145         void SetIterator(typename EventCallList::iterator iter)
146         {
147             m_iterator = iter;
148         }
149
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)
154         {
155             {
156                 Mutex::ScopedLock lock(&m_dataMutex);
157
158                 if (m_eventSupport != NULL) {
159                     (*m_eventSupport.*m_method)(event,
160                                                 listener,
161                                                 delegate,
162                                                 m_synchronization);
163                 } else {
164                     LogPedantic("EventSupport for this call does not "
165                                 "exist anymore. Ignored.");
166                 }
167
168                 // releasing mutex lock
169             }
170
171             // EventSupportData object is no more used.
172             // It can be safely destroyed now.
173             delete this;
174         }
175
176         void Reset()
177         {
178             LogPedantic("Reseting my EventSupport");
179
180             Mutex::ScopedLock lock(&m_dataMutex);
181             m_eventSupport = NULL;
182         }
183     };
184
185   private:
186     GenericEventCallType *RegisterEventCall(const EventType &event,
187                                             EventListenerType *eventListener,
188                                             DelegateType delegate,
189                                             WaitableEvent *waitableEvent)
190     {
191         LogPedantic("Create and Register EventCall in EventSupport");
192
193         Mutex::ScopedLock lock(&m_eventListMutex);
194
195         EventSupportDataPtr supportData =
196             new EventSupportData(
197                 this,
198                 &EventSupportType::ReceiveAbstractEventCall,
199                 waitableEvent);
200
201         GenericEventCallType *eventCall =
202             new GenericEventCallType(supportData, eventListener,
203                                      delegate, event);
204
205         typename EventCallList::iterator eventCallIter =
206             m_eventsList.insert(m_eventsList.end(), eventCall);
207
208         supportData->SetIterator(eventCallIter);
209
210         return eventCall;
211     }
212
213     void RemoveEventCall(typename EventCallList::iterator eventIterator)
214     {
215         Mutex::ScopedLock lock(&m_eventListMutex);
216
217         LogPedantic("Removing event call from EventSupport");
218
219         m_eventsList.erase(eventIterator);
220     }
221
222     // Note: Reentrant metod
223     void GuardedEventCall(const EventType &event,
224                           EventListenerType *eventListener)
225     {
226         LogPedantic("Guarded event listener call...");
227
228         ++m_guardedCallInProgress;
229
230         UNHANDLED_EXCEPTION_HANDLER_BEGIN
231         {
232             eventListener->OnEventReceived(event);
233         }
234         UNHANDLED_EXCEPTION_HANDLER_END
235
236         -- m_guardedCallInProgress;
237
238         LogPedantic("Guarded event listener finished");
239     }
240
241     // Note: Reentrant metod
242     void GuardedEventCall(const EventType &event,
243                           DelegateType delegate)
244     {
245         LogPedantic("Guarded delegate call...");
246
247         ++m_guardedCallInProgress;
248
249         UNHANDLED_EXCEPTION_HANDLER_BEGIN
250         {
251             delegate(event);
252         }
253         UNHANDLED_EXCEPTION_HANDLER_END
254
255         -- m_guardedCallInProgress;
256
257         LogPedantic("Guarded delegate call finished");
258     }
259
260     void ReceiveAbstractEventCall(const EventType &event,
261                                   EventListenerType *eventListener,
262                                   DelegateType delegate,
263                                   WaitableEvent *synchronization)
264     {
265         LogPedantic("Received abstract event call method");
266
267         Thread *targetThread;
268
269         // Listener might have been removed, ensure that it still exits
270         if (eventListener != NULL) {
271             Mutex::ScopedLock lock(&m_listenerDelegateMutex);
272
273             typename EventListenerList::iterator iterator =
274                 m_eventListenerList.find(eventListener);
275
276             if (iterator == m_eventListenerList.end()) {
277                 LogPedantic("Abstract event call listener disappeared."
278                             "Event ignored.");
279
280                 // Even though, synchronize caller if needed
281                 if (synchronization != NULL) {
282                     synchronization->Signal();
283                 }
284
285                 return;
286             }
287
288             // Get target thread id
289             targetThread = iterator->second;
290         } else {
291             // Delegate might have been removed, ensure that it still exits
292             Mutex::ScopedLock lock(&m_listenerDelegateMutex);
293
294             typename DelegateList::iterator iterator =
295                 m_delegateList.find(delegate);
296
297             if (iterator == m_delegateList.end()) {
298                 LogPedantic("Abstract event call delegate disappeared."
299                             "Event ignored.");
300
301                 // Even though, synchronize caller if needed
302                 if (synchronization != NULL) {
303                     synchronization->Signal();
304                 }
305
306                 return;
307             }
308
309             // Get target thread id
310             targetThread = iterator->second;
311         }
312
313         // Ensure that we are now in proper thread now
314         if (targetThread != Thread::GetCurrentThread()) {
315             LogPedantic("Detected event dispatching ping-pong scenario");
316
317             // Retry if it was not synchronized
318             if (synchronization == NULL) {
319                 // Cheat with event delivery
320                 EmitEvent(event, EmitMode::Queued);
321
322                 LogPedantic("Ping-Pong: Resent as queued event");
323             } else {
324                 // There is a problem
325                 // Developer did something nasty, and we will not clean up his
326                 // mess
327                 synchronization->Signal();
328
329                 LogPedantic("### Ping-Pong: Failed to deliver synchronized"
330                             "event in ping-pong scenario!");
331             }
332
333             return;
334         }
335
336         // Guard listener code for exceptions
337         if (eventListener != NULL) {
338             GuardedEventCall(event, eventListener);
339         } else {
340             GuardedEventCall(event, delegate);
341         }
342
343         // Release caller if synchronizing
344         if (synchronization != NULL) {
345             synchronization->Signal();
346         }
347     }
348
349   protected:
350     void EmitEvent(const EventType &event,
351                    EmitMode::Type mode = EmitMode::Queued,
352                    double dueTime = 0.0)
353     {
354         // Emit event, and retrieve later in current context to dispatch
355         std::unique_ptr<Mutex::ScopedLock> lock(
356             new Mutex::ScopedLock(&m_listenerDelegateMutex));
357
358         // Show some info
359         switch (mode) {
360         case EmitMode::Auto:
361             LogPedantic("Emitting AUTO event...");
362             break;
363
364         case EmitMode::Queued:
365             LogPedantic("Emitting QUEUED event...");
366             break;
367
368         case EmitMode::Blocking:
369             LogPedantic("Emitting BLOCKING event...");
370             break;
371
372         case EmitMode::Deffered:
373             LogPedantic("Emitting DEFFERED event...");
374             break;
375
376         default:
377             break;
378         }
379
380         // In some configurations there is a barrier
381         std::vector<WaitableEvent *> synchronizationBarrier;
382
383         // Emit to all listeners
384         FOREACH(iterator, m_eventListenerList)
385         {
386             // Switch to proper dispatcher and emit event
387             AbstractEventDispatcher *dispatcher = NULL;
388
389             if (iterator->second == NULL) {
390                 // Send to main thread
391                 LogPedantic("Sending event to main dispatcher");
392                 dispatcher = &GetMainEventDispatcherInstance();
393             } else {
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;
398             }
399
400             // Dispatch event to abstract dispatcher
401             WaitableEvent *synchronization;
402
403             // TODO: Pool synchronization objects
404             switch (mode) {
405             case EmitMode::Auto:
406                 // Check thread
407                 if (iterator->second == Thread::GetCurrentThread()) {
408                     // Guard listener code for exceptions
409                     GuardedEventCall(event, iterator->first);
410                 } else {
411                     // Handle non-synchronized event
412                     dispatcher->AddEventCall(
413                         RegisterEventCall(event, iterator->first,
414                                           DelegateType(), NULL));
415                 }
416                 break;
417
418             case EmitMode::Queued:
419                 // Handle non-synchronized event
420                 dispatcher->AddEventCall(
421                     RegisterEventCall(event, iterator->first,
422                                       DelegateType(), NULL));
423
424                 break;
425
426             case EmitMode::Blocking:
427                 // Check thread
428                 if (iterator->second == Thread::GetCurrentThread()) {
429                     // Guard listener code for exceptions
430                     GuardedEventCall(event, iterator->first);
431                 } else {
432                     // New synchronization object is needed
433                     synchronization = new WaitableEvent();
434
435                     // Handle synchronized event
436                     dispatcher->AddEventCall(
437                         RegisterEventCall(event, iterator->first,
438                                           DelegateType(), synchronization));
439
440                     // Add to barrier
441                     synchronizationBarrier.push_back(synchronization);
442                 }
443                 break;
444
445             case EmitMode::Deffered:
446                 // Handle deffered events
447                 Assert(dueTime >= 0.0 && "Due time must be non-negative");
448
449                 dispatcher->AddTimedEventCall(
450                     RegisterEventCall(event, iterator->first,
451                                       DelegateType(), NULL), dueTime);
452
453                 break;
454
455             default:
456                 Assert("Invalid emit mode");
457             }
458         }
459
460         LogPedantic("Added event to dispatchers");
461
462         // Emit to all delegates
463         FOREACH(iterator, m_delegateList)
464         {
465             // Switch to proper dispatcher and emit event
466             AbstractEventDispatcher *dispatcher = NULL;
467
468             if (iterator->second == NULL) {
469                 // Send to main thread
470                 LogPedantic("Sending event to main dispatcher");
471                 dispatcher = &GetMainEventDispatcherInstance();
472             } else {
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;
477             }
478
479             // Dispatch event to abstract dispatcher
480             WaitableEvent *synchronization;
481
482             // TODO: Pool synchronization objects
483             switch (mode) {
484             case EmitMode::Auto:
485                 // Check thread
486                 if (iterator->second == Thread::GetCurrentThread()) {
487                     // Guard listener code for exceptions
488                     GuardedEventCall(event, iterator->first);
489                 } else {
490                     // Handle non-synchronized event
491                     dispatcher->AddEventCall(
492                         RegisterEventCall(event,
493                                           NULL,
494                                           iterator->first,
495                                           NULL));
496                 }
497                 break;
498
499             case EmitMode::Queued:
500                 // Handle non-synchronized event
501                 dispatcher->AddEventCall(
502                     RegisterEventCall(event,
503                                       NULL,
504                                       iterator->first,
505                                       NULL));
506
507                 break;
508
509             case EmitMode::Blocking:
510                 // Check thread
511                 if (iterator->second == Thread::GetCurrentThread()) {
512                     // Guard listener code for exceptions
513                     GuardedEventCall(event, iterator->first);
514                 } else {
515                     // New synchronization object is needed
516                     synchronization = new WaitableEvent();
517
518                     // Handle synchronized event
519                     dispatcher->AddEventCall(
520                         RegisterEventCall(event,
521                                           NULL,
522                                           iterator->first,
523                                           synchronization));
524
525                     // Add to barrier
526                     synchronizationBarrier.push_back(synchronization);
527                 }
528                 break;
529
530             case EmitMode::Deffered:
531                 // Handle deffered events
532                 Assert(dueTime >= 0.0 && "Due time must be non-negative");
533
534                 dispatcher->AddTimedEventCall(
535                     RegisterEventCall(event,
536                                       NULL,
537                                       iterator->first,
538                                       NULL), dueTime);
539
540                 break;
541
542             default:
543                 Assert("Invalid emit mode");
544             }
545         }
546
547         LogPedantic("Added event to dispatchers");
548
549         // Leave listeners lock in case of blocking call
550         if (!synchronizationBarrier.empty()) {
551             LogPedantic("Leaving lock due to existing barrier");
552             lock.reset();
553         }
554
555         LogPedantic("Size of barrier: " << synchronizationBarrier.size());
556
557         // Synchronize with barrier
558         // TODO: Implement generic WaitForAllMultipleHandles call
559         while (!synchronizationBarrier.empty()) {
560             // Get barrier waitable handles
561             WaitableHandleList barrierHandles;
562
563             FOREACH(iterator, synchronizationBarrier)
564             barrierHandles.push_back((*iterator)->GetHandle());
565
566             // Await more events
567             WaitableHandleIndexList indexList =
568                 WaitForMultipleHandles(barrierHandles);
569
570             // Remove all awaited handles
571             // TODO: Return handles to pool
572             FOREACH(iterator, indexList)
573             {
574                 // Delete object
575                 delete synchronizationBarrier[*iterator];
576
577                 // Zero out place
578                 synchronizationBarrier[*iterator] = NULL;
579             }
580
581             // Now clean up
582             std::vector<WaitableEvent *> clearedSynchronizationBarrier;
583
584             FOREACH(iterator, synchronizationBarrier)
585             {
586                 if (*iterator == NULL) {
587                     continue;
588                 }
589
590                 clearedSynchronizationBarrier.push_back(*iterator);
591             }
592
593             synchronizationBarrier.swap(clearedSynchronizationBarrier);
594
595             LogPedantic("Reduced size of barrier: "
596                         << synchronizationBarrier.size());
597         }
598
599         LogPedantic("Event emitted");
600     }
601
602   public:
603     EventSupport() :
604         m_guardedCallInProgress(false)
605     {}
606
607     virtual ~EventSupport()
608     {
609         Assert(m_guardedCallInProgress == false);
610
611         m_eventListenerList.clear();
612         m_delegateList.clear();
613
614         Mutex::ScopedLock lock(&m_eventListMutex);
615
616         LogPedantic("Disabling events for EventSupport");
617
618         FOREACH(iterator, m_eventsList)
619             (*iterator)->DisableEvent();
620     }
621
622     void AddListener(EventListenerType *eventListener)
623     {
624         Mutex::ScopedLock lock(&m_listenerDelegateMutex);
625
626         // Listener must not be NULL
627         Assert(eventListener != NULL);
628
629         // Listener must not already exists
630         Assert(m_eventListenerList.find(eventListener)
631                == m_eventListenerList.end());
632
633         // Add new listener, inherit dispatcher from current context
634         m_eventListenerList.insert(
635             std::make_pair(eventListener, Thread::GetCurrentThread()));
636
637         // Done
638         LogPedantic("Listener registered");
639     }
640
641     void AddListener(DelegateType delegate)
642     {
643         Mutex::ScopedLock lock(&m_listenerDelegateMutex);
644
645         // Delegate must not be empty
646         Assert(!delegate.empty());
647
648         // Delegate must not already exists
649         Assert(m_delegateList.find(delegate) == m_delegateList.end());
650
651         // Add new delegate, inherit dispatcher from current context
652         m_delegateList.insert(
653             std::make_pair(delegate, Thread::GetCurrentThread()));
654
655         // Done
656         LogPedantic("Delegate registered");
657     }
658
659     void RemoveListener(EventListenerType *eventListener)
660     {
661         Mutex::ScopedLock lock(&m_listenerDelegateMutex);
662
663         // Listener must not be NULL
664         Assert(eventListener != NULL);
665
666         // Listener must exist
667         typename EventListenerList::iterator iterator =
668             m_eventListenerList.find(eventListener);
669
670         Assert(iterator != m_eventListenerList.end());
671
672         // Remove listener from list
673         m_eventListenerList.erase(iterator);
674         LogPedantic("Listener unregistered");
675     }
676
677     void RemoveListener(DelegateType delegate)
678     {
679         Mutex::ScopedLock lock(&m_listenerDelegateMutex);
680
681         // Delegate must not be empty
682         Assert(!delegate.empty());
683
684         // Delegate must exist
685         typename DelegateList::iterator iterator =
686             m_delegateList.find(delegate);
687
688         Assert(iterator != m_delegateList.end());
689
690         // Remove delegate from list
691         m_delegateList.erase(iterator);
692         LogPedantic("Delegate unregistered");
693     }
694
695     void SwitchListenerToThread(EventListenerType *eventListener,
696                                 Thread *thread)
697     {
698         Mutex::ScopedLock lock(&m_listenerDelegateMutex);
699
700         // Listener must not be NULL
701         Assert(eventListener != NULL);
702
703         // Listener must exist
704         typename EventListenerList::iterator iterator =
705             m_eventListenerList.find(eventListener);
706
707         Assert(iterator != m_eventListenerList.end());
708
709         // Set listener thread
710         iterator->second = thread;
711
712         LogPedantic("Listener switched");
713     }
714
715     void SwitchListenerToThread(DelegateType delegate,
716                                 Thread *thread)
717     {
718         Mutex::ScopedLock lock(&m_listenerDelegateMutex);
719
720         // Delegate must not be empty
721         Assert(!delegate.empty());
722
723         // Delegate must exist
724         typename EventListenerList::iterator iterator =
725             m_delegateList.find(delegate);
726
727         Assert(iterator != m_delegateList.end());
728
729         // Set delegate thread
730         iterator->second = thread;
731
732         LogPedantic("Delegate switched");
733     }
734
735     void SwitchAllListenersToThread(Thread *thread)
736     {
737         Mutex::ScopedLock lock(&m_listenerDelegateMutex);
738
739         // Switch all listeners and delegates
740         FOREACH(iterator, m_eventListenerList)
741         iterator->second = thread;
742
743         FOREACH(iterator, m_delegateList)
744         iterator->second = thread;
745
746         LogPedantic("All listeners and delegates switched");
747     }
748 };
749 }
750 } // namespace DPL
751
752 #endif // DPL_EVENT_SUPPORT_H