tizen 2.4 release
[framework/context/context-common.git] / src / event_driven.cpp
1 /*
2  * Copyright (c) 2015 Samsung Electronics Co., Ltd.
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16
17 #include <new>
18 #include <types_internal.h>
19 #include <event_driven.h>
20
21 struct thread_info_s {
22         GThread *thread;
23         gint is_running;
24         GAsyncQueue *event_queue;
25 };
26
27 struct event_message_s {
28         int type;
29         void* data;
30         bool is_stop_signal;
31         event_message_s() : type(-1), data(NULL), is_stop_signal(false) {}
32 };
33
34 event_driven_thread::event_driven_thread()
35 {
36         thread_info = static_cast<thread_info_s*>(g_malloc(sizeof(thread_info_s)));
37
38         if (thread_info) {
39                 thread_info->thread = NULL;
40                 thread_info->is_running = 0;
41                 thread_info->event_queue = NULL;
42         }
43 }
44
45 event_driven_thread::~event_driven_thread()
46 {
47         stop();
48         g_free(thread_info);
49 }
50
51 bool event_driven_thread::start()
52 {
53         IF_FAIL_RETURN_TAG(thread_info, false, _E, "Memory allocation failed");
54
55         if (!g_atomic_int_get(&(thread_info->is_running))) {
56
57 #if 0
58                 int stack_size = sysconf(_SC_PAGESIZE) * 4;
59                 void *stack = NULL;
60                 stack = g_malloc(stack_size);
61                 IF_FAIL_RETURN_TAG(stack, false, _E, "Memory allocation failed");
62 #endif
63
64                 thread_info->event_queue = g_async_queue_new();
65                 if (thread_info->event_queue == NULL) {
66                         _E("Memory allocation failed");
67                         return false;
68                 }
69
70                 g_atomic_int_set(&thread_info->is_running, 1);
71
72 #if 0
73                 thread_info->pid = clone(&thread_func_wrapper, (char*)stack + stack_size,
74                                 SIGCHLD | CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SYSVSEM, this);
75
76                 if (thread_info->pid < 0) {
77                         _E(RED("Thread creation failed"));
78                         g_atomic_int_set(&thread_info->is_running, 0);
79                         g_free(stack);
80                         g_async_queue_unref(thread_info->event_queue);
81                         return false;
82                 }
83
84                 _I(PURPLE("PID %d initiated"), thread_info->pid);
85 #endif
86
87                 thread_info->thread = g_thread_new(NULL, thread_func_wrapper, static_cast<gpointer>(this));
88
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);
93                         return false;
94                 }
95
96                 _I(PURPLE("A thread initiated"));
97         }
98
99         return true;
100 }
101
102 bool event_driven_thread::stop()
103 {
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");
107
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);
111
112 #if 0
113                 pid_t pid = waitpid(thread_info->pid, NULL, 0);
114                 _I(PURPLE("PID %d terminated"), pid);
115                 if (pid < 0) {
116                         _E(RED("Failed to join %d from %d"), thread_info->pid, getpid());
117                 }
118 #endif
119                 g_thread_join(thread_info->thread);
120
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)))) {
123                         if (event->data) {
124                                 delete_thread_event(event->type, event->data);
125                         }
126                         delete event;
127                 }
128                 g_async_queue_unref(thread_info->event_queue);
129         }
130
131         return true;
132 }
133
134 bool event_driven_thread::is_running()
135 {
136         if (g_atomic_int_get(&(thread_info->is_running))) {
137                 return true;
138         }
139         return false;
140 }
141
142 bool event_driven_thread::push_thread_event(int type, void* data)
143 {
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");
147
148                 event->type = type;
149                 event->data = data;
150                 g_async_queue_push(thread_info->event_queue, event);
151                 return true;
152         }
153
154         return false;
155 }
156
157 gpointer event_driven_thread::thread_func_wrapper(gpointer data)
158 {
159         static_cast<event_driven_thread*>(data)->process_event_queue();
160         return NULL;
161 }
162
163 void event_driven_thread::process_event_queue()
164 {
165 #if 0
166         struct sigaction signal_action;
167         signal_action.sa_handler = child_signal_handler;
168         sigemptyset(&signal_action.sa_mask);
169
170         sigaction(SIGINT, &signal_action, NULL);
171         sigaction(SIGHUP, &signal_action, NULL);
172         sigaction(SIGTERM, &signal_action, NULL);
173         sigaction(SIGQUIT, &signal_action, NULL);
174 #endif
175
176         event_message_s *event = NULL;
177
178         while (g_atomic_int_get(&(thread_info->is_running))) {
179
180                 event = static_cast<event_message_s*>(g_async_queue_pop(thread_info->event_queue));
181
182                 if (event) {
183                         if (event->is_stop_signal){
184                                 delete event;
185                                 break;
186                         } else {
187                                 on_thread_event_popped(event->type, event->data);
188                                 delete event;
189                         }
190                 }
191
192         }
193 }