Rectifyng this poniter deletion from member function
[platform/core/system/sensord.git] / src / shared / event_loop.cpp
1 /*
2  * sensord
3  *
4  * Copyright (c) 2017 Samsung Electronics Co., Ltd.
5  *
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
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
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.
17  *
18  */
19
20 #include "event_loop.h"
21
22 #include <stdio.h>
23 #include <stdint.h>
24 #include <unistd.h>
25 #include <time.h>
26 #include <sys/eventfd.h>
27 #include <glib.h>
28
29 #include "sensor_log.h"
30 #include "event_handler.h"
31
32 #define BAD_HANDLE 0
33
34 using namespace ipc;
35
36 static gboolean g_io_handler(GIOChannel *ch, GIOCondition condition, gpointer data)
37 {
38         uint64_t id;
39         int fd;
40         bool term;
41         bool ret;
42         event_loop *loop;
43         event_handler *handler;
44         unsigned int cond;
45
46         cond = (unsigned int)condition;
47
48         if (cond & (G_IO_HUP))
49                 cond &= ~(G_IO_IN | G_IO_OUT);
50
51         handler_info *info = (handler_info *)data;
52         loop = info->loop;
53         handler = info->handler;
54         retvm_if(!loop || !handler, FALSE, "Invalid event info");
55
56         id = info->id;
57         fd = info->fd;
58         term = loop->is_terminator(fd);
59
60         if (cond & G_IO_NVAL)
61                 return FALSE;
62
63         ret = handler->handle(fd, (event_condition)cond);
64
65         if (!ret && !term) {
66                 loop->remove_event(id);
67                 return FALSE;
68         }
69
70         return TRUE;
71 }
72
73 static gint on_timer(gpointer data)
74 {
75         event_loop *loop = (event_loop *)data;
76         loop->stop();
77
78         return FALSE;
79 }
80
81 event_loop::event_loop()
82 : m_mainloop(NULL)
83 , m_running(false)
84 , m_terminating(false)
85 , m_sequence(1)
86 , m_term_fd(-1)
87 {
88         m_mainloop = g_main_loop_new(NULL, FALSE);
89 }
90
91 event_loop::event_loop(GMainLoop *mainloop)
92 : m_mainloop(NULL)
93 , m_running(true)
94 , m_terminating(false)
95 , m_sequence(1)
96 , m_term_fd(-1)
97 {
98         if (m_mainloop) {
99                 g_main_loop_quit(m_mainloop);
100                 g_main_loop_unref(m_mainloop);
101         }
102
103         m_mainloop = mainloop;
104 }
105
106 event_loop::~event_loop()
107 {
108         remove_all_events();
109 }
110
111 uint64_t event_loop::add_event(const int fd, const event_condition cond, event_handler *handler)
112 {
113         GIOChannel *ch = NULL;
114         GSource *src = NULL;
115
116         retvm_if(m_terminating.load(), BAD_HANDLE,
117                         "Failed to add event, because event_loop is being terminated");
118
119         ch = g_io_channel_unix_new(fd);
120         retvm_if(!ch, BAD_HANDLE, "Failed to create g_io_channel_unix_new");
121
122         src = g_io_create_watch(ch, (GIOCondition)(cond));
123         if (!src) {
124                 g_io_channel_unref(ch);
125                 _E("Failed to create g_io_create_watch");
126                 return BAD_HANDLE;
127         }
128
129         uint64_t id = m_sequence++;
130
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");
133
134         g_source_set_callback(src, (GSourceFunc) g_io_handler, info, NULL);
135         g_source_attach(src, g_main_loop_get_context(m_mainloop));
136
137         m_handlers[id] = info;
138
139         /* _D("Added[%llu](fd:%d)", id, fd); */
140         return id;
141 }
142
143 uint64_t event_loop::add_idle_event(unsigned int priority, idle_handler *handler)
144 {
145         GSource *src;
146
147         retvm_if(m_terminating.load(), false,
148                         "Failed to remove event, because event_loop is terminated");
149
150         src = g_idle_source_new();
151         retvm_if(!src, false, "Failed to allocate memory");
152
153         g_source_unref(src);
154
155         /* Not Supported yet */
156         return false;
157 }
158
159 bool event_loop::remove_event(uint64_t id, bool close_channel)
160 {
161         auto it = m_handlers.find(id);
162         retv_if(it == m_handlers.end(), false);
163
164         if (close_channel)
165                 g_io_channel_shutdown(it->second->g_ch, TRUE, NULL);
166
167         release_info(it->second);
168         m_handlers.erase(it);
169
170         /* _D("Removed[%llu]", id); */
171         return true;
172 }
173
174 void event_loop::remove_all_events(void)
175 {
176         auto it = m_handlers.begin();
177         while (it != m_handlers.end()) {
178                 release_info(it->second);
179                 it = m_handlers.erase(it);
180         }
181 }
182
183 void event_loop::release_info(handler_info *info)
184 {
185         ret_if(!info->g_ch || info->id == 0);
186
187         g_source_destroy(info->g_src);
188         g_source_unref(info->g_src);
189
190         g_io_channel_unref(info->g_ch);
191         info->g_ch = NULL;
192
193         delete info->handler;
194         info->handler = NULL;
195
196         delete info;
197 }
198
199 class terminator : public event_handler
200 {
201 public:
202         terminator(event_loop *loop)
203         : m_loop(loop)
204         { }
205
206         bool handle(int fd, event_condition condition)
207         {
208                 m_loop->terminate();
209                 return false;
210         }
211
212 private:
213         event_loop *m_loop;
214 };
215
216 bool event_loop::run(int timeout)
217 {
218         retvm_if(!m_mainloop, false, "Invalid GMainLoop");
219         retv_if(is_running(), false);
220
221         if (timeout > 0) {
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));
225                 g_source_unref(src);
226         }
227
228         m_term_fd = eventfd(0, 0);
229         retv_if(m_term_fd == -1, false);
230
231         terminator *handler = new(std::nothrow) terminator(this);
232         retvm_if(!handler, false, "Failed to allocate memory");
233
234         add_event(m_term_fd, EVENT_IN | EVENT_HUP | EVENT_NVAL, handler);
235
236         m_running.store(true);
237
238         _I("Started");
239         g_main_loop_run(m_mainloop);
240
241         return true;
242 }
243
244 void event_loop::stop(void)
245 {
246         ret_if(!is_running() || m_terminating.load());
247
248         terminate();
249 }
250
251 void event_loop::terminate(void)
252 {
253         remove_all_events();
254
255         if (m_mainloop) {
256                 g_main_loop_quit(m_mainloop);
257                 g_main_loop_unref(m_mainloop);
258                 m_mainloop = NULL;
259         }
260
261         m_running.store(false);
262         m_terminating.store(false);
263
264         _I("Terminated");
265 }
266
267 bool event_loop::is_running(void)
268 {
269         return m_running.load();
270 }
271
272 bool event_loop::is_terminator(int fd)
273 {
274         return (m_term_fd == fd);
275 }