2 // Copyright (c) 2012 Samsung Electronics Co., Ltd.
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
8 // http://www.apache.org/licenses/LICENSE-2.0
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.
18 * @file FBaseRt_MainLoop.cpp
19 * @brief This is the implementation file for the _MainLoop class.
27 #include <sys/eventfd.h>
30 #include <FBaseColIEnumeratorT.h>
32 #include <FBaseSysLog.h>
33 #include "FBaseRt_MainLoop.h"
35 using namespace Tizen::Base;
36 using namespace Tizen::Base::Collection;
37 using namespace Tizen::Base::Runtime;
39 namespace Tizen { namespace Base { namespace Runtime
41 __thread _MainLoop* pCurrentMainLoop = null;
44 _MainLoop::_Message::operator==(const _Message& rhs) const
46 if (requestId == rhs.requestId && pArgs == rhs.pArgs)
55 _MainLoop::_Message::operator!=(const _Message& rhs) const
57 if (requestId != rhs.requestId || pArgs != rhs.pArgs)
65 _MainLoop::_MainLoop(void)
67 , __pGmainContext(null)
78 _MainLoop::~_MainLoop(void)
86 g_source_destroy(__pSource);
87 g_source_unref(__pSource);
93 g_io_channel_unref(__pChannel);
99 _MainLoop::Construct(GMainLoop* pGmainLoop, GMainContext* pGmainContext)
101 result r = E_SUCCESS;
102 GError* pGError = null;
104 __pGmainContext = pGmainContext;
105 g_main_context_ref(__pGmainContext);
107 int eventFd = eventfd(0, 0);
108 SysTryCatch(NID_BASE_RT, -1 != eventFd, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Failed to open eventfd.");
111 __pChannel = g_io_channel_unix_new(eventFd);
112 SysTryCatch(NID_BASE_RT, __pChannel != null, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Failed to create a channel for eventfd.");
114 g_io_channel_set_encoding(__pChannel, null, &pGError);
115 g_io_channel_set_flags(__pChannel, G_IO_FLAG_NONBLOCK, &pGError);
117 g_io_channel_set_close_on_unref(__pChannel, TRUE);
120 __pSource = g_io_create_watch(__pChannel, G_IO_IN);
121 SysTryCatch(NID_BASE_RT, __pSource != null, r = E_SYSTEM, E_SYSTEM,
122 "[E_SYSTEM] Failed to create a gsource for a channel.");
124 g_source_set_callback(__pSource, (GSourceFunc)OnMessageArrived, this, null);
125 g_source_attach(__pSource, __pGmainContext);
127 __pMutex = new (std::nothrow) Mutex();
128 SysTryCatch(NID_BASE_RT, __pMutex != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Not enough memory.");
130 r = __pMutex->Create();
131 SysTryCatch(NID_BASE_RT, !IsFailed(r), , r, "[%s] Failed to create mutex.", GetErrorMessage(r));
133 pCurrentMainLoop = this;
135 __pActive = &__messages1;
136 __pReady = &__messages2;
148 g_source_destroy(__pSource);
149 g_source_unref(__pSource);
155 g_io_channel_unref(__pChannel);
167 _MainLoop::SendUserEvent(RequestId requestId, const IList* pArgs)
169 SysTryReturnResult(NID_BASE_RT, __pGmainContext != null, E_INVALID_STATE, "Main loop is not constructed.");
173 message.requestId = requestId;
174 message.pArgs = pArgs;
178 __pActive->Add(message);
182 gsize writtenSize = 0;
185 g_io_channel_write(__pChannel, (const gchar*) &count, sizeof(count), &writtenSize);
191 _MainLoop::SetMainLoopEventListener(_IMainLoopEventListener* pListener)
193 __pListener = pListener;
197 _MainLoop::OnMessageArrived(GIOChannel* pChannel, GIOCondition condition, gpointer data)
199 _MainLoop* pMainLoop = (_MainLoop*) data;
204 ArrayListT<_Message>* pMessages = null;
206 pMainLoop->__pMutex->Acquire();
208 pMessages = pMainLoop->__pActive;
209 pMainLoop->__pActive = pMainLoop->__pReady;
210 pMainLoop->__pReady = pMessages;
212 pMainLoop->__pMutex->Release();
214 if (condition & G_IO_IN)
216 g_io_channel_read(pChannel, (gchar*) &count, sizeof(count), &readSize);
223 if (pMainLoop->__pListener)
226 IEnumeratorT<_Message>* pEnum = pMessages->GetEnumeratorN();;
227 SysTryReturn(NID_BASE_RT, pEnum, TRUE, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Not enough memory.");
229 while (pEnum->MoveNext() == E_SUCCESS)
231 pEnum->GetCurrent(message);
235 pMessages->RemoveAll();
238 count = pMainLoop->__pActive->GetCount();
241 gsize writtenSize = 0;
242 g_io_channel_write(pChannel, (const gchar*) &count, sizeof(count), &writtenSize);
249 _MainLoop::GetCurrentMainLoop(void)
251 SysTryReturn(NID_BASE_RT, pCurrentMainLoop != null, null, E_INVALID_STATE, "[E_INVALID_STATE] Main loop is exist.");
253 return pCurrentMainLoop;
257 _MainLoop::GetGmainContext(void) const
259 SysTryReturn(NID_BASE_RT, __pGmainContext != null, null, E_INVALID_STATE, "[E_INVALID_STATE] Main loop is not constructed..");
261 return __pGmainContext;
264 } } } // Tizen::Base::Runtime