91372770031a11288118d6a312085d785ca319bd
[platform/framework/native/appfw.git] / src / base / runtime / FBaseRt_EventDispatcher.cpp
1 //
2 // Open Service Platform
3 // Copyright (c) 2012 Samsung Electronics Co., Ltd.
4 //
5 // Licensed under the Apache License, Version 2.0 (the License);
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 // http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 //
17
18 /**
19  * @file        FBaseRt_EventDispatcher.cpp
20  * @brief       This is the implementation file for the _EventDispatcher class.
21  *
22  */
23
24 #include <unistd.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <memory.h>
28 #include <sys/eventfd.h>
29 #include <new>
30 #include <FBaseObject.h>
31 #include <FBaseRtIRunnable.h>
32 #include <FBaseSysLog.h>
33 #include "FBaseRt_ITask.h"
34 #include "FBaseRt_EventDispatcher.h"
35 #include "FBaseRt_ThreadManager.h"
36
37 using namespace Tizen::Base;
38 using namespace Tizen::Base::Runtime;
39
40 namespace Tizen { namespace Base { namespace Runtime
41 {
42 __thread _EventDispatcher* pCurrentEventDispatcher = null;
43
44 _EventDispatcher::_EventDispatcher(void)
45         : __pMutex(null)
46         , __pGMainContext(null)
47         , __pEventFdIo(null)
48         , __pEventFdSource(null)
49 {
50
51 }
52
53 _EventDispatcher::~_EventDispatcher(void)
54 {
55         if (__pEventFdSource)
56         {
57                 g_source_unref(__pEventFdSource);
58                 g_source_destroy(__pEventFdSource);
59                 __pEventFdSource = null;
60         }
61
62         if (__pEventFdIo)
63         {
64                 g_io_channel_unref(__pEventFdIo);
65                 __pEventFdIo = null;
66         }
67
68         if (__pMutex)
69         {
70                 delete __pMutex;
71                 __pMutex = null;
72         }
73 }
74
75 result
76 _EventDispatcher::Construct(GMainContext* pGMainContext)
77 {
78         result r = E_SUCCESS;
79         GError* pGError = null;
80         int eventFd = -1;
81
82         __pGMainContext = pGMainContext;
83         g_main_context_ref(__pGMainContext);
84
85         eventFd = eventfd(0, 0);
86         SysTryCatch(NID_BASE_RT, -1 != eventFd, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Failed to open eventfd.");
87
88         __pEventFdIo = g_io_channel_unix_new(eventFd);
89         SysTryCatch(NID_BASE_RT, __pEventFdIo != null, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Failed to create a channel for eventfd.");
90         g_io_channel_set_encoding(__pEventFdIo, null, &pGError);
91         g_io_channel_set_flags(__pEventFdIo, G_IO_FLAG_NONBLOCK, &pGError);
92
93         g_io_channel_set_close_on_unref(__pEventFdIo, TRUE);
94         eventFd = -1;
95
96         __pEventFdSource = g_io_create_watch(__pEventFdIo, G_IO_IN);
97         SysTryCatch(NID_BASE_RT, __pEventFdSource != null, r = E_SYSTEM, E_SYSTEM,
98                            "[E_SYSTEM] Failed to create a gsource for a channel.");
99
100         g_source_set_callback(__pEventFdSource, (GSourceFunc) _EventDispatcher::OnEventReceived, this, null);
101         g_source_attach(__pEventFdSource, __pGMainContext);
102
103         __pMutex = new (std::nothrow) Mutex();
104         SysTryCatch(NID_BASE_RT, __pMutex != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Not enough memory.");
105
106         r = __pMutex->Create();
107         SysTryCatch(NID_BASE_RT, !IsFailed(r), , r, "[%s] Failed to create mutex.", GetErrorMessage(r));
108
109         pCurrentEventDispatcher = this;
110
111         return E_SUCCESS;
112
113 CATCH:
114         if (__pMutex)
115         {
116                 delete __pMutex;
117                 __pMutex = null;
118         }
119
120         if (__pEventFdSource)
121         {
122                 g_source_unref(__pEventFdSource);
123                 g_source_destroy(__pEventFdSource);
124                 __pEventFdSource = null;
125         }
126
127         if (__pEventFdIo)
128         {
129                 g_io_channel_unref(__pEventFdIo);
130                 __pEventFdIo = null;
131         }
132
133         if (eventFd != -1)
134         {
135                 close(eventFd);
136         }
137
138         return r;
139 }
140
141 result
142 _EventDispatcher::PutTask(_ITask* pITask, void* pParam)
143 {
144         gsize writtenSize = 0;
145         uint64_t tmp = 1;
146         _EventMessage* pMessage = null;
147
148         SysTryReturn(NID_BASE_RT, __pMutex != null, E_INVALID_STATE, E_INVALID_STATE, "[E_INVALID_STATE] Not constructed.");
149
150         pMessage = new (std::nothrow) _EventMessage;
151         ;
152         SysTryReturn(NID_BASE_RT, pMessage != null, E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Not enough memory.");
153
154         pMessage->pITask = pITask;
155         pMessage->pParam = pParam;
156
157         __pMutex->Acquire();
158
159         __events.Add(pMessage);
160
161         __pMutex->Release();
162
163         g_io_channel_write(__pEventFdIo, (const gchar*) &tmp, sizeof(tmp), &writtenSize);
164
165         return E_SUCCESS;
166 }
167
168 gboolean
169 _EventDispatcher::OnEventReceived(GIOChannel* pGIOChannel, GIOCondition condition, gpointer data)
170 {
171         _EventMessage* pMessage = null;
172         _EventDispatcher* pEventDispatcher = (_EventDispatcher*) data;
173         uint64_t tmp = 0;
174         gsize readSize = 0;
175
176         if (condition & G_IO_IN)
177         {
178                 g_io_channel_read(pGIOChannel, (gchar*) &tmp, sizeof(tmp), &readSize);
179
180                 if (readSize == 0)
181                 {
182                         return TRUE;
183                 }
184
185                 while (true)
186                 {
187                         pEventDispatcher->__pMutex->Acquire();
188
189                         pMessage = null;
190                         if (pEventDispatcher->__events.GetAt(0, pMessage) == E_SUCCESS)
191                         {
192                                 pEventDispatcher->__events.RemoveAt(0);
193                         }
194
195                         pEventDispatcher->__pMutex->Release();
196
197                         if (pMessage)
198                         {
199                                 pMessage->pITask->DoTask(pMessage->pParam);
200
201                                 delete pMessage;
202                         }
203                         else
204                         {
205                                 break;
206                         }
207                 }
208         }
209
210         return TRUE;
211 }
212
213 _EventDispatcher*
214 _EventDispatcher::GetCurrentEventDispatcher(void)
215 {
216         return pCurrentEventDispatcher;
217 }
218
219 GMainContext*
220 _EventDispatcher::GetGMainContext(void)
221 {
222         SysTryReturn(NID_BASE_RT, __pMutex != null, null, E_INVALID_STATE, "[E_INVALID_STATE] Not constructed.");
223
224         return __pGMainContext;
225 }
226
227 } } } // Tizen::Base::Runtime