Update wrt-commons_0.2.54
[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     //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
104     ecore_shutdown();
105
106     // Late EFL event handling
107     Assert(g_lateMain == this);
108     g_lateMain = NULL;
109 }
110
111 Eina_Bool Main::StaticDispatchInvoker(void *data, Ecore_Fd_Handler *fd_handler)
112 {
113     LogPedantic("Static ECORE dispatch invoker");
114
115     Main *This = static_cast<Main *>(data);
116     (void)fd_handler;
117
118     Assert(This != NULL);
119
120     // Late EFL event handling
121     if (g_lateMain == NULL)
122     {
123         LogPedantic("WARNING: Late EFL invoker dispatch!");
124     }
125     else
126     {
127         This->DispatchInvoker();
128     }
129
130     return ECORE_CALLBACK_RENEW;
131 }
132
133 Eina_Bool Main::StaticDispatchReadWatcher(void* data, Ecore_Fd_Handler* fd_handler)
134 {
135     LogPedantic("Static ECORE dispatch read watcher");
136
137     Main *This = static_cast<Main *>(data);
138
139     Assert(This != NULL);
140
141     // Late EFL event handling
142     if (g_lateMain == NULL)
143     {
144         LogPedantic("WARNING: Late EFL read watcher dispatch!");
145     }
146     else
147     {
148         This->DispatchReadWatcher(static_cast<WaitableHandle>(ecore_main_fd_handler_fd_get(fd_handler)));
149     }
150
151     return ECORE_CALLBACK_RENEW;
152 }
153
154 Eina_Bool Main::StaticDispatchWriteWatcher(void* data, Ecore_Fd_Handler* fd_handler)
155 {
156     LogPedantic("Static ECORE dispatch write watcher");
157
158     Main *This = static_cast<Main *>(data);
159
160     Assert(This != NULL);
161
162     // Late EFL event handling
163     if (g_lateMain == NULL)
164     {
165         LogPedantic("WARNING: Late EFL write watcher dispatch!");
166     }
167     else
168     {
169         This->DispatchWriteWatcher(static_cast<WaitableHandle>(ecore_main_fd_handler_fd_get(fd_handler)));
170     }
171
172     return ECORE_CALLBACK_RENEW;
173 }
174
175 void Main::DispatchInvoker()
176 {
177     LogPedantic("Dispatching invoker...");
178
179     // Reload watch list
180     ReloadWatchList();
181
182     // Handle base invoker
183     WaitableHandleWatchSupport::InvokerFinished();
184
185     LogPedantic("Invoker dispatched");
186 }
187
188 void Main::ReloadWatchList()
189 {
190     LogPedantic("Reloading watch list... (" << m_readWatchersList.size() << " + " << m_writeWatchersList.size() << ")");
191
192     // Reload list of watchers
193     WaitableHandleListEx waitableWatcherHandles = WaitableHandleWatchSupport::WaitableWatcherHandles();
194
195     // Remove not existing read watchers
196     EcoreFdHandlerList::iterator watchersIterator = m_readWatchersList.begin();
197     WaitableHandleListEx::iterator handlesIterator;
198
199     while (watchersIterator != m_readWatchersList.end())
200     {
201         bool found = false;
202
203         for (handlesIterator = waitableWatcherHandles.begin(); handlesIterator != waitableWatcherHandles.end(); ++handlesIterator)
204         {
205             if (handlesIterator->second == WaitMode::Read &&
206                 handlesIterator->first == static_cast<WaitableHandle>(ecore_main_fd_handler_fd_get(*watchersIterator)))
207             {
208                 found = true;
209                 break;
210             }
211         }
212
213         if (!found)
214         {
215             // Unregister handler
216             ecore_main_fd_handler_del(*watchersIterator);
217
218             // Remove iterator
219             EcoreFdHandlerList::iterator next = watchersIterator;
220             ++next;
221
222             m_readWatchersList.erase(watchersIterator);
223             watchersIterator = next;
224         }
225         else
226         {
227             ++watchersIterator;
228         }
229     }
230
231     // Remove not existing write watchers
232     watchersIterator = m_writeWatchersList.begin();
233
234     while (watchersIterator != m_writeWatchersList.end())
235     {
236         bool found = false;
237
238         for (handlesIterator = waitableWatcherHandles.begin(); handlesIterator != waitableWatcherHandles.end(); ++handlesIterator)
239         {
240             if (handlesIterator->second == WaitMode::Write &&
241                 handlesIterator->first == static_cast<WaitableHandle>(ecore_main_fd_handler_fd_get(*watchersIterator)))
242             {
243                 found = true;
244                 break;
245             }
246         }
247
248         if (!found)
249         {
250             // Unregister handler
251             ecore_main_fd_handler_del(*watchersIterator);
252
253             // Remove iterator
254             EcoreFdHandlerList::iterator next = watchersIterator;
255             ++next;
256
257             m_writeWatchersList.erase(watchersIterator);
258             watchersIterator = next;
259         }
260         else
261         {
262             ++watchersIterator;
263         }
264     }
265
266     // Add new read/write watchers
267     for (handlesIterator = waitableWatcherHandles.begin(); handlesIterator != waitableWatcherHandles.end(); ++handlesIterator)
268     {
269         if (handlesIterator->second == WaitMode::Read)
270         {
271             bool found = false;
272
273             for (watchersIterator = m_readWatchersList.begin(); watchersIterator != m_readWatchersList.end(); ++watchersIterator)
274             {
275                 if (handlesIterator->first == static_cast<WaitableHandle>(ecore_main_fd_handler_fd_get(*watchersIterator)))
276                 {
277                     found = true;
278                     break;
279                 }
280             }
281
282             if (!found)
283             {
284                 Ecore_Fd_Handler *handler = ecore_main_fd_handler_add(handlesIterator->first,
285                                                                       ECORE_FD_READ, &StaticDispatchReadWatcher, this, NULL, NULL);
286                 if (handler == NULL)
287                     ThrowMsg(Exception::CreateFailed, "Failed to register read watcher handler!");
288
289                 // Push new watcher to list
290                 m_readWatchersList.push_back(handler);
291             }
292         }
293         else if (handlesIterator->second == WaitMode::Write)
294         {
295             bool found = false;
296
297             for (watchersIterator = m_writeWatchersList.begin(); watchersIterator != m_writeWatchersList.end(); ++watchersIterator)
298             {
299                 if (handlesIterator->first == static_cast<WaitableHandle>(ecore_main_fd_handler_fd_get(*watchersIterator)))
300                 {
301                     found = true;
302                     break;
303                 }
304             }
305
306             if (!found)
307             {
308                 Ecore_Fd_Handler *handler = ecore_main_fd_handler_add(handlesIterator->first,
309                                                                       ECORE_FD_WRITE, &StaticDispatchWriteWatcher, this, NULL, NULL);
310                 if (handler == NULL)
311                     ThrowMsg(Exception::CreateFailed, "Failed to register write watcher handler!");
312
313                 // Push new watcher to list
314                 m_writeWatchersList.push_back(handler);
315             }
316         }
317         else
318         {
319             Assert(0);
320         }
321     }
322
323     LogPedantic("Watch list reloaded  (" << m_readWatchersList.size() << " + " << m_writeWatchersList.size() << ")");
324 }
325
326 void Main::DispatchReadWatcher(WaitableHandle waitableHandle)
327 {
328     LogPedantic("Dispatching read watcher...");
329
330     // Handle watcher
331     WaitableHandleWatchSupport::HandleWatcher(waitableHandle, WaitMode::Read);
332
333     LogPedantic("Watcher dispatched");
334 }
335
336 void Main::DispatchWriteWatcher(WaitableHandle waitableHandle)
337 {
338     LogPedantic("Dispatching write watcher...");
339
340     // Handle watcher
341     WaitableHandleWatchSupport::HandleWatcher(waitableHandle, WaitMode::Write);
342
343     LogPedantic("Watcher dispatched");
344 }
345
346 Thread *Main::GetInvokerThread()
347 {
348     return NULL;
349 }
350
351 void Main::HandleDirectInvoker()
352 {
353     // Handle direct invoker
354     ReloadWatchList();
355 }
356
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)
360 {
361 #if 0
362     // Check each descriptor to see if it is valid
363     for (int i = 0; i < nfds; i++)
364     {
365         if (FD_ISSET(i, readfds) || FD_ISSET(i, writefds) || FD_ISSET(i, exceptfds))
366         {
367             // Try to get descriptor flags
368             int result = fcntl(i, F_GETFL);
369
370             if (result == -1)
371             {
372                 if (errno == EBADF)
373                 {
374                     // This a bad descriptor. Remove all occurrences of it.
375                     if (FD_ISSET(i, readfds))
376                     {
377                         LogPedantic("GLIB_LOOP_INTEGRATION_WORKAROUND: Bad read descriptor: " << i);
378                         FD_CLR(i, readfds);
379                     }
380
381                     if (FD_ISSET(i, writefds))
382                     {
383                         LogPedantic("GLIB_LOOP_INTEGRATION_WORKAROUND: Bad write descriptor: " << i);
384                         FD_CLR(i, writefds);
385                     }
386
387                     if (FD_ISSET(i, exceptfds))
388                     {
389                         LogPedantic("GLIB_LOOP_INTEGRATION_WORKAROUND: Bad exception descriptor: " << i);
390                         FD_CLR(i, exceptfds);
391                     }
392                 }
393                 else
394                 {
395                     // Unexpected error
396                     Assert(0);
397                 }
398             }
399         }
400     }
401
402     // Find out new maximum
403     int newNfds = 0;
404
405     for (int i = 0; i < nfds; i++)
406     {
407         if (FD_ISSET(i, readfds) || FD_ISSET(i, writefds) || FD_ISSET(i, exceptfds))
408             newNfds = i;
409     }
410
411     return MainSingleton::Instance().m_oldEcoreSelect(newNfds + 1, readfds, writefds, exceptfds, timeout);
412
413 #else
414
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));
420
421     int ret = MainSingleton::Instance().m_oldEcoreSelect(nfds, readfds, writefds, exceptfds, timeout);
422
423     if (ret == -1)
424     {
425         // Check each descriptor to see if it is valid
426         for (int i = 0; i < nfds; i++)
427         {
428             if (FD_ISSET(i, readfds) || FD_ISSET(i, writefds) || FD_ISSET(i, exceptfds))
429             {
430                 // Try to get descriptor flags
431                 int result = fcntl(i, F_GETFL);
432
433                 if (result == -1)
434                 {
435                     if (errno == EBADF)
436                     {
437                         // This a bad descriptor. Remove all occurrences of it.
438                         if (FD_ISSET(i, readfds))
439                         {
440                             LogPedantic("GLIB_LOOP_INTEGRATION_WORKAROUND: Bad read descriptor: " << i);
441                             FD_CLR(i, readfds);
442                         }
443
444                         if (FD_ISSET(i, writefds))
445                         {
446                             LogPedantic("GLIB_LOOP_INTEGRATION_WORKAROUND: Bad write descriptor: " << i);
447                             FD_CLR(i, writefds);
448                         }
449
450                         if (FD_ISSET(i, exceptfds))
451                         {
452                             LogPedantic("GLIB_LOOP_INTEGRATION_WORKAROUND: Bad exception descriptor: " << i);
453                             FD_CLR(i, exceptfds);
454                         }
455                     }
456                     else
457                     {
458                         // Unexpected error
459                         Assert(0);
460                     }
461                 }
462             }
463         }
464
465         LogPedantic("GLIB_LOOP_INTEGRATION_WORKAROUND: Bad read descriptor. Retrying with default select.");
466
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));
471
472         // Trying to do it very short
473         timeval tm;
474         tm.tv_sec = 0;
475         tm.tv_usec = 10;
476
477         if (timeout)
478             ret = select(nfds, readfds, writefds, exceptfds, &tm);
479         else
480             ret = select(nfds, readfds, writefds, exceptfds, NULL);
481     }
482
483     return ret;
484 #endif
485 }
486 #endif // DPL_ENABLE_GLIB_LOOP_INTEGRATION_WORKAROUND
487 } // namespace DPL