summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCedric BAIL <cedric.bail@free.fr>2012-10-19 05:47:33 +0000
committerCedric BAIL <cedric.bail@free.fr>2012-10-19 05:47:33 +0000
commit903bbfba828d552ad09e965bf0b6af463336d486 (patch)
treecbfb0b2a293579a0476927bd160c88da054c53f0
parent4b14ea628c1e029e84a59188981b4c4ca1d7d29f (diff)
efl: add Eina_Thread API.
SVN revision: 78225
-rw-r--r--ChangeLog4
-rw-r--r--NEWS1
-rw-r--r--src/lib/eina/Eina.h1
-rw-r--r--src/lib/eina/Makefile.am2
-rw-r--r--src/lib/eina/eina_main.c2
-rw-r--r--src/lib/eina/eina_thread.c279
-rw-r--r--src/lib/eina/eina_thread.h82
7 files changed, 371 insertions, 0 deletions
diff --git a/ChangeLog b/ChangeLog
index 53ae4e5826..a686ad5ae6 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -48,3 +48,7 @@
482012-10-19 Patryk Kaczmarek 482012-10-19 Patryk Kaczmarek
49 49
50 * eina_stringshare_add_length return NULL when func args are wrong. 50 * eina_stringshare_add_length return NULL when func args are wrong.
51
522012-10-19 Cedric Bail
53
54 * Add eina_thread API.
diff --git a/NEWS b/NEWS
index f976ac0f53..ff5e32f5d9 100644
--- a/NEWS
+++ b/NEWS
@@ -9,6 +9,7 @@ Additions:
9 * Add DOCTYPE children parsing in eina_simple_xml 9 * Add DOCTYPE children parsing in eina_simple_xml
10 * Add eina_barrier thread API 10 * Add eina_barrier thread API
11 * Add eina_tmpstr_add() and eina_tmpstr_del() 11 * Add eina_tmpstr_add() and eina_tmpstr_del()
12 * Add eina_thread API
12 13
13Improvements: 14Improvements:
14 * Single EFL tree now covring all EFL library components. 15 * Single EFL tree now covring all EFL library components.
diff --git a/src/lib/eina/Eina.h b/src/lib/eina/Eina.h
index 584bccd9de..71e8b59db7 100644
--- a/src/lib/eina/Eina.h
+++ b/src/lib/eina/Eina.h
@@ -225,6 +225,7 @@ extern "C" {
225#include "eina_cpu.h" 225#include "eina_cpu.h"
226#include "eina_sched.h" 226#include "eina_sched.h"
227#include "eina_tiler.h" 227#include "eina_tiler.h"
228#include "eina_thread.h"
228#include "eina_hamster.h" 229#include "eina_hamster.h"
229#include "eina_matrixsparse.h" 230#include "eina_matrixsparse.h"
230#include "eina_str.h" 231#include "eina_str.h"
diff --git a/src/lib/eina/Makefile.am b/src/lib/eina/Makefile.am
index d290892206..e9c34a35ff 100644
--- a/src/lib/eina/Makefile.am
+++ b/src/lib/eina/Makefile.am
@@ -59,6 +59,7 @@ eina_inline_rbtree.x \
59eina_inline_mempool.x \ 59eina_inline_mempool.x \
60eina_inline_rectangle.x \ 60eina_inline_rectangle.x \
61eina_inline_trash.x \ 61eina_inline_trash.x \
62eina_thread.h \
62eina_trash.h \ 63eina_trash.h \
63eina_iterator.h \ 64eina_iterator.h \
64eina_main.h \ 65eina_main.h \
@@ -145,6 +146,7 @@ eina_strbuf.c \
145eina_strbuf_common.c \ 146eina_strbuf_common.c \
146eina_stringshare.c \ 147eina_stringshare.c \
147eina_tiler.c \ 148eina_tiler.c \
149eina_thread.c \
148eina_unicode.c \ 150eina_unicode.c \
149eina_ustrbuf.c \ 151eina_ustrbuf.c \
150eina_ustringshare.c \ 152eina_ustringshare.c \
diff --git a/src/lib/eina/eina_main.c b/src/lib/eina/eina_main.c
index fb4241eb1b..fb2bb0df73 100644
--- a/src/lib/eina/eina_main.c
+++ b/src/lib/eina/eina_main.c
@@ -157,6 +157,7 @@ EAPI Eina_Inlist *_eina_tracking = NULL;
157 S(prefix); 157 S(prefix);
158 S(value); 158 S(value);
159 S(tmpstr); 159 S(tmpstr);
160 S(thread);
160/* no model for now 161/* no model for now
161 S(model); 162 S(model);
162 */ 163 */
@@ -198,6 +199,7 @@ static const struct eina_desc_setup _eina_desc_setup[] = {
198 S(prefix), 199 S(prefix),
199 S(value), 200 S(value),
200 S(tmpstr), 201 S(tmpstr),
202 S(thread)
201/* no model for now 203/* no model for now
202 S(model) 204 S(model)
203 */ 205 */
diff --git a/src/lib/eina/eina_thread.c b/src/lib/eina/eina_thread.c
new file mode 100644
index 0000000000..e7a5fcdc3d
--- /dev/null
+++ b/src/lib/eina/eina_thread.c
@@ -0,0 +1,279 @@
1/* EINA - EFL data type library
2 * Copyright (C) 2012 Cedric Bail
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library;
16 * if not, see <http://www.gnu.org/licenses/>.
17 */
18
19#ifdef HAVE_CONFIG_H
20# include "config.h"
21#endif
22
23#include <stdlib.h>
24
25#ifdef HAVE_EVIL
26# include <Evil.h>
27#endif
28
29#include "eina_config.h"
30#include "eina_thread.h"
31#include "eina_sched.h"
32
33#ifdef EINA_HAVE_THREADS
34# ifdef _WIN32_WCE
35
36# elif defined(_WIN32)
37
38# define WIN32_LEAN_AND_MEAN
39# include <windows.h>
40# undef WIN32_LEAN_AND_MEAN
41
42typedef struct _Eina_Thread_Win32 Eina_Thread_Win32;
43struct _Eina_Thread_Win32
44{
45 HANDLE thread;
46 Eina_Thread_Cb func;
47 void *data;
48 void *ret;
49
50 Eina_Thread index;
51};
52
53/* FIXME: For the moment Eina_Thread is considered not
54 thread safe, wondering if it's worth it */
55static unsigned long int _current_index = 1; /* start from one as the main loop == 0 */
56static Eina_List *_thread_pool = NULL;
57static Eina_List *_thread_running = NULL;
58
59static Eina_Thread_Win32 *
60_eina_thread_win32_find(Eina_Thread index)
61{
62 Eina_Thread_Win32 *tw;
63 Eina_List *l;
64
65 EINA_LIST_FOREACH(_thread_running, l, tw)
66 if (tw->index == index)
67 return tw;
68 return NULL;
69}
70
71static Eina_Thread
72_eina_thread_win32_self(void)
73{
74 HANDLE t;
75
76 t = GetCurrentThread();
77 EINA_LIST_FOREACH(_thread_running, l, tw)
78 if (tw->thread == t)
79 return tw->index;
80
81 /* We assume main loop == 0 on Windows */
82 return 0;
83}
84
85static Eina_Bool
86_eina_thread_win32_equal(Eina_Thread t1, Eina_Thread t2)
87{
88 if (t1 == t2) return EINA_TRUE;
89 return EINA_FALSE;
90}
91
92static DWORD WINAPI
93_eina_thread_win32_cb(LPVOID lpParam)
94{
95 Eina_Thread_Win32 *tw = lpParam;
96
97 tw->ret = tw->func(tw->data, tw->index);
98
99 return 0;
100}
101
102static Eina_Bool
103_eina_thread_win32_create(Eina_Thread *t,
104 Eina_Thread_Cb func,
105 const void *data)
106{
107 Eina_Thread_Win32 *tw;
108 Eina_List *l;
109
110 tw = eina_list_data_get(_thread_pool);
111 _thread_pool = eina_list_remove_list(_thread_pool, _thread_pool);
112
113 if (!tw)
114 {
115 tw = malloc(sizeof (Eina_Thread_Win32));
116 if (!tw) goto on_error;
117
118 do {
119 tw->index = _current_index++;
120 } while (tw->index == 0); /* prevent having a "false" main loop */
121 }
122
123 tw->func = f;
124 tw->data = d;
125
126 tw->thread = CreateThread(NULL, 0, _eina_thread_win32_cb, tw, 0, NULL);
127 if (!tw->thread) goto on_error;
128
129 _thread_running = eina_list_append(_thread_running, tw);
130
131 *t = tw->index;
132 return EINA_TRUE;
133
134 on_error:
135 _thread_pool = eina_list_append(_thread_pool, tw);
136 return EINA_FALSE;
137}
138
139static void *
140_eina_thread_win32_join(Eina_Thread t)
141{
142 Eina_Thread_Win32 *tw;
143 void *ret;
144
145 tw = _eina_thread_win32_find(index);
146 if (!tw) return NULL;
147
148 WaitForSingleObject(tw->thread, INFINITE);
149 CloseHandle(tw->thread);
150
151 ret = tw->ret;
152
153 tw->ret = NULL;
154 tw->thread = NULL;
155 tw->func = NULL;
156 tw->data = NULL;
157
158 _thread_running = eina_list_remove(_thread_running, tw);
159 _thread_pool = eina_list_append(_thread_pool, _thread_pool);
160
161 return ret;
162}
163
164# define PHE(x, y) _eina_thread_win32_equal(x, y)
165# define PHS() _eina_thread_win32_self()
166# define PHC(x, f, d) _eina_thread_win32_create(x, f, d)
167# define PHJ(x) _eina_thread_win32_join(x)
168
169# else
170# include <pthread.h>
171
172# ifdef __linux__
173# include <sched.h>
174# include <sys/resource.h>
175# include <unistd.h>
176# include <sys/syscall.h>
177# include <errno.h>
178# endif
179
180static void *
181_eina_thread_join(Eina_Thread t)
182{
183 void *ret = NULL;
184
185 if (!pthread_join(t, &ret))
186 return ret;
187 return NULL;
188}
189
190# define PHE(x, y) pthread_equal(x, y)
191# define PHS() pthread_self()
192# define PHC(x, f, d) pthread_create(x, NULL, (void*) f, d)
193# define PHJ(x) _eina_thread_join(x)
194
195# endif
196#else
197# error "Not supported any more"
198#endif
199
200typedef struct _Eina_Thread_Call Eina_Thread_Call;
201struct _Eina_Thread_Call
202{
203 Eina_Thread_Cb func;
204 const void *data;
205
206 Eina_Thread_Priority prio;
207 Eina_Bool affinity;
208};
209
210#include "eina_thread.h"
211
212static void *
213_eina_internal_call(void *context)
214{
215 Eina_Thread_Call *c = context;
216 void *r;
217
218 if (c->prio == EINA_THREAD_BACKGROUND ||
219 c->prio == EINA_THREAD_IDLE)
220 eina_sched_prio_drop();
221
222 /* FIXME: set priority and affinity */
223 r = c->func((void*) c->data, eina_thread_self());
224
225 free(c);
226
227 return r;
228}
229
230EAPI Eina_Thread
231eina_thread_self(void)
232{
233 return PHS();
234}
235
236EAPI Eina_Bool
237eina_thread_equal(Eina_Thread t1, Eina_Thread t2)
238{
239 return !!(PHE(t1, t2));
240}
241
242EAPI Eina_Bool
243eina_thread_create(Eina_Thread *t,
244 Eina_Thread_Priority prio, Eina_Bool affinity,
245 Eina_Thread_Cb func, const void *data)
246{
247 Eina_Thread_Call *c;
248
249 c = malloc(sizeof (Eina_Thread_Call));
250 if (!c) return EINA_FALSE;
251
252 c->func = func;
253 c->data = data;
254 c->prio = prio;
255 c->affinity = affinity;
256
257 if (PHC(t, _eina_internal_call, c) == 0)
258 return EINA_TRUE;
259
260 free(c);
261
262 return EINA_FALSE;
263}
264
265EAPI void *
266eina_thread_join(Eina_Thread t)
267{
268 return PHJ(t);
269}
270
271void
272eina_thread_init(void)
273{
274}
275
276void
277eina_thread_shutdown(void)
278{
279}
diff --git a/src/lib/eina/eina_thread.h b/src/lib/eina/eina_thread.h
new file mode 100644
index 0000000000..e615e27c43
--- /dev/null
+++ b/src/lib/eina/eina_thread.h
@@ -0,0 +1,82 @@
1/* EINA - EFL data type library
2 * Copyright (C) 2012 Cedric Bail
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library;
16 * if not, see <http://www.gnu.org/licenses/>.
17 */
18
19#ifndef EINA_THREAD_H_
20#define EINA_THREAD_H_
21
22#include "eina_config.h"
23#include "eina_types.h"
24#include "eina_error.h"
25
26/**
27 * @addtogroup Eina_Tools_Group Tools
28 *
29 * @{
30 */
31
32/**
33 * @defgroup Eina_Thread_Group Thread
34 *
35 * @{
36 */
37
38#ifdef EINA_HAVE_THREADS
39# ifdef _WIN32_WCE
40
41typedef unsigned long int Eina_Thread;
42
43# elif defined(_WIN32)
44
45typedef unsigned long int Eina_Thread;
46
47# else
48# include <pthread.h>
49
50typedef pthread_t Eina_Thread;
51
52# endif
53#else
54# error "Build without thread is not supported any more"
55#endif
56
57typedef void *(*Eina_Thread_Cb)(void *data, Eina_Thread t);
58
59typedef enum _Eina_Thread_Priority
60{
61 EINA_THREAD_URGENT,
62 EINA_THREAD_NORMAL,
63 EINA_THREAD_BACKGROUND,
64 EINA_THREAD_IDLE
65} Eina_Thread_Priority;
66
67EAPI Eina_Thread eina_thread_self(void);
68EAPI Eina_Bool eina_thread_equal(Eina_Thread t1, Eina_Thread t2);
69EAPI Eina_Bool eina_thread_create(Eina_Thread *t,
70 Eina_Thread_Priority prio, Eina_Bool affinity,
71 Eina_Thread_Cb func, const void *data);
72EAPI void *eina_thread_join(Eina_Thread t);
73
74/**
75 * @}
76 */
77
78/**
79 * @}
80 */
81
82#endif