tizen beta release
[framework/web/wrt-commons.git] / modules / core / src / main.cpp
1 /*
2  * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
3  *
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
7  *
8  *        http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16 /*
17  * @file        main.cpp
18  * @author      Przemyslaw Dobrowolski (p.dobrowolsk@samsung.com)
19  * @version     1.0
20  * @brief       This file is the implementation file of main for EFL
21  */
22 #include <dpl/main.h>
23 #include <dpl/log/log.h>
24 #include <sys/select.h>
25 #include <fcntl.h>
26 #include <errno.h>
27 #include <dpl/assert.h>
28 #include <dpl/singleton_impl.h>
29
30 IMPLEMENT_SINGLETON(DPL::Main)
31
32 namespace DPL
33 {
34 namespace // anonymous
35 {
36 // Late EFL event handling
37 Main *g_lateMain = NULL;
38 } // namespace anonymous
39
40 Main::Main()
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
45 {
46     // Late EFL event handling
47     Assert(g_lateMain == NULL);
48     g_lateMain = this;
49
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
54     ecore_init();
55
56 #ifdef DPL_ENABLE_GLIB_LOOP_INTEGRATION_WORKAROUND
57     // GLIB loop intergration workaround
58     union ConvertPointer
59     {
60         Ecore_Select_Function pointer;
61         EcoreSelectType function;
62     } convert;
63
64     convert.pointer = ecore_main_loop_select_func_get();
65     m_oldEcoreSelect = convert.function;
66
67     ecore_main_loop_select_func_set(&EcoreSelectInterceptor);
68 #endif // DPL_ENABLE_GLIB_LOOP_INTEGRATION_WORKAROUND
69
70     // Register event invoker
71     m_invokerHandler = ecore_main_fd_handler_add(WaitableHandleWatchSupport::WaitableInvokerHandle(),
72                                                  ECORE_FD_READ, &StaticDispatchInvoker, this, NULL, NULL);
73
74     if (m_invokerHandler == NULL)
75         ThrowMsg(Exception::CreateFailed, "Failed to register invoker handler!");
76
77     // It is impossible that there exist watchers at this time
78     // No need to add watchers
79     LogPedantic("ECORE event handler registered");
80 }
81
82 Main::~Main()
83 {
84     // Remove any watchers
85     for (EcoreFdHandlerList::iterator iterator = m_readWatchersList.begin(); iterator != m_readWatchersList.end(); ++iterator)
86         ecore_main_fd_handler_del(*iterator);
87
88     m_readWatchersList.clear();
89
90     for (EcoreFdHandlerList::iterator iterator = m_writeWatchersList.begin(); iterator != m_writeWatchersList.end(); ++iterator)
91         ecore_main_fd_handler_del(*iterator);
92
93     m_writeWatchersList.clear();
94
95     // Remove event invoker
96     ecore_main_fd_handler_del(m_invokerHandler);
97     m_invokerHandler = NULL;
98
99     // Decrement ECORE init count
100     // We do not need ecore routines any more
101     ecore_shutdown();
102
103     // Late EFL event handling
104     Assert(g_lateMain == this);
105     g_lateMain = NULL;
106 }
107
108 Eina_Bool Main::StaticDispatchInvoker(void *data, Ecore_Fd_Handler *fd_handler)
109 {
110     LogPedantic("Static ECORE dispatch invoker");
111
112     Main *This = static_cast<Main *>(data);
113     (void)fd_handler;
114
115     Assert(This != NULL);
116
117     // Late EFL event handling
118     if (g_lateMain == NULL)
119     {
120         LogPedantic("WARNING: Late EFL invoker dispatch!");
121     }
122     else
123     {
124         This->DispatchInvoker();
125     }
126
127     return ECORE_CALLBACK_RENEW;
128 }
129
130 Eina_Bool Main::StaticDispatchReadWatcher(void* data, Ecore_Fd_Handler* fd_handler)
131 {
132     LogPedantic("Static ECORE dispatch read watcher");
133
134     Main *This = static_cast<Main *>(data);
135
136     Assert(This != NULL);
137
138     // Late EFL event handling
139     if (g_lateMain == NULL)
140     {
141         LogPedantic("WARNING: Late EFL read watcher dispatch!");
142     }
143     else
144     {
145         This->DispatchReadWatcher(static_cast<WaitableHandle>(ecore_main_fd_handler_fd_get(fd_handler)));
146     }
147
148     return ECORE_CALLBACK_RENEW;
149 }
150
151 Eina_Bool Main::StaticDispatchWriteWatcher(void* data, Ecore_Fd_Handler* fd_handler)
152 {
153     LogPedantic("Static ECORE dispatch write watcher");
154
155     Main *This = static_cast<Main *>(data);
156
157     Assert(This != NULL);
158
159     // Late EFL event handling
160     if (g_lateMain == NULL)
161     {
162         LogPedantic("WARNING: Late EFL write watcher dispatch!");
163     }
164     else
165     {
166         This->DispatchWriteWatcher(static_cast<WaitableHandle>(ecore_main_fd_handler_fd_get(fd_handler)));
167     }
168
169     return ECORE_CALLBACK_RENEW;
170 }
171
172 void Main::DispatchInvoker()
173 {
174     LogPedantic("Dispatching invoker...");
175
176     // Reload watch list
177     ReloadWatchList();
178
179     // Handle base invoker
180     WaitableHandleWatchSupport::InvokerFinished();
181
182     LogPedantic("Invoker dispatched");
183 }
184
185 void Main::ReloadWatchList()
186 {
187     LogPedantic("Reloading watch list... (" << m_readWatchersList.size() << " + " << m_writeWatchersList.size() << ")");
188
189     // Reload list of watchers
190     WaitableHandleListEx waitableWatcherHandles = WaitableHandleWatchSupport::WaitableWatcherHandles();
191
192     // Remove not existing read watchers
193     EcoreFdHandlerList::iterator watchersIterator = m_readWatchersList.begin();
194     WaitableHandleListEx::iterator handlesIterator;
195
196     while (watchersIterator != m_readWatchersList.end())
197     {
198         bool found = false;
199
200         for (handlesIterator = waitableWatcherHandles.begin(); handlesIterator != waitableWatcherHandles.end(); ++handlesIterator)
201         {
202             if (handlesIterator->second == WaitMode::Read &&
203                 handlesIterator->first == static_cast<WaitableHandle>(ecore_main_fd_handler_fd_get(*watchersIterator)))
204             {
205                 found = true;
206                 break;
207             }
208         }
209
210         if (!found)
211         {
212             // Unregister handler
213             ecore_main_fd_handler_del(*watchersIterator);
214
215             // Remove iterator
216             EcoreFdHandlerList::iterator next = watchersIterator;
217             ++next;
218
219             m_readWatchersList.erase(watchersIterator);
220             watchersIterator = next;
221         }
222         else
223         {
224             ++watchersIterator;
225         }
226     }
227
228     // Remove not existing write watchers
229     watchersIterator = m_writeWatchersList.begin();
230
231     while (watchersIterator != m_writeWatchersList.end())
232     {
233         bool found = false;
234
235         for (handlesIterator = waitableWatcherHandles.begin(); handlesIterator != waitableWatcherHandles.end(); ++handlesIterator)
236         {
237             if (handlesIterator->second == WaitMode::Write &&
238                 handlesIterator->first == static_cast<WaitableHandle>(ecore_main_fd_handler_fd_get(*watchersIterator)))
239             {
240                 found = true;
241                 break;
242             }
243         }
244
245         if (!found)
246         {
247             // Unregister handler
248             ecore_main_fd_handler_del(*watchersIterator);
249
250             // Remove iterator
251             EcoreFdHandlerList::iterator next = watchersIterator;
252             ++next;
253
254             m_writeWatchersList.erase(watchersIterator);
255             watchersIterator = next;
256         }
257         else
258         {
259             ++watchersIterator;
260         }
261     }
262
263     // Add new read/write watchers
264     for (handlesIterator = waitableWatcherHandles.begin(); handlesIterator != waitableWatcherHandles.end(); ++handlesIterator)
265     {
266         if (handlesIterator->second == WaitMode::Read)
267         {
268             bool found = false;
269
270             for (watchersIterator = m_readWatchersList.begin(); watchersIterator != m_readWatchersList.end(); ++watchersIterator)
271             {
272                 if (handlesIterator->first == static_cast<WaitableHandle>(ecore_main_fd_handler_fd_get(*watchersIterator)))
273                 {
274                     found = true;
275                     break;
276                 }
277             }
278
279             if (!found)
280             {
281                 Ecore_Fd_Handler *handler = ecore_main_fd_handler_add(handlesIterator->first,
282                                                                       ECORE_FD_READ, &StaticDispatchReadWatcher, this, NULL, NULL);
283                 if (handler == NULL)
284                     ThrowMsg(Exception::CreateFailed, "Failed to register read watcher handler!");
285
286                 // Push new watcher to list
287                 m_readWatchersList.push_back(handler);
288             }
289         }
290         else if (handlesIterator->second == WaitMode::Write)
291         {
292             bool found = false;
293
294             for (watchersIterator = m_writeWatchersList.begin(); watchersIterator != m_writeWatchersList.end(); ++watchersIterator)
295             {
296                 if (handlesIterator->first == static_cast<WaitableHandle>(ecore_main_fd_handler_fd_get(*watchersIterator)))
297                 {
298                     found = true;
299                     break;
300                 }
301             }
302
303             if (!found)
304             {
305                 Ecore_Fd_Handler *handler = ecore_main_fd_handler_add(handlesIterator->first,
306                                                                       ECORE_FD_WRITE, &StaticDispatchWriteWatcher, this, NULL, NULL);
307                 if (handler == NULL)
308                     ThrowMsg(Exception::CreateFailed, "Failed to register write watcher handler!");
309
310                 // Push new watcher to list
311                 m_writeWatchersList.push_back(handler);
312             }
313         }
314         else
315         {
316             Assert(0);
317         }
318     }
319
320     LogPedantic("Watch list reloaded  (" << m_readWatchersList.size() << " + " << m_writeWatchersList.size() << ")");
321 }
322
323 void Main::DispatchReadWatcher(WaitableHandle waitableHandle)
324 {
325     LogPedantic("Dispatching read watcher...");
326
327     // Handle watcher
328     WaitableHandleWatchSupport::HandleWatcher(waitableHandle, WaitMode::Read);
329
330     LogPedantic("Watcher dispatched");
331 }
332
333 void Main::DispatchWriteWatcher(WaitableHandle waitableHandle)
334 {
335     LogPedantic("Dispatching write watcher...");
336
337     // Handle watcher
338     WaitableHandleWatchSupport::HandleWatcher(waitableHandle, WaitMode::Write);
339
340     LogPedantic("Watcher dispatched");
341 }
342
343 Thread *Main::GetInvokerThread()
344 {
345     return NULL;
346 }
347
348 void Main::HandleDirectInvoker()
349 {
350     // Handle direct invoker
351     ReloadWatchList();
352 }
353
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)
357 {
358 #if 0
359     // Check each descriptor to see if it is valid
360     for (int i = 0; i < nfds; i++)
361     {
362         if (FD_ISSET(i, readfds) || FD_ISSET(i, writefds) || FD_ISSET(i, exceptfds))
363         {
364             // Try to get descriptor flags
365             int result = fcntl(i, F_GETFL);
366
367             if (result == -1)
368             {
369                 if (errno == EBADF)
370                 {
371                     // This a bad descriptor. Remove all occurrences of it.
372                     if (FD_ISSET(i, readfds))
373                     {
374                         LogPedantic("GLIB_LOOP_INTEGRATION_WORKAROUND: Bad read descriptor: " << i);
375                         FD_CLR(i, readfds);
376                     }
377
378                     if (FD_ISSET(i, writefds))
379                     {
380                         LogPedantic("GLIB_LOOP_INTEGRATION_WORKAROUND: Bad write descriptor: " << i);
381                         FD_CLR(i, writefds);
382                     }
383
384                     if (FD_ISSET(i, exceptfds))
385                     {
386                         LogPedantic("GLIB_LOOP_INTEGRATION_WORKAROUND: Bad exception descriptor: " << i);
387                         FD_CLR(i, exceptfds);
388                     }
389                 }
390                 else
391                 {
392                     // Unexpected error
393                     Assert(0);
394                 }
395             }
396         }
397     }
398
399     // Find out new maximum
400     int newNfds = 0;
401
402     for (int i = 0; i < nfds; i++)
403     {
404         if (FD_ISSET(i, readfds) || FD_ISSET(i, writefds) || FD_ISSET(i, exceptfds))
405             newNfds = i;
406     }
407
408     return MainSingleton::Instance().m_oldEcoreSelect(newNfds + 1, readfds, writefds, exceptfds, timeout);
409
410 #else
411
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));
417
418     int ret = MainSingleton::Instance().m_oldEcoreSelect(nfds, readfds, writefds, exceptfds, timeout);
419
420     if (ret == -1)
421     {
422         // Check each descriptor to see if it is valid
423         for (int i = 0; i < nfds; i++)
424         {
425             if (FD_ISSET(i, readfds) || FD_ISSET(i, writefds) || FD_ISSET(i, exceptfds))
426             {
427                 // Try to get descriptor flags
428                 int result = fcntl(i, F_GETFL);
429
430                 if (result == -1)
431                 {
432                     if (errno == EBADF)
433                     {
434                         // This a bad descriptor. Remove all occurrences of it.
435                         if (FD_ISSET(i, readfds))
436                         {
437                             LogPedantic("GLIB_LOOP_INTEGRATION_WORKAROUND: Bad read descriptor: " << i);
438                             FD_CLR(i, readfds);
439                         }
440
441                         if (FD_ISSET(i, writefds))
442                         {
443                             LogPedantic("GLIB_LOOP_INTEGRATION_WORKAROUND: Bad write descriptor: " << i);
444                             FD_CLR(i, writefds);
445                         }
446
447                         if (FD_ISSET(i, exceptfds))
448                         {
449                             LogPedantic("GLIB_LOOP_INTEGRATION_WORKAROUND: Bad exception descriptor: " << i);
450                             FD_CLR(i, exceptfds);
451                         }
452                     }
453                     else
454                     {
455                         // Unexpected error
456                         Assert(0);
457                     }
458                 }
459             }
460         }
461
462         LogPedantic("GLIB_LOOP_INTEGRATION_WORKAROUND: Bad read descriptor. Retrying with default select.");
463
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));
468
469         // Trying to do it very short
470         timeval tm;
471         tm.tv_sec = 0;
472         tm.tv_usec = 10;
473
474         if (timeout)
475             ret = select(nfds, readfds, writefds, exceptfds, &tm);
476         else
477             ret = select(nfds, readfds, writefds, exceptfds, NULL);
478     }
479
480     return ret;
481 #endif
482 }
483 #endif // DPL_ENABLE_GLIB_LOOP_INTEGRATION_WORKAROUND
484 } // namespace DPL