summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Hacohen <tom@stosb.com>2016-03-08 14:23:57 +0000
committerTom Hacohen <tom@stosb.com>2016-03-08 14:23:57 +0000
commit7d8cd6c40f61537bff5ced41dce62d54cd311eb5 (patch)
tree126f01b4b7886f0d62f15e62c9a6cb10409207e0
parentf1a6ff29567c3db71c7ddd58e90715463ac81af9 (diff)
Revert "ecore: Create Promises"
Reverting this at Felipe's request following my email. There are many things I strongly object to in this commit. I've touched the surface of those on the ML (which doesn't work at the moment), though we need to better discuss it. The gist: 1. dlsym is a really bad hack that is not even needed. 2. I don't see why eo should even be aware of promises. It's not aware of list, hash and etc. 3. The eolian changes were done wrong. This should have been discussed and consulted before done, even if only because of the amount of hacks it includes and the cross-domain (ecore, eo and eolian) nature of it. This reverts commit f9ba80ab33e0b94dad7ec103e6d261a644f7835f.
-rw-r--r--src/Makefile_Ecore.am5
-rw-r--r--src/bin/eolian/eo_generator.c30
-rw-r--r--src/lib/ecore/Ecore.h1
-rw-r--r--src/lib/ecore/ecore_promise.c452
-rw-r--r--src/lib/ecore/ecore_promise.h136
-rw-r--r--src/lib/eo/Eo.h63
-rw-r--r--src/lib/eolian/eo_lexer.c3
-rw-r--r--src/lib/eolian/eo_lexer.h6
-rw-r--r--src/lib/eolian/eo_parser.c2
-rw-r--r--src/tests/ecore/ecore_suite.c1
-rw-r--r--src/tests/ecore/ecore_suite.h1
-rw-r--r--src/tests/ecore/ecore_test_promise.c364
12 files changed, 22 insertions, 1042 deletions
diff --git a/src/Makefile_Ecore.am b/src/Makefile_Ecore.am
index 79ac16c8ea..49936afffa 100644
--- a/src/Makefile_Ecore.am
+++ b/src/Makefile_Ecore.am
@@ -47,8 +47,7 @@ lib/ecore/Ecore.h \
47lib/ecore/Ecore_Common.h \ 47lib/ecore/Ecore_Common.h \
48lib/ecore/Ecore_Legacy.h \ 48lib/ecore/Ecore_Legacy.h \
49lib/ecore/Ecore_Eo.h \ 49lib/ecore/Ecore_Eo.h \
50lib/ecore/Ecore_Getopt.h \ 50lib/ecore/Ecore_Getopt.h
51lib/ecore/ecore_promise.h
52 51
53nodist_installed_ecoremainheaders_DATA = \ 52nodist_installed_ecoremainheaders_DATA = \
54 $(ecore_eolian_h) 53 $(ecore_eolian_h)
@@ -73,7 +72,6 @@ lib/ecore/ecore_timer.c \
73lib/ecore/ecore_thread.c \ 72lib/ecore/ecore_thread.c \
74lib/ecore/ecore_throttle.c \ 73lib/ecore/ecore_throttle.c \
75lib/ecore/ecore_exe.c \ 74lib/ecore/ecore_exe.c \
76lib/ecore/ecore_promise.c \
77lib/ecore/ecore_exe_private.h \ 75lib/ecore/ecore_exe_private.h \
78lib/ecore/ecore_private.h 76lib/ecore/ecore_private.h
79 77
@@ -201,7 +199,6 @@ tests/ecore/ecore_test_animator.c \
201tests/ecore/ecore_test_ecore_thread_eina_thread_queue.c \ 199tests/ecore/ecore_test_ecore_thread_eina_thread_queue.c \
202tests/ecore/ecore_test_ecore_input.c \ 200tests/ecore/ecore_test_ecore_input.c \
203tests/ecore/ecore_test_ecore_file.c \ 201tests/ecore/ecore_test_ecore_file.c \
204tests/ecore/ecore_test_promise.c \
205tests/ecore/ecore_suite.h 202tests/ecore/ecore_suite.h
206 203
207tests_ecore_ecore_suite_CPPFLAGS = -I$(top_builddir)/src/lib/efl \ 204tests_ecore_ecore_suite_CPPFLAGS = -I$(top_builddir)/src/lib/efl \
diff --git a/src/bin/eolian/eo_generator.c b/src/bin/eolian/eo_generator.c
index 4810658c6c..a97f2f01f2 100644
--- a/src/bin/eolian/eo_generator.c
+++ b/src/bin/eolian/eo_generator.c
@@ -311,9 +311,6 @@ eo_bind_func_generate(const Eolian_Class *class, const Eolian_Function *funcid,
311 if (ftype != EOLIAN_PROP_GET && ftype != EOLIAN_PROP_SET) ftype = eolian_function_type_get(funcid); 311 if (ftype != EOLIAN_PROP_GET && ftype != EOLIAN_PROP_SET) ftype = eolian_function_type_get(funcid);
312 Eina_Bool is_prop = (ftype == EOLIAN_PROP_GET || ftype == EOLIAN_PROP_SET); 312 Eina_Bool is_prop = (ftype == EOLIAN_PROP_GET || ftype == EOLIAN_PROP_SET);
313 313
314 Eina_Bool has_promise = EINA_FALSE;
315 const char* promise_param_name = NULL;
316 const char* promise_value_type = NULL;
317 Eina_Bool need_implementation = EINA_TRUE; 314 Eina_Bool need_implementation = EINA_TRUE;
318 if (!impl_env && eolian_function_is_virtual_pure(funcid, ftype)) need_implementation = EINA_FALSE; 315 if (!impl_env && eolian_function_is_virtual_pure(funcid, ftype)) need_implementation = EINA_FALSE;
319 316
@@ -340,11 +337,9 @@ eo_bind_func_generate(const Eolian_Class *class, const Eolian_Function *funcid,
340 if (eina_iterator_next(itr, &data) && !eina_iterator_next(itr, &data2)) 337 if (eina_iterator_next(itr, &data) && !eina_iterator_next(itr, &data2))
341 { 338 {
342 Eolian_Function_Parameter *param = data; 339 Eolian_Function_Parameter *param = data;
343 const char* rettype_str = NULL;
344 rettypet = eolian_parameter_type_get(param); 340 rettypet = eolian_parameter_type_get(param);
345 var_as_ret = EINA_TRUE; 341 var_as_ret = EINA_TRUE;
346 default_ret_val = eolian_parameter_default_value_get(param); 342 default_ret_val = eolian_parameter_default_value_get(param);
347 eina_stringshare_del(rettype_str);
348 } 343 }
349 eina_iterator_free(itr); 344 eina_iterator_free(itr);
350 } 345 }
@@ -380,24 +375,9 @@ eo_bind_func_generate(const Eolian_Class *class, const Eolian_Function *funcid,
380 const char *ptype = eolian_type_c_type_get(ptypet); 375 const char *ptype = eolian_type_c_type_get(ptypet);
381 Eolian_Parameter_Dir pdir = eolian_parameter_direction_get(param); 376 Eolian_Parameter_Dir pdir = eolian_parameter_direction_get(param);
382 Eina_Bool had_star = !!strchr(ptype, '*'); 377 Eina_Bool had_star = !!strchr(ptype, '*');
383
384 if(!has_promise && !strcmp(ptype, "Ecore_Promise *"))
385 {
386 Eina_Iterator* promise_values;
387 has_promise = EINA_TRUE;
388 promise_param_name = eina_stringshare_add(pname);
389 promise_values = eolian_type_subtypes_get(eolian_type_base_type_get(ptypet));
390 Eolian_Type* subtype;
391 if(eina_iterator_next(promise_values, (void**)&subtype))
392 promise_value_type = eolian_type_c_type_get(subtype);
393 }
394
395 if (ftype == EOLIAN_UNRESOLVED || ftype == EOLIAN_METHOD) add_star = (pdir == EOLIAN_OUT_PARAM || pdir == EOLIAN_INOUT_PARAM); 378 if (ftype == EOLIAN_UNRESOLVED || ftype == EOLIAN_METHOD) add_star = (pdir == EOLIAN_OUT_PARAM || pdir == EOLIAN_INOUT_PARAM);
396 if (eina_strbuf_length_get(params)) eina_strbuf_append(params, ", "); 379 if (eina_strbuf_length_get(params)) eina_strbuf_append(params, ", ");
397 if(has_promise) 380 eina_strbuf_append_printf(params, "%s", pname);
398 eina_strbuf_append_printf(params, "%s", "&__eo_promise");
399 else
400 eina_strbuf_append_printf(params, "%s", pname);
401 eina_strbuf_append_printf(full_params, ", %s%s%s%s%s", 381 eina_strbuf_append_printf(full_params, ", %s%s%s%s%s",
402 ptype, had_star?"":" ", add_star?"*":"", pname, is_empty && !dflt_value ?" EINA_UNUSED":""); 382 ptype, had_star?"":" ", add_star?"*":"", pname, is_empty && !dflt_value ?" EINA_UNUSED":"");
403 if (is_auto) 383 if (is_auto)
@@ -531,8 +511,8 @@ eo_bind_func_generate(const Eolian_Class *class, const Eolian_Function *funcid,
531 Eina_Bool ret_is_void = (!rettype || !strcmp(rettype, "void")); 511 Eina_Bool ret_is_void = (!rettype || !strcmp(rettype, "void"));
532 _class_func_env_create(class, eolian_function_name_get(funcid), ftype, &func_env); 512 _class_func_env_create(class, eolian_function_name_get(funcid), ftype, &func_env);
533 eina_strbuf_append_printf(eo_func_decl, 513 eina_strbuf_append_printf(eo_func_decl,
534 "EOAPI EO_%sFUNC_%sBODY%s%s(%s", 514 "EOAPI EO_%sFUNC_BODY%s%s(%s",
535 ret_is_void?"VOID_":"", has_promise?"PROMISE_":"", has_params?"V":"", 515 ret_is_void?"VOID_":"", has_params?"V":"",
536 (ftype == EOLIAN_PROP_GET || 516 (ftype == EOLIAN_PROP_GET ||
537 eolian_function_object_is_const(funcid) || 517 eolian_function_object_is_const(funcid) ||
538 eolian_function_is_class(funcid))?"_CONST":"", func_env.lower_eo_func); 518 eolian_function_is_class(funcid))?"_CONST":"", func_env.lower_eo_func);
@@ -555,10 +535,6 @@ eo_bind_func_generate(const Eolian_Class *class, const Eolian_Function *funcid,
555 eina_stringshare_del(string); 535 eina_stringshare_del(string);
556 } 536 }
557 } 537 }
558 if (has_promise)
559 {
560 eina_strbuf_append_printf(eo_func_decl, ", %s, %s", promise_param_name, promise_value_type);
561 }
562 if (has_params) 538 if (has_params)
563 { 539 {
564 eina_strbuf_replace_all(full_params, " EINA_UNUSED", ""); 540 eina_strbuf_replace_all(full_params, " EINA_UNUSED", "");
diff --git a/src/lib/ecore/Ecore.h b/src/lib/ecore/Ecore.h
index df28b644be..e843038964 100644
--- a/src/lib/ecore/Ecore.h
+++ b/src/lib/ecore/Ecore.h
@@ -356,7 +356,6 @@ extern "C" {
356#endif 356#endif
357#ifdef EFL_EO_API_SUPPORT 357#ifdef EFL_EO_API_SUPPORT
358#include "Ecore_Eo.h" 358#include "Ecore_Eo.h"
359#include "ecore_promise.h"
360#endif 359#endif
361 360
362#ifdef __cplusplus 361#ifdef __cplusplus
diff --git a/src/lib/ecore/ecore_promise.c b/src/lib/ecore/ecore_promise.c
deleted file mode 100644
index c55d5199b5..0000000000
--- a/src/lib/ecore/ecore_promise.c
+++ /dev/null
@@ -1,452 +0,0 @@
1#ifdef HAVE_CONFIG_H
2#include <config.h>
3#endif
4
5#include <Eina.h>
6#include <Ecore.h>
7
8#include <assert.h>
9
10typedef void(*Ecore_Promise_Free_Cb)(void*);
11
12struct _Ecore_Promise_Then_Cb
13{
14 EINA_INLIST;
15
16 Ecore_Promise_Cb callback;
17 void* data;
18};
19
20struct _Ecore_Promise
21{
22 Eina_Lock lock;
23 Eina_Condition condition;
24 Eina_Bool has_finished : 1;
25 Eina_Bool has_errored : 1;
26 Eina_Bool has_pending_call : 1;
27 Eina_Bool is_then_calls_manual : 1;
28 Eina_Error error;
29 size_t value_size;
30 int ref;
31
32 struct _Ecore_Promise_Then_Cb then_callbacks;
33 Ecore_Promise_Free_Cb free_cb;
34
35 char value[];
36};
37
38struct _Ecore_Promise_Thread_Data
39{
40 const void* data;
41 Ecore_Promise_Thread_Cb func_blocking;
42 Ecore_Promise* promise;
43};
44
45typedef struct _Ecore_Promise_Iterator _Ecore_Promise_Iterator;
46typedef struct _Ecore_Promise_Success_Iterator _Ecore_Promise_Success_Iterator;
47typedef struct _Ecore_Promise_Failure_Iterator _Ecore_Promise_Failure_Iterator;
48struct _Ecore_Promise_Iterator
49{
50 Eina_Iterator* success_iterator;
51 Eina_Iterator* failure_iterator;
52 struct _Ecore_Promise_Success_Iterator
53 {
54 Eina_Iterator success_iterator_impl;
55 struct _Ecore_Promise_Failure_Iterator
56 {
57 Eina_Iterator failure_iterator_impl;
58 unsigned int promise_index;
59 unsigned int num_promises;
60 unsigned int promises_finished;
61 Ecore_Promise* promises[];
62 } data;
63 } data;
64};
65
66static void _ecore_promise_lock_take(Ecore_Promise* promise);
67static void _ecore_promise_lock_release(Ecore_Promise* promise);
68static void _ecore_promise_finish(Ecore_Promise* promise);
69static void _ecore_promise_then_calls(Ecore_Promise* promise);
70static void _ecore_promise_unsafe_ref(Ecore_Promise const* promise);
71static void _ecore_promise_unsafe_unref(Ecore_Promise const* promise);
72static void _ecore_promise_unsafe_free_unref(Ecore_Promise const* promise);
73static Eina_Bool _ecore_promise_unlock_unsafe_free_unref(Ecore_Promise const* promise);
74
75static void _ecore_promise_iterator_setup(_Ecore_Promise_Iterator* iterator, Eina_Array* promises);
76
77static void _ecore_promise_thread_end(void* data, Ecore_Thread* thread EINA_UNUSED)
78{
79 struct _Ecore_Promise_Thread_Data* p = data;
80 _ecore_promise_lock_take(p->promise);
81 if(p->promise->has_finished)
82 {
83 p->promise->has_pending_call = EINA_FALSE;
84 if(!_ecore_promise_unlock_unsafe_free_unref(p->promise))
85 _ecore_promise_then_calls(p->promise);
86 }
87 else
88 {
89 p->promise->is_then_calls_manual = EINA_FALSE;
90 p->promise->has_pending_call = EINA_FALSE;
91 _ecore_promise_unlock_unsafe_free_unref(p->promise);
92 }
93 free(data);
94}
95
96static void
97_ecore_promise_thread_blocking(void* data, Ecore_Thread* thread EINA_UNUSED)
98{
99 struct _Ecore_Promise_Thread_Data* p = data;
100 (p->func_blocking)(p->data, p->promise);
101}
102
103static void
104_ecore_promise_then_calls(Ecore_Promise* promise)
105{
106 _ecore_promise_lock_take(promise);
107 struct _Ecore_Promise_Then_Cb then_callbacks = promise->then_callbacks;
108 memset(&promise->then_callbacks, 0, sizeof(promise->then_callbacks));
109 promise->has_pending_call = EINA_FALSE;
110 _ecore_promise_lock_release(promise);
111
112 struct _Ecore_Promise_Then_Cb* callback;
113
114 if(then_callbacks.callback)
115 {
116 (*then_callbacks.callback)(then_callbacks.data, &promise->value[0]);
117 _ecore_promise_unsafe_free_unref(promise);
118 }
119
120 if(EINA_INLIST_GET(&then_callbacks)->next)
121 {
122 Eina_Inlist* list2;
123 EINA_INLIST_FOREACH_SAFE(EINA_INLIST_GET(&then_callbacks)->next, list2, callback)
124 {
125 if(callback->callback)
126 {
127 (*callback->callback)(callback->data, promise);
128 }
129 _ecore_promise_unsafe_free_unref(promise);
130 }
131 }
132}
133
134Ecore_Promise* ecore_promise_thread_run(Ecore_Promise_Thread_Cb func_blocking, const void* data, size_t value_size)
135{
136 struct _Ecore_Promise_Thread_Data *new_data = malloc(sizeof(struct _Ecore_Promise_Thread_Data));
137 new_data->data = data;
138 new_data->func_blocking = func_blocking;
139 new_data->promise = ecore_promise_add(value_size);
140 new_data->promise->is_then_calls_manual = EINA_TRUE;
141 new_data->promise->has_pending_call = EINA_TRUE;
142 ecore_promise_ref(new_data->promise);
143 ecore_thread_run(&_ecore_promise_thread_blocking, &_ecore_promise_thread_end, NULL, new_data);
144 return new_data->promise;
145}
146
147Ecore_Promise* ecore_promise_add(int value_size)
148{
149 Ecore_Promise* p = malloc(sizeof(Ecore_Promise) + value_size);
150 eina_lock_new(&p->lock);
151 eina_condition_new(&p->condition, &p->lock);
152 p->has_finished = p->has_errored = p->has_pending_call = p->is_then_calls_manual = EINA_FALSE;
153 p->ref = 1;
154 memset(&p->then_callbacks, 0, sizeof(p->then_callbacks));
155 p->value_size = value_size;
156 p->free_cb = NULL;
157 return p;
158}
159
160static void _ecore_promise_del(Ecore_Promise* promise)
161{
162 if(promise->free_cb)
163 promise->free_cb((void*)&promise->value[0]);
164
165 eina_lock_free(&promise->lock);
166 eina_condition_free(&promise->condition);
167}
168
169void* ecore_promise_buffer_get(Ecore_Promise* promise)
170{
171 return &promise->value[0];
172}
173
174void* ecore_promise_value_get(Ecore_Promise const* promise)
175{
176 _ecore_promise_lock_take((Ecore_Promise*)promise);
177 _ecore_promise_unsafe_ref(promise);
178 while(!promise->has_finished)
179 {
180 eina_condition_wait((Eina_Condition*)&promise->condition);
181 }
182
183 void* v = (void*)(promise->value_size && !promise->has_errored ? &promise->value[0] : NULL);
184 _ecore_promise_unsafe_unref(promise);
185 _ecore_promise_lock_release((Ecore_Promise*)promise);
186 return v;
187}
188
189void ecore_promise_value_set(Ecore_Promise* promise, void* data)
190{
191 _ecore_promise_lock_take(promise);
192 if(data && promise->value_size)
193 {
194 memcpy(&promise->value[0], data, promise->value_size);
195 }
196
197 _ecore_promise_finish(promise);
198}
199
200static void _ecore_promise_all_compose_then_cb(Ecore_Promise* promise, void* value EINA_UNUSED)
201{
202 _ecore_promise_lock_take(promise);
203 _Ecore_Promise_Iterator* iterator = (_Ecore_Promise_Iterator*)promise->value;
204
205 if(++iterator->data.data.promises_finished == iterator->data.data.num_promises)
206 {
207 _ecore_promise_finish(promise);
208 }
209 else
210 _ecore_promise_lock_release(promise);
211}
212
213static void _ecore_promise_all_free(_Ecore_Promise_Iterator* value)
214{
215 unsigned i = 0;
216 eina_iterator_free(value->success_iterator);
217 /* eina_iterator_free(value->failure_iterator); */
218
219 for(;i != value->data.data.num_promises; ++i)
220 {
221 ecore_promise_unref(value->data.data.promises[i]);
222 }
223}
224
225Ecore_Promise* ecore_promise_all(Eina_Iterator* it)
226{
227 Ecore_Promise* current, *promise;
228 Eina_Array* promises;
229
230 promises = eina_array_new(20);
231
232 EINA_ITERATOR_FOREACH(it, current)
233 {
234 eina_array_push(promises, current);
235 }
236
237 promise = ecore_promise_add(sizeof(_Ecore_Promise_Iterator) + sizeof(Ecore_Promise*)*eina_array_count_get(promises));
238 //promise->is_then_calls_manual = EINA_TRUE;
239 promise->free_cb = (Ecore_Promise_Free_Cb)_ecore_promise_all_free;
240 _Ecore_Promise_Iterator* internal_it = ecore_promise_buffer_get(promise);
241 _ecore_promise_iterator_setup(internal_it, promises);
242 eina_array_free(promises);
243
244 {
245 Ecore_Promise** cur_promise = internal_it->data.data.promises, ** last =
246 internal_it->data.data.promises + internal_it->data.data.num_promises;
247 for(;cur_promise != last; ++cur_promise)
248 {
249 ecore_promise_ref(*cur_promise);
250 ecore_promise_then(*cur_promise, (Ecore_Promise_Cb)&_ecore_promise_all_compose_then_cb, promise);
251 }
252 }
253
254 return promise;
255}
256
257void ecore_promise_then(Ecore_Promise* promise, Ecore_Promise_Cb callback, void* data)
258{
259 _ecore_promise_lock_take(promise);
260 _ecore_promise_unsafe_ref(promise);
261 if(!promise->then_callbacks.callback && !EINA_INLIST_GET(&promise->then_callbacks)->next)
262 {
263 promise->then_callbacks.callback = callback;
264 promise->then_callbacks.data = data;
265 }
266 else
267 {
268 struct _Ecore_Promise_Then_Cb* p = malloc(sizeof(struct _Ecore_Promise_Then_Cb));
269 p->callback = callback;
270 p->data = data;
271 Eina_Inlist* l = eina_inlist_append(EINA_INLIST_GET(&promise->then_callbacks), EINA_INLIST_GET(p));
272 (void)l;
273 }
274 if(promise->has_finished && !promise->has_pending_call)
275 {
276 promise->has_pending_call = EINA_TRUE;
277 _ecore_promise_lock_release(promise);
278 ecore_job_add((Ecore_Cb)&_ecore_promise_then_calls, promise);
279 }
280 else
281 _ecore_promise_lock_release(promise);
282}
283
284EAPI Eina_Error ecore_promise_error_get(Ecore_Promise const* promise)
285{
286 _ecore_promise_lock_take((Ecore_Promise*)promise);
287 if(promise->has_errored)
288 {
289 Eina_Error error = promise->error;
290 _ecore_promise_lock_release((Ecore_Promise*)promise);
291 return error;
292 }
293 else
294 {
295 _ecore_promise_lock_release((Ecore_Promise*)promise);
296 return 0;
297 }
298}
299
300EAPI void ecore_promise_error_set(Ecore_Promise* promise, Eina_Error error)
301{
302 _ecore_promise_lock_take(promise);
303 promise->error = error;
304 promise->has_errored = EINA_TRUE;
305
306 _ecore_promise_finish(promise);
307}
308
309static void
310_ecore_promise_finish(Ecore_Promise* promise)
311{
312 promise->has_finished = EINA_TRUE;
313 eina_condition_broadcast(&promise->condition);
314 _ecore_promise_unsafe_unref(promise);
315 if(!promise->is_then_calls_manual && !promise->has_pending_call)
316 {
317 promise->has_pending_call = EINA_TRUE;
318 _ecore_promise_lock_release(promise);
319 ecore_job_add((Ecore_Cb)&_ecore_promise_then_calls, promise);
320 }
321 else
322 _ecore_promise_lock_release(promise);
323}
324
325static Eina_Bool
326_ecore_promise_iterator_next(_Ecore_Promise_Success_Iterator *it, void **data)
327{
328 if(it->data.promise_index == it->data.num_promises)
329 return EINA_FALSE;
330
331 if(ecore_promise_error_get(it->data.promises[it->data.promise_index]))
332 {
333 return EINA_FALSE;
334 }
335 else
336 {
337 *data = ecore_promise_value_get(it->data.promises[it->data.promise_index++]);
338 return EINA_TRUE;
339 }
340}
341
342static void**
343_ecore_promise_iterator_get_container(_Ecore_Promise_Success_Iterator *it)
344{
345 return (void**)it->data.promises;
346}
347
348static void
349_ecore_promise_iterator_free(_Ecore_Promise_Success_Iterator *it EINA_UNUSED)
350{
351}
352
353static void _ecore_promise_iterator_setup(_Ecore_Promise_Iterator* it, Eina_Array* promises_array)
354{
355 Ecore_Promise** promises;
356
357 it->success_iterator = &it->data.success_iterator_impl;
358 it->failure_iterator = &it->data.data.failure_iterator_impl;
359 it->data.data.num_promises = eina_array_count_get(promises_array);
360 it->data.data.promise_index = 0;
361 promises = (Ecore_Promise**)promises_array->data;
362
363 memcpy(&it->data.data.promises[0], promises, it->data.data.num_promises*sizeof(Ecore_Promise*));
364
365 EINA_MAGIC_SET(&it->data.success_iterator_impl, EINA_MAGIC_ITERATOR);
366 EINA_MAGIC_SET(&it->data.data.failure_iterator_impl, EINA_MAGIC_ITERATOR);
367
368 it->data.success_iterator_impl.version = EINA_ITERATOR_VERSION;
369 it->data.success_iterator_impl.next = FUNC_ITERATOR_NEXT(_ecore_promise_iterator_next);
370 it->data.success_iterator_impl.get_container = FUNC_ITERATOR_GET_CONTAINER(
371 _ecore_promise_iterator_get_container);
372 it->data.success_iterator_impl.free = FUNC_ITERATOR_FREE(_ecore_promise_iterator_free);
373}
374
375EAPI int ecore_promise_value_size_get(Ecore_Promise const* promise)
376{
377 return promise->value_size;
378}
379
380static void _ecore_promise_lock_take(Ecore_Promise* promise)
381{
382 eina_lock_take(&promise->lock);
383}
384
385static void _ecore_promise_lock_release(Ecore_Promise* promise)
386{
387 eina_lock_release(&promise->lock);
388}
389
390static void _ecore_promise_unsafe_ref(Ecore_Promise const* promise)
391{
392 Ecore_Promise* p = (Ecore_Promise*)promise;
393 ++p->ref;
394}
395
396static void _ecore_promise_free_cb(Ecore_Promise* promise)
397{
398 _ecore_promise_lock_take(promise);
399 _ecore_promise_unlock_unsafe_free_unref(promise);
400}
401
402static void _ecore_promise_unsafe_unref(Ecore_Promise const* promise)
403{
404 Ecore_Promise* p = (Ecore_Promise*)promise;
405 if(p->ref == 1 && !p->has_pending_call)
406 {
407 ecore_job_add((Ecore_Cb)_ecore_promise_free_cb, p);
408 }
409 else
410 --p->ref;
411}
412
413static void _ecore_promise_unsafe_free_unref(Ecore_Promise const* promise)
414{
415 Ecore_Promise* p = (Ecore_Promise*)promise;
416 if(--p->ref == 0)
417 {
418 assert(!p->has_pending_call);
419 _ecore_promise_del(p);
420 }
421}
422
423static Eina_Bool _ecore_promise_unlock_unsafe_free_unref(Ecore_Promise const* promise)
424{
425 Ecore_Promise* p = (Ecore_Promise*)promise;
426 if(--p->ref == 0)
427 {
428 assert(!p->has_pending_call);
429 _ecore_promise_lock_release((Ecore_Promise*)promise);
430 _ecore_promise_del(p);
431 return EINA_TRUE;
432 }
433 else
434 {
435 _ecore_promise_lock_release((Ecore_Promise*)promise);
436 return EINA_FALSE;
437 }
438}
439
440EAPI void ecore_promise_ref(Ecore_Promise* promise)
441{
442 _ecore_promise_lock_take(promise);
443 _ecore_promise_unsafe_ref(promise);
444 _ecore_promise_lock_release(promise);
445}
446
447EAPI void ecore_promise_unref(Ecore_Promise* promise)
448{
449 _ecore_promise_lock_take(promise);
450 _ecore_promise_unsafe_unref(promise);
451 _ecore_promise_lock_release(promise);
452}
diff --git a/src/lib/ecore/ecore_promise.h b/src/lib/ecore/ecore_promise.h
deleted file mode 100644
index 834c3368b7..0000000000
--- a/src/lib/ecore/ecore_promise.h
+++ /dev/null
@@ -1,136 +0,0 @@
1
2#ifdef EFL_BETA_API_SUPPORT
3
4struct _Ecore_Promise;
5
6/*
7 * @def _Ecore_Promise
8 */
9typedef struct _Ecore_Promise Ecore_Promise;
10
11/*
12 * @brief Function callback type for when using ecore_promise_then
13 */
14typedef void(*Ecore_Promise_Cb)(void* data, void* value);
15
16/*
17 * @brief Function callback type for when creating Ecore_Thread that
18 * uses Ecore_Promise for communication
19 */
20typedef void(*Ecore_Promise_Thread_Cb)(const void* data, Ecore_Promise* promise);
21
22/*
23 * @brief Function that instantiates a Ecore_Promise and automatically
24 * executes func_blocking callback function in another thread
25 */
26EAPI Ecore_Promise* ecore_promise_thread_run(Ecore_Promise_Thread_Cb func_blocking, const void* data, size_t value_size);
27
28/*
29 * @brief Creates a Ecore_Promise with a value of size value_size.
30 *
31 * @param value_size Size of value-type that Ecore_Promise will hold
32 */
33EAPI Ecore_Promise* ecore_promise_add(int value_size);
34
35/*
36 * @brief Appends a callback to be called when the Ecore_Promise is
37 * finished.
38 *
39 * @param promise The Ecore_Promise to wait for
40 * @param callback Callback to be called when Ecore_Promise is finished
41 * @param data Private data passed to the callback
42 */
43EAPI void ecore_promise_then(Ecore_Promise* promise, Ecore_Promise_Cb callback, void* data);
44
45/*
46 * @brief Creates a new Ecore_Promise from other Ecore_Promises
47 *
48 * @param promises An Eina_Iterator for all Ecore_Promises
49 */
50EAPI Ecore_Promise* ecore_promise_all(Eina_Iterator* promises);
51
52/*
53 * @brief Sets value for Ecore_Promise. This finishes the callback and
54 * calls all ecore_promise_then callbacks that have been registered on
55 * this Ecore_Promise. This function must be called only once per
56 * Ecore_Promise
57 *
58 * @param promise The promise for which to set the value
59 * @param value The pointer to the value that is going to be copied, or NULL.
60 */
61EAPI void ecore_promise_value_set(Ecore_Promise* promise, void* value);
62
63/*
64 * @brief Returns the pointer to the value if the Ecore_Promise is
65 * finished. Waits for it to be finished, otherwise.
66 *
67 * @param promise The promise for which to get the value
68 */
69EAPI void* ecore_promise_value_get(Ecore_Promise const* promise);
70
71/*
72 * @brief Returns the pointer to the buffer that holds the value. This
73 * function is useful to instantiate the value directly in the correct
74 * buffer, without needing to copy. The ecore_promise_value_set must
75 * still be called, possibly with NULL, to finish the Ecore_Promise
76 * and call the callbacks registered in it.
77 *
78 * @param promise The promise for which to get the buffer pointer
79 */
80EAPI void* ecore_promise_buffer_get(Ecore_Promise* promise);
81
82/*
83 * @brief Sets an error to the Ecore_Promise, thus finishing the
84 * promise and calling all ecore_promise_then callbacks registered.
85 *
86 * @param promise The promise for which to set the error
87 * @param error Eina_Error to be set
88 */
89EAPI void ecore_promise_error_set(Ecore_Promise* promise, Eina_Error error);
90
91/*
92 * @brief Gets an error to the Ecore_Promise if the promise is
93 * finished and has error'ed out. If it hasn't finished, it will wait,
94 * and if it has finished but otherwise not error'ed, returns 0.
95 *
96 * @param promise The promise for which to get the error
97 */
98EAPI Eina_Error ecore_promise_error_get(Ecore_Promise const* promise);
99
100/*
101 * @brief Gets the size of the value in ecore_promise_value_get.
102 *
103 * @param promise The promise for which to get the value size
104 */
105EAPI int ecore_promise_value_size_get(Ecore_Promise const* promise);
106
107/*
108 * @brief Returns @EINA_TRUE if the promise is ready and won't block
109 * on ecore_promise_value_get and @EINA_FALSE otherwise.
110 *
111 * @param promise The promise for which to get the ready status
112 */
113EAPI Eina_Bool ecore_promise_ready_is(Ecore_Promise const* promise);
114
115/*
116 * @brief Increments the reference count for the Ecore_Promise
117 *
118 * @param promise The promise for which to increment its reference
119 */
120EAPI void ecore_promise_ref(Ecore_Promise* promise);
121
122/*
123 * @brief Decrement the reference count for the Ecore_Promise and
124 * possibly schedule its destruction. The Ecore_Promise, if its
125 * reference count drops to zero, will only be free'd when all the
126 * current mainloop events have been processed. This allows the user
127 * to call ecore_promise_then before that happens so it can increment
128 * the reference back to 1 and wait for a value set or error set on
129 * the Ecore_Promise.
130 *
131 * @param promise The promise for which to decrement its reference
132 */
133EAPI void ecore_promise_unref(Ecore_Promise* promise);
134
135#endif
136
diff --git a/src/lib/eo/Eo.h b/src/lib/eo/Eo.h
index 4bfae9765e..387f187714 100644
--- a/src/lib/eo/Eo.h
+++ b/src/lib/eo/Eo.h
@@ -519,96 +519,61 @@ typedef struct _Eo_Call_Cache
519 __FILE__, __LINE__)) return DefRet; \ 519 __FILE__, __LINE__)) return DefRet; \
520 _Eo_##Name##_func _func_ = (_Eo_##Name##_func) ___call.func; \ 520 _Eo_##Name##_func _func_ = (_Eo_##Name##_func) ___call.func; \
521 521
522#define _EO_FUNC_PROMISE_CREATE0
523#define _EO_FUNC_PROMISE_FREE0
524#define _EO_FUNC_PROMISE_CREATE1 \
525 Ecore_Promise*(*ecore_promise_add)(int size) = dlsym(dlopen(NULL, RTLD_NOW), "ecore_promise_add"); \
526 Ecore_Promise* __eo_promise = ecore_promise_add(sizeof(PromiseValue));
527#define _EO_FUNC_PROMISE_FREE1 \
528 if(Promise) \
529 *Promise = __eo_promise; \
530 else \
531 { \
532 void(*ecore_promise_unref)(Ecore_Promise* p) = dlsym(dlopen(NULL, RTLD_NOW), "ecore_promise_unref"); \
533 ecore_promise_unref(__eo_promise); \
534 }
535#define _EO_EXPANSION_AUX(X) X
536#define _EO_FUNC_PROMISE_CREATE(p) _EO_EXPANSION_AUX(_EO_FUNC_PROMISE_CREATE ## p)
537#define _EO_FUNC_PROMISE_FREE(p) _EO_EXPANSION_AUX(_EO_FUNC_PROMISE_FREE ## p)
538
539// to define an EAPI function 522// to define an EAPI function
540#define _EO_FUNC_BODY(Name, ObjType, Promise, Ret, DefRet) \ 523#define _EO_FUNC_BODY(Name, ObjType, Ret, DefRet) \
541 Ret \ 524 Ret \
542 Name(ObjType obj) \ 525 Name(ObjType obj) \
543 { \ 526 { \
544 typedef Ret (*_Eo_##Name##_func)(Eo *, void *obj_data); \ 527 typedef Ret (*_Eo_##Name##_func)(Eo *, void *obj_data); \
545 Ret _r; \ 528 Ret _r; \
546 EO_FUNC_COMMON_OP(obj, Name, DefRet); \ 529 EO_FUNC_COMMON_OP(obj, Name, DefRet); \
547 _EO_FUNC_PROMISE_CREATE(Promise) \
548 _r = _func_(___call.eo_id, ___call.data); \ 530 _r = _func_(___call.eo_id, ___call.data); \
549 _eo_call_end(&___call); \ 531 _eo_call_end(&___call); \
550 _EO_FUNC_PROMISE_FREE(Promise) \
551 return _r; \ 532 return _r; \
552 } 533 }
553 534
554#define _EO_VOID_FUNC_BODY(Name, ObjType, Promise) \ 535#define _EO_VOID_FUNC_BODY(Name, ObjType) \
555 void \ 536 void \
556 Name(ObjType obj) \ 537 Name(ObjType obj) \
557 { \ 538 { \
558 typedef void (*_Eo_##Name##_func)(Eo *, void *obj_data); \ 539 typedef void (*_Eo_##Name##_func)(Eo *, void *obj_data); \
559 EO_FUNC_COMMON_OP(obj, Name, ); \ 540 EO_FUNC_COMMON_OP(obj, Name, ); \
560 _EO_FUNC_PROMISE_CREATE(Promise) \
561 _func_(___call.eo_id, ___call.data); \ 541 _func_(___call.eo_id, ___call.data); \
562 _eo_call_end(&___call); \ 542 _eo_call_end(&___call); \
563 _EO_FUNC_PROMISE_FREE(Promise) \
564 } 543 }
565 544
566#define _EO_FUNC_BODYV(Name, ObjType, Promise, Ret, DefRet, Arguments, ...) \ 545#define _EO_FUNC_BODYV(Name, ObjType, Ret, DefRet, Arguments, ...) \
567 Ret \ 546 Ret \
568 Name(ObjType obj, __VA_ARGS__) \ 547 Name(ObjType obj, __VA_ARGS__) \
569 { \ 548 { \
570 typedef Ret (*_Eo_##Name##_func)(Eo *, void *obj_data, __VA_ARGS__); \ 549 typedef Ret (*_Eo_##Name##_func)(Eo *, void *obj_data, __VA_ARGS__); \
571 Ret _r; \ 550 Ret _r; \
572 EO_FUNC_COMMON_OP(obj, Name, DefRet); \ 551 EO_FUNC_COMMON_OP(obj, Name, DefRet); \
573 _EO_FUNC_PROMISE_CREATE(Promise) \
574 _r = _func_(___call.eo_id, ___call.data, Arguments); \ 552 _r = _func_(___call.eo_id, ___call.data, Arguments); \
575 _eo_call_end(&___call); \ 553 _eo_call_end(&___call); \
576 _EO_FUNC_PROMISE_FREE(Promise) \
577 return _r; \ 554 return _r; \
578 } 555 }
579 556
580#define _EO_VOID_FUNC_BODYV(Name, ObjType, Promise, Arguments, ...) \ 557#define _EO_VOID_FUNC_BODYV(Name, ObjType, Arguments, ...) \
581 void \ 558 void \
582 Name(ObjType obj, __VA_ARGS__) \ 559 Name(ObjType obj, __VA_ARGS__) \
583 { \ 560 { \
584 typedef void (*_Eo_##Name##_func)(Eo *, void *obj_data, __VA_ARGS__); \ 561 typedef void (*_Eo_##Name##_func)(Eo *, void *obj_data, __VA_ARGS__); \
585 EO_FUNC_COMMON_OP(obj, Name, ); \ 562 EO_FUNC_COMMON_OP(obj, Name, ); \
586 _EO_FUNC_PROMISE_CREATE(Promise) \
587 _func_(___call.eo_id, ___call.data, Arguments); \ 563 _func_(___call.eo_id, ___call.data, Arguments); \
588 _eo_call_end(&___call); \ 564 _eo_call_end(&___call); \
589 _EO_FUNC_PROMISE_FREE(Promise) \
590 } 565 }
591 566
592#define EO_FUNC_BODY(Name, Ret, DefRet) _EO_FUNC_BODY(Name, Eo *, 0, Ret, DefRet) 567#define EO_FUNC_BODY(Name, Ret, DefRet) _EO_FUNC_BODY(Name, Eo *, Ret, DefRet)
593#define EO_VOID_FUNC_BODY(Name) _EO_VOID_FUNC_BODY(Name, Eo *, 0) 568#define EO_VOID_FUNC_BODY(Name) _EO_VOID_FUNC_BODY(Name, Eo *)
594#define EO_FUNC_BODYV(Name, Ret, DefRet, Arguments, ...) _EO_FUNC_BODYV(Name, Eo *, 0, Ret, DefRet, EO_FUNC_CALL(Arguments), __VA_ARGS__) 569#define EO_FUNC_BODYV(Name, Ret, DefRet, Arguments, ...) _EO_FUNC_BODYV(Name, Eo *, Ret, DefRet, EO_FUNC_CALL(Arguments), __VA_ARGS__)
595#define EO_VOID_FUNC_BODYV(Name, Arguments, ...) _EO_VOID_FUNC_BODYV(Name, Eo *, 0, EO_FUNC_CALL(Arguments), __VA_ARGS__) 570#define EO_VOID_FUNC_BODYV(Name, Arguments, ...) _EO_VOID_FUNC_BODYV(Name, Eo *, EO_FUNC_CALL(Arguments), __VA_ARGS__)
596 571
597#define EO_FUNC_BODY_CONST(Name, Ret, DefRet) _EO_FUNC_BODY(Name, const Eo *, 0, Ret, DefRet) 572#define EO_FUNC_BODY_CONST(Name, Ret, DefRet) _EO_FUNC_BODY(Name, const Eo *, Ret, DefRet)
598#define EO_VOID_FUNC_BODY_CONST(Name) _EO_VOID_FUNC_BODY(Name, const Eo *, 0) 573#define EO_VOID_FUNC_BODY_CONST(Name) _EO_VOID_FUNC_BODY(Name, const Eo *)
599#define EO_FUNC_BODYV_CONST(Name, Ret, DefRet, Arguments, ...) _EO_FUNC_BODYV(Name, const Eo *, 0, Ret, DefRet, EO_FUNC_CALL(Arguments), __VA_ARGS__) 574#define EO_FUNC_BODYV_CONST(Name, Ret, DefRet, Arguments, ...) _EO_FUNC_BODYV(Name, const Eo *, Ret, DefRet, EO_FUNC_CALL(Arguments), __VA_ARGS__)
600#define EO_VOID_FUNC_BODYV_CONST(Name, Arguments, ...) _EO_VOID_FUNC_BODYV(Name, const Eo *, 0, EO_FUNC_CALL(Arguments), __VA_ARGS__) 575#define EO_VOID_FUNC_BODYV_CONST(Name, Arguments, ...) _EO_VOID_FUNC_BODYV(Name, const Eo *, EO_FUNC_CALL(Arguments), __VA_ARGS__)
601 576
602#define EO_FUNC_PROMISE_BODY(Name, Ret, DefRet) _EO_FUNC_BODY(Name, Eo *, 1, Ret, DefRet)
603#define EO_VOID_FUNC_PROMISE_BODY(Name) _EO_VOID_FUNC_BODY(Name, Eo *, 1)
604#define EO_FUNC_PROMISE_BODYV(Name, Ret, DefRet, Arguments, ...) _EO_FUNC_BODYV(Name, Eo *, 1, Ret, DefRet, EO_FUNC_CALL(Arguments), __VA_ARGS__)
605#define EO_VOID_FUNC_PROMISE_BODYV(Name, Arguments, ...) _EO_VOID_FUNC_BODYV(Name, Eo *, 1, EO_FUNC_CALL(Arguments), __VA_ARGS__)
606
607#define EO_FUNC_PROMISE_BODY_CONST(Name, Ret, DefRet) _EO_FUNC_BODY(Name, const Eo *, 1, Ret, DefRet)
608#define EO_VOID_FUNC_PROMISE_BODY_CONST(Name) _EO_VOID_FUNC_BODY(Name, const Eo *, 1)
609#define EO_FUNC_PROMISE_BODYV_CONST(Name, Ret, DefRet, Arguments, ...) _EO_FUNC_BODYV(Name, const Eo *, 1, Ret, DefRet, EO_FUNC_CALL(Arguments), __VA_ARGS__)
610#define EO_VOID_FUNC_PROMISE_BODYV_CONST(Name, Arguments, ...) _EO_VOID_FUNC_BODYV(Name, const Eo *, 1, EO_FUNC_CALL(Arguments), __VA_ARGS__)
611
612#ifndef _WIN32 577#ifndef _WIN32
613# define _EO_OP_API_ENTRY(a) (void*)a 578# define _EO_OP_API_ENTRY(a) (void*)a
614#else 579#else
diff --git a/src/lib/eolian/eo_lexer.c b/src/lib/eolian/eo_lexer.c
index 1aeb6a9b0f..0e98313d51 100644
--- a/src/lib/eolian/eo_lexer.c
+++ b/src/lib/eolian/eo_lexer.c
@@ -75,8 +75,7 @@ static const char * const ctypes[] =
75 "Eina_Accessor", "Eina_Array", "Eina_Iterator", "Eina_Hash", "Eina_List", 75 "Eina_Accessor", "Eina_Array", "Eina_Iterator", "Eina_Hash", "Eina_List",
76 "Eina_Value", 76 "Eina_Value",
77 77
78 "Eo_Event_Cb", 78 "Eo_Event_Cb"
79 "Ecore_Promise"
80}; 79};
81 80
82#undef KW 81#undef KW
diff --git a/src/lib/eolian/eo_lexer.h b/src/lib/eolian/eo_lexer.h
index bb4385b560..b28a3fc530 100644
--- a/src/lib/eolian/eo_lexer.h
+++ b/src/lib/eolian/eo_lexer.h
@@ -52,9 +52,7 @@ enum Tokens
52 \ 52 \
53 KW(accessor), KW(array), KW(iterator), KW(hash), KW(list), KW(generic_value), \ 53 KW(accessor), KW(array), KW(iterator), KW(hash), KW(list), KW(generic_value), \
54 \ 54 \
55 KW(__builtin_event_cb), \ 55 KW(__builtin_event_cb), KW(__undefined_type), \
56 KW(Promise), \
57 KW(__undefined_type), \
58 \ 56 \
59 KW(true), KW(false), KW(null) 57 KW(true), KW(false), KW(null)
60 58
@@ -208,4 +206,4 @@ void eo_lexer_context_pop (Eo_Lexer *ls);
208void eo_lexer_context_restore(Eo_Lexer *ls); 206void eo_lexer_context_restore(Eo_Lexer *ls);
209void eo_lexer_context_clear (Eo_Lexer *ls); 207void eo_lexer_context_clear (Eo_Lexer *ls);
210 208
211#endif /* __EO_LEXER_H__ */ 209#endif /* __EO_LEXER_H__ */ \ No newline at end of file
diff --git a/src/lib/eolian/eo_parser.c b/src/lib/eolian/eo_parser.c
index c16019e8fe..e02fd57a64 100644
--- a/src/lib/eolian/eo_parser.c
+++ b/src/lib/eolian/eo_parser.c
@@ -782,7 +782,7 @@ parse_type_void_base(Eo_Lexer *ls, Eina_Bool noptr)
782 _fill_name(eina_stringshare_ref(ls->t.value.s), &def->full_name, 782 _fill_name(eina_stringshare_ref(ls->t.value.s), &def->full_name,
783 &def->name, &def->namespaces); 783 &def->name, &def->namespaces);
784 eo_lexer_get(ls); 784 eo_lexer_get(ls);
785 if ((tpid >= KW_accessor && tpid <= KW_list) || tpid == KW_Promise) 785 if (tpid >= KW_accessor && tpid <= KW_list)
786 { 786 {
787 int bline = ls->line_number, bcol = ls->column; 787 int bline = ls->line_number, bcol = ls->column;
788 def->type = EOLIAN_TYPE_COMPLEX; 788 def->type = EOLIAN_TYPE_COMPLEX;
diff --git a/src/tests/ecore/ecore_suite.c b/src/tests/ecore/ecore_suite.c
index 04ad191a13..787a455d74 100644
--- a/src/tests/ecore/ecore_suite.c
+++ b/src/tests/ecore/ecore_suite.c
@@ -26,7 +26,6 @@ static const Efl_Test_Case etc[] = {
26#endif 26#endif
27 { "Ecore_Input", ecore_test_ecore_input }, 27 { "Ecore_Input", ecore_test_ecore_input },
28 { "Ecore_File", ecore_test_ecore_file }, 28 { "Ecore_File", ecore_test_ecore_file },
29 { "Ecore_Promise", ecore_test_ecore_promise },
30 { NULL, NULL } 29 { NULL, NULL }
31}; 30};
32 31
diff --git a/src/tests/ecore/ecore_suite.h b/src/tests/ecore/ecore_suite.h
index 558e610fed..f0e4c2a400 100644
--- a/src/tests/ecore/ecore_suite.h
+++ b/src/tests/ecore/ecore_suite.h
@@ -15,6 +15,5 @@ void ecore_test_ecore_drm(TCase *tc);
15void ecore_test_ecore_fb(TCase *tc); 15void ecore_test_ecore_fb(TCase *tc);
16void ecore_test_ecore_input(TCase *tc); 16void ecore_test_ecore_input(TCase *tc);
17void ecore_test_ecore_file(TCase *tc); 17void ecore_test_ecore_file(TCase *tc);
18void ecore_test_ecore_promise(TCase *tc);
19 18
20#endif /* _ECORE_SUITE_H */ 19#endif /* _ECORE_SUITE_H */
diff --git a/src/tests/ecore/ecore_test_promise.c b/src/tests/ecore/ecore_test_promise.c
deleted file mode 100644
index 0f003fd669..0000000000
--- a/src/tests/ecore/ecore_test_promise.c
+++ /dev/null
@@ -1,364 +0,0 @@
1#ifdef HAVE_CONFIG_H
2# include <config.h>
3#endif
4
5#include <Ecore.h>
6#include "ecore_suite.h"
7#include <time.h>
8
9void promised_thread(const void* data EINA_UNUSED, Ecore_Promise* promise)
10{
11 fprintf(stderr, "%s:%d %s\n", __FILE__, __LINE__, __func__); fflush(stderr);
12 ecore_promise_value_set(promise, NULL);
13}
14
15void promise_callback(void* data EINA_UNUSED, void* value EINA_UNUSED)
16{
17 fprintf(stderr, "%s:%d %s\n", __FILE__, __LINE__, __func__); fflush(stderr);
18 ecore_main_loop_quit();
19}
20
21START_TEST(ecore_test_promise)
22{
23 ecore_init();
24 fprintf(stderr, "%s:%d %s ---------- BEGIN test\n", __FILE__, __LINE__, __func__); fflush(stderr);
25
26 fprintf(stderr, "%s:%d %s\n", __FILE__, __LINE__, __func__); fflush(stderr);
27 Ecore_Promise* promise = ecore_promise_thread_run(&promised_thread, NULL, 0);
28 ecore_promise_then(promise, &promise_callback, NULL);
29 fprintf(stderr, "%s:%d %s\n", __FILE__, __LINE__, __func__); fflush(stderr);
30
31 ecore_main_loop_begin();
32
33 fprintf(stderr, "%s:%d %s ---------- END test\n", __FILE__, __LINE__, __func__); fflush(stderr);
34 ecore_shutdown();
35}
36END_TEST
37
38void promise_error_thread(const void* data EINA_UNUSED, Ecore_Promise* promise)
39{
40 fprintf(stderr, "%s:%d %s\n", __FILE__, __LINE__, __func__); fflush(stderr);
41 ecore_promise_error_set(promise, EINA_ERROR_OUT_OF_MEMORY);
42}
43
44void promise_error_callback(void* data EINA_UNUSED, void* value EINA_UNUSED)
45{
46 fprintf(stderr, "%s:%d %s\n", __FILE__, __LINE__, __func__); fflush(stderr);
47 ecore_main_loop_quit();
48}
49
50START_TEST(ecore_test_promise_error)
51{
52 ecore_init();
53 fprintf(stderr, "%s:%d %s ---------- BEGIN test\n", __FILE__, __LINE__, __func__); fflush(stderr);
54
55 fprintf(stderr, "%s:%d %s\n", __FILE__, __LINE__, __func__); fflush(stderr);
56 Ecore_Promise* promise = ecore_promise_thread_run(&promise_error_thread, NULL, 0);
57 ecore_promise_then(promise, &promise_error_callback, NULL);
58 fprintf(stderr, "%s:%d %s\n", __FILE__, __LINE__, __func__); fflush(stderr);
59
60 ecore_main_loop_begin();
61
62 fprintf(stderr, "%s:%d %s ---------- END test\n", __FILE__, __LINE__, __func__); fflush(stderr);
63 ecore_shutdown();
64}
65END_TEST
66
67START_TEST(ecore_test_promise_all)
68{
69 ecore_init();
70 fprintf(stderr, "%s:%d %s ---------- BEGIN test\n", __FILE__, __LINE__, __func__); fflush(stderr);
71
72 fprintf(stderr, "%s:%d %s\n", __FILE__, __LINE__, __func__); fflush(stderr);
73 Ecore_Promise* first[2] = { ecore_promise_thread_run(&promised_thread, NULL, 0), NULL };
74 Ecore_Promise* promise = ecore_promise_all(eina_carray_iterator_new((void**)&first[0]));
75 ecore_promise_then(promise, &promise_callback, NULL);
76 fprintf(stderr, "%s:%d %s\n", __FILE__, __LINE__, __func__); fflush(stderr);
77
78 ecore_main_loop_begin();
79
80 fprintf(stderr, "%s:%d %s ---------- END test\n", __FILE__, __LINE__, __func__); fflush(stderr);
81 ecore_shutdown();
82}
83END_TEST
84
85void promise_callback2(void* data, void* value EINA_UNUSED)
86{
87 fprintf(stderr, "%s:%d %s\n", __FILE__, __LINE__, __func__); fflush(stderr);
88 if(++(*(int*)data) == 2)
89 ecore_main_loop_quit();
90}
91
92START_TEST(ecore_test_promise_all_then_then)
93{
94 ecore_init();
95 fprintf(stderr, "%s:%d %s ---------- BEGIN test\n", __FILE__, __LINE__, __func__); fflush(stderr);
96
97 int i = 0;
98
99 fprintf(stderr, "%s:%d %s\n", __FILE__, __LINE__, __func__); fflush(stderr);
100 Ecore_Promise* first[2] = { ecore_promise_thread_run(&promised_thread, NULL, 0), NULL };
101 ecore_promise_then(first[0], &promise_callback2, &i);
102 Ecore_Promise* promise = ecore_promise_all(eina_carray_iterator_new((void**)&first[0]));
103 ecore_promise_then(promise, &promise_callback2, &i);
104 fprintf(stderr, "%s:%d %s\n", __FILE__, __LINE__, __func__); fflush(stderr);
105
106 ecore_main_loop_begin();
107
108 fprintf(stderr, "%s:%d %s ---------- END test\n", __FILE__, __LINE__, __func__); fflush(stderr);
109 ecore_shutdown();
110}
111END_TEST
112
113struct sync_data
114{
115 Eina_Lock lock;
116 Eina_Condition cond;
117 Eina_Bool var;
118};
119
120void promised_exit_thread(struct sync_data* data EINA_UNUSED, Ecore_Promise* promise)
121{
122 fprintf(stderr, "%s:%d %s\n", __FILE__, __LINE__, __func__); fflush(stderr);
123 ecore_promise_value_set(promise, NULL);
124 eina_lock_take(&data->lock);
125 data->var = EINA_TRUE;
126 eina_condition_broadcast(&data->cond);
127 eina_lock_release(&data->lock);
128}
129
130static void _ecore_test_promise_then_after_thread_finished_main_cb()
131{
132 struct sync_data data;
133 data.var = EINA_FALSE;
134 eina_lock_new(&data.lock);
135 eina_condition_new(&data.cond, &data.lock);
136
137 Ecore_Promise* promise = ecore_promise_thread_run((Ecore_Promise_Thread_Cb)&promised_exit_thread, &data, 0);
138
139 eina_lock_take(&data.lock);
140 while(!data.var)
141 {
142 eina_condition_wait(&data.cond);
143 }
144 eina_lock_release(&data.lock);
145 ecore_promise_then(promise, &promise_callback, NULL);
146}
147
148START_TEST(ecore_test_promise_then_after_thread_finished)
149{
150 ecore_init();
151 fprintf(stderr, "%s:%d %s ---------- BEGIN test\n", __FILE__, __LINE__, __func__); fflush(stderr);
152
153 ecore_job_add(&_ecore_test_promise_then_after_thread_finished_main_cb, NULL);
154 ecore_main_loop_begin();
155
156 fprintf(stderr, "%s:%d %s ---------- END test\n", __FILE__, __LINE__, __func__); fflush(stderr);
157 ecore_shutdown();
158}
159END_TEST
160
161static void _ecore_test_promise_then_after_thread_finished_all_main_cb()
162{
163 struct sync_data data;
164 data.var = EINA_FALSE;
165 eina_lock_new(&data.lock);
166 eina_condition_new(&data.cond, &data.lock);
167
168 Ecore_Promise* first[] = {ecore_promise_thread_run((Ecore_Promise_Thread_Cb)&promised_exit_thread, &data, 0), NULL};
169 Ecore_Promise* promise = ecore_promise_all(eina_carray_iterator_new((void**)&first[0]));
170
171 eina_lock_take(&data.lock);
172 while(!data.var)
173 {
174 eina_condition_wait(&data.cond);
175 }
176 eina_lock_release(&data.lock);
177 ecore_promise_then(promise, &promise_callback, NULL);
178}
179
180START_TEST(ecore_test_promise_then_after_thread_finished_all)
181{
182 ecore_init();
183 fprintf(stderr, "%s:%d %s ---------- BEGIN test\n", __FILE__, __LINE__, __func__); fflush(stderr);
184
185 ecore_job_add(&_ecore_test_promise_then_after_thread_finished_all_main_cb, NULL);
186 ecore_main_loop_begin();
187
188 fprintf(stderr, "%s:%d %s ---------- END test\n", __FILE__, __LINE__, __func__); fflush(stderr);
189 ecore_shutdown();
190}
191END_TEST
192
193void promised_block_thread(const void* data EINA_UNUSED, Ecore_Promise* promise)
194{
195 struct timespec v = {.tv_sec = 1, .tv_nsec = 0}, rem;
196 if(nanosleep(&v, &rem) == -1 && errno == EINTR)
197 do
198 {
199 v = rem;
200 }
201 while(nanosleep(&v, &rem) == -1 && errno == EINTR);
202
203 int r = 10;
204 ecore_promise_value_set(promise, &r);
205}
206
207static void
208_ecore_test_promise_blocking_get_quit_cb(void* data EINA_UNUSED)
209{
210 ecore_main_loop_quit();
211}
212
213static void
214_ecore_test_promise_blocking_get_main_cb(void* data EINA_UNUSED)
215{
216 Ecore_Promise* promise = ecore_promise_thread_run(&promised_block_thread, NULL, sizeof(int));
217 const void* value = ecore_promise_value_get(promise);
218 ck_assert(*(int*)value == 10);
219
220 ecore_job_add(&_ecore_test_promise_blocking_get_quit_cb, NULL);
221}
222
223START_TEST(ecore_test_promise_blocking_get)
224{
225 ecore_init();
226 fprintf(stderr, "%s:%d %s ---------- BEGIN test\n", __FILE__, __LINE__, __func__); fflush(stderr);
227
228 ecore_job_add(&_ecore_test_promise_blocking_get_main_cb, NULL);
229 ecore_main_loop_begin();
230
231 fprintf(stderr, "%s:%d %s ---------- END test\n", __FILE__, __LINE__, __func__); fflush(stderr);
232 ecore_shutdown();
233}
234END_TEST
235
236static void
237_ecore_test_promise_blocking_get_all_value_get_cb(Ecore_Promise* promise, Ecore_Thread* thread EINA_UNUSED)
238{
239 Eina_Iterator** iterator = ecore_promise_value_get(promise);
240 int* v;
241 ck_assert(eina_iterator_next(*iterator, (void**)&v));
242 ck_assert(*v == 10);
243 ecore_main_loop_quit();
244}
245
246static void
247_ecore_test_promise_blocking_get_all_main_cb(void* data EINA_UNUSED)
248{
249 Ecore_Promise* first[2] = {ecore_promise_thread_run(&promised_block_thread, NULL, sizeof(int)), NULL};
250 Ecore_Promise* promise = ecore_promise_all(eina_carray_iterator_new((void**)&first[0]));
251
252 ecore_thread_run((Ecore_Thread_Cb)&_ecore_test_promise_blocking_get_all_value_get_cb, NULL, NULL, promise);
253}
254
255START_TEST(ecore_test_promise_blocking_get_all)
256{
257 ecore_init();
258 fprintf(stderr, "%s:%d %s ---------- BEGIN test\n", __FILE__, __LINE__, __func__); fflush(stderr);
259
260 ecore_job_add(&_ecore_test_promise_blocking_get_all_main_cb, NULL);
261 ecore_main_loop_begin();
262
263 fprintf(stderr, "%s:%d %s ---------- END test\n", __FILE__, __LINE__, __func__); fflush(stderr);
264 ecore_shutdown();
265}
266END_TEST
267
268static void
269_ecore_test_promise_normal_lifetime_cb(void* data EINA_UNUSED, void* value EINA_UNUSED)
270{
271 ecore_main_loop_quit();
272}
273
274START_TEST(ecore_test_promise_normal_lifetime)
275{
276 ecore_init();
277 fprintf(stderr, "%s:%d %s ---------- BEGIN test\n", __FILE__, __LINE__, __func__); fflush(stderr);
278
279 Ecore_Promise* promise = ecore_promise_add(0);
280
281 ecore_promise_then(promise, &_ecore_test_promise_normal_lifetime_cb, NULL);
282 ecore_promise_value_set(promise, NULL);
283
284 ecore_main_loop_begin();
285
286 fprintf(stderr, "%s:%d %s ---------- END test\n", __FILE__, __LINE__, __func__); fflush(stderr);
287 ecore_shutdown();
288}
289END_TEST
290
291START_TEST(ecore_test_promise_normal_lifetime_all)
292{
293 ecore_init();
294 fprintf(stderr, "%s:%d %s ---------- BEGIN test\n", __FILE__, __LINE__, __func__); fflush(stderr);
295
296 Ecore_Promise* first[2] = {ecore_promise_add(0), NULL};
297 Ecore_Promise* promise = ecore_promise_all(eina_carray_iterator_new((void**)&first[0]));
298
299 ecore_promise_then(promise, &_ecore_test_promise_normal_lifetime_cb, NULL);
300 ecore_promise_value_set(promise, NULL);
301
302 ecore_main_loop_begin();
303
304 fprintf(stderr, "%s:%d %s ---------- END test\n", __FILE__, __LINE__, __func__); fflush(stderr);
305 ecore_shutdown();
306}
307END_TEST
308
309static void
310_ecore_test_promise_immediate_set_lifetime_cb(void* data EINA_UNUSED, void* value EINA_UNUSED)
311{
312 ecore_main_loop_quit();
313}
314
315START_TEST(ecore_test_promise_immediate_set_lifetime)
316{
317 ecore_init();
318 fprintf(stderr, "%s:%d %s ---------- BEGIN test\n", __FILE__, __LINE__, __func__); fflush(stderr);
319
320 Ecore_Promise* promise = ecore_promise_add(0);
321
322 ecore_promise_value_set(promise, NULL);
323 ecore_promise_then(promise, &_ecore_test_promise_immediate_set_lifetime_cb, NULL);
324
325 ecore_main_loop_begin();
326
327 fprintf(stderr, "%s:%d %s ---------- END test\n", __FILE__, __LINE__, __func__); fflush(stderr);
328 ecore_shutdown();
329}
330END_TEST
331
332START_TEST(ecore_test_promise_immediate_set_lifetime_all)
333{
334 ecore_init();
335 fprintf(stderr, "%s:%d %s ---------- BEGIN test\n", __FILE__, __LINE__, __func__); fflush(stderr);
336
337 Ecore_Promise* first[2] = {ecore_promise_add(0), NULL};
338 Ecore_Promise* promise = ecore_promise_all(eina_carray_iterator_new((void**)&first[0]));
339
340 ecore_promise_value_set(first[0], NULL);
341 ecore_promise_then(promise, &_ecore_test_promise_immediate_set_lifetime_cb, NULL);
342
343 ecore_main_loop_begin();
344
345 fprintf(stderr, "%s:%d %s ---------- END test\n", __FILE__, __LINE__, __func__); fflush(stderr);
346 ecore_shutdown();
347}
348END_TEST
349
350void ecore_test_ecore_promise(TCase *tc EINA_UNUSED)
351{
352 tcase_add_test(tc, ecore_test_promise);
353 tcase_add_test(tc, ecore_test_promise_error);
354 tcase_add_test(tc, ecore_test_promise_all);
355 tcase_add_test(tc, ecore_test_promise_all_then_then);
356 tcase_add_test(tc, ecore_test_promise_then_after_thread_finished);
357 tcase_add_test(tc, ecore_test_promise_then_after_thread_finished_all);
358 tcase_add_test(tc, ecore_test_promise_blocking_get);
359 tcase_add_test(tc, ecore_test_promise_blocking_get_all);
360 tcase_add_test(tc, ecore_test_promise_normal_lifetime);
361 tcase_add_test(tc, ecore_test_promise_normal_lifetime_all);
362 tcase_add_test(tc, ecore_test_promise_immediate_set_lifetime);
363 tcase_add_test(tc, ecore_test_promise_immediate_set_lifetime_all);
364}