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