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 //set old ecore select function, because after ecore_shutdown() call,
100 //it is being called once again and it may crash.
101 ecore_main_loop_select_func_set(m_oldEcoreSelect);
102 // Decrement ECORE init count
103 // We do not need ecore routines any more
106 // Late EFL event handling
107 Assert(g_lateMain == this);
111 Eina_Bool Main::StaticDispatchInvoker(void *data, Ecore_Fd_Handler *fd_handler)
113 LogPedantic("Static ECORE dispatch invoker");
115 Main *This = static_cast<Main *>(data);
118 Assert(This != NULL);
120 // Late EFL event handling
121 if (g_lateMain == NULL)
123 LogPedantic("WARNING: Late EFL invoker dispatch!");
127 This->DispatchInvoker();
130 return ECORE_CALLBACK_RENEW;
133 Eina_Bool Main::StaticDispatchReadWatcher(void* data, Ecore_Fd_Handler* fd_handler)
135 LogPedantic("Static ECORE dispatch read watcher");
137 Main *This = static_cast<Main *>(data);
139 Assert(This != NULL);
141 // Late EFL event handling
142 if (g_lateMain == NULL)
144 LogPedantic("WARNING: Late EFL read watcher dispatch!");
148 This->DispatchReadWatcher(static_cast<WaitableHandle>(ecore_main_fd_handler_fd_get(fd_handler)));
151 return ECORE_CALLBACK_RENEW;
154 Eina_Bool Main::StaticDispatchWriteWatcher(void* data, Ecore_Fd_Handler* fd_handler)
156 LogPedantic("Static ECORE dispatch write watcher");
158 Main *This = static_cast<Main *>(data);
160 Assert(This != NULL);
162 // Late EFL event handling
163 if (g_lateMain == NULL)
165 LogPedantic("WARNING: Late EFL write watcher dispatch!");
169 This->DispatchWriteWatcher(static_cast<WaitableHandle>(ecore_main_fd_handler_fd_get(fd_handler)));
172 return ECORE_CALLBACK_RENEW;
175 void Main::DispatchInvoker()
177 LogPedantic("Dispatching invoker...");
182 // Handle base invoker
183 WaitableHandleWatchSupport::InvokerFinished();
185 LogPedantic("Invoker dispatched");
188 void Main::ReloadWatchList()
190 LogPedantic("Reloading watch list... (" << m_readWatchersList.size() << " + " << m_writeWatchersList.size() << ")");
192 // Reload list of watchers
193 WaitableHandleListEx waitableWatcherHandles = WaitableHandleWatchSupport::WaitableWatcherHandles();
195 // Remove not existing read watchers
196 EcoreFdHandlerList::iterator watchersIterator = m_readWatchersList.begin();
197 WaitableHandleListEx::iterator handlesIterator;
199 while (watchersIterator != m_readWatchersList.end())
203 for (handlesIterator = waitableWatcherHandles.begin(); handlesIterator != waitableWatcherHandles.end(); ++handlesIterator)
205 if (handlesIterator->second == WaitMode::Read &&
206 handlesIterator->first == static_cast<WaitableHandle>(ecore_main_fd_handler_fd_get(*watchersIterator)))
215 // Unregister handler
216 ecore_main_fd_handler_del(*watchersIterator);
219 EcoreFdHandlerList::iterator next = watchersIterator;
222 m_readWatchersList.erase(watchersIterator);
223 watchersIterator = next;
231 // Remove not existing write watchers
232 watchersIterator = m_writeWatchersList.begin();
234 while (watchersIterator != m_writeWatchersList.end())
238 for (handlesIterator = waitableWatcherHandles.begin(); handlesIterator != waitableWatcherHandles.end(); ++handlesIterator)
240 if (handlesIterator->second == WaitMode::Write &&
241 handlesIterator->first == static_cast<WaitableHandle>(ecore_main_fd_handler_fd_get(*watchersIterator)))
250 // Unregister handler
251 ecore_main_fd_handler_del(*watchersIterator);
254 EcoreFdHandlerList::iterator next = watchersIterator;
257 m_writeWatchersList.erase(watchersIterator);
258 watchersIterator = next;
266 // Add new read/write watchers
267 for (handlesIterator = waitableWatcherHandles.begin(); handlesIterator != waitableWatcherHandles.end(); ++handlesIterator)
269 if (handlesIterator->second == WaitMode::Read)
273 for (watchersIterator = m_readWatchersList.begin(); watchersIterator != m_readWatchersList.end(); ++watchersIterator)
275 if (handlesIterator->first == static_cast<WaitableHandle>(ecore_main_fd_handler_fd_get(*watchersIterator)))
284 Ecore_Fd_Handler *handler = ecore_main_fd_handler_add(handlesIterator->first,
285 ECORE_FD_READ, &StaticDispatchReadWatcher, this, NULL, NULL);
287 ThrowMsg(Exception::CreateFailed, "Failed to register read watcher handler!");
289 // Push new watcher to list
290 m_readWatchersList.push_back(handler);
293 else if (handlesIterator->second == WaitMode::Write)
297 for (watchersIterator = m_writeWatchersList.begin(); watchersIterator != m_writeWatchersList.end(); ++watchersIterator)
299 if (handlesIterator->first == static_cast<WaitableHandle>(ecore_main_fd_handler_fd_get(*watchersIterator)))
308 Ecore_Fd_Handler *handler = ecore_main_fd_handler_add(handlesIterator->first,
309 ECORE_FD_WRITE, &StaticDispatchWriteWatcher, this, NULL, NULL);
311 ThrowMsg(Exception::CreateFailed, "Failed to register write watcher handler!");
313 // Push new watcher to list
314 m_writeWatchersList.push_back(handler);
323 LogPedantic("Watch list reloaded (" << m_readWatchersList.size() << " + " << m_writeWatchersList.size() << ")");
326 void Main::DispatchReadWatcher(WaitableHandle waitableHandle)
328 LogPedantic("Dispatching read watcher...");
331 WaitableHandleWatchSupport::HandleWatcher(waitableHandle, WaitMode::Read);
333 LogPedantic("Watcher dispatched");
336 void Main::DispatchWriteWatcher(WaitableHandle waitableHandle)
338 LogPedantic("Dispatching write watcher...");
341 WaitableHandleWatchSupport::HandleWatcher(waitableHandle, WaitMode::Write);
343 LogPedantic("Watcher dispatched");
346 Thread *Main::GetInvokerThread()
351 void Main::HandleDirectInvoker()
353 // Handle direct invoker
357 #ifdef DPL_ENABLE_GLIB_LOOP_INTEGRATION_WORKAROUND
358 // GLIB loop intergration workaround
359 int Main::EcoreSelectInterceptor(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout)
362 // Check each descriptor to see if it is valid
363 for (int i = 0; i < nfds; i++)
365 if (FD_ISSET(i, readfds) || FD_ISSET(i, writefds) || FD_ISSET(i, exceptfds))
367 // Try to get descriptor flags
368 int result = fcntl(i, F_GETFL);
374 // This a bad descriptor. Remove all occurrences of it.
375 if (FD_ISSET(i, readfds))
377 LogPedantic("GLIB_LOOP_INTEGRATION_WORKAROUND: Bad read descriptor: " << i);
381 if (FD_ISSET(i, writefds))
383 LogPedantic("GLIB_LOOP_INTEGRATION_WORKAROUND: Bad write descriptor: " << i);
387 if (FD_ISSET(i, exceptfds))
389 LogPedantic("GLIB_LOOP_INTEGRATION_WORKAROUND: Bad exception descriptor: " << i);
390 FD_CLR(i, exceptfds);
402 // Find out new maximum
405 for (int i = 0; i < nfds; i++)
407 if (FD_ISSET(i, readfds) || FD_ISSET(i, writefds) || FD_ISSET(i, exceptfds))
411 return MainSingleton::Instance().m_oldEcoreSelect(newNfds + 1, readfds, writefds, exceptfds, timeout);
415 // We have to check error code here and make another try because of some glib error's.
416 fd_set rfds, wfds, efds;
417 memcpy(&rfds, readfds, sizeof(fd_set));
418 memcpy(&wfds, writefds, sizeof(fd_set));
419 memcpy(&efds, exceptfds, sizeof(fd_set));
421 int ret = MainSingleton::Instance().m_oldEcoreSelect(nfds, readfds, writefds, exceptfds, timeout);
425 // Check each descriptor to see if it is valid
426 for (int i = 0; i < nfds; i++)
428 if (FD_ISSET(i, readfds) || FD_ISSET(i, writefds) || FD_ISSET(i, exceptfds))
430 // Try to get descriptor flags
431 int result = fcntl(i, F_GETFL);
437 // This a bad descriptor. Remove all occurrences of it.
438 if (FD_ISSET(i, readfds))
440 LogPedantic("GLIB_LOOP_INTEGRATION_WORKAROUND: Bad read descriptor: " << i);
444 if (FD_ISSET(i, writefds))
446 LogPedantic("GLIB_LOOP_INTEGRATION_WORKAROUND: Bad write descriptor: " << i);
450 if (FD_ISSET(i, exceptfds))
452 LogPedantic("GLIB_LOOP_INTEGRATION_WORKAROUND: Bad exception descriptor: " << i);
453 FD_CLR(i, exceptfds);
465 LogPedantic("GLIB_LOOP_INTEGRATION_WORKAROUND: Bad read descriptor. Retrying with default select.");
467 //Retry with old values and return new error
468 memcpy(readfds, &rfds, sizeof(fd_set));
469 memcpy(writefds, &wfds, sizeof(fd_set));
470 memcpy(exceptfds, &efds, sizeof(fd_set));
472 // Trying to do it very short
478 ret = select(nfds, readfds, writefds, exceptfds, &tm);
480 ret = select(nfds, readfds, writefds, exceptfds, NULL);
486 #endif // DPL_ENABLE_GLIB_LOOP_INTEGRATION_WORKAROUND