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 event_handler *handler;
46 cond = (unsigned int)condition;
48 if (cond & (G_IO_HUP))
49 cond &= ~(G_IO_IN | G_IO_OUT);
51 handler_info *info = (handler_info *)data;
53 handler = info->handler;
54 retvm_if(!loop || !handler, FALSE, "Invalid event info");
58 term = loop->is_terminator(fd);
63 ret = handler->handle(fd, (event_condition)cond);
66 loop->remove_event(id);
73 static gint on_timer(gpointer data)
75 event_loop *loop = (event_loop *)data;
81 event_loop::event_loop()
84 , m_terminating(false)
88 m_mainloop = g_main_loop_new(NULL, FALSE);
91 event_loop::event_loop(GMainLoop *mainloop)
94 , m_terminating(false)
99 g_main_loop_quit(m_mainloop);
100 g_main_loop_unref(m_mainloop);
103 m_mainloop = mainloop;
106 event_loop::~event_loop()
111 uint64_t event_loop::add_event(const int fd, const event_condition cond, event_handler *handler)
113 GIOChannel *ch = NULL;
116 retvm_if(m_terminating.load(), BAD_HANDLE,
117 "Failed to add event, because event_loop is being terminated");
119 ch = g_io_channel_unix_new(fd);
120 retvm_if(!ch, BAD_HANDLE, "Failed to create g_io_channel_unix_new");
122 src = g_io_create_watch(ch, (GIOCondition)(cond));
124 g_io_channel_unref(ch);
125 _E("Failed to create g_io_create_watch");
129 uint64_t id = m_sequence++;
131 handler_info *info = new(std::nothrow) handler_info(id, fd, ch, src, handler, this);
132 retvm_if(!info, BAD_HANDLE, "Failed to allocate memory");
134 g_source_set_callback(src, (GSourceFunc) g_io_handler, info, NULL);
135 g_source_attach(src, g_main_loop_get_context(m_mainloop));
137 m_handlers[id] = info;
139 /* _D("Added[%llu](fd:%d)", id, fd); */
143 uint64_t event_loop::add_idle_event(unsigned int priority, idle_handler *handler)
147 retvm_if(m_terminating.load(), false,
148 "Failed to remove event, because event_loop is terminated");
150 src = g_idle_source_new();
151 retvm_if(!src, false, "Failed to allocate memory");
155 /* Not Supported yet */
159 bool event_loop::remove_event(uint64_t id, bool close_channel)
161 auto it = m_handlers.find(id);
162 retv_if(it == m_handlers.end(), false);
165 g_io_channel_shutdown(it->second->g_ch, TRUE, NULL);
167 release_info(it->second);
168 m_handlers.erase(it);
170 /* _D("Removed[%llu]", id); */
174 void event_loop::remove_all_events(void)
176 auto it = m_handlers.begin();
177 while (it != m_handlers.end()) {
178 release_info(it->second);
179 it = m_handlers.erase(it);
183 void event_loop::release_info(handler_info *info)
185 ret_if(!info->g_ch || info->id == 0);
187 g_source_destroy(info->g_src);
188 g_source_unref(info->g_src);
190 g_io_channel_unref(info->g_ch);
193 delete info->handler;
194 info->handler = NULL;
199 class terminator : public event_handler
202 terminator(event_loop *loop)
206 bool handle(int fd, event_condition condition)
216 bool event_loop::run(int timeout)
218 retvm_if(!m_mainloop, false, "Invalid GMainLoop");
219 retv_if(is_running(), false);
222 GSource *src = g_timeout_source_new(timeout);
223 g_source_set_callback(src, on_timer, this, NULL);
224 g_source_attach(src, g_main_loop_get_context(m_mainloop));
228 m_term_fd = eventfd(0, 0);
229 retv_if(m_term_fd == -1, false);
231 terminator *handler = new(std::nothrow) terminator(this);
232 retvm_if(!handler, false, "Failed to allocate memory");
234 add_event(m_term_fd, EVENT_IN | EVENT_HUP | EVENT_NVAL, handler);
236 m_running.store(true);
239 g_main_loop_run(m_mainloop);
244 void event_loop::stop(void)
246 ret_if(!is_running() || m_terminating.load());
251 void event_loop::terminate(void)
256 g_main_loop_quit(m_mainloop);
257 g_main_loop_unref(m_mainloop);
261 m_running.store(false);
262 m_terminating.store(false);
267 bool event_loop::is_running(void)
269 return m_running.load();
272 bool event_loop::is_terminator(int fd)
274 return (m_term_fd == fd);