Added support for Event creation in worker thread
[platform/framework/native/appfw.git] / src / base / runtime / FBaseRt_EventManager.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_EventManager.cpp
19  * @brief       This is the implementation file for the _EventManager class.
20  *
21  */
22
23 #include <unistd.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <sys/eventfd.h>
27 #include <memory.h>
28 #include <new>
29
30 #include <FBaseSysLog.h>
31 #include "FBaseRt_Event.h"
32 #include "FBaseRt_ThreadManager.h"
33 #include "FBaseRt_ThreadImpl.h"
34 #include "FBaseRt_EventManager.h"
35
36
37 using namespace Tizen::Base;
38 using namespace Tizen::Base::Collection;
39 using namespace Tizen::Base::Runtime;
40
41 namespace Tizen { namespace Base { namespace Runtime
42 {
43 bool
44 _EventManager::_EventMessage::operator ==(const _EventMessage& rhs) const
45 {
46         if (id == rhs.id)
47         {
48                 return true;
49         }
50
51         return false;
52 }
53
54 bool
55 _EventManager::_EventMessage::operator !=(const _EventMessage& rhs) const
56 {
57         if (id != rhs.id)
58         {
59                 return true;
60         }
61
62         return false;
63 }
64
65 _EventManager::_EventMessage&
66 _EventManager::_EventMessage::operator =(const _EventMessage& rhs)
67 {
68         if (this != &rhs)
69         {
70                 id = rhs.id;
71                 type = rhs.type;
72                 event = rhs.event;
73                 arg = *const_cast< std::tr1::shared_ptr< IEventArg >* >(&rhs.arg);
74                 listener = rhs.listener;
75         }
76
77         return *this;
78 }
79
80 _EventManager::_EventManager(void)
81         : __pMutex(null)
82         , __pSource(null)
83         , __pChannel(null)
84         , __pGmainContext(null)
85         , __pActive(null)
86         , __pReady(null)
87 {
88
89 }
90
91 _EventManager::~_EventManager(void)
92 {
93         GetEventManagerObjectManager().Unregister(__handle);
94
95         if (__pSource)
96         {
97                 g_source_destroy(__pSource);
98                 g_source_unref(__pSource);
99         }
100
101         if (__pChannel)
102         {
103                 g_io_channel_unref(__pChannel);
104         }
105
106         delete __pMutex;
107 }
108
109 result
110 _EventManager::Construct(GMainContext* pGmainContext)
111 {
112         result r = E_SUCCESS;
113         GError* pGError = null;
114         GIOChannel* pChannel = null;
115         GSource* pSource = null;
116         Mutex* pMutex = null;
117
118         int eventFd = eventfd(0, 0);
119         SysTryReturnResult(NID_BASE_RT, eventFd != -1, E_SYSTEM, "Failed to open eventfd.");
120
121         pChannel = g_io_channel_unix_new(eventFd);
122         SysTryCatch(NID_BASE_RT, pChannel != null, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Failed to create a channel for eventfd.");
123
124         g_io_channel_set_encoding(pChannel, null, &pGError);
125         g_io_channel_set_flags(pChannel, G_IO_FLAG_NONBLOCK, &pGError);
126
127         g_io_channel_set_close_on_unref(pChannel, TRUE);
128         eventFd = -1;
129
130         pSource = g_io_create_watch(pChannel, G_IO_IN);
131         SysTryCatch(NID_BASE_RT, pSource != null, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Failed to create a gsource for a channel.");
132
133         g_source_set_callback(pSource, (GSourceFunc) _EventManager::OnEventReceived, this, null);
134         g_source_attach(pSource, pGmainContext);
135
136         pMutex = new (std::nothrow) Mutex();
137         SysTryCatch(NID_BASE_RT, pMutex != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Not enough memory.");
138
139         r = pMutex->Create();
140         SysTryCatch(NID_BASE_RT, !IsFailed(r), , r, "[%s] Failed to create mutex.", GetErrorMessage(r));
141
142         __handle = GetEventManagerObjectManager().Register(*this);
143
144         __pChannel = pChannel;
145         __pSource = pSource;
146         __pMutex = pMutex;
147         __pGmainContext = pGmainContext;
148
149         __pActive = &__messages1;
150         __pReady = &__messages2;
151
152         return E_SUCCESS;
153
154 CATCH:
155         delete pMutex;
156
157         if (pSource)
158         {
159                 g_source_destroy(pSource);
160                 g_source_unref(pSource);
161         }
162
163         if (pChannel)
164         {
165                 g_io_channel_unref(pChannel);
166         }
167
168         if (eventFd != -1)
169         {
170                 close(eventFd);
171         }
172
173         return r;
174 }
175
176 result
177 _EventManager::CallListenerAsync(const _HandleT< _Event >& event, std::tr1::shared_ptr< IEventArg > arg, const _HandleT< IEventListener >& listener)
178 {
179         SysTryReturn(NID_BASE_RT, __pGmainContext != null, E_INVALID_STATE, E_INVALID_STATE, "[E_INVALID_STATE] Not constructed.");
180
181         _EventMessage message;
182
183         message.type = MESSAGE_TYPE_CALL_LISTENER;
184         message.event = event;
185         message.arg = arg;
186         message.listener = listener;
187
188         __pMutex->Acquire();
189
190         __pActive->Add(message);
191
192         __pMutex->Release();
193
194         uint64_t count = 1;
195         gsize writtenSize = 0;
196
197         g_io_channel_write(__pChannel, (const gchar*) &count, sizeof(count), &writtenSize);
198
199         return E_SUCCESS;
200 }
201
202 result
203 _EventManager::FireEventAsync(const _HandleT< _Event >& event, std::tr1::shared_ptr< IEventArg > arg)
204 {
205         SysTryReturnResult(NID_BASE_RT, __pGmainContext != null, E_INVALID_STATE, "Not constructed.");
206
207         _EventMessage message;
208
209         message.type = MESSAGE_TYPE_FIRE_EVENT;
210         message.event = event;
211         message.arg = arg;
212
213         __pMutex->Acquire();
214
215         __pActive->Add(message);
216
217         __pMutex->Release();
218
219         uint64_t count = 1;
220         gsize writtenSize = 0;
221
222         g_io_channel_write(__pChannel, (const gchar*) &count, sizeof(count), &writtenSize);
223
224         return E_SUCCESS;
225 }
226
227 gboolean
228 _EventManager::OnEventReceived(GIOChannel* pGIOChannel, GIOCondition condition, gpointer data)
229 {
230         _EventManager* pEventManager = (_EventManager*) data;
231
232         if (condition & G_IO_IN)
233         {
234                 uint64_t tmp = 0;
235                 gsize readSize = 0;
236
237                 g_io_channel_read(pGIOChannel, (gchar*) &tmp, sizeof(tmp), &readSize);
238
239                 if (readSize == 0)
240                 {
241                         return TRUE;
242                 }
243
244                 pEventManager->__pMutex->Acquire();
245
246                 ArrayListT< _EventMessage >* pMessages = pEventManager->__pActive;
247
248                 pEventManager->__pActive = pEventManager->__pReady;
249                 pEventManager->__pReady = pMessages;
250
251                 pEventManager->__pMutex->Release();
252
253                 IEnumeratorT< _EventMessage >* pEnum = pMessages->GetEnumeratorN();
254                 _Event* pEvent = null;
255                 IEventListener* pEventListener = null;
256                 _EventMessage message;
257
258                 while (pEnum->MoveNext() == E_SUCCESS)
259                 {
260                         pEnum->GetCurrent(message);
261
262                         pEvent = GetEventObjectManager().GetObject(message.event);
263
264                         if (pEvent != null)
265                         {
266                                 if (message.type == MESSAGE_TYPE_FIRE_EVENT)
267                                 {
268                                         pEvent->Fire(message.arg);
269                                 }
270                                 else
271                                 {
272                                         pEventListener = GetEventListenerObjectManager().GetObject(message.listener);
273                                         if (pEventListener != null)
274                                         {
275                                                 pEvent->FireImpl(*pEventListener, *message.arg);
276                                         }
277                                 }
278                         }
279                 }
280
281                 delete pEnum;
282                 pMessages->RemoveAll();
283         }
284
285         return TRUE;
286 }
287
288 _EventManager*
289 _EventManager::GetCurrentEventManager(void)
290 {
291         _ThreadImpl* pThreadImpl = _ThreadImpl::GetCurrentThreadImpl();
292         SysTryReturn(NID_BASE_RT, pThreadImpl != null, null, E_OBJ_NOT_FOUND, "[E_OBJ_NOT_FOUND] This is not OSP thread.");
293
294         ThreadType threadType = pThreadImpl->GetThreadType();
295         if (threadType == THREAD_TYPE_WORKER)
296         {
297                 pThreadImpl = _ThreadImpl::GetMainThreadImpl();
298                 SysTryReturn(NID_BASE_RT, pThreadImpl != null, null, E_OBJ_NOT_FOUND, "[E_OBJ_NOT_FOUND] This is not OSP thread.");
299         }
300
301         _EventManager* pEventManager = pThreadImpl->GetEventManager();
302         SysTryReturn(NID_BASE_RT, pEventManager != null, null, E_INVALID_STATE, "[E_INVALID_STATE] Event manager is not initialized.");
303
304         return pEventManager;
305 }
306
307 result
308 _EventManager::RegisterEvent(const _HandleT< _Event >& event)
309 {
310         SysTryReturnResult(NID_BASE_RT, __pGmainContext != null, E_INVALID_STATE, "Not constructed.");
311
312         result r = E_SUCCESS;
313         bool exist = false;
314
315         exist = __events.Contains(event);
316         SysTryReturnResult(NID_BASE_RT, !exist, E_OBJ_ALREADY_EXIST, "_Event already exist.");
317
318         r = __events.Add(event);
319         SysTryReturn(NID_BASE_RT, !IsFailed(r), r, r, "[%s] Propagating.", GetErrorMessage(r));
320
321         return E_SUCCESS;
322 }
323
324 result
325 _EventManager::UnregisterEvent(const _HandleT< _Event >& event)
326 {
327         SysTryReturnResult(NID_BASE_RT, __pGmainContext != null, E_INVALID_STATE, "Not constructed.");
328
329         result r = E_SUCCESS;
330
331         r = __events.Remove(event);
332         SysTryReturnResult(NID_BASE_RT, !IsFailed(r), E_OBJ_NOT_FOUND, "Listener not found.");
333
334         ClearAllPendingEventMessages(event);
335
336         return E_SUCCESS;
337 }
338
339 void
340 _EventManager::ClearAllPendingEventMessages(const _HandleT< _Event >& event)
341 {
342         ArrayListT< _EventMessage > messages;
343         _EventMessage message;
344
345         __pMutex->Acquire();
346
347         IEnumeratorT< _EventMessage >* pEnum = __pActive->GetEnumeratorN();
348         while (pEnum->MoveNext() == E_SUCCESS)
349         {
350                 pEnum->GetCurrent(message);
351                 if (message.event != event)
352                 {
353                         messages.Add(message);
354                 }
355         }
356
357         delete pEnum;
358         pEnum = null;
359
360         __pActive->RemoveAll();
361         __pActive->AddItems(messages);
362         messages.RemoveAll();
363
364         pEnum = __pReady->GetEnumeratorN();
365         while (pEnum->MoveNext() == E_SUCCESS)
366         {
367                 pEnum->GetCurrent(message);
368                 if (message.event != event)
369                 {
370                         messages.Add(message);
371                 }
372         }
373
374         delete pEnum;
375
376         __pReady->RemoveAll();
377         __pReady->AddItems(messages);
378         messages.RemoveAll();
379
380         __pMutex->Release();
381 }
382
383 _HandleT< _EventManager >
384 _EventManager::GetHandle(void) const
385 {
386         return __handle;
387 }
388
389 _EventManager*
390 _EventManager::GetEventManagerByHandle(const _HandleT< _EventManager >& handle)
391 {
392         _EventManager* pEventManager = GetEventManagerObjectManager().GetObject(handle);
393         SysTryReturn(NID_BASE_RT, pEventManager != null, null, E_OBJ_NOT_FOUND, "[E_OBJ_NOT_FOUND]");
394
395         return pEventManager;
396 }
397
398 _ObjectManagerT< _EventManager >&
399 _EventManager::GetEventManagerObjectManager(void)
400 {
401         static _ObjectManagerT< _EventManager > objectManager;
402
403         return objectManager;
404 }
405
406 _ObjectManagerT< _Event >&
407 _EventManager::GetEventObjectManager(void)
408 {
409         static _ObjectManagerT< _Event > objectManager;
410
411         return objectManager;
412 }
413
414 _ObjectManagerT< IEventListener >&
415 _EventManager::GetEventListenerObjectManager(void)
416 {
417         static _ObjectManagerT< IEventListener > objectManager;
418
419         return objectManager;
420 }
421
422 } } } // Tizen::Base::Runtime