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