tizen 2.3.1 release
[framework/web/wearable/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 <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             Mutex::ScopedLock 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         Mutex::ScopedLock 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         Mutex::ScopedLock 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             Mutex::ScopedLock lock(&m_listenerDelegateMutex);
274
275             typename EventListenerList::iterator iterator =
276                 m_eventListenerList.find(eventListener);
277
278             if (iterator == m_eventListenerList.end()) {
279                 LogPedantic("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             Mutex::ScopedLock lock(&m_listenerDelegateMutex);
295
296             typename DelegateList::iterator iterator =
297                 m_delegateList.find(delegate);
298
299             if (iterator == m_delegateList.end()) {
300                 LogPedantic("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             LogPedantic("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                 LogPedantic("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                 LogPedantic("### 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_ptr<Mutex::ScopedLock> lock(
358             new Mutex::ScopedLock(&m_listenerDelegateMutex));
359
360         // Show some info
361         switch (mode) {
362         case EmitMode::Auto:
363             break;
364
365         case EmitMode::Queued:
366             break;
367
368         case EmitMode::Blocking:
369             break;
370
371         case EmitMode::Deffered:
372             break;
373
374         default:
375             break;
376         }
377
378         // In some configurations there is a barrier
379         std::vector<WaitableEvent *> synchronizationBarrier;
380
381         // Emit to all listeners
382         FOREACH(iterator, m_eventListenerList)
383         {
384             // Switch to proper dispatcher and emit event
385             AbstractEventDispatcher *dispatcher = NULL;
386
387             if (iterator->second == NULL) {
388                 // Send to main thread
389                 dispatcher = &GetMainEventDispatcherInstance();
390             } else {
391                 // Setup thread dispatcher, and send to proper thread
392                 m_threadEventDispatcher.SetThread(iterator->second);
393                 dispatcher = &m_threadEventDispatcher;
394             }
395
396             // Dispatch event to abstract dispatcher
397             WaitableEvent *synchronization;
398
399             // TODO: Pool synchronization objects
400             switch (mode) {
401             case EmitMode::Auto:
402                 // Check thread
403                 if (iterator->second == Thread::GetCurrentThread()) {
404                     // Guard listener code for exceptions
405                     GuardedEventCall(event, iterator->first);
406                 } else {
407                     // Handle non-synchronized event
408                     dispatcher->AddEventCall(
409                         RegisterEventCall(event, iterator->first,
410                                           DelegateType(), NULL));
411                 }
412                 break;
413
414             case EmitMode::Queued:
415                 // Handle non-synchronized event
416                 dispatcher->AddEventCall(
417                     RegisterEventCall(event, iterator->first,
418                                       DelegateType(), NULL));
419
420                 break;
421
422             case EmitMode::Blocking:
423                 // Check thread
424                 if (iterator->second == Thread::GetCurrentThread()) {
425                     // Guard listener code for exceptions
426                     GuardedEventCall(event, iterator->first);
427                 } else {
428                     // New synchronization object is needed
429                     synchronization = new WaitableEvent();
430
431                     // Handle synchronized event
432                     dispatcher->AddEventCall(
433                         RegisterEventCall(event, iterator->first,
434                                           DelegateType(), synchronization));
435
436                     // Add to barrier
437                     synchronizationBarrier.push_back(synchronization);
438                 }
439                 break;
440
441             case EmitMode::Deffered:
442                 // Handle deffered events
443                 Assert(dueTime >= 0.0 && "Due time must be non-negative");
444
445                 dispatcher->AddTimedEventCall(
446                     RegisterEventCall(event, iterator->first,
447                                       DelegateType(), NULL), dueTime);
448
449                 break;
450
451             default:
452                 Assert("Invalid emit mode");
453             }
454         }
455
456         // Emit to all delegates
457         FOREACH(iterator, m_delegateList)
458         {
459             // Switch to proper dispatcher and emit event
460             AbstractEventDispatcher *dispatcher = NULL;
461
462             if (iterator->second == NULL) {
463                 // Send to main thread
464                 dispatcher = &GetMainEventDispatcherInstance();
465             } else {
466                 // Setup thread dispatcher, and send to proper thread
467                 m_threadEventDispatcher.SetThread(iterator->second);
468                 dispatcher = &m_threadEventDispatcher;
469             }
470
471             // Dispatch event to abstract dispatcher
472             WaitableEvent *synchronization;
473
474             // TODO: Pool synchronization objects
475             switch (mode) {
476             case EmitMode::Auto:
477                 // Check thread
478                 if (iterator->second == Thread::GetCurrentThread()) {
479                     // Guard listener code for exceptions
480                     GuardedEventCall(event, iterator->first);
481                 } else {
482                     // Handle non-synchronized event
483                     dispatcher->AddEventCall(
484                         RegisterEventCall(event,
485                                           NULL,
486                                           iterator->first,
487                                           NULL));
488                 }
489                 break;
490
491             case EmitMode::Queued:
492                 // Handle non-synchronized event
493                 dispatcher->AddEventCall(
494                     RegisterEventCall(event,
495                                       NULL,
496                                       iterator->first,
497                                       NULL));
498
499                 break;
500
501             case EmitMode::Blocking:
502                 // Check thread
503                 if (iterator->second == Thread::GetCurrentThread()) {
504                     // Guard listener code for exceptions
505                     GuardedEventCall(event, iterator->first);
506                 } else {
507                     // New synchronization object is needed
508                     synchronization = new WaitableEvent();
509
510                     // Handle synchronized event
511                     dispatcher->AddEventCall(
512                         RegisterEventCall(event,
513                                           NULL,
514                                           iterator->first,
515                                           synchronization));
516
517                     // Add to barrier
518                     synchronizationBarrier.push_back(synchronization);
519                 }
520                 break;
521
522             case EmitMode::Deffered:
523                 // Handle deffered events
524                 Assert(dueTime >= 0.0 && "Due time must be non-negative");
525
526                 dispatcher->AddTimedEventCall(
527                     RegisterEventCall(event,
528                                       NULL,
529                                       iterator->first,
530                                       NULL), dueTime);
531
532                 break;
533
534             default:
535                 Assert("Invalid emit mode");
536             }
537         }
538
539         // Leave listeners lock in case of blocking call
540         if (!synchronizationBarrier.empty()) {
541             LogPedantic("Leaving lock due to existing barrier");
542             lock.reset();
543         }
544
545         // Synchronize with barrier
546         // TODO: Implement generic WaitForAllMultipleHandles call
547         while (!synchronizationBarrier.empty()) {
548             // Get barrier waitable handles
549             WaitableHandleList barrierHandles;
550
551             FOREACH(iterator, synchronizationBarrier)
552             barrierHandles.push_back((*iterator)->GetHandle());
553
554             // Await more events
555             WaitableHandleIndexList indexList =
556                 WaitForMultipleHandles(barrierHandles);
557
558             // Remove all awaited handles
559             // TODO: Return handles to pool
560             FOREACH(iterator, indexList)
561             {
562                 // Delete object
563                 delete synchronizationBarrier[*iterator];
564
565                 // Zero out place
566                 synchronizationBarrier[*iterator] = NULL;
567             }
568
569             // Now clean up
570             std::vector<WaitableEvent *> clearedSynchronizationBarrier;
571
572             FOREACH(iterator, synchronizationBarrier)
573             {
574                 if (*iterator == NULL) {
575                     continue;
576                 }
577
578                 clearedSynchronizationBarrier.push_back(*iterator);
579             }
580
581             synchronizationBarrier.swap(clearedSynchronizationBarrier);
582         }
583     }
584
585   public:
586     EventSupport() :
587         m_guardedCallInProgress(false)
588     {}
589
590     virtual ~EventSupport()
591     {
592         if( m_guardedCallInProgress != 0 ){
593             LogError("The object will terminate, but guardCall is in progress, it could cause segmentation fault");
594         }
595
596         m_eventListenerList.clear();
597         m_delegateList.clear();
598
599         Mutex::ScopedLock lock(&m_eventListMutex);
600
601         FOREACH(iterator, m_eventsList)
602             (*iterator)->DisableEvent();
603     }
604
605     void AddListener(EventListenerType *eventListener)
606     {
607         Mutex::ScopedLock lock(&m_listenerDelegateMutex);
608
609         // Listener must not be NULL
610         Assert(eventListener != NULL);
611
612         // Listener must not already exists
613         Assert(m_eventListenerList.find(eventListener)
614                == m_eventListenerList.end());
615
616         // Add new listener, inherit dispatcher from current context
617         m_eventListenerList.insert(
618             std::make_pair(eventListener, Thread::GetCurrentThread()));
619     }
620
621     void AddListener(DelegateType delegate)
622     {
623         Mutex::ScopedLock lock(&m_listenerDelegateMutex);
624
625         // Delegate must not be empty
626         Assert(delegate);
627
628         // Delegate must not already exists
629         Assert(m_delegateList.find(delegate) == m_delegateList.end());
630
631         // Add new delegate, inherit dispatcher from current context
632         m_delegateList.insert(
633             std::make_pair(delegate, Thread::GetCurrentThread()));
634     }
635
636     void RemoveListener(EventListenerType *eventListener)
637     {
638         Mutex::ScopedLock lock(&m_listenerDelegateMutex);
639
640         // Listener must not be NULL
641         Assert(eventListener != NULL);
642
643         // Listener must exist
644         typename EventListenerList::iterator iterator =
645             m_eventListenerList.find(eventListener);
646
647         Assert(iterator != m_eventListenerList.end());
648
649         // Remove listener from list
650         m_eventListenerList.erase(iterator);
651     }
652
653     void RemoveListener(DelegateType delegate)
654     {
655         Mutex::ScopedLock lock(&m_listenerDelegateMutex);
656
657         // Delegate must not be empty
658         Assert(delegate);
659
660         // Delegate must exist
661         typename DelegateList::iterator iterator =
662             m_delegateList.find(delegate);
663
664         Assert(iterator != m_delegateList.end());
665
666         // Remove delegate from list
667         m_delegateList.erase(iterator);
668     }
669
670     void SwitchListenerToThread(EventListenerType *eventListener,
671                                 Thread *thread)
672     {
673         Mutex::ScopedLock lock(&m_listenerDelegateMutex);
674
675         // Listener must not be NULL
676         Assert(eventListener != NULL);
677
678         // Listener must exist
679         typename EventListenerList::iterator iterator =
680             m_eventListenerList.find(eventListener);
681
682         Assert(iterator != m_eventListenerList.end());
683
684         // Set listener thread
685         iterator->second = thread;
686     }
687
688     void SwitchListenerToThread(DelegateType delegate,
689                                 Thread *thread)
690     {
691         Mutex::ScopedLock lock(&m_listenerDelegateMutex);
692
693         // Delegate must not be empty
694         Assert(!delegate.empty());
695
696         // Delegate must exist
697         typename EventListenerList::iterator iterator =
698             m_delegateList.find(delegate);
699
700         Assert(iterator != m_delegateList.end());
701
702         // Set delegate thread
703         iterator->second = thread;
704     }
705
706     void SwitchAllListenersToThread(Thread *thread)
707     {
708         Mutex::ScopedLock lock(&m_listenerDelegateMutex);
709
710         // Switch all listeners and delegates
711         FOREACH(iterator, m_eventListenerList)
712         iterator->second = thread;
713
714         FOREACH(iterator, m_delegateList)
715         iterator->second = thread;
716     }
717 };
718 }
719 } // namespace DPL
720
721 #endif // DPL_EVENT_SUPPORT_H