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