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