2 * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
4 * Contact: Jan Olszak <j.olszak@samsung.com>
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License
21 * @author Jan Olszak (j.olszak@samsung.com)
22 * @brief Class for creating a dedicated GSource
28 #include "ipc/ipc-gsource.hpp"
29 #include "utils/callback-wrapper.hpp"
30 #include "logger/logger.hpp"
39 gushort conditions = static_cast<gushort>(G_IO_IN |
45 IPCGSource::IPCGSource(const HandlerCallback& handlerCallback)
46 : mHandlerCallback(handlerCallback)
48 LOGT("IPCGSource Constructor");
51 IPCGSource::~IPCGSource()
53 LOGT("IPCGSource Destructor");
56 IPCGSource::Pointer IPCGSource::create(const HandlerCallback& handlerCallback)
58 LOGT("Creating IPCGSource");
60 static GSourceFuncs funcs = { &IPCGSource::prepare,
62 &IPCGSource::dispatch,
63 &IPCGSource::finalize,
69 GSource* gSource = g_source_new(&funcs, sizeof(IPCGSource));
70 g_source_set_priority(gSource, G_PRIORITY_HIGH);
72 // Fill additional data
73 IPCGSource* source = reinterpret_cast<IPCGSource*>(gSource);
74 new(source) IPCGSource(handlerCallback);
76 auto deleter = [](IPCGSource * ptr) {
78 g_source_unref(&ptr->mGSource);
81 Pointer ipcGSourcePtr(source, deleter);
83 g_source_set_callback(gSource,
84 &IPCGSource::onHandlerCall,
85 utils::createCallbackWrapper(Pointer(ipcGSourcePtr), ipcGSourcePtr->mGuard.spawn()),
86 &utils::deleteCallbackWrapper<Pointer>);
91 void IPCGSource::addFD(const FileDescriptor fd)
93 LOGI("Adding to glib FD: " << fd);
94 Lock lock(mStateMutex);
96 mGPollFDs.push_back({fd, conditions, 0});
97 g_source_add_poll(&mGSource, &mGPollFDs.back());
100 void IPCGSource::removeFD(const FileDescriptor fd)
102 Lock lock(mStateMutex);
104 auto it = std::find_if(mGPollFDs.begin(), mGPollFDs.end(), [fd](GPollFD gPollFD) {
105 return gPollFD.fd = fd;
108 if (it == mGPollFDs.end()) {
112 g_source_remove_poll(&mGSource, &(*it));
114 LOGI("Removed from glib FD: " << fd);
117 guint IPCGSource::attach(GMainContext* context)
119 LOGT("Attaching to GMainContext");
120 guint ret = g_source_attach(&mGSource, context);
124 void IPCGSource::detach()
127 Lock lock(mStateMutex);
129 for (GPollFD gPollFD : mGPollFDs) {
130 g_source_remove_poll(&mGSource, &gPollFD);
134 if (!g_source_is_destroyed(&mGSource)) {
136 // This way finalize method will be run in glib loop's thread
137 g_source_destroy(&mGSource);
141 void IPCGSource::callHandler()
143 Lock lock(mStateMutex);
145 for (const GPollFD& gPollFD : mGPollFDs) {
146 if (gPollFD.revents & conditions) {
147 mHandlerCallback(gPollFD.fd, gPollFD.revents);
152 gboolean IPCGSource::onHandlerCall(gpointer userData)
154 const auto& source = utils::getCallbackFromPointer<Pointer>(userData);
156 source->callHandler();
161 gboolean IPCGSource::prepare(GSource* gSource, gint* timeout)
163 if (!gSource || g_source_is_destroyed(gSource)) {
169 // TODO: Implement hasEvents() method in Client and Service and use it here as a callback:
170 // return source->hasEvents();
174 gboolean IPCGSource::check(GSource* gSource)
176 if (!gSource || g_source_is_destroyed(gSource)) {
183 gboolean IPCGSource::dispatch(GSource* gSource,
184 GSourceFunc callback,
187 if (!gSource || g_source_is_destroyed(gSource)) {
188 // Remove the GSource from the GMainContext
199 void IPCGSource::finalize(GSource* gSource)
202 IPCGSource* source = reinterpret_cast<IPCGSource*>(gSource);
203 source->~IPCGSource();