2 * Copyright (c) 2015 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 #include <types_internal.h>
19 #include <event_driven.h>
21 struct thread_info_s {
24 GAsyncQueue *event_queue;
27 struct event_message_s {
31 event_message_s() : type(-1), data(NULL), is_stop_signal(false) {}
34 event_driven_thread::event_driven_thread()
36 thread_info = static_cast<thread_info_s*>(g_malloc(sizeof(thread_info_s)));
39 thread_info->thread = NULL;
40 thread_info->is_running = 0;
41 thread_info->event_queue = NULL;
45 event_driven_thread::~event_driven_thread()
51 bool event_driven_thread::start()
53 IF_FAIL_RETURN_TAG(thread_info, false, _E, "Memory allocation failed");
55 if (!g_atomic_int_get(&(thread_info->is_running))) {
58 int stack_size = sysconf(_SC_PAGESIZE) * 4;
60 stack = g_malloc(stack_size);
61 IF_FAIL_RETURN_TAG(stack, false, _E, "Memory allocation failed");
64 thread_info->event_queue = g_async_queue_new();
65 if (thread_info->event_queue == NULL) {
66 _E("Memory allocation failed");
70 g_atomic_int_set(&thread_info->is_running, 1);
73 thread_info->pid = clone(&thread_func_wrapper, (char*)stack + stack_size,
74 SIGCHLD | CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SYSVSEM, this);
76 if (thread_info->pid < 0) {
77 _E(RED("Thread creation failed"));
78 g_atomic_int_set(&thread_info->is_running, 0);
80 g_async_queue_unref(thread_info->event_queue);
84 _I(PURPLE("PID %d initiated"), thread_info->pid);
87 thread_info->thread = g_thread_new(NULL, thread_func_wrapper, static_cast<gpointer>(this));
89 if (thread_info->thread == NULL) {
90 _E(RED("Thread creation failed"));
91 g_atomic_int_set(&thread_info->is_running, 0);
92 g_async_queue_unref(thread_info->event_queue);
96 _I(PURPLE("A thread initiated"));
102 bool event_driven_thread::stop()
104 if (g_atomic_int_get(&(thread_info->is_running))) {
105 event_message_s* event = new(std::nothrow) event_message_s;
106 IF_FAIL_RETURN_TAG(event, false, _E, "Memory allocation failed");
108 event->is_stop_signal = true;
109 g_async_queue_push(thread_info->event_queue, event);
110 g_atomic_int_set(&thread_info->is_running, 0);
113 pid_t pid = waitpid(thread_info->pid, NULL, 0);
114 _I(PURPLE("PID %d terminated"), pid);
116 _E(RED("Failed to join %d from %d"), thread_info->pid, getpid());
119 g_thread_join(thread_info->thread);
121 // Free the memory allocated for the event queue
122 while ((event = static_cast<event_message_s*>(g_async_queue_try_pop(thread_info->event_queue)))) {
124 delete_thread_event(event->type, event->data);
128 g_async_queue_unref(thread_info->event_queue);
134 bool event_driven_thread::is_running()
136 if (g_atomic_int_get(&(thread_info->is_running))) {
142 bool event_driven_thread::push_thread_event(int type, void* data)
144 if (g_atomic_int_get(&(thread_info->is_running))) {
145 event_message_s* event = new(std::nothrow) event_message_s;
146 IF_FAIL_RETURN_TAG(event, false, _E, "Memory allocation failed");
150 g_async_queue_push(thread_info->event_queue, event);
157 gpointer event_driven_thread::thread_func_wrapper(gpointer data)
159 static_cast<event_driven_thread*>(data)->process_event_queue();
163 void event_driven_thread::process_event_queue()
166 struct sigaction signal_action;
167 signal_action.sa_handler = child_signal_handler;
168 sigemptyset(&signal_action.sa_mask);
170 sigaction(SIGINT, &signal_action, NULL);
171 sigaction(SIGHUP, &signal_action, NULL);
172 sigaction(SIGTERM, &signal_action, NULL);
173 sigaction(SIGQUIT, &signal_action, NULL);
176 event_message_s *event = NULL;
178 while (g_atomic_int_get(&(thread_info->is_running))) {
180 event = static_cast<event_message_s*>(g_async_queue_pop(thread_info->event_queue));
183 if (event->is_stop_signal){
187 on_thread_event_popped(event->type, event->data);