Initialize Tizen 2.3
[framework/web/wrt-commons.git] / modules_wearable / 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 <functional>
26 #include <list>
27 #include <map>
28 #include <memory>
29 #include <type_traits>
30 #include <vector>
31
32 #include <dpl/event/event_listener.h>
33 #include <dpl/event/abstract_event_dispatcher.h>
34 #include <dpl/event/main_event_dispatcher.h>
35 #include <dpl/event/thread_event_dispatcher.h>
36 #include <dpl/event/generic_event_call.h>
37 #include <dpl/waitable_event.h>
38 #include <dpl/exception.h>
39 #include <dpl/thread.h>
40 #include <dpl/assert.h>
41 #include <dpl/atomic.h>
42 #include <dpl/mutex.h>
43 #include <dpl/foreach.h>
44 #include <dpl/log/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     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     Atomic 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     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         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             Mutex::ScopedLock lock(&m_dataMutex);
153
154             if (!m_eventSupport) {
155                 LogPedantic("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                 Mutex::ScopedLock 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                     LogPedantic("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             LogPedantic("Reseting my EventSupport");
197
198             Mutex::ScopedLock lock(&m_dataMutex);
199             m_eventSupport = NULL;
200         }
201     };
202
203   private:
204     GenericEventCallType *RegisterEventCall(const EventType &event,
205                                             EventListenerType *eventListener,
206                                             DelegateType delegate,
207                                             WaitableEvent *waitableEvent)
208     {
209         LogPedantic("Create and Register EventCall in EventSupport");
210
211         Mutex::ScopedLock lock(&m_eventListMutex);
212
213         EventSupportDataPtr supportData =
214             new EventSupportData(
215                 this,
216                 &EventSupportType::ReceiveAbstractEventCall,
217                 waitableEvent);
218
219         GenericEventCallType *eventCall =
220             new GenericEventCallType(supportData, eventListener,
221                                      delegate, event);
222
223         typename EventCallList::iterator eventCallIter =
224             m_eventsList.insert(m_eventsList.end(), eventCall);
225
226         supportData->SetIterator(eventCallIter);
227
228         return eventCall;
229     }
230
231     void RemoveEventCall(typename EventCallList::iterator eventIterator)
232     {
233         Mutex::ScopedLock lock(&m_eventListMutex);
234
235         LogPedantic("Removing event call from EventSupport");
236
237         m_eventsList.erase(eventIterator);
238     }
239
240     // Note: Reentrant metod
241     void GuardedEventCall(const EventType &event,
242                           EventListenerType *eventListener)
243     {
244         LogPedantic("Guarded event listener call...");
245
246         ++m_guardedCallInProgress;
247
248         UNHANDLED_EXCEPTION_HANDLER_BEGIN
249         {
250             eventListener->OnEventReceived(event);
251         }
252         UNHANDLED_EXCEPTION_HANDLER_END
253
254         -- m_guardedCallInProgress;
255
256         LogPedantic("Guarded event listener finished");
257     }
258
259     // Note: Reentrant metod
260     void GuardedEventCall(const EventType &event,
261                           DelegateType delegate)
262     {
263         LogPedantic("Guarded delegate call...");
264
265         ++m_guardedCallInProgress;
266
267         UNHANDLED_EXCEPTION_HANDLER_BEGIN
268         {
269             delegate(event);
270         }
271         UNHANDLED_EXCEPTION_HANDLER_END
272
273         -- m_guardedCallInProgress;
274
275         LogPedantic("Guarded delegate call finished");
276     }
277
278     void ReceiveAbstractEventCall(const EventType &event,
279                                   EventListenerType *eventListener,
280                                   DelegateType delegate,
281                                   WaitableEvent *synchronization)
282     {
283         LogPedantic("Received abstract event call method");
284
285         Thread *targetThread;
286
287         // Listener might have been removed, ensure that it still exits
288         if (eventListener != NULL) {
289             Mutex::ScopedLock lock(&m_listenerDelegateMutex);
290
291             typename EventListenerList::iterator iterator =
292                 m_eventListenerList.find(eventListener);
293
294             if (iterator == m_eventListenerList.end()) {
295                 LogPedantic("Abstract event call listener disappeared."
296                             "Event ignored.");
297
298                 // Even though, synchronize caller if needed
299                 if (synchronization != NULL) {
300                     synchronization->Signal();
301                 }
302
303                 return;
304             }
305
306             // Get target thread id
307             targetThread = iterator->second;
308         } else {
309             // Delegate might have been removed, ensure that it still exits
310             Mutex::ScopedLock lock(&m_listenerDelegateMutex);
311
312             typename DelegateList::iterator iterator =
313                 m_delegateList.find(delegate);
314
315             if (iterator == m_delegateList.end()) {
316                 LogPedantic("Abstract event call delegate disappeared."
317                             "Event ignored.");
318
319                 // Even though, synchronize caller if needed
320                 if (synchronization != NULL) {
321                     synchronization->Signal();
322                 }
323
324                 return;
325             }
326
327             // Get target thread id
328             targetThread = iterator->second;
329         }
330
331         // Ensure that we are now in proper thread now
332         if (targetThread != Thread::GetCurrentThread()) {
333             LogPedantic("Detected event dispatching ping-pong scenario");
334
335             // Retry if it was not synchronized
336             if (synchronization == NULL) {
337                 // Cheat with event delivery
338                 EmitEvent(event, EmitMode::Queued);
339
340                 LogPedantic("Ping-Pong: Resent as queued event");
341             } else {
342                 // There is a problem
343                 // Developer did something nasty, and we will not clean up his
344                 // mess
345                 synchronization->Signal();
346
347                 LogPedantic("### Ping-Pong: Failed to deliver synchronized"
348                             "event in ping-pong scenario!");
349             }
350
351             return;
352         }
353
354         // Guard listener code for exceptions
355         if (eventListener != NULL) {
356             GuardedEventCall(event, eventListener);
357         } else {
358             GuardedEventCall(event, delegate);
359         }
360
361         // Release caller if synchronizing
362         if (synchronization != NULL) {
363             synchronization->Signal();
364         }
365     }
366
367   protected:
368     void EmitEvent(const EventType &event,
369                    EmitMode::Type mode = EmitMode::Queued,
370                    double dueTime = 0.0)
371     {
372         // Emit event, and retrieve later in current context to dispatch
373         std::unique_ptr<Mutex::ScopedLock> lock(
374             new Mutex::ScopedLock(&m_listenerDelegateMutex));
375
376         // Show some info
377         switch (mode) {
378         case EmitMode::Auto:
379             LogPedantic("Emitting AUTO event...");
380             break;
381
382         case EmitMode::Queued:
383             LogPedantic("Emitting QUEUED event...");
384             break;
385
386         case EmitMode::Blocking:
387             LogPedantic("Emitting BLOCKING event...");
388             break;
389
390         case EmitMode::Deffered:
391             LogPedantic("Emitting DEFFERED event...");
392             break;
393
394         default:
395             break;
396         }
397
398         // In some configurations there is a barrier
399         std::vector<WaitableEvent *> synchronizationBarrier;
400
401         // Emit to all listeners
402         FOREACH(iterator, m_eventListenerList)
403         {
404             // Switch to proper dispatcher and emit event
405             AbstractEventDispatcher *dispatcher = NULL;
406
407             if (iterator->second == NULL) {
408                 // Send to main thread
409                 LogPedantic("Sending event to main dispatcher");
410                 dispatcher = &GetMainEventDispatcherInstance();
411             } else {
412                 // Setup thread dispatcher, and send to proper thread
413                 LogPedantic("Sending event to thread dispatcher");
414                 m_threadEventDispatcher.SetThread(iterator->second);
415                 dispatcher = &m_threadEventDispatcher;
416             }
417
418             // Dispatch event to abstract dispatcher
419             WaitableEvent *synchronization;
420
421             // TODO: Pool synchronization objects
422             switch (mode) {
423             case EmitMode::Auto:
424                 // Check thread
425                 if (iterator->second == Thread::GetCurrentThread()) {
426                     // Guard listener code for exceptions
427                     GuardedEventCall(event, iterator->first);
428                 } else {
429                     // Handle non-synchronized event
430                     dispatcher->AddEventCall(
431                         RegisterEventCall(event, iterator->first,
432                                           DelegateType(), NULL));
433                 }
434                 break;
435
436             case EmitMode::Queued:
437                 // Handle non-synchronized event
438                 dispatcher->AddEventCall(
439                     RegisterEventCall(event, iterator->first,
440                                       DelegateType(), NULL));
441
442                 break;
443
444             case EmitMode::Blocking:
445                 // Check thread
446                 if (iterator->second == Thread::GetCurrentThread()) {
447                     // Guard listener code for exceptions
448                     GuardedEventCall(event, iterator->first);
449                 } else {
450                     // New synchronization object is needed
451                     synchronization = new WaitableEvent();
452
453                     // Handle synchronized event
454                     dispatcher->AddEventCall(
455                         RegisterEventCall(event, iterator->first,
456                                           DelegateType(), synchronization));
457
458                     // Add to barrier
459                     synchronizationBarrier.push_back(synchronization);
460                 }
461                 break;
462
463             case EmitMode::Deffered:
464                 // Handle deffered events
465                 Assert(dueTime >= 0.0 && "Due time must be non-negative");
466
467                 dispatcher->AddTimedEventCall(
468                     RegisterEventCall(event, iterator->first,
469                                       DelegateType(), NULL), dueTime);
470
471                 break;
472
473             default:
474                 Assert("Invalid emit mode");
475             }
476         }
477
478         LogPedantic("Added event to dispatchers");
479
480         // Emit to all delegates
481         FOREACH(iterator, m_delegateList)
482         {
483             // Switch to proper dispatcher and emit event
484             AbstractEventDispatcher *dispatcher = NULL;
485
486             if (iterator->second == NULL) {
487                 // Send to main thread
488                 LogPedantic("Sending event to main dispatcher");
489                 dispatcher = &GetMainEventDispatcherInstance();
490             } else {
491                 // Setup thread dispatcher, and send to proper thread
492                 LogPedantic("Sending event to thread dispatcher");
493                 m_threadEventDispatcher.SetThread(iterator->second);
494                 dispatcher = &m_threadEventDispatcher;
495             }
496
497             // Dispatch event to abstract dispatcher
498             WaitableEvent *synchronization;
499
500             // TODO: Pool synchronization objects
501             switch (mode) {
502             case EmitMode::Auto:
503                 // Check thread
504                 if (iterator->second == Thread::GetCurrentThread()) {
505                     // Guard listener code for exceptions
506                     GuardedEventCall(event, iterator->first);
507                 } else {
508                     // Handle non-synchronized event
509                     dispatcher->AddEventCall(
510                         RegisterEventCall(event,
511                                           NULL,
512                                           iterator->first,
513                                           NULL));
514                 }
515                 break;
516
517             case EmitMode::Queued:
518                 // Handle non-synchronized event
519                 dispatcher->AddEventCall(
520                     RegisterEventCall(event,
521                                       NULL,
522                                       iterator->first,
523                                       NULL));
524
525                 break;
526
527             case EmitMode::Blocking:
528                 // Check thread
529                 if (iterator->second == Thread::GetCurrentThread()) {
530                     // Guard listener code for exceptions
531                     GuardedEventCall(event, iterator->first);
532                 } else {
533                     // New synchronization object is needed
534                     synchronization = new WaitableEvent();
535
536                     // Handle synchronized event
537                     dispatcher->AddEventCall(
538                         RegisterEventCall(event,
539                                           NULL,
540                                           iterator->first,
541                                           synchronization));
542
543                     // Add to barrier
544                     synchronizationBarrier.push_back(synchronization);
545                 }
546                 break;
547
548             case EmitMode::Deffered:
549                 // Handle deffered events
550                 Assert(dueTime >= 0.0 && "Due time must be non-negative");
551
552                 dispatcher->AddTimedEventCall(
553                     RegisterEventCall(event,
554                                       NULL,
555                                       iterator->first,
556                                       NULL), dueTime);
557
558                 break;
559
560             default:
561                 Assert("Invalid emit mode");
562             }
563         }
564
565         LogPedantic("Added event to dispatchers");
566
567         // Leave listeners lock in case of blocking call
568         if (!synchronizationBarrier.empty()) {
569             LogPedantic("Leaving lock due to existing barrier");
570             lock.reset();
571         }
572
573         LogPedantic("Size of barrier: " << synchronizationBarrier.size());
574
575         // Synchronize with barrier
576         // TODO: Implement generic WaitForAllMultipleHandles call
577         while (!synchronizationBarrier.empty()) {
578             // Get barrier waitable handles
579             WaitableHandleList barrierHandles;
580
581             FOREACH(iterator, synchronizationBarrier)
582             barrierHandles.push_back((*iterator)->GetHandle());
583
584             // Await more events
585             WaitableHandleIndexList indexList =
586                 WaitForMultipleHandles(barrierHandles);
587
588             // Remove all awaited handles
589             // TODO: Return handles to pool
590             FOREACH(iterator, indexList)
591             {
592                 // Delete object
593                 delete synchronizationBarrier[*iterator];
594
595                 // Zero out place
596                 synchronizationBarrier[*iterator] = NULL;
597             }
598
599             // Now clean up
600             std::vector<WaitableEvent *> clearedSynchronizationBarrier;
601
602             FOREACH(iterator, synchronizationBarrier)
603             {
604                 if (*iterator == NULL) {
605                     continue;
606                 }
607
608                 clearedSynchronizationBarrier.push_back(*iterator);
609             }
610
611             synchronizationBarrier.swap(clearedSynchronizationBarrier);
612
613             LogPedantic("Reduced size of barrier: "
614                         << synchronizationBarrier.size());
615         }
616
617         LogPedantic("Event emitted");
618     }
619
620   public:
621     EventSupport() :
622         m_guardedCallInProgress(false)
623     {}
624
625     virtual ~EventSupport()
626     {
627         if (m_guardedCallInProgress != 0) {
628             LogError("The object will terminate, but guardCall is in progress, it could cause segmentation fault");
629         }
630
631         m_eventListenerList.clear();
632         m_delegateList.clear();
633
634         Mutex::ScopedLock lock(&m_eventListMutex);
635
636         LogPedantic("Disabling events for EventSupport");
637
638         FOREACH(iterator, m_eventsList)
639             (*iterator)->DisableEvent();
640     }
641
642     void AddListener(EventListenerType *eventListener)
643     {
644         Mutex::ScopedLock lock(&m_listenerDelegateMutex);
645
646         // Listener must not be NULL
647         Assert(eventListener != NULL);
648
649         // Listener must not already exists
650         Assert(m_eventListenerList.find(eventListener)
651                == m_eventListenerList.end());
652
653         // Add new listener, inherit dispatcher from current context
654         m_eventListenerList.insert(
655             std::make_pair(eventListener, Thread::GetCurrentThread()));
656
657         // Done
658         LogPedantic("Listener registered");
659     }
660
661     void AddListener(DelegateType delegate)
662     {
663         Mutex::ScopedLock lock(&m_listenerDelegateMutex);
664
665         // Delegate must not be empty
666         Assert(delegate);
667
668         // Delegate must not already exists
669         Assert(m_delegateList.find(delegate) == m_delegateList.end());
670
671         // Add new delegate, inherit dispatcher from current context
672         m_delegateList.insert(
673             std::make_pair(delegate, Thread::GetCurrentThread()));
674
675         // Done
676         LogPedantic("Delegate registered");
677     }
678
679     void RemoveListener(EventListenerType *eventListener)
680     {
681         Mutex::ScopedLock lock(&m_listenerDelegateMutex);
682
683         // Listener must not be NULL
684         Assert(eventListener != NULL);
685
686         // Listener must exist
687         typename EventListenerList::iterator iterator =
688             m_eventListenerList.find(eventListener);
689
690         Assert(iterator != m_eventListenerList.end());
691
692         // Remove listener from list
693         m_eventListenerList.erase(iterator);
694         LogPedantic("Listener unregistered");
695     }
696
697     void RemoveListener(DelegateType delegate)
698     {
699         Mutex::ScopedLock lock(&m_listenerDelegateMutex);
700
701         // Delegate must not be empty
702         Assert(delegate);
703
704         // Delegate must exist
705         typename DelegateList::iterator iterator =
706             m_delegateList.find(delegate);
707
708         Assert(iterator != m_delegateList.end());
709
710         // Remove delegate from list
711         m_delegateList.erase(iterator);
712         LogPedantic("Delegate unregistered");
713     }
714
715     void SwitchListenerToThread(EventListenerType *eventListener,
716                                 Thread *thread)
717     {
718         Mutex::ScopedLock lock(&m_listenerDelegateMutex);
719
720         // Listener must not be NULL
721         Assert(eventListener != NULL);
722
723         // Listener must exist
724         typename EventListenerList::iterator iterator =
725             m_eventListenerList.find(eventListener);
726
727         Assert(iterator != m_eventListenerList.end());
728
729         // Set listener thread
730         iterator->second = thread;
731
732         LogPedantic("Listener switched");
733     }
734
735     void SwitchListenerToThread(DelegateType delegate,
736                                 Thread *thread)
737     {
738         Mutex::ScopedLock lock(&m_listenerDelegateMutex);
739
740         // Delegate must not be empty
741         Assert(!delegate.empty());
742
743         // Delegate must exist
744         typename EventListenerList::iterator iterator =
745             m_delegateList.find(delegate);
746
747         Assert(iterator != m_delegateList.end());
748
749         // Set delegate thread
750         iterator->second = thread;
751
752         LogPedantic("Delegate switched");
753     }
754
755     void SwitchAllListenersToThread(Thread *thread)
756     {
757         Mutex::ScopedLock lock(&m_listenerDelegateMutex);
758
759         // Switch all listeners and delegates
760         FOREACH(iterator, m_eventListenerList)
761         iterator->second = thread;
762
763         FOREACH(iterator, m_delegateList)
764         iterator->second = thread;
765
766         LogPedantic("All listeners and delegates switched");
767     }
768 };
769 }
770 } // namespace DPL
771
772 #endif // DPL_EVENT_SUPPORT_H