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)
35 namespace // anonymous
37 // Late EFL event handling
38 Main *g_lateMain = NULL;
39 } // namespace anonymous
42 #ifdef DPL_ENABLE_GLIB_LOOP_INTEGRATION_WORKAROUND
43 // GLIB loop intergration workaround
44 : m_oldEcoreSelect(NULL)
45 #endif // DPL_ENABLE_GLIB_LOOP_INTEGRATION_WORKAROUND
47 // Late EFL event handling
48 Assert(g_lateMain == NULL);
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 #ifdef DPL_ENABLE_GLIB_LOOP_INTEGRATION_WORKAROUND
58 // GLIB loop intergration workaround
61 Ecore_Select_Function pointer;
62 EcoreSelectType function;
65 convert.pointer = ecore_main_loop_select_func_get();
66 m_oldEcoreSelect = convert.function;
68 ecore_main_loop_select_func_set(&EcoreSelectInterceptor);
69 #endif // DPL_ENABLE_GLIB_LOOP_INTEGRATION_WORKAROUND
71 // Register event invoker
72 m_invokerHandler = ecore_main_fd_handler_add(WaitableHandleWatchSupport::WaitableInvokerHandle(),
73 ECORE_FD_READ, &StaticDispatchInvoker, this, NULL, NULL);
75 if (m_invokerHandler == NULL)
76 ThrowMsg(Exception::CreateFailed, "Failed to register invoker handler!");
78 // It is impossible that there exist watchers at this time
79 // No need to add watchers
80 LogPedantic("ECORE event handler registered");
85 // Remove any watchers
86 for (EcoreFdHandlerList::iterator iterator = m_readWatchersList.begin(); iterator != m_readWatchersList.end(); ++iterator)
87 ecore_main_fd_handler_del(*iterator);
89 m_readWatchersList.clear();
91 for (EcoreFdHandlerList::iterator iterator = m_writeWatchersList.begin(); iterator != m_writeWatchersList.end(); ++iterator)
92 ecore_main_fd_handler_del(*iterator);
94 m_writeWatchersList.clear();
96 // Remove event invoker
97 ecore_main_fd_handler_del(m_invokerHandler);
98 m_invokerHandler = NULL;
100 //set old ecore select function, because after ecore_shutdown() call,
101 //it is being called once again and it may crash.
102 ecore_main_loop_select_func_set(m_oldEcoreSelect);
103 // Decrement ECORE init count
104 // We do not need ecore routines any more
107 // Late EFL event handling
108 Assert(g_lateMain == this);
112 Eina_Bool Main::StaticDispatchInvoker(void *data, Ecore_Fd_Handler *fd_handler)
114 LogPedantic("Static ECORE dispatch invoker");
116 Main *This = static_cast<Main *>(data);
119 Assert(This != NULL);
121 // Late EFL event handling
122 if (g_lateMain == NULL)
124 LogPedantic("WARNING: Late EFL invoker dispatch!");
128 This->DispatchInvoker();
131 return ECORE_CALLBACK_RENEW;
134 Eina_Bool Main::StaticDispatchReadWatcher(void* data, Ecore_Fd_Handler* fd_handler)
136 LogPedantic("Static ECORE dispatch read watcher");
138 Main *This = static_cast<Main *>(data);
140 Assert(This != NULL);
142 // Late EFL event handling
143 if (g_lateMain == NULL)
145 LogPedantic("WARNING: Late EFL read watcher dispatch!");
149 This->DispatchReadWatcher(static_cast<WaitableHandle>(ecore_main_fd_handler_fd_get(fd_handler)));
152 return ECORE_CALLBACK_RENEW;
155 Eina_Bool Main::StaticDispatchWriteWatcher(void* data, Ecore_Fd_Handler* fd_handler)
157 LogPedantic("Static ECORE dispatch write watcher");
159 Main *This = static_cast<Main *>(data);
161 Assert(This != NULL);
163 // Late EFL event handling
164 if (g_lateMain == NULL)
166 LogPedantic("WARNING: Late EFL write watcher dispatch!");
170 This->DispatchWriteWatcher(static_cast<WaitableHandle>(ecore_main_fd_handler_fd_get(fd_handler)));
173 return ECORE_CALLBACK_RENEW;
176 void Main::DispatchInvoker()
178 LogPedantic("Dispatching invoker...");
183 // Handle base invoker
184 WaitableHandleWatchSupport::InvokerFinished();
186 LogPedantic("Invoker dispatched");
189 void Main::ReloadWatchList()
191 LogPedantic("Reloading watch list... (" << m_readWatchersList.size() << " + " << m_writeWatchersList.size() << ")");
193 // Reload list of watchers
194 WaitableHandleListEx waitableWatcherHandles = WaitableHandleWatchSupport::WaitableWatcherHandles();
196 // Remove not existing read watchers
197 EcoreFdHandlerList::iterator watchersIterator = m_readWatchersList.begin();
198 WaitableHandleListEx::iterator handlesIterator;
200 while (watchersIterator != m_readWatchersList.end())
204 for (handlesIterator = waitableWatcherHandles.begin(); handlesIterator != waitableWatcherHandles.end(); ++handlesIterator)
206 if (handlesIterator->second == WaitMode::Read &&
207 handlesIterator->first == static_cast<WaitableHandle>(ecore_main_fd_handler_fd_get(*watchersIterator)))
216 // Unregister handler
217 ecore_main_fd_handler_del(*watchersIterator);
220 EcoreFdHandlerList::iterator next = watchersIterator;
223 m_readWatchersList.erase(watchersIterator);
224 watchersIterator = next;
232 // Remove not existing write watchers
233 watchersIterator = m_writeWatchersList.begin();
235 while (watchersIterator != m_writeWatchersList.end())
239 for (handlesIterator = waitableWatcherHandles.begin(); handlesIterator != waitableWatcherHandles.end(); ++handlesIterator)
241 if (handlesIterator->second == WaitMode::Write &&
242 handlesIterator->first == static_cast<WaitableHandle>(ecore_main_fd_handler_fd_get(*watchersIterator)))
251 // Unregister handler
252 ecore_main_fd_handler_del(*watchersIterator);
255 EcoreFdHandlerList::iterator next = watchersIterator;
258 m_writeWatchersList.erase(watchersIterator);
259 watchersIterator = next;
267 // Add new read/write watchers
268 for (handlesIterator = waitableWatcherHandles.begin(); handlesIterator != waitableWatcherHandles.end(); ++handlesIterator)
270 if (handlesIterator->second == WaitMode::Read)
274 for (watchersIterator = m_readWatchersList.begin(); watchersIterator != m_readWatchersList.end(); ++watchersIterator)
276 if (handlesIterator->first == static_cast<WaitableHandle>(ecore_main_fd_handler_fd_get(*watchersIterator)))
285 Ecore_Fd_Handler *handler = ecore_main_fd_handler_add(handlesIterator->first,
286 ECORE_FD_READ, &StaticDispatchReadWatcher, this, NULL, NULL);
288 ThrowMsg(Exception::CreateFailed, "Failed to register read watcher handler!");
290 // Push new watcher to list
291 m_readWatchersList.push_back(handler);
294 else if (handlesIterator->second == WaitMode::Write)
298 for (watchersIterator = m_writeWatchersList.begin(); watchersIterator != m_writeWatchersList.end(); ++watchersIterator)
300 if (handlesIterator->first == static_cast<WaitableHandle>(ecore_main_fd_handler_fd_get(*watchersIterator)))
309 Ecore_Fd_Handler *handler = ecore_main_fd_handler_add(handlesIterator->first,
310 ECORE_FD_WRITE, &StaticDispatchWriteWatcher, this, NULL, NULL);
312 ThrowMsg(Exception::CreateFailed, "Failed to register write watcher handler!");
314 // Push new watcher to list
315 m_writeWatchersList.push_back(handler);
324 LogPedantic("Watch list reloaded (" << m_readWatchersList.size() << " + " << m_writeWatchersList.size() << ")");
327 void Main::DispatchReadWatcher(WaitableHandle waitableHandle)
329 LogPedantic("Dispatching read watcher...");
332 WaitableHandleWatchSupport::HandleWatcher(waitableHandle, WaitMode::Read);
334 LogPedantic("Watcher dispatched");
337 void Main::DispatchWriteWatcher(WaitableHandle waitableHandle)
339 LogPedantic("Dispatching write watcher...");
342 WaitableHandleWatchSupport::HandleWatcher(waitableHandle, WaitMode::Write);
344 LogPedantic("Watcher dispatched");
347 Thread *Main::GetInvokerThread()
352 void Main::HandleDirectInvoker()
354 // Handle direct invoker
358 #ifdef DPL_ENABLE_GLIB_LOOP_INTEGRATION_WORKAROUND
359 // GLIB loop intergration workaround
360 int Main::EcoreSelectInterceptor(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout)
362 // We have to check error code here and make another try because of some glib error's.
363 fd_set rfds, wfds, efds;
364 memcpy(&rfds, readfds, sizeof(fd_set));
365 memcpy(&wfds, writefds, sizeof(fd_set));
366 memcpy(&efds, exceptfds, sizeof(fd_set));
368 int ret = MainSingleton::Instance().m_oldEcoreSelect(nfds, readfds, writefds, exceptfds, timeout);
372 // Check each descriptor to see if it is valid
373 for (int i = 0; i < nfds; i++)
375 if (FD_ISSET(i, readfds) || FD_ISSET(i, writefds) || FD_ISSET(i, exceptfds))
377 // Try to get descriptor flags
378 int result = fcntl(i, F_GETFL);
384 // This a bad descriptor. Remove all occurrences of it.
385 if (FD_ISSET(i, readfds))
387 LogPedantic("GLIB_LOOP_INTEGRATION_WORKAROUND: Bad read descriptor: " << i);
391 if (FD_ISSET(i, writefds))
393 LogPedantic("GLIB_LOOP_INTEGRATION_WORKAROUND: Bad write descriptor: " << i);
397 if (FD_ISSET(i, exceptfds))
399 LogPedantic("GLIB_LOOP_INTEGRATION_WORKAROUND: Bad exception descriptor: " << i);
400 FD_CLR(i, exceptfds);
412 LogPedantic("GLIB_LOOP_INTEGRATION_WORKAROUND: Bad read descriptor. Retrying with default select.");
414 //Retry with old values and return new error
415 memcpy(readfds, &rfds, sizeof(fd_set));
416 memcpy(writefds, &wfds, sizeof(fd_set));
417 memcpy(exceptfds, &efds, sizeof(fd_set));
419 // Trying to do it very short
425 ret = select(nfds, readfds, writefds, exceptfds, &tm);
427 ret = select(nfds, readfds, writefds, exceptfds, NULL);
432 #endif // DPL_ENABLE_GLIB_LOOP_INTEGRATION_WORKAROUND