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/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 LogPedantic("ECORE event class registered: " << 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 LogPedantic("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 LogPedantic("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 LogPedantic("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 LogPedantic("ECORE cross-event handler re-registered");
140 void MainEventDispatcher::StaticDeleteEvent(void *data, void *event)
142 LogPedantic("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 LogPedantic("WARNING: Late EFL event delete!");
154 delete abstractEventCall;
156 This->DeleteEvent(abstractEventCall);
160 Eina_Bool MainEventDispatcher::StaticDispatchEvent(void *data,
164 LogPedantic("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 LogPedantic("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 LogPedantic("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 LogPedantic("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 LogPedantic("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 LogPedantic("WARNING: Late EFL cross invoker dispatch!");
231 This->DispatchCrossInvoker();
234 return ECORE_CALLBACK_RENEW;
237 void MainEventDispatcher::DeleteEvent(AbstractEventCall *abstractEventCall)
239 LogPedantic("ECORE delete event");
240 delete abstractEventCall;
243 void MainEventDispatcher::DispatchEvent(AbstractEventCall *abstractEventCall)
245 LogPedantic("ECORE dispatch event");
247 // Call event handler
248 abstractEventCall->Call();
251 void MainEventDispatcher::DispatchTimedEvent(
252 AbstractEventCall *abstractEventCall)
254 LogPedantic("ECORE dispatch timed event");
256 // Call event handler
257 abstractEventCall->Call();
260 void MainEventDispatcher::DispatchCrossInvoker()
262 LogPedantic("ECORE dispatch cross invoker");
264 // Steal cross events list
265 WrappedEventCallList stolenCrossEvents;
269 m_crossEventCallInvoker->Reset();
270 Mutex::ScopedLock lock(&m_crossEventCallMutex);
271 m_wrappedCrossEventCallList.swap(stolenCrossEvents);
275 "Cross-thread event list stolen. Number of events: " <<
276 stolenCrossEvents.size());
278 // Repush all stolen events
279 WrappedEventCallList::const_iterator eventIterator;
281 for (eventIterator = stolenCrossEvents.begin();
282 eventIterator != stolenCrossEvents.end();
286 LogPedantic("Dispatching event from invoker");
287 InternalAddEvent(eventIterator->abstractEventCall,
288 eventIterator->timed,
289 eventIterator->dueTime);
292 LogPedantic("Cross-thread events dispatched");
295 void MainEventDispatcher::AddEventCall(AbstractEventCall *abstractEventCall)
297 if (pthread_equal(pthread_self(), g_threadMain)) {
298 LogPedantic("Main thread ECORE event push");
299 InternalAddEvent(abstractEventCall, false, 0.0);
301 LogPedantic("Cross-thread ECORE event push");
303 // Push event to cross event list
305 Mutex::ScopedLock lock(&m_crossEventCallMutex);
306 m_wrappedCrossEventCallList.push_back(WrappedEventCall(
307 abstractEventCall, false,
309 m_crossEventCallInvoker->Signal();
312 LogPedantic("Event pushed to cross-thread event list");
316 void MainEventDispatcher::AddTimedEventCall(
317 AbstractEventCall *abstractEventCall,
320 if (pthread_equal(pthread_self(), g_threadMain)) {
321 LogPedantic("Main thread timed ECORE event push");
322 InternalAddEvent(abstractEventCall, true, dueTime);
324 LogPedantic("Cross-thread timed ECORE event push");
326 // Push event to cross event list
328 Mutex::ScopedLock lock(&m_crossEventCallMutex);
329 m_wrappedCrossEventCallList.push_back(WrappedEventCall(
330 abstractEventCall, true,
332 m_crossEventCallInvoker->Signal();
335 LogPedantic("Event pushed to cross-thread event list");
339 void MainEventDispatcher::InternalAddEvent(AbstractEventCall *abstractEventCall,
343 LogPedantic("Adding base event");
346 // Push timed event onto ecore stack
347 TimedEventStruct* eventData = new TimedEventStruct(abstractEventCall,
349 Ecore_Timer *timedEvent = ecore_timer_add(dueTime,
350 &StaticDispatchTimedEvent,
353 if (timedEvent == NULL) {
355 delete abstractEventCall;
356 ThrowMsg(Exception::AddTimedEventFailed,
357 "Failed to add ECORE timed event");
360 LogPedantic("Timed wrapped event added");
362 // Push immediate event onto ecore stack
363 Ecore_Event *event = ecore_event_add(m_eventId,
369 delete abstractEventCall;
370 ThrowMsg(Exception::AddEventFailed, "Failed to add ECORE event");
373 LogPedantic("Wrapped event added");
377 MainEventDispatcher& GetMainEventDispatcherInstance()
379 return MainEventDispatcherSingleton::Instance();