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
23 #include <dpl/log/log.h>
24 #include <sys/select.h>
27 #include <dpl/assert.h>
28 #include <dpl/singleton_impl.h>
30 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(WaitableHandleWatchSupport::WaitableInvokerHandle(),
72 ECORE_FD_READ, &StaticDispatchInvoker, this, NULL, NULL);
74 if (m_invokerHandler == NULL)
75 ThrowMsg(Exception::CreateFailed, "Failed to register invoker handler!");
77 // It is impossible that there exist watchers at this time
78 // No need to add watchers
79 LogPedantic("ECORE event handler registered");
84 // Remove any watchers
85 for (EcoreFdHandlerList::iterator iterator = m_readWatchersList.begin(); iterator != m_readWatchersList.end(); ++iterator)
86 ecore_main_fd_handler_del(*iterator);
88 m_readWatchersList.clear();
90 for (EcoreFdHandlerList::iterator iterator = m_writeWatchersList.begin(); iterator != m_writeWatchersList.end(); ++iterator)
91 ecore_main_fd_handler_del(*iterator);
93 m_writeWatchersList.clear();
95 // Remove event invoker
96 ecore_main_fd_handler_del(m_invokerHandler);
97 m_invokerHandler = NULL;
99 // Decrement ECORE init count
100 // We do not need ecore routines any more
103 // Late EFL event handling
104 Assert(g_lateMain == this);
108 Eina_Bool Main::StaticDispatchInvoker(void *data, Ecore_Fd_Handler *fd_handler)
110 LogPedantic("Static ECORE dispatch invoker");
112 Main *This = static_cast<Main *>(data);
115 Assert(This != NULL);
117 // Late EFL event handling
118 if (g_lateMain == NULL)
120 LogPedantic("WARNING: Late EFL invoker dispatch!");
124 This->DispatchInvoker();
127 return ECORE_CALLBACK_RENEW;
130 Eina_Bool Main::StaticDispatchReadWatcher(void* data, Ecore_Fd_Handler* fd_handler)
132 LogPedantic("Static ECORE dispatch read watcher");
134 Main *This = static_cast<Main *>(data);
136 Assert(This != NULL);
138 // Late EFL event handling
139 if (g_lateMain == NULL)
141 LogPedantic("WARNING: Late EFL read watcher dispatch!");
145 This->DispatchReadWatcher(static_cast<WaitableHandle>(ecore_main_fd_handler_fd_get(fd_handler)));
148 return ECORE_CALLBACK_RENEW;
151 Eina_Bool Main::StaticDispatchWriteWatcher(void* data, Ecore_Fd_Handler* fd_handler)
153 LogPedantic("Static ECORE dispatch write watcher");
155 Main *This = static_cast<Main *>(data);
157 Assert(This != NULL);
159 // Late EFL event handling
160 if (g_lateMain == NULL)
162 LogPedantic("WARNING: Late EFL write watcher dispatch!");
166 This->DispatchWriteWatcher(static_cast<WaitableHandle>(ecore_main_fd_handler_fd_get(fd_handler)));
169 return ECORE_CALLBACK_RENEW;
172 void Main::DispatchInvoker()
174 LogPedantic("Dispatching invoker...");
179 // Handle base invoker
180 WaitableHandleWatchSupport::InvokerFinished();
182 LogPedantic("Invoker dispatched");
185 void Main::ReloadWatchList()
187 LogPedantic("Reloading watch list... (" << m_readWatchersList.size() << " + " << m_writeWatchersList.size() << ")");
189 // Reload list of watchers
190 WaitableHandleListEx waitableWatcherHandles = WaitableHandleWatchSupport::WaitableWatcherHandles();
192 // Remove not existing read watchers
193 EcoreFdHandlerList::iterator watchersIterator = m_readWatchersList.begin();
194 WaitableHandleListEx::iterator handlesIterator;
196 while (watchersIterator != m_readWatchersList.end())
200 for (handlesIterator = waitableWatcherHandles.begin(); handlesIterator != waitableWatcherHandles.end(); ++handlesIterator)
202 if (handlesIterator->second == WaitMode::Read &&
203 handlesIterator->first == static_cast<WaitableHandle>(ecore_main_fd_handler_fd_get(*watchersIterator)))
212 // Unregister handler
213 ecore_main_fd_handler_del(*watchersIterator);
216 EcoreFdHandlerList::iterator next = watchersIterator;
219 m_readWatchersList.erase(watchersIterator);
220 watchersIterator = next;
228 // Remove not existing write watchers
229 watchersIterator = m_writeWatchersList.begin();
231 while (watchersIterator != m_writeWatchersList.end())
235 for (handlesIterator = waitableWatcherHandles.begin(); handlesIterator != waitableWatcherHandles.end(); ++handlesIterator)
237 if (handlesIterator->second == WaitMode::Write &&
238 handlesIterator->first == static_cast<WaitableHandle>(ecore_main_fd_handler_fd_get(*watchersIterator)))
247 // Unregister handler
248 ecore_main_fd_handler_del(*watchersIterator);
251 EcoreFdHandlerList::iterator next = watchersIterator;
254 m_writeWatchersList.erase(watchersIterator);
255 watchersIterator = next;
263 // Add new read/write watchers
264 for (handlesIterator = waitableWatcherHandles.begin(); handlesIterator != waitableWatcherHandles.end(); ++handlesIterator)
266 if (handlesIterator->second == WaitMode::Read)
270 for (watchersIterator = m_readWatchersList.begin(); watchersIterator != m_readWatchersList.end(); ++watchersIterator)
272 if (handlesIterator->first == static_cast<WaitableHandle>(ecore_main_fd_handler_fd_get(*watchersIterator)))
281 Ecore_Fd_Handler *handler = ecore_main_fd_handler_add(handlesIterator->first,
282 ECORE_FD_READ, &StaticDispatchReadWatcher, this, NULL, NULL);
284 ThrowMsg(Exception::CreateFailed, "Failed to register read watcher handler!");
286 // Push new watcher to list
287 m_readWatchersList.push_back(handler);
290 else if (handlesIterator->second == WaitMode::Write)
294 for (watchersIterator = m_writeWatchersList.begin(); watchersIterator != m_writeWatchersList.end(); ++watchersIterator)
296 if (handlesIterator->first == static_cast<WaitableHandle>(ecore_main_fd_handler_fd_get(*watchersIterator)))
305 Ecore_Fd_Handler *handler = ecore_main_fd_handler_add(handlesIterator->first,
306 ECORE_FD_WRITE, &StaticDispatchWriteWatcher, this, NULL, NULL);
308 ThrowMsg(Exception::CreateFailed, "Failed to register write watcher handler!");
310 // Push new watcher to list
311 m_writeWatchersList.push_back(handler);
320 LogPedantic("Watch list reloaded (" << m_readWatchersList.size() << " + " << m_writeWatchersList.size() << ")");
323 void Main::DispatchReadWatcher(WaitableHandle waitableHandle)
325 LogPedantic("Dispatching read watcher...");
328 WaitableHandleWatchSupport::HandleWatcher(waitableHandle, WaitMode::Read);
330 LogPedantic("Watcher dispatched");
333 void Main::DispatchWriteWatcher(WaitableHandle waitableHandle)
335 LogPedantic("Dispatching write watcher...");
338 WaitableHandleWatchSupport::HandleWatcher(waitableHandle, WaitMode::Write);
340 LogPedantic("Watcher dispatched");
343 Thread *Main::GetInvokerThread()
348 void Main::HandleDirectInvoker()
350 // Handle direct invoker
354 #ifdef DPL_ENABLE_GLIB_LOOP_INTEGRATION_WORKAROUND
355 // GLIB loop intergration workaround
356 int Main::EcoreSelectInterceptor(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout)
359 // Check each descriptor to see if it is valid
360 for (int i = 0; i < nfds; i++)
362 if (FD_ISSET(i, readfds) || FD_ISSET(i, writefds) || FD_ISSET(i, exceptfds))
364 // Try to get descriptor flags
365 int result = fcntl(i, F_GETFL);
371 // This a bad descriptor. Remove all occurrences of it.
372 if (FD_ISSET(i, readfds))
374 LogPedantic("GLIB_LOOP_INTEGRATION_WORKAROUND: Bad read descriptor: " << i);
378 if (FD_ISSET(i, writefds))
380 LogPedantic("GLIB_LOOP_INTEGRATION_WORKAROUND: Bad write descriptor: " << i);
384 if (FD_ISSET(i, exceptfds))
386 LogPedantic("GLIB_LOOP_INTEGRATION_WORKAROUND: Bad exception descriptor: " << i);
387 FD_CLR(i, exceptfds);
399 // Find out new maximum
402 for (int i = 0; i < nfds; i++)
404 if (FD_ISSET(i, readfds) || FD_ISSET(i, writefds) || FD_ISSET(i, exceptfds))
408 return MainSingleton::Instance().m_oldEcoreSelect(newNfds + 1, readfds, writefds, exceptfds, timeout);
412 // We have to check error code here and make another try because of some glib error's.
413 fd_set rfds, wfds, efds;
414 memcpy(&rfds, readfds, sizeof(fd_set));
415 memcpy(&wfds, writefds, sizeof(fd_set));
416 memcpy(&efds, exceptfds, sizeof(fd_set));
418 int ret = MainSingleton::Instance().m_oldEcoreSelect(nfds, readfds, writefds, exceptfds, timeout);
422 // Check each descriptor to see if it is valid
423 for (int i = 0; i < nfds; i++)
425 if (FD_ISSET(i, readfds) || FD_ISSET(i, writefds) || FD_ISSET(i, exceptfds))
427 // Try to get descriptor flags
428 int result = fcntl(i, F_GETFL);
434 // This a bad descriptor. Remove all occurrences of it.
435 if (FD_ISSET(i, readfds))
437 LogPedantic("GLIB_LOOP_INTEGRATION_WORKAROUND: Bad read descriptor: " << i);
441 if (FD_ISSET(i, writefds))
443 LogPedantic("GLIB_LOOP_INTEGRATION_WORKAROUND: Bad write descriptor: " << i);
447 if (FD_ISSET(i, exceptfds))
449 LogPedantic("GLIB_LOOP_INTEGRATION_WORKAROUND: Bad exception descriptor: " << i);
450 FD_CLR(i, exceptfds);
462 LogPedantic("GLIB_LOOP_INTEGRATION_WORKAROUND: Bad read descriptor. Retrying with default select.");
464 //Retry with old values and return new error
465 memcpy(readfds, &rfds, sizeof(fd_set));
466 memcpy(writefds, &wfds, sizeof(fd_set));
467 memcpy(exceptfds, &efds, sizeof(fd_set));
469 // Trying to do it very short
475 ret = select(nfds, readfds, writefds, exceptfds, &tm);
477 ret = select(nfds, readfds, writefds, exceptfds, NULL);
483 #endif // DPL_ENABLE_GLIB_LOOP_INTEGRATION_WORKAROUND