Initialize Tizen 2.3
[framework/web/wrt-commons.git] / modules_wearable / 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 <stddef.h>
23 #include <dpl/main.h>
24 #include <dpl/log/log.h>
25 #include <sys/select.h>
26 #include <fcntl.h>
27 #include <errno.h>
28 #include <dpl/assert.h>
29 #include <dpl/singleton_impl.h>
30
31 IMPLEMENT_SINGLETON(DPL::Main)
32
33 namespace DPL {
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(
72             WaitableHandleWatchSupport::WaitableInvokerHandle(),
73             ECORE_FD_READ,
74             &StaticDispatchInvoker,
75             this,
76             NULL,
77             NULL);
78
79     if (m_invokerHandler == NULL) {
80         ThrowMsg(Exception::CreateFailed, "Failed to register invoker handler!");
81     }
82
83     // It is impossible that there exist watchers at this time
84     // No need to add watchers
85     LogPedantic("ECORE event handler registered");
86 }
87
88 Main::~Main()
89 {
90     // Remove any watchers
91     for (EcoreFdHandlerList::iterator iterator = m_readWatchersList.begin();
92          iterator != m_readWatchersList.end();
93          ++iterator)
94     {
95         ecore_main_fd_handler_del(*iterator);
96     }
97
98     m_readWatchersList.clear();
99
100     for (EcoreFdHandlerList::iterator iterator = m_writeWatchersList.begin();
101          iterator != m_writeWatchersList.end();
102          ++iterator)
103     {
104         ecore_main_fd_handler_del(*iterator);
105     }
106
107     m_writeWatchersList.clear();
108
109     // Remove event invoker
110     ecore_main_fd_handler_del(m_invokerHandler);
111     m_invokerHandler = NULL;
112
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
118     ecore_shutdown();
119
120     // Late EFL event handling
121     Assert(g_lateMain == this);
122     g_lateMain = NULL;
123 }
124
125 Eina_Bool Main::StaticDispatchInvoker(void *data, Ecore_Fd_Handler *fd_handler)
126 {
127     LogPedantic("Static ECORE dispatch invoker");
128
129     Main *This = static_cast<Main *>(data);
130     (void)fd_handler;
131
132     Assert(This != NULL);
133
134     // Late EFL event handling
135     if (g_lateMain == NULL) {
136         LogPedantic("WARNING: Late EFL invoker dispatch!");
137     } else {
138         This->DispatchInvoker();
139     }
140
141     return ECORE_CALLBACK_RENEW;
142 }
143
144 Eina_Bool Main::StaticDispatchReadWatcher(void* data,
145                                           Ecore_Fd_Handler* fd_handler)
146 {
147     LogPedantic("Static ECORE dispatch read watcher");
148
149     Main *This = static_cast<Main *>(data);
150
151     Assert(This != NULL);
152
153     // Late EFL event handling
154     if (g_lateMain == NULL) {
155         LogPedantic("WARNING: Late EFL read watcher dispatch!");
156     } else {
157         This->DispatchReadWatcher(static_cast<WaitableHandle>(
158                                       ecore_main_fd_handler_fd_get(fd_handler)));
159     }
160
161     return ECORE_CALLBACK_RENEW;
162 }
163
164 Eina_Bool Main::StaticDispatchWriteWatcher(void* data,
165                                            Ecore_Fd_Handler* fd_handler)
166 {
167     LogPedantic("Static ECORE dispatch write watcher");
168
169     Main *This = static_cast<Main *>(data);
170
171     Assert(This != NULL);
172
173     // Late EFL event handling
174     if (g_lateMain == NULL) {
175         LogPedantic("WARNING: Late EFL write watcher dispatch!");
176     } else {
177         This->DispatchWriteWatcher(static_cast<WaitableHandle>(
178                                        ecore_main_fd_handler_fd_get(fd_handler)));
179     }
180
181     return ECORE_CALLBACK_RENEW;
182 }
183
184 void Main::DispatchInvoker()
185 {
186     LogPedantic("Dispatching invoker...");
187
188     // Reload watch list
189     ReloadWatchList();
190
191     // Handle base invoker
192     WaitableHandleWatchSupport::InvokerFinished();
193
194     LogPedantic("Invoker dispatched");
195 }
196
197 void Main::ReloadWatchList()
198 {
199     LogPedantic(
200         "Reloading watch list... (" << m_readWatchersList.size() << " + " <<
201         m_writeWatchersList.size() << ")");
202
203     // Reload list of watchers
204     WaitableHandleListEx waitableWatcherHandles =
205         WaitableHandleWatchSupport::WaitableWatcherHandles();
206
207     // Remove not existing read watchers
208     EcoreFdHandlerList::iterator watchersIterator = m_readWatchersList.begin();
209     WaitableHandleListEx::iterator handlesIterator;
210
211     while (watchersIterator != m_readWatchersList.end()) {
212         bool found = false;
213
214         for (handlesIterator = waitableWatcherHandles.begin();
215              handlesIterator != waitableWatcherHandles.end();
216              ++handlesIterator)
217         {
218             if (handlesIterator->second == WaitMode::Read &&
219                 handlesIterator->first ==
220                 static_cast<WaitableHandle>(ecore_main_fd_handler_fd_get(*
221                                                                          watchersIterator)))
222             {
223                 found = true;
224                 break;
225             }
226         }
227
228         if (!found) {
229             // Unregister handler
230             ecore_main_fd_handler_del(*watchersIterator);
231
232             // Remove iterator
233             EcoreFdHandlerList::iterator next = watchersIterator;
234             ++next;
235
236             m_readWatchersList.erase(watchersIterator);
237             watchersIterator = next;
238         } else {
239             ++watchersIterator;
240         }
241     }
242
243     // Remove not existing write watchers
244     watchersIterator = m_writeWatchersList.begin();
245
246     while (watchersIterator != m_writeWatchersList.end()) {
247         bool found = false;
248
249         for (handlesIterator = waitableWatcherHandles.begin();
250              handlesIterator != waitableWatcherHandles.end();
251              ++handlesIterator)
252         {
253             if (handlesIterator->second == WaitMode::Write &&
254                 handlesIterator->first ==
255                 static_cast<WaitableHandle>(ecore_main_fd_handler_fd_get(*
256                                                                          watchersIterator)))
257             {
258                 found = true;
259                 break;
260             }
261         }
262
263         if (!found) {
264             // Unregister handler
265             ecore_main_fd_handler_del(*watchersIterator);
266
267             // Remove iterator
268             EcoreFdHandlerList::iterator next = watchersIterator;
269             ++next;
270
271             m_writeWatchersList.erase(watchersIterator);
272             watchersIterator = next;
273         } else {
274             ++watchersIterator;
275         }
276     }
277
278     // Add new read/write watchers
279     for (handlesIterator = waitableWatcherHandles.begin();
280          handlesIterator != waitableWatcherHandles.end();
281          ++handlesIterator)
282     {
283         if (handlesIterator->second == WaitMode::Read) {
284             bool found = false;
285
286             for (watchersIterator = m_readWatchersList.begin();
287                  watchersIterator != m_readWatchersList.end();
288                  ++watchersIterator)
289             {
290                 if (handlesIterator->first ==
291                     static_cast<WaitableHandle>(ecore_main_fd_handler_fd_get(*
292                                                                              watchersIterator)))
293                 {
294                     found = true;
295                     break;
296                 }
297             }
298
299             if (!found) {
300                 Ecore_Fd_Handler *handler = ecore_main_fd_handler_add(
301                         handlesIterator->first,
302                         ECORE_FD_READ,
303                         &StaticDispatchReadWatcher,
304                         this,
305                         NULL,
306                         NULL);
307                 if (handler == NULL) {
308                     ThrowMsg(Exception::CreateFailed,
309                              "Failed to register read watcher handler!");
310                 }
311
312                 // Push new watcher to list
313                 m_readWatchersList.push_back(handler);
314             }
315         } else if (handlesIterator->second == WaitMode::Write) {
316             bool found = false;
317
318             for (watchersIterator = m_writeWatchersList.begin();
319                  watchersIterator != m_writeWatchersList.end();
320                  ++watchersIterator)
321             {
322                 if (handlesIterator->first ==
323                     static_cast<WaitableHandle>(ecore_main_fd_handler_fd_get(*
324                                                                              watchersIterator)))
325                 {
326                     found = true;
327                     break;
328                 }
329             }
330
331             if (!found) {
332                 Ecore_Fd_Handler *handler = ecore_main_fd_handler_add(
333                         handlesIterator->first,
334                         ECORE_FD_WRITE,
335                         &StaticDispatchWriteWatcher,
336                         this,
337                         NULL,
338                         NULL);
339                 if (handler == NULL) {
340                     ThrowMsg(Exception::CreateFailed,
341                              "Failed to register write watcher handler!");
342                 }
343
344                 // Push new watcher to list
345                 m_writeWatchersList.push_back(handler);
346             }
347         } else {
348             Assert(0);
349         }
350     }
351
352     LogPedantic(
353         "Watch list reloaded  (" << m_readWatchersList.size() << " + " <<
354         m_writeWatchersList.size() << ")");
355 }
356
357 void Main::DispatchReadWatcher(WaitableHandle waitableHandle)
358 {
359     LogPedantic("Dispatching read watcher...");
360
361     // Handle watcher
362     WaitableHandleWatchSupport::HandleWatcher(waitableHandle, WaitMode::Read);
363
364     LogPedantic("Watcher dispatched");
365 }
366
367 void Main::DispatchWriteWatcher(WaitableHandle waitableHandle)
368 {
369     LogPedantic("Dispatching write watcher...");
370
371     // Handle watcher
372     WaitableHandleWatchSupport::HandleWatcher(waitableHandle, WaitMode::Write);
373
374     LogPedantic("Watcher dispatched");
375 }
376
377 Thread *Main::GetInvokerThread()
378 {
379     return NULL;
380 }
381
382 void Main::HandleDirectInvoker()
383 {
384     // Handle direct invoker
385     ReloadWatchList();
386 }
387
388 #ifdef DPL_ENABLE_GLIB_LOOP_INTEGRATION_WORKAROUND
389 // GLIB loop intergration workaround
390 int Main::EcoreSelectInterceptor(int nfds,
391                                  fd_set *readfds,
392                                  fd_set *writefds,
393                                  fd_set *exceptfds,
394                                  struct timeval *timeout)
395 {
396     // We have to check error code here and make another try because of some
397     // glib error's.
398     fd_set rfds, wfds, efds;
399     memcpy(&rfds, readfds, sizeof(fd_set));
400     memcpy(&wfds, writefds, sizeof(fd_set));
401     memcpy(&efds, exceptfds, sizeof(fd_set));
402
403     int ret = MainSingleton::Instance().m_oldEcoreSelect(nfds,
404                                                          readfds,
405                                                          writefds,
406                                                          exceptfds,
407                                                          timeout);
408
409     if (ret == -1) {
410         // Check each descriptor to see if it is valid
411         for (int i = 0; i < nfds; i++) {
412             if (FD_ISSET(i,
413                          readfds) ||
414                 FD_ISSET(i, writefds) || FD_ISSET(i, exceptfds))
415             {
416                 // Try to get descriptor flags
417                 int result = fcntl(i, F_GETFL);
418
419                 if (result == -1) {
420                     if (errno == EBADF) {
421                         // This a bad descriptor. Remove all occurrences of it.
422                         if (FD_ISSET(i, readfds)) {
423                             LogPedantic(
424                                 "GLIB_LOOP_INTEGRATION_WORKAROUND: Bad read descriptor: "
425                                 << i);
426                             FD_CLR(i, readfds);
427                         }
428
429                         if (FD_ISSET(i, writefds)) {
430                             LogPedantic(
431                                 "GLIB_LOOP_INTEGRATION_WORKAROUND: Bad write descriptor: "
432                                 << i);
433                             FD_CLR(i, writefds);
434                         }
435
436                         if (FD_ISSET(i, exceptfds)) {
437                             LogPedantic(
438                                 "GLIB_LOOP_INTEGRATION_WORKAROUND: Bad exception descriptor: "
439                                 << i);
440                             FD_CLR(i, exceptfds);
441                         }
442                     } else {
443                         // Unexpected error
444                         Assert(0);
445                     }
446                 }
447             }
448         }
449
450         LogPedantic(
451             "GLIB_LOOP_INTEGRATION_WORKAROUND: Bad read descriptor. Retrying with default select.");
452
453         //Retry with old values and return new error
454         memcpy(readfds, &rfds, sizeof(fd_set));
455         memcpy(writefds, &wfds, sizeof(fd_set));
456         memcpy(exceptfds, &efds, sizeof(fd_set));
457
458         // Trying to do it very short
459         timeval tm;
460         tm.tv_sec = 0;
461         tm.tv_usec = 10;
462
463         if (timeout) {
464             ret = select(nfds, readfds, writefds, exceptfds, &tm);
465         } else {
466             ret = select(nfds, readfds, writefds, exceptfds, NULL);
467         }
468     }
469
470     return ret;
471 }
472 #endif // DPL_ENABLE_GLIB_LOOP_INTEGRATION_WORKAROUND
473 } // namespace DPL