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
24 #include <dpl/event/main_event_dispatcher.h>
25 #include <dpl/log/wrt_log.h>
26 #include <dpl/assert.h>
27 #include <dpl/singleton_impl.h>
30 IMPLEMENT_SINGLETON(Event::MainEventDispatcher)
33 typedef Singleton<Event::MainEventDispatcher> MainEventDispatcherSingleton;
35 namespace // anonymous
37 static const pthread_t g_threadMain = pthread_self();
39 // Late EFL event handling
40 MainEventDispatcher *g_lateMainEventDispatcher = NULL;
41 } // namespace anonymous
43 MainEventDispatcher::MainEventDispatcher()
45 // Late EFL event handling
46 Assert(g_lateMainEventDispatcher == NULL);
47 g_lateMainEventDispatcher = this;
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
55 // Add new global ECORE event
56 m_eventId = ecore_event_type_new();
58 WrtLogD("ECORE event class registered: %i", m_eventId);
60 // Register event class handler
61 if ((m_eventCallHandler =
62 ecore_event_handler_add(m_eventId, &StaticDispatchEvent,
65 ThrowMsg(Exception::CreateFailed, "Failed to register event handler!");
68 // Allocate WaitableEvent
69 m_crossEventCallInvoker = new WaitableEvent();
71 // Register cross event handler
72 m_crossEventCallHandler = ecore_main_fd_handler_add(
73 m_crossEventCallInvoker->GetHandle(),
75 &StaticDispatchCrossInvoker,
80 if (m_crossEventCallHandler == NULL) {
81 ThrowMsg(Exception::CreateFailed,
82 "Failed to register cross event handler!");
85 WrtLogD("ECORE cross-event handler registered");
88 MainEventDispatcher::~MainEventDispatcher()
90 // Remove cross event handler
91 ecore_main_fd_handler_del(m_crossEventCallHandler);
92 m_crossEventCallHandler = NULL;
93 WrtLogD("ECORE cross-event handler unregistered");
95 // Remove m_crossEventCallInvoker
96 delete m_crossEventCallInvoker;
97 m_crossEventCallInvoker = NULL;
99 // Remove event class handler
100 ecore_event_handler_del(m_eventCallHandler);
101 m_eventCallHandler = NULL;
103 // Decrement ECORE init count
104 // We do not need ecore routines any more
107 // Late EFL event handling
108 Assert(g_lateMainEventDispatcher == this);
109 g_lateMainEventDispatcher = NULL;
112 void MainEventDispatcher::ResetCrossEventCallHandler()
114 // Remove cross event handler
115 ecore_main_fd_handler_del(m_crossEventCallHandler);
116 m_crossEventCallHandler = NULL;
117 WrtLogD("ECORE cross-event handler unregistered");
119 // Re-allocate WaitableEvent
120 delete m_crossEventCallInvoker;
121 m_crossEventCallInvoker = new WaitableEvent();
123 // Register cross event handler
124 m_crossEventCallHandler =
125 ecore_main_fd_handler_add(m_crossEventCallInvoker->GetHandle(),
127 &StaticDispatchCrossInvoker,
132 if (m_crossEventCallHandler == NULL) {
133 ThrowMsg(Exception::CreateFailed,
134 "Failed to register cross event handler!");
137 WrtLogD("ECORE cross-event handler re-registered");
140 void MainEventDispatcher::StaticDeleteEvent(void *data, void *event)
142 WrtLogD("Static ECORE delete event handler");
144 MainEventDispatcher *This = static_cast<MainEventDispatcher *>(data);
145 AbstractEventCall *abstractEventCall =
146 static_cast<AbstractEventCall *>(event);
148 Assert(This != NULL);
149 Assert(abstractEventCall != NULL);
151 // Late EFL event handling
152 if (g_lateMainEventDispatcher == NULL) {
153 WrtLogD("WARNING: Late EFL event delete!");
154 delete abstractEventCall;
156 This->DeleteEvent(abstractEventCall);
160 Eina_Bool MainEventDispatcher::StaticDispatchEvent(void *data,
164 WrtLogD("Static ECORE dispatch event");
166 MainEventDispatcher *This = static_cast<MainEventDispatcher *>(data);
167 AbstractEventCall *abstractEventCall =
168 static_cast<AbstractEventCall *>(event);
171 Assert(This != NULL);
172 Assert(abstractEventCall != NULL);
174 // Late EFL event handling
175 if (g_lateMainEventDispatcher == NULL) {
176 WrtLogD("WARNING: Late EFL event dispatch!");
178 This->DispatchEvent(abstractEventCall);
181 // Continue to handler other ECORE events
182 return ECORE_CALLBACK_RENEW;
185 Eina_Bool MainEventDispatcher::StaticDispatchTimedEvent(void *data)
187 WrtLogD("Static ECORE dispatch timed event");
189 TimedEventStruct *timedEventStruct = static_cast<TimedEventStruct *>(data);
190 MainEventDispatcher *This = timedEventStruct->This;
191 AbstractEventCall *abstractEventCall = timedEventStruct->abstractEventCall;
192 delete timedEventStruct;
194 Assert(This != NULL);
195 Assert(abstractEventCall != NULL);
197 // Late EFL event handling
198 if (g_lateMainEventDispatcher == NULL) {
199 WrtLogD("WARNING: Late EFL timed event dispatch!");
201 // Dispatch timed event
202 This->DispatchEvent(abstractEventCall);
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));
210 // Do not continue timed event handlers
211 // This also releases ECORE timer
212 return ECORE_CALLBACK_CANCEL;
215 Eina_Bool MainEventDispatcher::StaticDispatchCrossInvoker(
220 WrtLogD("Static ECORE dispatch cross invoker");
222 MainEventDispatcher *This = static_cast<MainEventDispatcher *>(data);
225 Assert(This != NULL);
227 // Late EFL event handling
228 if (g_lateMainEventDispatcher == NULL) {
229 WrtLogD("WARNING: Late EFL cross invoker dispatch!");
231 This->DispatchCrossInvoker();
234 return ECORE_CALLBACK_RENEW;
237 void MainEventDispatcher::DeleteEvent(AbstractEventCall *abstractEventCall)
239 WrtLogD("ECORE delete event");
240 delete abstractEventCall;
243 void MainEventDispatcher::DispatchEvent(AbstractEventCall *abstractEventCall)
245 WrtLogD("ECORE dispatch event");
247 // Call event handler
248 abstractEventCall->Call();
251 void MainEventDispatcher::DispatchTimedEvent(
252 AbstractEventCall *abstractEventCall)
254 WrtLogD("ECORE dispatch timed event");
256 // Call event handler
257 abstractEventCall->Call();
260 void MainEventDispatcher::DispatchCrossInvoker()
262 WrtLogD("ECORE dispatch cross invoker");
264 // Steal cross events list
265 WrappedEventCallList stolenCrossEvents;
269 m_crossEventCallInvoker->Reset();
270 std::lock_guard<std::mutex> lock(m_crossEventCallMutex);
271 m_wrappedCrossEventCallList.swap(stolenCrossEvents);
274 WrtLogD("Cross-thread event list stolen. Number of events: %i",
275 stolenCrossEvents.size());
277 // Repush all stolen events
278 WrappedEventCallList::const_iterator eventIterator;
280 for (eventIterator = stolenCrossEvents.begin();
281 eventIterator != stolenCrossEvents.end();
285 WrtLogD("Dispatching event from invoker");
286 InternalAddEvent(eventIterator->abstractEventCall,
287 eventIterator->timed,
288 eventIterator->dueTime);
291 WrtLogD("Cross-thread events dispatched");
294 void MainEventDispatcher::AddEventCall(AbstractEventCall *abstractEventCall)
296 if (pthread_equal(pthread_self(), g_threadMain)) {
297 WrtLogD("Main thread ECORE event push");
298 InternalAddEvent(abstractEventCall, false, 0.0);
300 WrtLogD("Cross-thread ECORE event push");
302 // Push event to cross event list
304 std::lock_guard<std::mutex> lock(m_crossEventCallMutex);
305 m_wrappedCrossEventCallList.push_back(WrappedEventCall(
306 abstractEventCall, false,
308 m_crossEventCallInvoker->Signal();
311 WrtLogD("Event pushed to cross-thread event list");
315 void MainEventDispatcher::AddTimedEventCall(
316 AbstractEventCall *abstractEventCall,
319 if (pthread_equal(pthread_self(), g_threadMain)) {
320 WrtLogD("Main thread timed ECORE event push");
321 InternalAddEvent(abstractEventCall, true, dueTime);
323 WrtLogD("Cross-thread timed ECORE event push");
325 // Push event to cross event list
327 std::lock_guard<std::mutex> lock(m_crossEventCallMutex);
328 m_wrappedCrossEventCallList.push_back(WrappedEventCall(
329 abstractEventCall, true,
331 m_crossEventCallInvoker->Signal();
334 WrtLogD("Event pushed to cross-thread event list");
338 void MainEventDispatcher::InternalAddEvent(AbstractEventCall *abstractEventCall,
342 WrtLogD("Adding base event");
345 // Push timed event onto ecore stack
346 TimedEventStruct* eventData = new TimedEventStruct(abstractEventCall,
348 Ecore_Timer *timedEvent = ecore_timer_add(dueTime,
349 &StaticDispatchTimedEvent,
352 if (timedEvent == NULL) {
354 delete abstractEventCall;
355 ThrowMsg(Exception::AddTimedEventFailed,
356 "Failed to add ECORE timed event");
359 WrtLogD("Timed wrapped event added");
361 // Push immediate event onto ecore stack
362 Ecore_Event *event = ecore_event_add(m_eventId,
368 delete abstractEventCall;
369 ThrowMsg(Exception::AddEventFailed, "Failed to add ECORE event");
372 WrtLogD("Wrapped event added");
376 MainEventDispatcher& GetMainEventDispatcherInstance()
378 return MainEventDispatcherSingleton::Instance();