4 * Copyright (c) 2017 Samsung Electronics Co., Ltd.
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.
20 #include "event_loop.h"
26 #include <sys/eventfd.h>
29 #include "sensor_log.h"
30 #include "event_handler.h"
36 static gboolean g_io_handler(GIOChannel *ch, GIOCondition condition, gpointer data)
43 cond = (unsigned int)condition;
45 if (cond & (G_IO_HUP))
46 cond &= ~(G_IO_IN | G_IO_OUT);
48 handler_info *info = (handler_info *)data;
51 term = info->loop->is_terminator(fd);
56 bool ret = info->handler->handle(fd, (event_condition)cond);
59 info->loop->remove_event(id);
66 static gint on_timer(gpointer data)
68 event_loop *loop = (event_loop *)data;
74 event_loop::event_loop()
77 , m_terminating(false)
81 m_mainloop = g_main_loop_new(NULL, FALSE);
84 event_loop::event_loop(GMainLoop *mainloop)
87 , m_terminating(false)
92 g_main_loop_quit(m_mainloop);
93 g_main_loop_unref(m_mainloop);
96 m_mainloop = mainloop;
99 event_loop::~event_loop()
104 uint64_t event_loop::add_event(const int fd, const event_condition cond, event_handler *handler)
106 GIOChannel *ch = NULL;
109 retvm_if(m_terminating.load(), BAD_HANDLE,
110 "Failed to add event, because event_loop is being terminated");
112 ch = g_io_channel_unix_new(fd);
113 retvm_if(!ch, BAD_HANDLE, "Failed to create g_io_channel_unix_new");
115 src = g_io_create_watch(ch, (GIOCondition)(cond));
117 g_io_channel_unref(ch);
118 _E("Failed to create g_io_create_watch");
122 uint64_t id = m_sequence++;
124 handler_info *info = new(std::nothrow) handler_info(id, fd, ch, src, handler, this);
125 retvm_if(!info, BAD_HANDLE, "Failed to allocate memory");
127 g_source_set_callback(src, (GSourceFunc) g_io_handler, info, NULL);
128 g_source_attach(src, g_main_loop_get_context(m_mainloop));
130 m_handlers[id] = info;
132 /* _D("Added[%llu](fd:%d)", id, fd); */
136 uint64_t event_loop::add_idle_event(unsigned int priority, idle_handler *handler)
140 retvm_if(m_terminating.load(), false,
141 "Failed to remove event, because event_loop is terminated");
143 src = g_idle_source_new();
144 retvm_if(!src, false, "Failed to allocate memory");
148 /* Not Supported yet */
152 bool event_loop::remove_event(uint64_t id, bool close_channel)
154 auto it = m_handlers.find(id);
155 retv_if(it == m_handlers.end(), false);
158 g_io_channel_shutdown(it->second->g_ch, TRUE, NULL);
160 release_info(it->second);
161 m_handlers.erase(it);
163 /* _D("Removed[%llu]", id); */
167 void event_loop::remove_all_events(void)
169 auto it = m_handlers.begin();
170 while (it != m_handlers.end()) {
171 release_info(it->second);
172 it = m_handlers.erase(it);
176 void event_loop::release_info(handler_info *info)
178 ret_if(!info->g_ch || info->id == 0);
180 g_source_destroy(info->g_src);
181 g_source_unref(info->g_src);
184 g_io_channel_unref(info->g_ch);
187 delete info->handler;
188 info->handler = NULL;
194 class terminator : public event_handler
197 terminator(event_loop *loop)
201 bool handle(int fd, event_condition condition)
211 bool event_loop::run(int timeout)
213 retvm_if(!m_mainloop, false, "Invalid GMainLoop");
214 retv_if(is_running(), false);
217 GSource *src = g_timeout_source_new(timeout);
218 g_source_set_callback(src, on_timer, this, NULL);
219 g_source_attach(src, g_main_loop_get_context(m_mainloop));
223 m_term_fd = eventfd(0, 0);
224 retv_if(m_term_fd == -1, false);
226 terminator *handler = new(std::nothrow) terminator(this);
227 retvm_if(!handler, false, "Failed to allocate memory");
229 add_event(m_term_fd, EVENT_IN | EVENT_HUP | EVENT_NVAL, handler);
231 m_running.store(true);
234 g_main_loop_run(m_mainloop);
239 void event_loop::stop(void)
241 ret_if(!is_running() || m_terminating.load());
246 void event_loop::terminate(void)
251 g_main_loop_quit(m_mainloop);
252 g_main_loop_unref(m_mainloop);
256 m_running.store(false);
257 m_terminating.store(false);
262 bool event_loop::is_running(void)
264 return m_running.load();
267 bool event_loop::is_terminator(int fd)
269 return (m_term_fd == fd);