Fix the boiler plate codes
[platform/framework/native/appfw.git] / src / base / runtime / FBaseRt_EventDispatcher.cpp
1 //
2 // Copyright (c) 2012 Samsung Electronics Co., Ltd.
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 /**
18  * @file        FBaseRt_EventDispatcher.cpp
19  * @brief       This is the implementation file for the _EventDispatcher class.
20  *
21  */
22
23 #include <unistd.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <memory.h>
27 #include <sys/eventfd.h>
28 #include <new>
29 #include <FBaseObject.h>
30 #include <FBaseRtIRunnable.h>
31 #include <FBaseSysLog.h>
32 #include "FBaseRt_ITask.h"
33 #include "FBaseRt_EventDispatcher.h"
34 #include "FBaseRt_ThreadManager.h"
35
36 using namespace Tizen::Base;
37 using namespace Tizen::Base::Runtime;
38
39 namespace Tizen { namespace Base { namespace Runtime
40 {
41 __thread _EventDispatcher* pCurrentEventDispatcher = null;
42
43 _EventDispatcher::_EventDispatcher(void)
44         : __pMutex(null)
45         , __pGMainContext(null)
46         , __pEventFdIo(null)
47         , __pEventFdSource(null)
48 {
49
50 }
51
52 _EventDispatcher::~_EventDispatcher(void)
53 {
54         if (__pEventFdSource)
55         {
56                 g_source_destroy(__pEventFdSource);
57                 g_source_unref(__pEventFdSource);
58                 __pEventFdSource = null;
59         }
60
61         if (__pEventFdIo)
62         {
63                 g_io_channel_unref(__pEventFdIo);
64                 __pEventFdIo = null;
65         }
66
67         if (__pMutex)
68         {
69                 delete __pMutex;
70                 __pMutex = null;
71         }
72         g_main_context_unref(__pGMainContext);
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
84         eventFd = eventfd(0, 0);
85         SysTryCatch(NID_BASE_RT, -1 != eventFd, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Failed to open eventfd.");
86
87         __pEventFdIo = g_io_channel_unix_new(eventFd);
88         SysTryCatch(NID_BASE_RT, __pEventFdIo != null, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Failed to create a channel for eventfd.");
89         g_io_channel_set_encoding(__pEventFdIo, null, &pGError);
90         g_io_channel_set_flags(__pEventFdIo, G_IO_FLAG_NONBLOCK, &pGError);
91
92         g_io_channel_set_close_on_unref(__pEventFdIo, TRUE);
93         eventFd = -1;
94
95         __pEventFdSource = g_io_create_watch(__pEventFdIo, G_IO_IN);
96         SysTryCatch(NID_BASE_RT, __pEventFdSource != null, r = E_SYSTEM, E_SYSTEM,
97                            "[E_SYSTEM] Failed to create a gsource for a channel.");
98
99         g_source_set_callback(__pEventFdSource, (GSourceFunc) _EventDispatcher::OnEventReceived, this, null);
100         g_source_attach(__pEventFdSource, __pGMainContext);
101
102         __pMutex = new (std::nothrow) Mutex();
103         SysTryCatch(NID_BASE_RT, __pMutex != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Not enough memory.");
104
105         r = __pMutex->Create();
106         SysTryCatch(NID_BASE_RT, !IsFailed(r), , r, "[%s] Failed to create mutex.", GetErrorMessage(r));
107
108         pCurrentEventDispatcher = this;
109
110         return E_SUCCESS;
111
112 CATCH:
113         if (__pMutex)
114         {
115                 delete __pMutex;
116                 __pMutex = null;
117         }
118
119         if (__pEventFdSource)
120         {
121                 g_source_destroy(__pEventFdSource);
122                 g_source_unref(__pEventFdSource);
123                 __pEventFdSource = null;
124         }
125
126         if (__pEventFdIo)
127         {
128                 g_io_channel_unref(__pEventFdIo);
129                 __pEventFdIo = null;
130         }
131
132         if (eventFd != -1)
133         {
134                 close(eventFd);
135         }
136
137         return r;
138 }
139
140 result
141 _EventDispatcher::PutTask(_ITask* pITask, void* pParam)
142 {
143         gsize writtenSize = 0;
144         uint64_t tmp = 1;
145         _EventMessage* pMessage = null;
146
147         SysTryReturn(NID_BASE_RT, __pMutex != null, E_INVALID_STATE, E_INVALID_STATE, "[E_INVALID_STATE] Not constructed.");
148
149         pMessage = new (std::nothrow) _EventMessage;
150         ;
151         SysTryReturn(NID_BASE_RT, pMessage != null, E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Not enough memory.");
152
153         pMessage->pITask = pITask;
154         pMessage->pParam = pParam;
155
156         __pMutex->Acquire();
157
158         __events.Add(pMessage);
159
160         __pMutex->Release();
161
162         g_io_channel_write(__pEventFdIo, (const gchar*) &tmp, sizeof(tmp), &writtenSize);
163
164         return E_SUCCESS;
165 }
166
167 gboolean
168 _EventDispatcher::OnEventReceived(GIOChannel* pGIOChannel, GIOCondition condition, gpointer data)
169 {
170         _EventMessage* pMessage = null;
171         _EventDispatcher* pEventDispatcher = (_EventDispatcher*) data;
172         uint64_t tmp = 0;
173         gsize readSize = 0;
174
175         if (condition & G_IO_IN)
176         {
177                 g_io_channel_read(pGIOChannel, (gchar*) &tmp, sizeof(tmp), &readSize);
178
179                 if (readSize == 0)
180                 {
181                         return TRUE;
182                 }
183
184                 while (true)
185                 {
186                         pEventDispatcher->__pMutex->Acquire();
187
188                         pMessage = null;
189                         if (pEventDispatcher->__events.GetAt(0, pMessage) == E_SUCCESS)
190                         {
191                                 pEventDispatcher->__events.RemoveAt(0);
192                         }
193
194                         pEventDispatcher->__pMutex->Release();
195
196                         if (pMessage)
197                         {
198                                 pMessage->pITask->DoTask(pMessage->pParam);
199
200                                 delete pMessage;
201                         }
202                         else
203                         {
204                                 break;
205                         }
206                 }
207         }
208
209         return TRUE;
210 }
211
212 _EventDispatcher*
213 _EventDispatcher::GetCurrentEventDispatcher(void)
214 {
215         return pCurrentEventDispatcher;
216 }
217
218 GMainContext*
219 _EventDispatcher::GetGMainContext(void)
220 {
221         SysTryReturn(NID_BASE_RT, __pMutex != null, null, E_INVALID_STATE, "[E_INVALID_STATE] Not constructed.");
222
223         return __pGMainContext;
224 }
225
226 } } } // Tizen::Base::Runtime