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.
18 * @author Przemyslaw Dobrowolski (p.dobrowolsk@samsung.com)
20 * @brief This file is the implementation file of main for EFL
24 #include <dpl/log/log.h>
25 #include <sys/select.h>
28 #include <dpl/assert.h>
29 #include <dpl/singleton_impl.h>
31 IMPLEMENT_SINGLETON(DPL::Main)
34 namespace // anonymous
36 // Late EFL event handling
37 Main *g_lateMain = NULL;
38 } // namespace anonymous
41 #ifdef DPL_ENABLE_GLIB_LOOP_INTEGRATION_WORKAROUND
42 // GLIB loop intergration workaround
43 : m_oldEcoreSelect(NULL)
44 #endif // DPL_ENABLE_GLIB_LOOP_INTEGRATION_WORKAROUND
46 // Late EFL event handling
47 Assert(g_lateMain == NULL);
50 // Increment ECORE init count to ensure we have all
51 // subsystems correctly set-up until main dispatcher dtor
52 // This is especially important when MainEventDispatcher
53 // is a global object destroyed no earlier than crt destroy routine
56 #ifdef DPL_ENABLE_GLIB_LOOP_INTEGRATION_WORKAROUND
57 // GLIB loop intergration workaround
60 Ecore_Select_Function pointer;
61 EcoreSelectType function;
64 convert.pointer = ecore_main_loop_select_func_get();
65 m_oldEcoreSelect = convert.function;
67 ecore_main_loop_select_func_set(&EcoreSelectInterceptor);
68 #endif // DPL_ENABLE_GLIB_LOOP_INTEGRATION_WORKAROUND
70 // Register event invoker
71 m_invokerHandler = ecore_main_fd_handler_add(
72 WaitableHandleWatchSupport::WaitableInvokerHandle(),
74 &StaticDispatchInvoker,
79 if (m_invokerHandler == NULL) {
80 ThrowMsg(Exception::CreateFailed, "Failed to register invoker handler!");
83 // It is impossible that there exist watchers at this time
84 // No need to add watchers
85 LogPedantic("ECORE event handler registered");
90 // Remove any watchers
91 for (EcoreFdHandlerList::iterator iterator = m_readWatchersList.begin();
92 iterator != m_readWatchersList.end();
95 ecore_main_fd_handler_del(*iterator);
98 m_readWatchersList.clear();
100 for (EcoreFdHandlerList::iterator iterator = m_writeWatchersList.begin();
101 iterator != m_writeWatchersList.end();
104 ecore_main_fd_handler_del(*iterator);
107 m_writeWatchersList.clear();
109 // Remove event invoker
110 ecore_main_fd_handler_del(m_invokerHandler);
111 m_invokerHandler = NULL;
113 //set old ecore select function, because after ecore_shutdown() call,
114 //it is being called once again and it may crash.
115 ecore_main_loop_select_func_set(m_oldEcoreSelect);
116 // Decrement ECORE init count
117 // We do not need ecore routines any more
120 // Late EFL event handling
121 Assert(g_lateMain == this);
125 Eina_Bool Main::StaticDispatchInvoker(void *data, Ecore_Fd_Handler *fd_handler)
127 LogPedantic("Static ECORE dispatch invoker");
129 Main *This = static_cast<Main *>(data);
132 Assert(This != NULL);
134 // Late EFL event handling
135 if (g_lateMain == NULL) {
136 LogPedantic("WARNING: Late EFL invoker dispatch!");
138 This->DispatchInvoker();
141 return ECORE_CALLBACK_RENEW;
144 Eina_Bool Main::StaticDispatchReadWatcher(void* data,
145 Ecore_Fd_Handler* fd_handler)
147 LogPedantic("Static ECORE dispatch read watcher");
149 Main *This = static_cast<Main *>(data);
151 Assert(This != NULL);
153 // Late EFL event handling
154 if (g_lateMain == NULL) {
155 LogPedantic("WARNING: Late EFL read watcher dispatch!");
157 This->DispatchReadWatcher(static_cast<WaitableHandle>(
158 ecore_main_fd_handler_fd_get(fd_handler)));
161 return ECORE_CALLBACK_RENEW;
164 Eina_Bool Main::StaticDispatchWriteWatcher(void* data,
165 Ecore_Fd_Handler* fd_handler)
167 LogPedantic("Static ECORE dispatch write watcher");
169 Main *This = static_cast<Main *>(data);
171 Assert(This != NULL);
173 // Late EFL event handling
174 if (g_lateMain == NULL) {
175 LogPedantic("WARNING: Late EFL write watcher dispatch!");
177 This->DispatchWriteWatcher(static_cast<WaitableHandle>(
178 ecore_main_fd_handler_fd_get(fd_handler)));
181 return ECORE_CALLBACK_RENEW;
184 void Main::DispatchInvoker()
186 LogPedantic("Dispatching invoker...");
191 // Handle base invoker
192 WaitableHandleWatchSupport::InvokerFinished();
194 LogPedantic("Invoker dispatched");
197 void Main::ReloadWatchList()
200 "Reloading watch list... (" << m_readWatchersList.size() << " + " <<
201 m_writeWatchersList.size() << ")");
203 // Reload list of watchers
204 WaitableHandleListEx waitableWatcherHandles =
205 WaitableHandleWatchSupport::WaitableWatcherHandles();
207 // Remove not existing read watchers
208 EcoreFdHandlerList::iterator watchersIterator = m_readWatchersList.begin();
209 WaitableHandleListEx::iterator handlesIterator;
211 while (watchersIterator != m_readWatchersList.end()) {
214 for (handlesIterator = waitableWatcherHandles.begin();
215 handlesIterator != waitableWatcherHandles.end();
218 if (handlesIterator->second == WaitMode::Read &&
219 handlesIterator->first ==
220 static_cast<WaitableHandle>(ecore_main_fd_handler_fd_get(*
229 // Unregister handler
230 ecore_main_fd_handler_del(*watchersIterator);
233 EcoreFdHandlerList::iterator next = watchersIterator;
236 m_readWatchersList.erase(watchersIterator);
237 watchersIterator = next;
243 // Remove not existing write watchers
244 watchersIterator = m_writeWatchersList.begin();
246 while (watchersIterator != m_writeWatchersList.end()) {
249 for (handlesIterator = waitableWatcherHandles.begin();
250 handlesIterator != waitableWatcherHandles.end();
253 if (handlesIterator->second == WaitMode::Write &&
254 handlesIterator->first ==
255 static_cast<WaitableHandle>(ecore_main_fd_handler_fd_get(*
264 // Unregister handler
265 ecore_main_fd_handler_del(*watchersIterator);
268 EcoreFdHandlerList::iterator next = watchersIterator;
271 m_writeWatchersList.erase(watchersIterator);
272 watchersIterator = next;
278 // Add new read/write watchers
279 for (handlesIterator = waitableWatcherHandles.begin();
280 handlesIterator != waitableWatcherHandles.end();
283 if (handlesIterator->second == WaitMode::Read) {
286 for (watchersIterator = m_readWatchersList.begin();
287 watchersIterator != m_readWatchersList.end();
290 if (handlesIterator->first ==
291 static_cast<WaitableHandle>(ecore_main_fd_handler_fd_get(*
300 Ecore_Fd_Handler *handler = ecore_main_fd_handler_add(
301 handlesIterator->first,
303 &StaticDispatchReadWatcher,
307 if (handler == NULL) {
308 ThrowMsg(Exception::CreateFailed,
309 "Failed to register read watcher handler!");
312 // Push new watcher to list
313 m_readWatchersList.push_back(handler);
315 } else if (handlesIterator->second == WaitMode::Write) {
318 for (watchersIterator = m_writeWatchersList.begin();
319 watchersIterator != m_writeWatchersList.end();
322 if (handlesIterator->first ==
323 static_cast<WaitableHandle>(ecore_main_fd_handler_fd_get(*
332 Ecore_Fd_Handler *handler = ecore_main_fd_handler_add(
333 handlesIterator->first,
335 &StaticDispatchWriteWatcher,
339 if (handler == NULL) {
340 ThrowMsg(Exception::CreateFailed,
341 "Failed to register write watcher handler!");
344 // Push new watcher to list
345 m_writeWatchersList.push_back(handler);
353 "Watch list reloaded (" << m_readWatchersList.size() << " + " <<
354 m_writeWatchersList.size() << ")");
357 void Main::DispatchReadWatcher(WaitableHandle waitableHandle)
359 LogPedantic("Dispatching read watcher...");
362 WaitableHandleWatchSupport::HandleWatcher(waitableHandle, WaitMode::Read);
364 LogPedantic("Watcher dispatched");
367 void Main::DispatchWriteWatcher(WaitableHandle waitableHandle)
369 LogPedantic("Dispatching write watcher...");
372 WaitableHandleWatchSupport::HandleWatcher(waitableHandle, WaitMode::Write);
374 LogPedantic("Watcher dispatched");
377 Thread *Main::GetInvokerThread()
382 void Main::HandleDirectInvoker()
384 // Handle direct invoker
388 #ifdef DPL_ENABLE_GLIB_LOOP_INTEGRATION_WORKAROUND
389 // GLIB loop intergration workaround
390 int Main::EcoreSelectInterceptor(int nfds,
394 struct timeval *timeout)
396 // We have to check error code here and make another try because of some
398 fd_set rfds, wfds, efds;
399 memcpy(&rfds, readfds, sizeof(fd_set));
400 memcpy(&wfds, writefds, sizeof(fd_set));
401 memcpy(&efds, exceptfds, sizeof(fd_set));
403 int ret = MainSingleton::Instance().m_oldEcoreSelect(nfds,
410 // Check each descriptor to see if it is valid
411 for (int i = 0; i < nfds; i++) {
414 FD_ISSET(i, writefds) || FD_ISSET(i, exceptfds))
416 // Try to get descriptor flags
417 int result = fcntl(i, F_GETFL);
420 if (errno == EBADF) {
421 // This a bad descriptor. Remove all occurrences of it.
422 if (FD_ISSET(i, readfds)) {
424 "GLIB_LOOP_INTEGRATION_WORKAROUND: Bad read descriptor: "
429 if (FD_ISSET(i, writefds)) {
431 "GLIB_LOOP_INTEGRATION_WORKAROUND: Bad write descriptor: "
436 if (FD_ISSET(i, exceptfds)) {
438 "GLIB_LOOP_INTEGRATION_WORKAROUND: Bad exception descriptor: "
440 FD_CLR(i, exceptfds);
451 "GLIB_LOOP_INTEGRATION_WORKAROUND: Bad read descriptor. Retrying with default select.");
453 //Retry with old values and return new error
454 memcpy(readfds, &rfds, sizeof(fd_set));
455 memcpy(writefds, &wfds, sizeof(fd_set));
456 memcpy(exceptfds, &efds, sizeof(fd_set));
458 // Trying to do it very short
464 ret = select(nfds, readfds, writefds, exceptfds, &tm);
466 ret = select(nfds, readfds, writefds, exceptfds, NULL);
472 #endif // DPL_ENABLE_GLIB_LOOP_INTEGRATION_WORKAROUND