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/wrt_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 WrtLogD("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 WrtLogD("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 WrtLogD("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 WrtLogD("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 WrtLogD("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 WrtLogD("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 WrtLogD("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 WrtLogD("Dispatching invoker...");
191 // Handle base invoker
192 WaitableHandleWatchSupport::InvokerFinished();
194 WrtLogD("Invoker dispatched");
197 void Main::ReloadWatchList()
199 WrtLogD("Reloading watch list... (%i + %i)",
200 m_readWatchersList.size(), m_writeWatchersList.size());
202 // Reload list of watchers
203 WaitableHandleListEx waitableWatcherHandles =
204 WaitableHandleWatchSupport::WaitableWatcherHandles();
206 // Remove not existing read watchers
207 EcoreFdHandlerList::iterator watchersIterator = m_readWatchersList.begin();
208 WaitableHandleListEx::iterator handlesIterator;
210 while (watchersIterator != m_readWatchersList.end()) {
213 for (handlesIterator = waitableWatcherHandles.begin();
214 handlesIterator != waitableWatcherHandles.end();
217 if (handlesIterator->second == WaitMode::Read &&
218 handlesIterator->first ==
219 static_cast<WaitableHandle>(ecore_main_fd_handler_fd_get(*
228 // Unregister handler
229 ecore_main_fd_handler_del(*watchersIterator);
232 EcoreFdHandlerList::iterator next = watchersIterator;
235 m_readWatchersList.erase(watchersIterator);
236 watchersIterator = next;
242 // Remove not existing write watchers
243 watchersIterator = m_writeWatchersList.begin();
245 while (watchersIterator != m_writeWatchersList.end()) {
248 for (handlesIterator = waitableWatcherHandles.begin();
249 handlesIterator != waitableWatcherHandles.end();
252 if (handlesIterator->second == WaitMode::Write &&
253 handlesIterator->first ==
254 static_cast<WaitableHandle>(ecore_main_fd_handler_fd_get(*
263 // Unregister handler
264 ecore_main_fd_handler_del(*watchersIterator);
267 EcoreFdHandlerList::iterator next = watchersIterator;
270 m_writeWatchersList.erase(watchersIterator);
271 watchersIterator = next;
277 // Add new read/write watchers
278 for (handlesIterator = waitableWatcherHandles.begin();
279 handlesIterator != waitableWatcherHandles.end();
282 if (handlesIterator->second == WaitMode::Read) {
285 for (watchersIterator = m_readWatchersList.begin();
286 watchersIterator != m_readWatchersList.end();
289 if (handlesIterator->first ==
290 static_cast<WaitableHandle>(ecore_main_fd_handler_fd_get(*
299 Ecore_Fd_Handler *handler = ecore_main_fd_handler_add(
300 handlesIterator->first,
302 &StaticDispatchReadWatcher,
306 if (handler == NULL) {
307 ThrowMsg(Exception::CreateFailed,
308 "Failed to register read watcher handler!");
311 // Push new watcher to list
312 m_readWatchersList.push_back(handler);
314 } else if (handlesIterator->second == WaitMode::Write) {
317 for (watchersIterator = m_writeWatchersList.begin();
318 watchersIterator != m_writeWatchersList.end();
321 if (handlesIterator->first ==
322 static_cast<WaitableHandle>(ecore_main_fd_handler_fd_get(*
331 Ecore_Fd_Handler *handler = ecore_main_fd_handler_add(
332 handlesIterator->first,
334 &StaticDispatchWriteWatcher,
338 if (handler == NULL) {
339 ThrowMsg(Exception::CreateFailed,
340 "Failed to register write watcher handler!");
343 // Push new watcher to list
344 m_writeWatchersList.push_back(handler);
351 WrtLogD("Watch list reloaded (%i + %i)",
352 m_readWatchersList.size(), m_writeWatchersList.size());
355 void Main::DispatchReadWatcher(WaitableHandle waitableHandle)
357 WrtLogD("Dispatching read watcher...");
360 WaitableHandleWatchSupport::HandleWatcher(waitableHandle, WaitMode::Read);
362 WrtLogD("Watcher dispatched");
365 void Main::DispatchWriteWatcher(WaitableHandle waitableHandle)
367 WrtLogD("Dispatching write watcher...");
370 WaitableHandleWatchSupport::HandleWatcher(waitableHandle, WaitMode::Write);
372 WrtLogD("Watcher dispatched");
375 Thread *Main::GetInvokerThread()
380 void Main::HandleDirectInvoker()
382 // Handle direct invoker
386 #ifdef DPL_ENABLE_GLIB_LOOP_INTEGRATION_WORKAROUND
387 // GLIB loop intergration workaround
388 int Main::EcoreSelectInterceptor(int nfds,
392 struct timeval *timeout)
394 // We have to check error code here and make another try because of some
396 fd_set rfds, wfds, efds;
397 memcpy(&rfds, readfds, sizeof(fd_set));
398 memcpy(&wfds, writefds, sizeof(fd_set));
399 memcpy(&efds, exceptfds, sizeof(fd_set));
401 int ret = MainSingleton::Instance().m_oldEcoreSelect(nfds,
408 // Check each descriptor to see if it is valid
409 for (int i = 0; i < nfds; i++) {
412 FD_ISSET(i, writefds) || FD_ISSET(i, exceptfds))
414 // Try to get descriptor flags
415 int result = fcntl(i, F_GETFL);
418 if (errno == EBADF) {
419 // This a bad descriptor. Remove all occurrences of it.
420 if (FD_ISSET(i, readfds)) {
422 "GLIB_LOOP_INTEGRATION_WORKAROUND: Bad read descriptor: %i", i);
426 if (FD_ISSET(i, writefds)) {
428 "GLIB_LOOP_INTEGRATION_WORKAROUND: Bad write descriptor: %i", i);
432 if (FD_ISSET(i, exceptfds)) {
434 "GLIB_LOOP_INTEGRATION_WORKAROUND: Bad exception descriptor: %i", i);
435 FD_CLR(i, exceptfds);
445 WrtLogD("GLIB_LOOP_INTEGRATION_WORKAROUND: Bad read descriptor. Retrying with default select.");
447 //Retry with old values and return new error
448 memcpy(readfds, &rfds, sizeof(fd_set));
449 memcpy(writefds, &wfds, sizeof(fd_set));
450 memcpy(exceptfds, &efds, sizeof(fd_set));
452 // Trying to do it very short
458 ret = select(nfds, readfds, writefds, exceptfds, &tm);
460 ret = select(nfds, readfds, writefds, exceptfds, NULL);
466 #endif // DPL_ENABLE_GLIB_LOOP_INTEGRATION_WORKAROUND