2 * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 * @file main_event_dispatcher.cpp
18 * @author Przemyslaw Dobrowolski (p.dobrowolsk@samsung.com)
20 * @brief This file is the implementation file of main event dispatcher for EFL
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>
31 IMPLEMENT_SINGLETON(Event::MainEventDispatcher)
36 typedef Singleton<Event::MainEventDispatcher> MainEventDispatcherSingleton;
38 namespace // anonymous
40 static const pthread_t g_threadMain = pthread_self();
42 // Late EFL event handling
43 MainEventDispatcher *g_lateMainEventDispatcher = NULL;
44 } // namespace anonymous
46 MainEventDispatcher::MainEventDispatcher()
48 // Late EFL event handling
49 Assert(g_lateMainEventDispatcher == NULL);
50 g_lateMainEventDispatcher = this;
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
58 // Add new global ECORE event
59 m_eventId = ecore_event_type_new();
61 LogPedantic("ECORE event class registered: " << m_eventId);
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!");
67 // Allocate WaitableEvent
68 m_crossEventCallInvoker = new WaitableEvent();
70 // Register cross event handler
71 m_crossEventCallHandler = ecore_main_fd_handler_add(m_crossEventCallInvoker->GetHandle(), ECORE_FD_READ, &StaticDispatchCrossInvoker, this, NULL, NULL);
73 if (m_crossEventCallHandler == NULL)
74 ThrowMsg(Exception::CreateFailed, "Failed to register cross event handler!");
76 LogPedantic("ECORE cross-event handler registered");
79 MainEventDispatcher::~MainEventDispatcher()
81 // Remove cross event handler
82 ecore_main_fd_handler_del(m_crossEventCallHandler);
83 m_crossEventCallHandler = NULL;
84 LogPedantic("ECORE cross-event handler unregistered");
86 // Remove m_crossEventCallInvoker
87 delete m_crossEventCallInvoker;
88 m_crossEventCallInvoker = NULL;
90 // Remove event class handler
91 ecore_event_handler_del(m_eventCallHandler);
92 m_eventCallHandler = NULL;
94 // Decrement ECORE init count
95 // We do not need ecore routines any more
98 // Late EFL event handling
99 Assert(g_lateMainEventDispatcher == this);
100 g_lateMainEventDispatcher = NULL;
103 void MainEventDispatcher::ResetCrossEventCallHandler()
105 // Remove cross event handler
106 ecore_main_fd_handler_del(m_crossEventCallHandler);
107 m_crossEventCallHandler = NULL;
108 LogPedantic("ECORE cross-event handler unregistered");
110 // Re-allocate WaitableEvent
111 delete m_crossEventCallInvoker;
112 m_crossEventCallInvoker = new WaitableEvent();
114 // Register cross event handler
115 m_crossEventCallHandler =
116 ecore_main_fd_handler_add(m_crossEventCallInvoker->GetHandle(),
118 &StaticDispatchCrossInvoker,
123 if (m_crossEventCallHandler == NULL) {
124 ThrowMsg(Exception::CreateFailed, "Failed to register cross event handler!");
127 LogPedantic("ECORE cross-event handler re-registered");
130 void MainEventDispatcher::StaticDeleteEvent(void *data, void *event)
132 LogPedantic("Static ECORE delete event handler");
134 MainEventDispatcher *This = static_cast<MainEventDispatcher *>(data);
135 AbstractEventCall *abstractEventCall = static_cast<AbstractEventCall *>(event);
137 Assert(This != NULL);
138 Assert(abstractEventCall != NULL);
140 // Late EFL event handling
141 if (g_lateMainEventDispatcher == NULL)
143 LogPedantic("WARNING: Late EFL event delete!");
144 delete abstractEventCall;
148 This->DeleteEvent(abstractEventCall);
152 Eina_Bool MainEventDispatcher::StaticDispatchEvent(void *data, int type, void *event)
154 LogPedantic("Static ECORE dispatch event");
156 MainEventDispatcher *This = static_cast<MainEventDispatcher *>(data);
157 AbstractEventCall *abstractEventCall = static_cast<AbstractEventCall *>(event);
160 Assert(This != NULL);
161 Assert(abstractEventCall != NULL);
163 // Late EFL event handling
164 if (g_lateMainEventDispatcher == NULL)
166 LogPedantic("WARNING: Late EFL event dispatch!");
170 This->DispatchEvent(abstractEventCall);
173 // Continue to handler other ECORE events
174 return ECORE_CALLBACK_RENEW;
177 Eina_Bool MainEventDispatcher::StaticDispatchTimedEvent(void *data)
179 LogPedantic("Static ECORE dispatch timed event");
181 TimedEventStruct *timedEventStruct = static_cast<TimedEventStruct *>(data);
182 MainEventDispatcher *This = timedEventStruct->This;
183 AbstractEventCall *abstractEventCall = timedEventStruct->abstractEventCall;
184 delete timedEventStruct;
186 Assert(This != NULL);
187 Assert(abstractEventCall != NULL);
189 // Late EFL event handling
190 if (g_lateMainEventDispatcher == NULL)
192 LogPedantic("WARNING: Late EFL timed event dispatch!");
196 // Dispatch timed event
197 This->DispatchEvent(abstractEventCall);
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));
204 // Do not continue timed event handlers
205 // This also releases ECORE timer
206 return ECORE_CALLBACK_CANCEL;
209 Eina_Bool MainEventDispatcher::StaticDispatchCrossInvoker(void *data, Ecore_Fd_Handler *fd_handler)
211 LogPedantic("Static ECORE dispatch cross invoker");
213 MainEventDispatcher *This = static_cast<MainEventDispatcher *>(data);
216 Assert(This != NULL);
218 // Late EFL event handling
219 if (g_lateMainEventDispatcher == NULL)
221 LogPedantic("WARNING: Late EFL cross invoker dispatch!");
225 This->DispatchCrossInvoker();
228 return ECORE_CALLBACK_RENEW;
231 void MainEventDispatcher::DeleteEvent(AbstractEventCall *abstractEventCall)
233 LogPedantic("ECORE delete event");
234 delete abstractEventCall;
237 void MainEventDispatcher::DispatchEvent(AbstractEventCall *abstractEventCall)
239 LogPedantic("ECORE dispatch event");
241 // Call event handler
242 abstractEventCall->Call();
245 void MainEventDispatcher::DispatchTimedEvent(AbstractEventCall *abstractEventCall)
247 LogPedantic("ECORE dispatch timed event");
249 // Call event handler
250 abstractEventCall->Call();
253 void MainEventDispatcher::DispatchCrossInvoker()
255 LogPedantic("ECORE dispatch cross invoker");
257 // Steal cross events list
258 WrappedEventCallList stolenCrossEvents;
262 m_crossEventCallInvoker->Reset();
263 Mutex::ScopedLock lock(&m_crossEventCallMutex);
264 m_wrappedCrossEventCallList.swap(stolenCrossEvents);
267 LogPedantic("Cross-thread event list stolen. Number of events: " << stolenCrossEvents.size());
269 // Repush all stolen events
270 WrappedEventCallList::const_iterator eventIterator;
272 for (eventIterator = stolenCrossEvents.begin(); eventIterator != stolenCrossEvents.end(); ++eventIterator)
275 LogPedantic("Dispatching event from invoker");
276 InternalAddEvent(eventIterator->abstractEventCall, eventIterator->timed, eventIterator->dueTime);
279 LogPedantic("Cross-thread events dispatched");
282 void MainEventDispatcher::AddEventCall(AbstractEventCall *abstractEventCall)
284 if (pthread_equal(pthread_self(), g_threadMain))
286 LogPedantic("Main thread ECORE event push");
287 InternalAddEvent(abstractEventCall, false, 0.0);
291 LogPedantic("Cross-thread ECORE event push");
293 // Push event to cross event list
295 Mutex::ScopedLock lock(&m_crossEventCallMutex);
296 m_wrappedCrossEventCallList.push_back(WrappedEventCall(abstractEventCall, false, 0.0));
297 m_crossEventCallInvoker->Signal();
300 LogPedantic("Event pushed to cross-thread event list");
304 void MainEventDispatcher::AddTimedEventCall(AbstractEventCall *abstractEventCall, double dueTime)
306 if (pthread_equal(pthread_self(), g_threadMain))
308 LogPedantic("Main thread timed ECORE event push");
309 InternalAddEvent(abstractEventCall, true, dueTime);
313 LogPedantic("Cross-thread timed ECORE event push");
315 // Push event to cross event list
317 Mutex::ScopedLock lock(&m_crossEventCallMutex);
318 m_wrappedCrossEventCallList.push_back(WrappedEventCall(abstractEventCall, true, dueTime));
319 m_crossEventCallInvoker->Signal();
322 LogPedantic("Event pushed to cross-thread event list");
326 void MainEventDispatcher::InternalAddEvent(AbstractEventCall *abstractEventCall, bool timed, double dueTime)
328 LogPedantic("Adding base event");
332 // Push timed event onto ecore stack
333 TimedEventStruct* eventData = new TimedEventStruct(abstractEventCall, this);
334 Ecore_Timer *timedEvent = ecore_timer_add(dueTime, &StaticDispatchTimedEvent, eventData);
336 if (timedEvent == NULL)
339 delete abstractEventCall;
340 ThrowMsg(Exception::AddTimedEventFailed, "Failed to add ECORE timed event");
343 LogPedantic("Timed wrapped event added");
347 // Push immediate event onto ecore stack
348 Ecore_Event *event = ecore_event_add(m_eventId, abstractEventCall, &StaticDeleteEvent, this);
352 delete abstractEventCall;
353 ThrowMsg(Exception::AddEventFailed, "Failed to add ECORE event");
356 LogPedantic("Wrapped event added");
360 MainEventDispatcher& GetMainEventDispatcherInstance()
362 return MainEventDispatcherSingleton::Instance();