aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/libraries/evas/src/lib/cache/evas_preload.c
diff options
context:
space:
mode:
authorDavid Walter Seikel2012-01-04 18:41:13 +1000
committerDavid Walter Seikel2012-01-04 18:41:13 +1000
commitdd7595a3475407a7fa96a97393bae8c5220e8762 (patch)
treee341e911d7eb911a51684a7412ef7f7c7605d28e /libraries/evas/src/lib/cache/evas_preload.c
parentAdd the skeleton. (diff)
downloadSledjHamr-dd7595a3475407a7fa96a97393bae8c5220e8762.zip
SledjHamr-dd7595a3475407a7fa96a97393bae8c5220e8762.tar.gz
SledjHamr-dd7595a3475407a7fa96a97393bae8c5220e8762.tar.bz2
SledjHamr-dd7595a3475407a7fa96a97393bae8c5220e8762.tar.xz
Add the base Enlightenment Foundation Libraries - eina, eet, evas, ecore, embryo, and edje.
Note that embryo wont be used, but I'm not sure yet if you can build edje without it.
Diffstat (limited to 'libraries/evas/src/lib/cache/evas_preload.c')
-rw-r--r--libraries/evas/src/lib/cache/evas_preload.c264
1 files changed, 264 insertions, 0 deletions
diff --git a/libraries/evas/src/lib/cache/evas_preload.c b/libraries/evas/src/lib/cache/evas_preload.c
new file mode 100644
index 0000000..6e0412a
--- /dev/null
+++ b/libraries/evas/src/lib/cache/evas_preload.c
@@ -0,0 +1,264 @@
1#ifdef HAVE_CONFIG_H
2# include <config.h>
3#endif
4
5#ifdef HAVE_EVIL
6# include <Evil.h>
7#endif
8
9#ifdef BUILD_ASYNC_PRELOAD
10# include <pthread.h>
11# ifdef __linux__
12# include <sys/syscall.h>
13# endif
14#endif
15
16#include "evas_common.h"
17#include "evas_private.h"
18#include "Evas.h"
19
20#ifdef BUILD_ASYNC_PRELOAD
21
22static int _threads_max = 0;
23
24typedef struct _Evas_Preload_Pthread_Worker Evas_Preload_Pthread_Worker;
25typedef struct _Evas_Preload_Pthread_Data Evas_Preload_Pthread_Data;
26
27typedef void (*_evas_preload_pthread_func)(void *data);
28
29struct _Evas_Preload_Pthread_Worker
30{
31 EINA_INLIST;
32
33 _evas_preload_pthread_func func_heavy;
34 _evas_preload_pthread_func func_end;
35 _evas_preload_pthread_func func_cancel;
36 void *data;
37 Eina_Bool cancel : 1;
38};
39
40struct _Evas_Preload_Pthread_Data
41{
42 pthread_t thread;
43};
44
45static int _threads_count = 0;
46static Evas_Preload_Pthread_Worker *_workers = NULL;
47
48static LK(_mutex);
49
50static void
51_evas_preload_thread_end(void *data)
52{
53 Evas_Preload_Pthread_Data *pth = data;
54 Evas_Preload_Pthread_Data *p = NULL;
55
56 if (pthread_join(pth->thread, (void **)&p) == 0) free(p);
57 else return;
58 eina_threads_shutdown();
59}
60
61static void
62_evas_preload_thread_done(void *target __UNUSED__, Evas_Callback_Type type __UNUSED__, void *event_info)
63{
64 Evas_Preload_Pthread_Worker *work = event_info;
65 if (work->cancel)
66 {
67 if (work->func_cancel) work->func_cancel(work->data);
68 }
69 else
70 work->func_end(work->data);
71
72 free(work);
73}
74
75static void *
76_evas_preload_thread_worker(void *data)
77{
78 Evas_Preload_Pthread_Data *pth = data;
79 Evas_Preload_Pthread_Worker *work;
80
81 eina_sched_prio_drop();
82 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
83 pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
84on_error:
85 for (;;)
86 {
87 LKL(_mutex);
88 if (!_workers)
89 {
90 LKU(_mutex);
91 break;
92 }
93
94 work = _workers;
95 _workers = EINA_INLIST_CONTAINER_GET(eina_inlist_remove(EINA_INLIST_GET(_workers),
96 EINA_INLIST_GET(_workers)),
97 Evas_Preload_Pthread_Worker);
98 LKU(_mutex);
99
100 if (work->func_heavy) work->func_heavy(work->data);
101 evas_async_events_put(pth, 0, work, _evas_preload_thread_done);
102 }
103
104 LKL(_mutex);
105 if (_workers)
106 {
107 LKU(_mutex);
108 goto on_error;
109 }
110 _threads_count--;
111 LKU(_mutex);
112
113 // dummy worker to wake things up
114 work = malloc(sizeof(Evas_Preload_Pthread_Worker));
115 if (!work) return NULL;
116
117 work->data = pth;
118 work->func_heavy = NULL;
119 work->func_end = (_evas_preload_pthread_func) _evas_preload_thread_end;
120 work->func_cancel = NULL;
121 work->cancel = EINA_FALSE;
122
123 evas_async_events_put(pth, 0, work, _evas_preload_thread_done);
124 return pth;
125}
126#endif
127
128void
129_evas_preload_thread_init(void)
130{
131#ifdef BUILD_ASYNC_PRELOAD
132 _threads_max = eina_cpu_count();
133 if (_threads_max < 1) _threads_max = 1;
134
135 LKI(_mutex);
136#endif
137}
138
139void
140_evas_preload_thread_shutdown(void)
141{
142 /* FIXME: If function are still running in the background, should we kill them ? */
143#ifdef BUILD_ASYNC_PRELOAD
144 Evas_Preload_Pthread_Worker *work;
145
146 /* Force processing of async events. */
147 evas_async_events_process();
148 LKL(_mutex);
149 while (_workers)
150 {
151 work = _workers;
152 _workers = EINA_INLIST_CONTAINER_GET(eina_inlist_remove(EINA_INLIST_GET(_workers),
153 EINA_INLIST_GET(_workers)),
154 Evas_Preload_Pthread_Worker);
155 if (work->func_cancel) work->func_cancel(work->data);
156 free(work);
157 }
158 LKU(_mutex);
159
160 LKD(_mutex);
161#endif
162}
163
164Evas_Preload_Pthread *
165evas_preload_thread_run(void (*func_heavy) (void *data),
166 void (*func_end) (void *data),
167 void (*func_cancel) (void *data),
168 const void *data)
169{
170#ifdef BUILD_ASYNC_PRELOAD
171 Evas_Preload_Pthread_Worker *work;
172 Evas_Preload_Pthread_Data *pth;
173
174 work = malloc(sizeof(Evas_Preload_Pthread_Worker));
175 if (!work)
176 {
177 func_cancel((void *)data);
178 return NULL;
179 }
180
181 work->func_heavy = func_heavy;
182 work->func_end = func_end;
183 work->func_cancel = func_cancel;
184 work->cancel = EINA_FALSE;
185 work->data = (void *)data;
186
187 LKL(_mutex);
188 _workers = (Evas_Preload_Pthread_Worker *)eina_inlist_append(EINA_INLIST_GET(_workers), EINA_INLIST_GET(work));
189 if (_threads_count == _threads_max)
190 {
191 LKU(_mutex);
192 return (Evas_Preload_Pthread *)work;
193 }
194 LKU(_mutex);
195
196 /* One more thread could be created. */
197 pth = malloc(sizeof(Evas_Preload_Pthread_Data));
198 if (!pth) goto on_error;
199
200 eina_threads_init();
201
202 if (pthread_create(&pth->thread, NULL, _evas_preload_thread_worker, pth) == 0)
203 {
204 LKL(_mutex);
205 _threads_count++;
206 LKU(_mutex);
207 return (Evas_Preload_Pthread*)work;
208 }
209
210 eina_threads_shutdown();
211
212 on_error:
213 LKL(_mutex);
214 if (_threads_count == 0)
215 {
216 LKU(_mutex);
217 if (work->func_cancel) work->func_cancel(work->data);
218 free(work);
219 return NULL;
220 }
221 LKU(_mutex);
222 return NULL;
223#else
224 /*
225 If no thread and as we don't want to break app that rely on this
226 facility, we will lock the interface until we are done.
227 */
228 func_heavy((void *)data);
229 func_end((void *)data);
230 return (void *)1;
231#endif
232}
233
234Eina_Bool
235evas_preload_thread_cancel(Evas_Preload_Pthread *thread)
236{
237#ifdef BUILD_ASYNC_PRELOAD
238 Evas_Preload_Pthread_Worker *work;
239
240 if (!thread) return EINA_TRUE;
241 LKL(_mutex);
242 EINA_INLIST_FOREACH(_workers, work)
243 {
244 if (work == (Evas_Preload_Pthread_Worker *)thread)
245 {
246 _workers = EINA_INLIST_CONTAINER_GET(eina_inlist_remove(EINA_INLIST_GET(_workers),
247 EINA_INLIST_GET(work)),
248 Evas_Preload_Pthread_Worker);
249 LKU(_mutex);
250 if (work->func_cancel) work->func_cancel(work->data);
251 free(work);
252 return EINA_TRUE;
253 }
254 }
255 LKU(_mutex);
256
257 /* Delay the destruction */
258 work = (Evas_Preload_Pthread_Worker *)thread;
259 work->cancel = EINA_TRUE;
260 return EINA_FALSE;
261#else
262 return EINA_TRUE;
263#endif
264}