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
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>
30 IMPLEMENT_SINGLETON(Event::MainEventDispatcher)
35 typedef Singleton<Event::MainEventDispatcher> MainEventDispatcherSingleton;
37 namespace // anonymous
39 static const pthread_t g_threadMain = pthread_self();
41 // Late EFL event handling
42 MainEventDispatcher *g_lateMainEventDispatcher = NULL;
43 } // namespace anonymous
45 MainEventDispatcher::MainEventDispatcher()
47 // Late EFL event handling
48 Assert(g_lateMainEventDispatcher == NULL);
49 g_lateMainEventDispatcher = this;
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
57 // Add new global ECORE event
58 m_eventId = ecore_event_type_new();
60 LogPedantic("ECORE event class registered: " << m_eventId);
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!");
66 // Register cross event handler
67 m_crossEventCallHandler = ecore_main_fd_handler_add(m_crossEventCallInvoker.GetHandle(), ECORE_FD_READ, &StaticDispatchCrossInvoker, this, NULL, NULL);
69 if (m_crossEventCallHandler == NULL)
70 ThrowMsg(Exception::CreateFailed, "Failed to register cross event handler!");
72 LogPedantic("ECORE cross-event handler registered");
75 MainEventDispatcher::~MainEventDispatcher()
77 // Remove event class handler
78 ecore_event_handler_del(m_eventCallHandler);
79 m_eventCallHandler = NULL;
81 // Remove cross event handler
82 ecore_main_fd_handler_del(m_crossEventCallHandler);
83 m_crossEventCallHandler = NULL;
85 LogPedantic("ECORE cross-event handler unregistered");
87 // Decrement ECORE init count
88 // We do not need ecore routines any more
91 // Late EFL event handling
92 Assert(g_lateMainEventDispatcher == this);
93 g_lateMainEventDispatcher = NULL;
96 void MainEventDispatcher::StaticDeleteEvent(void *data, void *event)
98 LogPedantic("Static ECORE delete event handler");
100 MainEventDispatcher *This = static_cast<MainEventDispatcher *>(data);
101 AbstractEventCall *abstractEventCall = static_cast<AbstractEventCall *>(event);
103 Assert(This != NULL);
104 Assert(abstractEventCall != NULL);
106 // Late EFL event handling
107 if (g_lateMainEventDispatcher == NULL)
109 LogPedantic("WARNING: Late EFL event delete!");
110 delete abstractEventCall;
114 This->DeleteEvent(abstractEventCall);
118 Eina_Bool MainEventDispatcher::StaticDispatchEvent(void *data, int type, void *event)
120 LogPedantic("Static ECORE dispatch event");
122 MainEventDispatcher *This = static_cast<MainEventDispatcher *>(data);
123 AbstractEventCall *abstractEventCall = static_cast<AbstractEventCall *>(event);
126 Assert(This != NULL);
127 Assert(abstractEventCall != NULL);
129 // Late EFL event handling
130 if (g_lateMainEventDispatcher == NULL)
132 LogPedantic("WARNING: Late EFL event dispatch!");
136 This->DispatchEvent(abstractEventCall);
139 // Continue to handler other ECORE events
140 return ECORE_CALLBACK_RENEW;
143 Eina_Bool MainEventDispatcher::StaticDispatchTimedEvent(void *data)
145 LogPedantic("Static ECORE dispatch timed event");
147 TimedEventStruct *timedEventStruct = static_cast<TimedEventStruct *>(data);
148 MainEventDispatcher *This = timedEventStruct->This;
149 AbstractEventCall *abstractEventCall = timedEventStruct->abstractEventCall;
150 delete timedEventStruct;
152 Assert(This != NULL);
153 Assert(abstractEventCall != NULL);
155 // Late EFL event handling
156 if (g_lateMainEventDispatcher == NULL)
158 LogPedantic("WARNING: Late EFL timed event dispatch!");
162 // Dispatch timed event
163 This->DispatchEvent(abstractEventCall);
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));
170 // Do not continue timed event handlers
171 // This also releases ECORE timer
172 return ECORE_CALLBACK_CANCEL;
175 Eina_Bool MainEventDispatcher::StaticDispatchCrossInvoker(void *data, Ecore_Fd_Handler *fd_handler)
177 LogPedantic("Static ECORE dispatch cross invoker");
179 MainEventDispatcher *This = static_cast<MainEventDispatcher *>(data);
182 Assert(This != NULL);
184 // Late EFL event handling
185 if (g_lateMainEventDispatcher == NULL)
187 LogPedantic("WARNING: Late EFL cross invoker dispatch!");
191 This->DispatchCrossInvoker();
194 return ECORE_CALLBACK_RENEW;
197 void MainEventDispatcher::DeleteEvent(AbstractEventCall *abstractEventCall)
199 LogPedantic("ECORE delete event");
200 delete abstractEventCall;
203 void MainEventDispatcher::DispatchEvent(AbstractEventCall *abstractEventCall)
205 LogPedantic("ECORE dispatch event");
207 // Call event handler
208 abstractEventCall->Call();
211 void MainEventDispatcher::DispatchTimedEvent(AbstractEventCall *abstractEventCall)
213 LogPedantic("ECORE dispatch timed event");
215 // Call event handler
216 abstractEventCall->Call();
219 void MainEventDispatcher::DispatchCrossInvoker()
221 LogPedantic("ECORE dispatch cross invoker");
223 // Steal cross events list
224 WrappedEventCallList stolenCrossEvents;
228 m_crossEventCallInvoker.Reset();
229 Mutex::ScopedLock lock(&m_crossEventCallMutex);
230 m_wrappedCrossEventCallList.swap(stolenCrossEvents);
233 LogPedantic("Cross-thread event list stolen. Number of events: " << stolenCrossEvents.size());
235 // Repush all stolen events
236 WrappedEventCallList::const_iterator eventIterator;
238 for (eventIterator = stolenCrossEvents.begin(); eventIterator != stolenCrossEvents.end(); ++eventIterator)
241 LogPedantic("Dispatching event from invoker");
242 InternalAddEvent(eventIterator->abstractEventCall, eventIterator->timed, eventIterator->dueTime);
245 LogPedantic("Cross-thread events dispatched");
248 void MainEventDispatcher::AddEventCall(AbstractEventCall *abstractEventCall)
250 if (pthread_equal(pthread_self(), g_threadMain))
252 LogPedantic("Main thread ECORE event push");
253 InternalAddEvent(abstractEventCall, false, 0.0);
257 LogPedantic("Cross-thread ECORE event push");
259 // Push event to cross event list
261 Mutex::ScopedLock lock(&m_crossEventCallMutex);
262 m_wrappedCrossEventCallList.push_back(WrappedEventCall(abstractEventCall, false, 0.0));
263 m_crossEventCallInvoker.Signal();
266 LogPedantic("Event pushed to cross-thread event list");
270 void MainEventDispatcher::AddTimedEventCall(AbstractEventCall *abstractEventCall, double dueTime)
272 if (pthread_equal(pthread_self(), g_threadMain))
274 LogPedantic("Main thread timed ECORE event push");
275 InternalAddEvent(abstractEventCall, true, dueTime);
279 LogPedantic("Cross-thread timed ECORE event push");
281 // Push event to cross event list
283 Mutex::ScopedLock lock(&m_crossEventCallMutex);
284 m_wrappedCrossEventCallList.push_back(WrappedEventCall(abstractEventCall, true, dueTime));
285 m_crossEventCallInvoker.Signal();
288 LogPedantic("Event pushed to cross-thread event list");
292 void MainEventDispatcher::InternalAddEvent(AbstractEventCall *abstractEventCall, bool timed, double dueTime)
294 LogPedantic("Adding base event");
298 // Push timed event onto ecore stack
299 TimedEventStruct* eventData = new TimedEventStruct(abstractEventCall, this);
300 Ecore_Timer *timedEvent = ecore_timer_add(dueTime, &StaticDispatchTimedEvent, eventData);
302 if (timedEvent == NULL)
305 delete abstractEventCall;
306 ThrowMsg(Exception::AddTimedEventFailed, "Failed to add ECORE timed event");
309 LogPedantic("Timed wrapped event added");
313 // Push immediate event onto ecore stack
314 Ecore_Event *event = ecore_event_add(m_eventId, abstractEventCall, &StaticDeleteEvent, this);
318 delete abstractEventCall;
319 ThrowMsg(Exception::AddEventFailed, "Failed to add ECORE event");
322 LogPedantic("Wrapped event added");
326 MainEventDispatcher& GetMainEventDispatcherInstance()
328 return MainEventDispatcherSingleton::Instance();