Initialize Tizen 2.3
[framework/web/wrt-commons.git] / modules_wearable / event / src / main_event_dispatcher.cpp
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        main_event_dispatcher.cpp
18  * @author      Przemyslaw Dobrowolski (p.dobrowolsk@samsung.com)
19  * @version     1.0
20  * @brief       This file is the implementation file of main event dispatcher
21  * for EFL
22  */
23 #include <stddef.h>
24 #include <dpl/event/main_event_dispatcher.h>
25 #include <dpl/log/log.h>
26 #include <dpl/assert.h>
27 #include <dpl/singleton_impl.h>
28
29 namespace DPL {
30 IMPLEMENT_SINGLETON(Event::MainEventDispatcher)
31
32 namespace Event {
33 typedef Singleton<Event::MainEventDispatcher> MainEventDispatcherSingleton;
34
35 namespace // anonymous
36 {
37 static const pthread_t g_threadMain = pthread_self();
38
39 // Late EFL event handling
40 MainEventDispatcher *g_lateMainEventDispatcher = NULL;
41 } // namespace anonymous
42
43 MainEventDispatcher::MainEventDispatcher()
44 {
45     // Late EFL event handling
46     Assert(g_lateMainEventDispatcher == NULL);
47     g_lateMainEventDispatcher = this;
48
49     // Increment ECORE init count to ensure we have all
50     // subsystems correctly set-up until main dispatcher dtor
51     // This is especially important when MainEventDispatcher
52     // is a global object destroyed no earlier than crt destroy routine
53     ecore_init();
54
55     // Add new global ECORE event
56     m_eventId = ecore_event_type_new();
57
58     LogPedantic("ECORE event class registered: " << m_eventId);
59
60     // Register event class handler
61     if ((m_eventCallHandler =
62              ecore_event_handler_add(m_eventId, &StaticDispatchEvent,
63                                      this)) == NULL)
64     {
65         ThrowMsg(Exception::CreateFailed, "Failed to register event handler!");
66     }
67
68     // Allocate WaitableEvent
69     m_crossEventCallInvoker = new WaitableEvent();
70
71     // Register cross event handler
72     m_crossEventCallHandler = ecore_main_fd_handler_add(
73             m_crossEventCallInvoker->GetHandle(),
74             ECORE_FD_READ,
75             &StaticDispatchCrossInvoker,
76             this,
77             NULL,
78             NULL);
79
80     if (m_crossEventCallHandler == NULL) {
81         ThrowMsg(Exception::CreateFailed,
82                  "Failed to register cross event handler!");
83     }
84
85     LogPedantic("ECORE cross-event handler registered");
86 }
87
88 MainEventDispatcher::~MainEventDispatcher()
89 {
90     // Remove cross event handler
91     ecore_main_fd_handler_del(m_crossEventCallHandler);
92     m_crossEventCallHandler = NULL;
93     LogPedantic("ECORE cross-event handler unregistered");
94
95     // Remove m_crossEventCallInvoker
96     delete m_crossEventCallInvoker;
97     m_crossEventCallInvoker = NULL;
98
99     // Remove event class handler
100     ecore_event_handler_del(m_eventCallHandler);
101     m_eventCallHandler = NULL;
102
103     // Decrement ECORE init count
104     // We do not need ecore routines any more
105     ecore_shutdown();
106
107     // Late EFL event handling
108     Assert(g_lateMainEventDispatcher == this);
109     g_lateMainEventDispatcher = NULL;
110 }
111
112 void MainEventDispatcher::ResetCrossEventCallHandler()
113 {
114     // Remove cross event handler
115     ecore_main_fd_handler_del(m_crossEventCallHandler);
116     m_crossEventCallHandler = NULL;
117     LogPedantic("ECORE cross-event handler unregistered");
118
119     // Re-allocate WaitableEvent
120     delete m_crossEventCallInvoker;
121     m_crossEventCallInvoker = new WaitableEvent();
122
123     // Register cross event handler
124     m_crossEventCallHandler =
125         ecore_main_fd_handler_add(m_crossEventCallInvoker->GetHandle(),
126                                   ECORE_FD_READ,
127                                   &StaticDispatchCrossInvoker,
128                                   this,
129                                   NULL,
130                                   NULL);
131
132     if (m_crossEventCallHandler == NULL) {
133         ThrowMsg(Exception::CreateFailed,
134                  "Failed to register cross event handler!");
135     }
136
137     LogPedantic("ECORE cross-event handler re-registered");
138 }
139
140 void MainEventDispatcher::StaticDeleteEvent(void *data, void *event)
141 {
142     LogPedantic("Static ECORE delete event handler");
143
144     MainEventDispatcher *This = static_cast<MainEventDispatcher *>(data);
145     AbstractEventCall *abstractEventCall =
146         static_cast<AbstractEventCall *>(event);
147
148     Assert(This != NULL);
149     Assert(abstractEventCall != NULL);
150
151     // Late EFL event handling
152     if (g_lateMainEventDispatcher == NULL) {
153         LogPedantic("WARNING: Late EFL event delete!");
154         delete abstractEventCall;
155     } else {
156         This->DeleteEvent(abstractEventCall);
157     }
158 }
159
160 Eina_Bool MainEventDispatcher::StaticDispatchEvent(void *data,
161                                                    int type,
162                                                    void *event)
163 {
164     LogPedantic("Static ECORE dispatch event");
165
166     MainEventDispatcher *This = static_cast<MainEventDispatcher *>(data);
167     AbstractEventCall *abstractEventCall =
168         static_cast<AbstractEventCall *>(event);
169     (void)type;
170
171     Assert(This != NULL);
172     Assert(abstractEventCall != NULL);
173
174     // Late EFL event handling
175     if (g_lateMainEventDispatcher == NULL) {
176         LogPedantic("WARNING: Late EFL event dispatch!");
177     } else {
178         This->DispatchEvent(abstractEventCall);
179     }
180
181     // Continue to handler other ECORE events
182     return ECORE_CALLBACK_RENEW;
183 }
184
185 Eina_Bool MainEventDispatcher::StaticDispatchTimedEvent(void *data)
186 {
187     LogPedantic("Static ECORE dispatch timed event");
188
189     TimedEventStruct *timedEventStruct = static_cast<TimedEventStruct *>(data);
190     MainEventDispatcher *This = timedEventStruct->This;
191     AbstractEventCall *abstractEventCall = timedEventStruct->abstractEventCall;
192     delete timedEventStruct;
193
194     Assert(This != NULL);
195     Assert(abstractEventCall != NULL);
196
197     // Late EFL event handling
198     if (g_lateMainEventDispatcher == NULL) {
199         LogPedantic("WARNING: Late EFL timed event dispatch!");
200     } else {
201         // Dispatch timed event
202         This->DispatchEvent(abstractEventCall);
203     }
204
205     // And delete manually event, because ECORE does not
206     // use delete handler for timers
207     StaticDeleteEvent(static_cast<void *>(This),
208                       static_cast<void *>(abstractEventCall));
209
210     // Do not continue timed event handlers
211     // This also releases ECORE timer
212     return ECORE_CALLBACK_CANCEL;
213 }
214
215 Eina_Bool MainEventDispatcher::StaticDispatchCrossInvoker(
216     void *data,
217     Ecore_Fd_Handler *
218     fd_handler)
219 {
220     LogPedantic("Static ECORE dispatch cross invoker");
221
222     MainEventDispatcher *This = static_cast<MainEventDispatcher *>(data);
223     (void)fd_handler;
224
225     Assert(This != NULL);
226
227     // Late EFL event handling
228     if (g_lateMainEventDispatcher == NULL) {
229         LogPedantic("WARNING: Late EFL cross invoker dispatch!");
230     } else {
231         This->DispatchCrossInvoker();
232     }
233
234     return ECORE_CALLBACK_RENEW;
235 }
236
237 void MainEventDispatcher::DeleteEvent(AbstractEventCall *abstractEventCall)
238 {
239     LogPedantic("ECORE delete event");
240     delete abstractEventCall;
241 }
242
243 void MainEventDispatcher::DispatchEvent(AbstractEventCall *abstractEventCall)
244 {
245     LogPedantic("ECORE dispatch event");
246
247     // Call event handler
248     abstractEventCall->Call();
249 }
250
251 void MainEventDispatcher::DispatchTimedEvent(
252     AbstractEventCall *abstractEventCall)
253 {
254     LogPedantic("ECORE dispatch timed event");
255
256     // Call event handler
257     abstractEventCall->Call();
258 }
259
260 void MainEventDispatcher::DispatchCrossInvoker()
261 {
262     LogPedantic("ECORE dispatch cross invoker");
263
264     // Steal cross events list
265     WrappedEventCallList stolenCrossEvents;
266
267     // Critical section
268     {
269         m_crossEventCallInvoker->Reset();
270         Mutex::ScopedLock lock(&m_crossEventCallMutex);
271         m_wrappedCrossEventCallList.swap(stolenCrossEvents);
272     }
273
274     LogPedantic(
275         "Cross-thread event list stolen. Number of events: " <<
276         stolenCrossEvents.size());
277
278     // Repush all stolen events
279     WrappedEventCallList::const_iterator eventIterator;
280
281     for (eventIterator = stolenCrossEvents.begin();
282          eventIterator != stolenCrossEvents.end();
283          ++eventIterator)
284     {
285         // Unwrap events
286         LogPedantic("Dispatching event from invoker");
287         InternalAddEvent(eventIterator->abstractEventCall,
288                          eventIterator->timed,
289                          eventIterator->dueTime);
290     }
291
292     LogPedantic("Cross-thread events dispatched");
293 }
294
295 void MainEventDispatcher::AddEventCall(AbstractEventCall *abstractEventCall)
296 {
297     if (pthread_equal(pthread_self(), g_threadMain)) {
298         LogPedantic("Main thread ECORE event push");
299         InternalAddEvent(abstractEventCall, false, 0.0);
300     } else {
301         LogPedantic("Cross-thread ECORE event push");
302
303         // Push event to cross event list
304         {
305             Mutex::ScopedLock lock(&m_crossEventCallMutex);
306             m_wrappedCrossEventCallList.push_back(WrappedEventCall(
307                                                       abstractEventCall, false,
308                                                       0.0));
309             m_crossEventCallInvoker->Signal();
310         }
311
312         LogPedantic("Event pushed to cross-thread event list");
313     }
314 }
315
316 void MainEventDispatcher::AddTimedEventCall(
317     AbstractEventCall *abstractEventCall,
318     double dueTime)
319 {
320     if (pthread_equal(pthread_self(), g_threadMain)) {
321         LogPedantic("Main thread timed ECORE event push");
322         InternalAddEvent(abstractEventCall, true, dueTime);
323     } else {
324         LogPedantic("Cross-thread timed ECORE event push");
325
326         // Push event to cross event list
327         {
328             Mutex::ScopedLock lock(&m_crossEventCallMutex);
329             m_wrappedCrossEventCallList.push_back(WrappedEventCall(
330                                                       abstractEventCall, true,
331                                                       dueTime));
332             m_crossEventCallInvoker->Signal();
333         }
334
335         LogPedantic("Event pushed to cross-thread event list");
336     }
337 }
338
339 void MainEventDispatcher::InternalAddEvent(AbstractEventCall *abstractEventCall,
340                                            bool timed,
341                                            double dueTime)
342 {
343     LogPedantic("Adding base event");
344
345     if (timed == true) {
346         // Push timed event onto ecore stack
347         TimedEventStruct* eventData = new TimedEventStruct(abstractEventCall,
348                                                            this);
349         Ecore_Timer *timedEvent = ecore_timer_add(dueTime,
350                                                   &StaticDispatchTimedEvent,
351                                                   eventData);
352
353         if (timedEvent == NULL) {
354             delete eventData;
355             delete abstractEventCall;
356             ThrowMsg(Exception::AddTimedEventFailed,
357                      "Failed to add ECORE timed event");
358         }
359
360         LogPedantic("Timed wrapped event added");
361     } else {
362         // Push immediate event onto ecore stack
363         Ecore_Event *event = ecore_event_add(m_eventId,
364                                              abstractEventCall,
365                                              &StaticDeleteEvent,
366                                              this);
367
368         if (event == NULL) {
369             delete abstractEventCall;
370             ThrowMsg(Exception::AddEventFailed, "Failed to add ECORE event");
371         }
372
373         LogPedantic("Wrapped event added");
374     }
375 }
376
377 MainEventDispatcher& GetMainEventDispatcherInstance()
378 {
379     return MainEventDispatcherSingleton::Instance();
380 }
381 }
382 } // namespace DPL