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 f9ba80ab33.
This commit is contained in:
Tom Hacohen 2016-03-08 14:23:57 +00:00
parent f1a6ff2956
commit 7d8cd6c40f
12 changed files with 20 additions and 1040 deletions

View File

@ -47,8 +47,7 @@ lib/ecore/Ecore.h \
lib/ecore/Ecore_Common.h \
lib/ecore/Ecore_Legacy.h \
lib/ecore/Ecore_Eo.h \
lib/ecore/Ecore_Getopt.h \
lib/ecore/ecore_promise.h
lib/ecore/Ecore_Getopt.h
nodist_installed_ecoremainheaders_DATA = \
$(ecore_eolian_h)
@ -73,7 +72,6 @@ lib/ecore/ecore_timer.c \
lib/ecore/ecore_thread.c \
lib/ecore/ecore_throttle.c \
lib/ecore/ecore_exe.c \
lib/ecore/ecore_promise.c \
lib/ecore/ecore_exe_private.h \
lib/ecore/ecore_private.h
@ -201,7 +199,6 @@ tests/ecore/ecore_test_animator.c \
tests/ecore/ecore_test_ecore_thread_eina_thread_queue.c \
tests/ecore/ecore_test_ecore_input.c \
tests/ecore/ecore_test_ecore_file.c \
tests/ecore/ecore_test_promise.c \
tests/ecore/ecore_suite.h
tests_ecore_ecore_suite_CPPFLAGS = -I$(top_builddir)/src/lib/efl \

View File

@ -311,9 +311,6 @@ eo_bind_func_generate(const Eolian_Class *class, const Eolian_Function *funcid,
if (ftype != EOLIAN_PROP_GET && ftype != EOLIAN_PROP_SET) ftype = eolian_function_type_get(funcid);
Eina_Bool is_prop = (ftype == EOLIAN_PROP_GET || ftype == EOLIAN_PROP_SET);
Eina_Bool has_promise = EINA_FALSE;
const char* promise_param_name = NULL;
const char* promise_value_type = NULL;
Eina_Bool need_implementation = EINA_TRUE;
if (!impl_env && eolian_function_is_virtual_pure(funcid, ftype)) need_implementation = EINA_FALSE;
@ -340,11 +337,9 @@ eo_bind_func_generate(const Eolian_Class *class, const Eolian_Function *funcid,
if (eina_iterator_next(itr, &data) && !eina_iterator_next(itr, &data2))
{
Eolian_Function_Parameter *param = data;
const char* rettype_str = NULL;
rettypet = eolian_parameter_type_get(param);
var_as_ret = EINA_TRUE;
default_ret_val = eolian_parameter_default_value_get(param);
eina_stringshare_del(rettype_str);
}
eina_iterator_free(itr);
}
@ -380,24 +375,9 @@ eo_bind_func_generate(const Eolian_Class *class, const Eolian_Function *funcid,
const char *ptype = eolian_type_c_type_get(ptypet);
Eolian_Parameter_Dir pdir = eolian_parameter_direction_get(param);
Eina_Bool had_star = !!strchr(ptype, '*');
if(!has_promise && !strcmp(ptype, "Ecore_Promise *"))
{
Eina_Iterator* promise_values;
has_promise = EINA_TRUE;
promise_param_name = eina_stringshare_add(pname);
promise_values = eolian_type_subtypes_get(eolian_type_base_type_get(ptypet));
Eolian_Type* subtype;
if(eina_iterator_next(promise_values, (void**)&subtype))
promise_value_type = eolian_type_c_type_get(subtype);
}
if (ftype == EOLIAN_UNRESOLVED || ftype == EOLIAN_METHOD) add_star = (pdir == EOLIAN_OUT_PARAM || pdir == EOLIAN_INOUT_PARAM);
if (eina_strbuf_length_get(params)) eina_strbuf_append(params, ", ");
if(has_promise)
eina_strbuf_append_printf(params, "%s", "&__eo_promise");
else
eina_strbuf_append_printf(params, "%s", pname);
eina_strbuf_append_printf(params, "%s", pname);
eina_strbuf_append_printf(full_params, ", %s%s%s%s%s",
ptype, had_star?"":" ", add_star?"*":"", pname, is_empty && !dflt_value ?" EINA_UNUSED":"");
if (is_auto)
@ -531,8 +511,8 @@ eo_bind_func_generate(const Eolian_Class *class, const Eolian_Function *funcid,
Eina_Bool ret_is_void = (!rettype || !strcmp(rettype, "void"));
_class_func_env_create(class, eolian_function_name_get(funcid), ftype, &func_env);
eina_strbuf_append_printf(eo_func_decl,
"EOAPI EO_%sFUNC_%sBODY%s%s(%s",
ret_is_void?"VOID_":"", has_promise?"PROMISE_":"", has_params?"V":"",
"EOAPI EO_%sFUNC_BODY%s%s(%s",
ret_is_void?"VOID_":"", has_params?"V":"",
(ftype == EOLIAN_PROP_GET ||
eolian_function_object_is_const(funcid) ||
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,
eina_stringshare_del(string);
}
}
if (has_promise)
{
eina_strbuf_append_printf(eo_func_decl, ", %s, %s", promise_param_name, promise_value_type);
}
if (has_params)
{
eina_strbuf_replace_all(full_params, " EINA_UNUSED", "");

View File

@ -356,7 +356,6 @@ extern "C" {
#endif
#ifdef EFL_EO_API_SUPPORT
#include "Ecore_Eo.h"
#include "ecore_promise.h"
#endif
#ifdef __cplusplus

View File

@ -1,452 +0,0 @@
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <Eina.h>
#include <Ecore.h>
#include <assert.h>
typedef void(*Ecore_Promise_Free_Cb)(void*);
struct _Ecore_Promise_Then_Cb
{
EINA_INLIST;
Ecore_Promise_Cb callback;
void* data;
};
struct _Ecore_Promise
{
Eina_Lock lock;
Eina_Condition condition;
Eina_Bool has_finished : 1;
Eina_Bool has_errored : 1;
Eina_Bool has_pending_call : 1;
Eina_Bool is_then_calls_manual : 1;
Eina_Error error;
size_t value_size;
int ref;
struct _Ecore_Promise_Then_Cb then_callbacks;
Ecore_Promise_Free_Cb free_cb;
char value[];
};
struct _Ecore_Promise_Thread_Data
{
const void* data;
Ecore_Promise_Thread_Cb func_blocking;
Ecore_Promise* promise;
};
typedef struct _Ecore_Promise_Iterator _Ecore_Promise_Iterator;
typedef struct _Ecore_Promise_Success_Iterator _Ecore_Promise_Success_Iterator;
typedef struct _Ecore_Promise_Failure_Iterator _Ecore_Promise_Failure_Iterator;
struct _Ecore_Promise_Iterator
{
Eina_Iterator* success_iterator;
Eina_Iterator* failure_iterator;
struct _Ecore_Promise_Success_Iterator
{
Eina_Iterator success_iterator_impl;
struct _Ecore_Promise_Failure_Iterator
{
Eina_Iterator failure_iterator_impl;
unsigned int promise_index;
unsigned int num_promises;
unsigned int promises_finished;
Ecore_Promise* promises[];
} data;
} data;
};
static void _ecore_promise_lock_take(Ecore_Promise* promise);
static void _ecore_promise_lock_release(Ecore_Promise* promise);
static void _ecore_promise_finish(Ecore_Promise* promise);
static void _ecore_promise_then_calls(Ecore_Promise* promise);
static void _ecore_promise_unsafe_ref(Ecore_Promise const* promise);
static void _ecore_promise_unsafe_unref(Ecore_Promise const* promise);
static void _ecore_promise_unsafe_free_unref(Ecore_Promise const* promise);
static Eina_Bool _ecore_promise_unlock_unsafe_free_unref(Ecore_Promise const* promise);
static void _ecore_promise_iterator_setup(_Ecore_Promise_Iterator* iterator, Eina_Array* promises);
static void _ecore_promise_thread_end(void* data, Ecore_Thread* thread EINA_UNUSED)
{
struct _Ecore_Promise_Thread_Data* p = data;
_ecore_promise_lock_take(p->promise);
if(p->promise->has_finished)
{
p->promise->has_pending_call = EINA_FALSE;
if(!_ecore_promise_unlock_unsafe_free_unref(p->promise))
_ecore_promise_then_calls(p->promise);
}
else
{
p->promise->is_then_calls_manual = EINA_FALSE;
p->promise->has_pending_call = EINA_FALSE;
_ecore_promise_unlock_unsafe_free_unref(p->promise);
}
free(data);
}
static void
_ecore_promise_thread_blocking(void* data, Ecore_Thread* thread EINA_UNUSED)
{
struct _Ecore_Promise_Thread_Data* p = data;
(p->func_blocking)(p->data, p->promise);
}
static void
_ecore_promise_then_calls(Ecore_Promise* promise)
{
_ecore_promise_lock_take(promise);
struct _Ecore_Promise_Then_Cb then_callbacks = promise->then_callbacks;
memset(&promise->then_callbacks, 0, sizeof(promise->then_callbacks));
promise->has_pending_call = EINA_FALSE;
_ecore_promise_lock_release(promise);
struct _Ecore_Promise_Then_Cb* callback;
if(then_callbacks.callback)
{
(*then_callbacks.callback)(then_callbacks.data, &promise->value[0]);
_ecore_promise_unsafe_free_unref(promise);
}
if(EINA_INLIST_GET(&then_callbacks)->next)
{
Eina_Inlist* list2;
EINA_INLIST_FOREACH_SAFE(EINA_INLIST_GET(&then_callbacks)->next, list2, callback)
{
if(callback->callback)
{
(*callback->callback)(callback->data, promise);
}
_ecore_promise_unsafe_free_unref(promise);
}
}
}
Ecore_Promise* ecore_promise_thread_run(Ecore_Promise_Thread_Cb func_blocking, const void* data, size_t value_size)
{
struct _Ecore_Promise_Thread_Data *new_data = malloc(sizeof(struct _Ecore_Promise_Thread_Data));
new_data->data = data;
new_data->func_blocking = func_blocking;
new_data->promise = ecore_promise_add(value_size);
new_data->promise->is_then_calls_manual = EINA_TRUE;
new_data->promise->has_pending_call = EINA_TRUE;
ecore_promise_ref(new_data->promise);
ecore_thread_run(&_ecore_promise_thread_blocking, &_ecore_promise_thread_end, NULL, new_data);
return new_data->promise;
}
Ecore_Promise* ecore_promise_add(int value_size)
{
Ecore_Promise* p = malloc(sizeof(Ecore_Promise) + value_size);
eina_lock_new(&p->lock);
eina_condition_new(&p->condition, &p->lock);
p->has_finished = p->has_errored = p->has_pending_call = p->is_then_calls_manual = EINA_FALSE;
p->ref = 1;
memset(&p->then_callbacks, 0, sizeof(p->then_callbacks));
p->value_size = value_size;
p->free_cb = NULL;
return p;
}
static void _ecore_promise_del(Ecore_Promise* promise)
{
if(promise->free_cb)
promise->free_cb((void*)&promise->value[0]);
eina_lock_free(&promise->lock);
eina_condition_free(&promise->condition);
}
void* ecore_promise_buffer_get(Ecore_Promise* promise)
{
return &promise->value[0];
}
void* ecore_promise_value_get(Ecore_Promise const* promise)
{
_ecore_promise_lock_take((Ecore_Promise*)promise);
_ecore_promise_unsafe_ref(promise);
while(!promise->has_finished)
{
eina_condition_wait((Eina_Condition*)&promise->condition);
}
void* v = (void*)(promise->value_size && !promise->has_errored ? &promise->value[0] : NULL);
_ecore_promise_unsafe_unref(promise);
_ecore_promise_lock_release((Ecore_Promise*)promise);
return v;
}
void ecore_promise_value_set(Ecore_Promise* promise, void* data)
{
_ecore_promise_lock_take(promise);
if(data && promise->value_size)
{
memcpy(&promise->value[0], data, promise->value_size);
}
_ecore_promise_finish(promise);
}
static void _ecore_promise_all_compose_then_cb(Ecore_Promise* promise, void* value EINA_UNUSED)
{
_ecore_promise_lock_take(promise);
_Ecore_Promise_Iterator* iterator = (_Ecore_Promise_Iterator*)promise->value;
if(++iterator->data.data.promises_finished == iterator->data.data.num_promises)
{
_ecore_promise_finish(promise);
}
else
_ecore_promise_lock_release(promise);
}
static void _ecore_promise_all_free(_Ecore_Promise_Iterator* value)
{
unsigned i = 0;
eina_iterator_free(value->success_iterator);
/* eina_iterator_free(value->failure_iterator); */
for(;i != value->data.data.num_promises; ++i)
{
ecore_promise_unref(value->data.data.promises[i]);
}
}
Ecore_Promise* ecore_promise_all(Eina_Iterator* it)
{
Ecore_Promise* current, *promise;
Eina_Array* promises;
promises = eina_array_new(20);
EINA_ITERATOR_FOREACH(it, current)
{
eina_array_push(promises, current);
}
promise = ecore_promise_add(sizeof(_Ecore_Promise_Iterator) + sizeof(Ecore_Promise*)*eina_array_count_get(promises));
//promise->is_then_calls_manual = EINA_TRUE;
promise->free_cb = (Ecore_Promise_Free_Cb)_ecore_promise_all_free;
_Ecore_Promise_Iterator* internal_it = ecore_promise_buffer_get(promise);
_ecore_promise_iterator_setup(internal_it, promises);
eina_array_free(promises);
{
Ecore_Promise** cur_promise = internal_it->data.data.promises, ** last =
internal_it->data.data.promises + internal_it->data.data.num_promises;
for(;cur_promise != last; ++cur_promise)
{
ecore_promise_ref(*cur_promise);
ecore_promise_then(*cur_promise, (Ecore_Promise_Cb)&_ecore_promise_all_compose_then_cb, promise);
}
}
return promise;
}
void ecore_promise_then(Ecore_Promise* promise, Ecore_Promise_Cb callback, void* data)
{
_ecore_promise_lock_take(promise);
_ecore_promise_unsafe_ref(promise);
if(!promise->then_callbacks.callback && !EINA_INLIST_GET(&promise->then_callbacks)->next)
{
promise->then_callbacks.callback = callback;
promise->then_callbacks.data = data;
}
else
{
struct _Ecore_Promise_Then_Cb* p = malloc(sizeof(struct _Ecore_Promise_Then_Cb));
p->callback = callback;
p->data = data;
Eina_Inlist* l = eina_inlist_append(EINA_INLIST_GET(&promise->then_callbacks), EINA_INLIST_GET(p));
(void)l;
}
if(promise->has_finished && !promise->has_pending_call)
{
promise->has_pending_call = EINA_TRUE;
_ecore_promise_lock_release(promise);
ecore_job_add((Ecore_Cb)&_ecore_promise_then_calls, promise);
}
else
_ecore_promise_lock_release(promise);
}
EAPI Eina_Error ecore_promise_error_get(Ecore_Promise const* promise)
{
_ecore_promise_lock_take((Ecore_Promise*)promise);
if(promise->has_errored)
{
Eina_Error error = promise->error;
_ecore_promise_lock_release((Ecore_Promise*)promise);
return error;
}
else
{
_ecore_promise_lock_release((Ecore_Promise*)promise);
return 0;
}
}
EAPI void ecore_promise_error_set(Ecore_Promise* promise, Eina_Error error)
{
_ecore_promise_lock_take(promise);
promise->error = error;
promise->has_errored = EINA_TRUE;
_ecore_promise_finish(promise);
}
static void
_ecore_promise_finish(Ecore_Promise* promise)
{
promise->has_finished = EINA_TRUE;
eina_condition_broadcast(&promise->condition);
_ecore_promise_unsafe_unref(promise);
if(!promise->is_then_calls_manual && !promise->has_pending_call)
{
promise->has_pending_call = EINA_TRUE;
_ecore_promise_lock_release(promise);
ecore_job_add((Ecore_Cb)&_ecore_promise_then_calls, promise);
}
else
_ecore_promise_lock_release(promise);
}
static Eina_Bool
_ecore_promise_iterator_next(_Ecore_Promise_Success_Iterator *it, void **data)
{
if(it->data.promise_index == it->data.num_promises)
return EINA_FALSE;
if(ecore_promise_error_get(it->data.promises[it->data.promise_index]))
{
return EINA_FALSE;
}
else
{
*data = ecore_promise_value_get(it->data.promises[it->data.promise_index++]);
return EINA_TRUE;
}
}
static void**
_ecore_promise_iterator_get_container(_Ecore_Promise_Success_Iterator *it)
{
return (void**)it->data.promises;
}
static void
_ecore_promise_iterator_free(_Ecore_Promise_Success_Iterator *it EINA_UNUSED)
{
}
static void _ecore_promise_iterator_setup(_Ecore_Promise_Iterator* it, Eina_Array* promises_array)
{
Ecore_Promise** promises;
it->success_iterator = &it->data.success_iterator_impl;
it->failure_iterator = &it->data.data.failure_iterator_impl;
it->data.data.num_promises = eina_array_count_get(promises_array);
it->data.data.promise_index = 0;
promises = (Ecore_Promise**)promises_array->data;
memcpy(&it->data.data.promises[0], promises, it->data.data.num_promises*sizeof(Ecore_Promise*));
EINA_MAGIC_SET(&it->data.success_iterator_impl, EINA_MAGIC_ITERATOR);
EINA_MAGIC_SET(&it->data.data.failure_iterator_impl, EINA_MAGIC_ITERATOR);
it->data.success_iterator_impl.version = EINA_ITERATOR_VERSION;
it->data.success_iterator_impl.next = FUNC_ITERATOR_NEXT(_ecore_promise_iterator_next);
it->data.success_iterator_impl.get_container = FUNC_ITERATOR_GET_CONTAINER(
_ecore_promise_iterator_get_container);
it->data.success_iterator_impl.free = FUNC_ITERATOR_FREE(_ecore_promise_iterator_free);
}
EAPI int ecore_promise_value_size_get(Ecore_Promise const* promise)
{
return promise->value_size;
}
static void _ecore_promise_lock_take(Ecore_Promise* promise)
{
eina_lock_take(&promise->lock);
}
static void _ecore_promise_lock_release(Ecore_Promise* promise)
{
eina_lock_release(&promise->lock);
}
static void _ecore_promise_unsafe_ref(Ecore_Promise const* promise)
{
Ecore_Promise* p = (Ecore_Promise*)promise;
++p->ref;
}
static void _ecore_promise_free_cb(Ecore_Promise* promise)
{
_ecore_promise_lock_take(promise);
_ecore_promise_unlock_unsafe_free_unref(promise);
}
static void _ecore_promise_unsafe_unref(Ecore_Promise const* promise)
{
Ecore_Promise* p = (Ecore_Promise*)promise;
if(p->ref == 1 && !p->has_pending_call)
{
ecore_job_add((Ecore_Cb)_ecore_promise_free_cb, p);
}
else
--p->ref;
}
static void _ecore_promise_unsafe_free_unref(Ecore_Promise const* promise)
{
Ecore_Promise* p = (Ecore_Promise*)promise;
if(--p->ref == 0)
{
assert(!p->has_pending_call);
_ecore_promise_del(p);
}
}
static Eina_Bool _ecore_promise_unlock_unsafe_free_unref(Ecore_Promise const* promise)
{
Ecore_Promise* p = (Ecore_Promise*)promise;
if(--p->ref == 0)
{
assert(!p->has_pending_call);
_ecore_promise_lock_release((Ecore_Promise*)promise);
_ecore_promise_del(p);
return EINA_TRUE;
}
else
{
_ecore_promise_lock_release((Ecore_Promise*)promise);
return EINA_FALSE;
}
}
EAPI void ecore_promise_ref(Ecore_Promise* promise)
{
_ecore_promise_lock_take(promise);
_ecore_promise_unsafe_ref(promise);
_ecore_promise_lock_release(promise);
}
EAPI void ecore_promise_unref(Ecore_Promise* promise)
{
_ecore_promise_lock_take(promise);
_ecore_promise_unsafe_unref(promise);
_ecore_promise_lock_release(promise);
}

View File

@ -1,136 +0,0 @@
#ifdef EFL_BETA_API_SUPPORT
struct _Ecore_Promise;
/*
* @def _Ecore_Promise
*/
typedef struct _Ecore_Promise Ecore_Promise;
/*
* @brief Function callback type for when using ecore_promise_then
*/
typedef void(*Ecore_Promise_Cb)(void* data, void* value);
/*
* @brief Function callback type for when creating Ecore_Thread that
* uses Ecore_Promise for communication
*/
typedef void(*Ecore_Promise_Thread_Cb)(const void* data, Ecore_Promise* promise);
/*
* @brief Function that instantiates a Ecore_Promise and automatically
* executes func_blocking callback function in another thread
*/
EAPI Ecore_Promise* ecore_promise_thread_run(Ecore_Promise_Thread_Cb func_blocking, const void* data, size_t value_size);
/*
* @brief Creates a Ecore_Promise with a value of size value_size.
*
* @param value_size Size of value-type that Ecore_Promise will hold
*/
EAPI Ecore_Promise* ecore_promise_add(int value_size);
/*
* @brief Appends a callback to be called when the Ecore_Promise is
* finished.
*
* @param promise The Ecore_Promise to wait for
* @param callback Callback to be called when Ecore_Promise is finished
* @param data Private data passed to the callback
*/
EAPI void ecore_promise_then(Ecore_Promise* promise, Ecore_Promise_Cb callback, void* data);
/*
* @brief Creates a new Ecore_Promise from other Ecore_Promises
*
* @param promises An Eina_Iterator for all Ecore_Promises
*/
EAPI Ecore_Promise* ecore_promise_all(Eina_Iterator* promises);
/*
* @brief Sets value for Ecore_Promise. This finishes the callback and
* calls all ecore_promise_then callbacks that have been registered on
* this Ecore_Promise. This function must be called only once per
* Ecore_Promise
*
* @param promise The promise for which to set the value
* @param value The pointer to the value that is going to be copied, or NULL.
*/
EAPI void ecore_promise_value_set(Ecore_Promise* promise, void* value);
/*
* @brief Returns the pointer to the value if the Ecore_Promise is
* finished. Waits for it to be finished, otherwise.
*
* @param promise The promise for which to get the value
*/
EAPI void* ecore_promise_value_get(Ecore_Promise const* promise);
/*
* @brief Returns the pointer to the buffer that holds the value. This
* function is useful to instantiate the value directly in the correct
* buffer, without needing to copy. The ecore_promise_value_set must
* still be called, possibly with NULL, to finish the Ecore_Promise
* and call the callbacks registered in it.
*
* @param promise The promise for which to get the buffer pointer
*/
EAPI void* ecore_promise_buffer_get(Ecore_Promise* promise);
/*
* @brief Sets an error to the Ecore_Promise, thus finishing the
* promise and calling all ecore_promise_then callbacks registered.
*
* @param promise The promise for which to set the error
* @param error Eina_Error to be set
*/
EAPI void ecore_promise_error_set(Ecore_Promise* promise, Eina_Error error);
/*
* @brief Gets an error to the Ecore_Promise if the promise is
* finished and has error'ed out. If it hasn't finished, it will wait,
* and if it has finished but otherwise not error'ed, returns 0.
*
* @param promise The promise for which to get the error
*/
EAPI Eina_Error ecore_promise_error_get(Ecore_Promise const* promise);
/*
* @brief Gets the size of the value in ecore_promise_value_get.
*
* @param promise The promise for which to get the value size
*/
EAPI int ecore_promise_value_size_get(Ecore_Promise const* promise);
/*
* @brief Returns @EINA_TRUE if the promise is ready and won't block
* on ecore_promise_value_get and @EINA_FALSE otherwise.
*
* @param promise The promise for which to get the ready status
*/
EAPI Eina_Bool ecore_promise_ready_is(Ecore_Promise const* promise);
/*
* @brief Increments the reference count for the Ecore_Promise
*
* @param promise The promise for which to increment its reference
*/
EAPI void ecore_promise_ref(Ecore_Promise* promise);
/*
* @brief Decrement the reference count for the Ecore_Promise and
* possibly schedule its destruction. The Ecore_Promise, if its
* reference count drops to zero, will only be free'd when all the
* current mainloop events have been processed. This allows the user
* to call ecore_promise_then before that happens so it can increment
* the reference back to 1 and wait for a value set or error set on
* the Ecore_Promise.
*
* @param promise The promise for which to decrement its reference
*/
EAPI void ecore_promise_unref(Ecore_Promise* promise);
#endif

View File

@ -519,96 +519,61 @@ typedef struct _Eo_Call_Cache
__FILE__, __LINE__)) return DefRet; \
_Eo_##Name##_func _func_ = (_Eo_##Name##_func) ___call.func; \
#define _EO_FUNC_PROMISE_CREATE0
#define _EO_FUNC_PROMISE_FREE0
#define _EO_FUNC_PROMISE_CREATE1 \
Ecore_Promise*(*ecore_promise_add)(int size) = dlsym(dlopen(NULL, RTLD_NOW), "ecore_promise_add"); \
Ecore_Promise* __eo_promise = ecore_promise_add(sizeof(PromiseValue));
#define _EO_FUNC_PROMISE_FREE1 \
if(Promise) \
*Promise = __eo_promise; \
else \
{ \
void(*ecore_promise_unref)(Ecore_Promise* p) = dlsym(dlopen(NULL, RTLD_NOW), "ecore_promise_unref"); \
ecore_promise_unref(__eo_promise); \
}
#define _EO_EXPANSION_AUX(X) X
#define _EO_FUNC_PROMISE_CREATE(p) _EO_EXPANSION_AUX(_EO_FUNC_PROMISE_CREATE ## p)
#define _EO_FUNC_PROMISE_FREE(p) _EO_EXPANSION_AUX(_EO_FUNC_PROMISE_FREE ## p)
// to define an EAPI function
#define _EO_FUNC_BODY(Name, ObjType, Promise, Ret, DefRet) \
#define _EO_FUNC_BODY(Name, ObjType, Ret, DefRet) \
Ret \
Name(ObjType obj) \
{ \
typedef Ret (*_Eo_##Name##_func)(Eo *, void *obj_data); \
Ret _r; \
EO_FUNC_COMMON_OP(obj, Name, DefRet); \
_EO_FUNC_PROMISE_CREATE(Promise) \
_r = _func_(___call.eo_id, ___call.data); \
_eo_call_end(&___call); \
_EO_FUNC_PROMISE_FREE(Promise) \
return _r; \
}
#define _EO_VOID_FUNC_BODY(Name, ObjType, Promise) \
#define _EO_VOID_FUNC_BODY(Name, ObjType) \
void \
Name(ObjType obj) \
{ \
typedef void (*_Eo_##Name##_func)(Eo *, void *obj_data); \
EO_FUNC_COMMON_OP(obj, Name, ); \
_EO_FUNC_PROMISE_CREATE(Promise) \
_func_(___call.eo_id, ___call.data); \
_eo_call_end(&___call); \
_EO_FUNC_PROMISE_FREE(Promise) \
}
#define _EO_FUNC_BODYV(Name, ObjType, Promise, Ret, DefRet, Arguments, ...) \
#define _EO_FUNC_BODYV(Name, ObjType, Ret, DefRet, Arguments, ...) \
Ret \
Name(ObjType obj, __VA_ARGS__) \
{ \
typedef Ret (*_Eo_##Name##_func)(Eo *, void *obj_data, __VA_ARGS__); \
Ret _r; \
EO_FUNC_COMMON_OP(obj, Name, DefRet); \
_EO_FUNC_PROMISE_CREATE(Promise) \
_r = _func_(___call.eo_id, ___call.data, Arguments); \
_eo_call_end(&___call); \
_EO_FUNC_PROMISE_FREE(Promise) \
return _r; \
}
#define _EO_VOID_FUNC_BODYV(Name, ObjType, Promise, Arguments, ...) \
#define _EO_VOID_FUNC_BODYV(Name, ObjType, Arguments, ...) \
void \
Name(ObjType obj, __VA_ARGS__) \
{ \
typedef void (*_Eo_##Name##_func)(Eo *, void *obj_data, __VA_ARGS__); \
EO_FUNC_COMMON_OP(obj, Name, ); \
_EO_FUNC_PROMISE_CREATE(Promise) \
_func_(___call.eo_id, ___call.data, Arguments); \
_eo_call_end(&___call); \
_EO_FUNC_PROMISE_FREE(Promise) \
}
#define EO_FUNC_BODY(Name, Ret, DefRet) _EO_FUNC_BODY(Name, Eo *, 0, Ret, DefRet)
#define EO_VOID_FUNC_BODY(Name) _EO_VOID_FUNC_BODY(Name, Eo *, 0)
#define EO_FUNC_BODYV(Name, Ret, DefRet, Arguments, ...) _EO_FUNC_BODYV(Name, Eo *, 0, Ret, DefRet, EO_FUNC_CALL(Arguments), __VA_ARGS__)
#define EO_VOID_FUNC_BODYV(Name, Arguments, ...) _EO_VOID_FUNC_BODYV(Name, Eo *, 0, EO_FUNC_CALL(Arguments), __VA_ARGS__)
#define EO_FUNC_BODY(Name, Ret, DefRet) _EO_FUNC_BODY(Name, Eo *, Ret, DefRet)
#define EO_VOID_FUNC_BODY(Name) _EO_VOID_FUNC_BODY(Name, Eo *)
#define EO_FUNC_BODYV(Name, Ret, DefRet, Arguments, ...) _EO_FUNC_BODYV(Name, Eo *, Ret, DefRet, EO_FUNC_CALL(Arguments), __VA_ARGS__)
#define EO_VOID_FUNC_BODYV(Name, Arguments, ...) _EO_VOID_FUNC_BODYV(Name, Eo *, EO_FUNC_CALL(Arguments), __VA_ARGS__)
#define EO_FUNC_BODY_CONST(Name, Ret, DefRet) _EO_FUNC_BODY(Name, const Eo *, 0, Ret, DefRet)
#define EO_VOID_FUNC_BODY_CONST(Name) _EO_VOID_FUNC_BODY(Name, const Eo *, 0)
#define EO_FUNC_BODYV_CONST(Name, Ret, DefRet, Arguments, ...) _EO_FUNC_BODYV(Name, const Eo *, 0, Ret, DefRet, EO_FUNC_CALL(Arguments), __VA_ARGS__)
#define EO_VOID_FUNC_BODYV_CONST(Name, Arguments, ...) _EO_VOID_FUNC_BODYV(Name, const Eo *, 0, EO_FUNC_CALL(Arguments), __VA_ARGS__)
#define EO_FUNC_BODY_CONST(Name, Ret, DefRet) _EO_FUNC_BODY(Name, const Eo *, Ret, DefRet)
#define EO_VOID_FUNC_BODY_CONST(Name) _EO_VOID_FUNC_BODY(Name, const Eo *)
#define EO_FUNC_BODYV_CONST(Name, Ret, DefRet, Arguments, ...) _EO_FUNC_BODYV(Name, const Eo *, Ret, DefRet, EO_FUNC_CALL(Arguments), __VA_ARGS__)
#define EO_VOID_FUNC_BODYV_CONST(Name, Arguments, ...) _EO_VOID_FUNC_BODYV(Name, const Eo *, EO_FUNC_CALL(Arguments), __VA_ARGS__)
#define EO_FUNC_PROMISE_BODY(Name, Ret, DefRet) _EO_FUNC_BODY(Name, Eo *, 1, Ret, DefRet)
#define EO_VOID_FUNC_PROMISE_BODY(Name) _EO_VOID_FUNC_BODY(Name, Eo *, 1)
#define EO_FUNC_PROMISE_BODYV(Name, Ret, DefRet, Arguments, ...) _EO_FUNC_BODYV(Name, Eo *, 1, Ret, DefRet, EO_FUNC_CALL(Arguments), __VA_ARGS__)
#define EO_VOID_FUNC_PROMISE_BODYV(Name, Arguments, ...) _EO_VOID_FUNC_BODYV(Name, Eo *, 1, EO_FUNC_CALL(Arguments), __VA_ARGS__)
#define EO_FUNC_PROMISE_BODY_CONST(Name, Ret, DefRet) _EO_FUNC_BODY(Name, const Eo *, 1, Ret, DefRet)
#define EO_VOID_FUNC_PROMISE_BODY_CONST(Name) _EO_VOID_FUNC_BODY(Name, const Eo *, 1)
#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__)
#define EO_VOID_FUNC_PROMISE_BODYV_CONST(Name, Arguments, ...) _EO_VOID_FUNC_BODYV(Name, const Eo *, 1, EO_FUNC_CALL(Arguments), __VA_ARGS__)
#ifndef _WIN32
# define _EO_OP_API_ENTRY(a) (void*)a
#else

View File

@ -75,8 +75,7 @@ static const char * const ctypes[] =
"Eina_Accessor", "Eina_Array", "Eina_Iterator", "Eina_Hash", "Eina_List",
"Eina_Value",
"Eo_Event_Cb",
"Ecore_Promise"
"Eo_Event_Cb"
};
#undef KW

View File

@ -52,9 +52,7 @@ enum Tokens
\
KW(accessor), KW(array), KW(iterator), KW(hash), KW(list), KW(generic_value), \
\
KW(__builtin_event_cb), \
KW(Promise), \
KW(__undefined_type), \
KW(__builtin_event_cb), KW(__undefined_type), \
\
KW(true), KW(false), KW(null)
@ -208,4 +206,4 @@ void eo_lexer_context_pop (Eo_Lexer *ls);
void eo_lexer_context_restore(Eo_Lexer *ls);
void eo_lexer_context_clear (Eo_Lexer *ls);
#endif /* __EO_LEXER_H__ */
#endif /* __EO_LEXER_H__ */

View File

@ -782,7 +782,7 @@ parse_type_void_base(Eo_Lexer *ls, Eina_Bool noptr)
_fill_name(eina_stringshare_ref(ls->t.value.s), &def->full_name,
&def->name, &def->namespaces);
eo_lexer_get(ls);
if ((tpid >= KW_accessor && tpid <= KW_list) || tpid == KW_Promise)
if (tpid >= KW_accessor && tpid <= KW_list)
{
int bline = ls->line_number, bcol = ls->column;
def->type = EOLIAN_TYPE_COMPLEX;

View File

@ -26,7 +26,6 @@ static const Efl_Test_Case etc[] = {
#endif
{ "Ecore_Input", ecore_test_ecore_input },
{ "Ecore_File", ecore_test_ecore_file },
{ "Ecore_Promise", ecore_test_ecore_promise },
{ NULL, NULL }
};

View File

@ -15,6 +15,5 @@ void ecore_test_ecore_drm(TCase *tc);
void ecore_test_ecore_fb(TCase *tc);
void ecore_test_ecore_input(TCase *tc);
void ecore_test_ecore_file(TCase *tc);
void ecore_test_ecore_promise(TCase *tc);
#endif /* _ECORE_SUITE_H */

View File

@ -1,364 +0,0 @@
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <Ecore.h>
#include "ecore_suite.h"
#include <time.h>
void promised_thread(const void* data EINA_UNUSED, Ecore_Promise* promise)
{
fprintf(stderr, "%s:%d %s\n", __FILE__, __LINE__, __func__); fflush(stderr);
ecore_promise_value_set(promise, NULL);
}
void promise_callback(void* data EINA_UNUSED, void* value EINA_UNUSED)
{
fprintf(stderr, "%s:%d %s\n", __FILE__, __LINE__, __func__); fflush(stderr);
ecore_main_loop_quit();
}
START_TEST(ecore_test_promise)
{
ecore_init();
fprintf(stderr, "%s:%d %s ---------- BEGIN test\n", __FILE__, __LINE__, __func__); fflush(stderr);
fprintf(stderr, "%s:%d %s\n", __FILE__, __LINE__, __func__); fflush(stderr);
Ecore_Promise* promise = ecore_promise_thread_run(&promised_thread, NULL, 0);
ecore_promise_then(promise, &promise_callback, NULL);
fprintf(stderr, "%s:%d %s\n", __FILE__, __LINE__, __func__); fflush(stderr);
ecore_main_loop_begin();
fprintf(stderr, "%s:%d %s ---------- END test\n", __FILE__, __LINE__, __func__); fflush(stderr);
ecore_shutdown();
}
END_TEST
void promise_error_thread(const void* data EINA_UNUSED, Ecore_Promise* promise)
{
fprintf(stderr, "%s:%d %s\n", __FILE__, __LINE__, __func__); fflush(stderr);
ecore_promise_error_set(promise, EINA_ERROR_OUT_OF_MEMORY);
}
void promise_error_callback(void* data EINA_UNUSED, void* value EINA_UNUSED)
{
fprintf(stderr, "%s:%d %s\n", __FILE__, __LINE__, __func__); fflush(stderr);
ecore_main_loop_quit();
}
START_TEST(ecore_test_promise_error)
{
ecore_init();
fprintf(stderr, "%s:%d %s ---------- BEGIN test\n", __FILE__, __LINE__, __func__); fflush(stderr);
fprintf(stderr, "%s:%d %s\n", __FILE__, __LINE__, __func__); fflush(stderr);
Ecore_Promise* promise = ecore_promise_thread_run(&promise_error_thread, NULL, 0);
ecore_promise_then(promise, &promise_error_callback, NULL);
fprintf(stderr, "%s:%d %s\n", __FILE__, __LINE__, __func__); fflush(stderr);
ecore_main_loop_begin();
fprintf(stderr, "%s:%d %s ---------- END test\n", __FILE__, __LINE__, __func__); fflush(stderr);
ecore_shutdown();
}
END_TEST
START_TEST(ecore_test_promise_all)
{
ecore_init();
fprintf(stderr, "%s:%d %s ---------- BEGIN test\n", __FILE__, __LINE__, __func__); fflush(stderr);
fprintf(stderr, "%s:%d %s\n", __FILE__, __LINE__, __func__); fflush(stderr);
Ecore_Promise* first[2] = { ecore_promise_thread_run(&promised_thread, NULL, 0), NULL };
Ecore_Promise* promise = ecore_promise_all(eina_carray_iterator_new((void**)&first[0]));
ecore_promise_then(promise, &promise_callback, NULL);
fprintf(stderr, "%s:%d %s\n", __FILE__, __LINE__, __func__); fflush(stderr);
ecore_main_loop_begin();
fprintf(stderr, "%s:%d %s ---------- END test\n", __FILE__, __LINE__, __func__); fflush(stderr);
ecore_shutdown();
}
END_TEST
void promise_callback2(void* data, void* value EINA_UNUSED)
{
fprintf(stderr, "%s:%d %s\n", __FILE__, __LINE__, __func__); fflush(stderr);
if(++(*(int*)data) == 2)
ecore_main_loop_quit();
}
START_TEST(ecore_test_promise_all_then_then)
{
ecore_init();
fprintf(stderr, "%s:%d %s ---------- BEGIN test\n", __FILE__, __LINE__, __func__); fflush(stderr);
int i = 0;
fprintf(stderr, "%s:%d %s\n", __FILE__, __LINE__, __func__); fflush(stderr);
Ecore_Promise* first[2] = { ecore_promise_thread_run(&promised_thread, NULL, 0), NULL };
ecore_promise_then(first[0], &promise_callback2, &i);
Ecore_Promise* promise = ecore_promise_all(eina_carray_iterator_new((void**)&first[0]));
ecore_promise_then(promise, &promise_callback2, &i);
fprintf(stderr, "%s:%d %s\n", __FILE__, __LINE__, __func__); fflush(stderr);
ecore_main_loop_begin();
fprintf(stderr, "%s:%d %s ---------- END test\n", __FILE__, __LINE__, __func__); fflush(stderr);
ecore_shutdown();
}
END_TEST
struct sync_data
{
Eina_Lock lock;
Eina_Condition cond;
Eina_Bool var;
};
void promised_exit_thread(struct sync_data* data EINA_UNUSED, Ecore_Promise* promise)
{
fprintf(stderr, "%s:%d %s\n", __FILE__, __LINE__, __func__); fflush(stderr);
ecore_promise_value_set(promise, NULL);
eina_lock_take(&data->lock);
data->var = EINA_TRUE;
eina_condition_broadcast(&data->cond);
eina_lock_release(&data->lock);
}
static void _ecore_test_promise_then_after_thread_finished_main_cb()
{
struct sync_data data;
data.var = EINA_FALSE;
eina_lock_new(&data.lock);
eina_condition_new(&data.cond, &data.lock);
Ecore_Promise* promise = ecore_promise_thread_run((Ecore_Promise_Thread_Cb)&promised_exit_thread, &data, 0);
eina_lock_take(&data.lock);
while(!data.var)
{
eina_condition_wait(&data.cond);
}
eina_lock_release(&data.lock);
ecore_promise_then(promise, &promise_callback, NULL);
}
START_TEST(ecore_test_promise_then_after_thread_finished)
{
ecore_init();
fprintf(stderr, "%s:%d %s ---------- BEGIN test\n", __FILE__, __LINE__, __func__); fflush(stderr);
ecore_job_add(&_ecore_test_promise_then_after_thread_finished_main_cb, NULL);
ecore_main_loop_begin();
fprintf(stderr, "%s:%d %s ---------- END test\n", __FILE__, __LINE__, __func__); fflush(stderr);
ecore_shutdown();
}
END_TEST
static void _ecore_test_promise_then_after_thread_finished_all_main_cb()
{
struct sync_data data;
data.var = EINA_FALSE;
eina_lock_new(&data.lock);
eina_condition_new(&data.cond, &data.lock);
Ecore_Promise* first[] = {ecore_promise_thread_run((Ecore_Promise_Thread_Cb)&promised_exit_thread, &data, 0), NULL};
Ecore_Promise* promise = ecore_promise_all(eina_carray_iterator_new((void**)&first[0]));
eina_lock_take(&data.lock);
while(!data.var)
{
eina_condition_wait(&data.cond);
}
eina_lock_release(&data.lock);
ecore_promise_then(promise, &promise_callback, NULL);
}
START_TEST(ecore_test_promise_then_after_thread_finished_all)
{
ecore_init();
fprintf(stderr, "%s:%d %s ---------- BEGIN test\n", __FILE__, __LINE__, __func__); fflush(stderr);
ecore_job_add(&_ecore_test_promise_then_after_thread_finished_all_main_cb, NULL);
ecore_main_loop_begin();
fprintf(stderr, "%s:%d %s ---------- END test\n", __FILE__, __LINE__, __func__); fflush(stderr);
ecore_shutdown();
}
END_TEST
void promised_block_thread(const void* data EINA_UNUSED, Ecore_Promise* promise)
{
struct timespec v = {.tv_sec = 1, .tv_nsec = 0}, rem;
if(nanosleep(&v, &rem) == -1 && errno == EINTR)
do
{
v = rem;
}
while(nanosleep(&v, &rem) == -1 && errno == EINTR);
int r = 10;
ecore_promise_value_set(promise, &r);
}
static void
_ecore_test_promise_blocking_get_quit_cb(void* data EINA_UNUSED)
{
ecore_main_loop_quit();
}
static void
_ecore_test_promise_blocking_get_main_cb(void* data EINA_UNUSED)
{
Ecore_Promise* promise = ecore_promise_thread_run(&promised_block_thread, NULL, sizeof(int));
const void* value = ecore_promise_value_get(promise);
ck_assert(*(int*)value == 10);
ecore_job_add(&_ecore_test_promise_blocking_get_quit_cb, NULL);
}
START_TEST(ecore_test_promise_blocking_get)
{
ecore_init();
fprintf(stderr, "%s:%d %s ---------- BEGIN test\n", __FILE__, __LINE__, __func__); fflush(stderr);
ecore_job_add(&_ecore_test_promise_blocking_get_main_cb, NULL);
ecore_main_loop_begin();
fprintf(stderr, "%s:%d %s ---------- END test\n", __FILE__, __LINE__, __func__); fflush(stderr);
ecore_shutdown();
}
END_TEST
static void
_ecore_test_promise_blocking_get_all_value_get_cb(Ecore_Promise* promise, Ecore_Thread* thread EINA_UNUSED)
{
Eina_Iterator** iterator = ecore_promise_value_get(promise);
int* v;
ck_assert(eina_iterator_next(*iterator, (void**)&v));
ck_assert(*v == 10);
ecore_main_loop_quit();
}
static void
_ecore_test_promise_blocking_get_all_main_cb(void* data EINA_UNUSED)
{
Ecore_Promise* first[2] = {ecore_promise_thread_run(&promised_block_thread, NULL, sizeof(int)), NULL};
Ecore_Promise* promise = ecore_promise_all(eina_carray_iterator_new((void**)&first[0]));
ecore_thread_run((Ecore_Thread_Cb)&_ecore_test_promise_blocking_get_all_value_get_cb, NULL, NULL, promise);
}
START_TEST(ecore_test_promise_blocking_get_all)
{
ecore_init();
fprintf(stderr, "%s:%d %s ---------- BEGIN test\n", __FILE__, __LINE__, __func__); fflush(stderr);
ecore_job_add(&_ecore_test_promise_blocking_get_all_main_cb, NULL);
ecore_main_loop_begin();
fprintf(stderr, "%s:%d %s ---------- END test\n", __FILE__, __LINE__, __func__); fflush(stderr);
ecore_shutdown();
}
END_TEST
static void
_ecore_test_promise_normal_lifetime_cb(void* data EINA_UNUSED, void* value EINA_UNUSED)
{
ecore_main_loop_quit();
}
START_TEST(ecore_test_promise_normal_lifetime)
{
ecore_init();
fprintf(stderr, "%s:%d %s ---------- BEGIN test\n", __FILE__, __LINE__, __func__); fflush(stderr);
Ecore_Promise* promise = ecore_promise_add(0);
ecore_promise_then(promise, &_ecore_test_promise_normal_lifetime_cb, NULL);
ecore_promise_value_set(promise, NULL);
ecore_main_loop_begin();
fprintf(stderr, "%s:%d %s ---------- END test\n", __FILE__, __LINE__, __func__); fflush(stderr);
ecore_shutdown();
}
END_TEST
START_TEST(ecore_test_promise_normal_lifetime_all)
{
ecore_init();
fprintf(stderr, "%s:%d %s ---------- BEGIN test\n", __FILE__, __LINE__, __func__); fflush(stderr);
Ecore_Promise* first[2] = {ecore_promise_add(0), NULL};
Ecore_Promise* promise = ecore_promise_all(eina_carray_iterator_new((void**)&first[0]));
ecore_promise_then(promise, &_ecore_test_promise_normal_lifetime_cb, NULL);
ecore_promise_value_set(promise, NULL);
ecore_main_loop_begin();
fprintf(stderr, "%s:%d %s ---------- END test\n", __FILE__, __LINE__, __func__); fflush(stderr);
ecore_shutdown();
}
END_TEST
static void
_ecore_test_promise_immediate_set_lifetime_cb(void* data EINA_UNUSED, void* value EINA_UNUSED)
{
ecore_main_loop_quit();
}
START_TEST(ecore_test_promise_immediate_set_lifetime)
{
ecore_init();
fprintf(stderr, "%s:%d %s ---------- BEGIN test\n", __FILE__, __LINE__, __func__); fflush(stderr);
Ecore_Promise* promise = ecore_promise_add(0);
ecore_promise_value_set(promise, NULL);
ecore_promise_then(promise, &_ecore_test_promise_immediate_set_lifetime_cb, NULL);
ecore_main_loop_begin();
fprintf(stderr, "%s:%d %s ---------- END test\n", __FILE__, __LINE__, __func__); fflush(stderr);
ecore_shutdown();
}
END_TEST
START_TEST(ecore_test_promise_immediate_set_lifetime_all)
{
ecore_init();
fprintf(stderr, "%s:%d %s ---------- BEGIN test\n", __FILE__, __LINE__, __func__); fflush(stderr);
Ecore_Promise* first[2] = {ecore_promise_add(0), NULL};
Ecore_Promise* promise = ecore_promise_all(eina_carray_iterator_new((void**)&first[0]));
ecore_promise_value_set(first[0], NULL);
ecore_promise_then(promise, &_ecore_test_promise_immediate_set_lifetime_cb, NULL);
ecore_main_loop_begin();
fprintf(stderr, "%s:%d %s ---------- END test\n", __FILE__, __LINE__, __func__); fflush(stderr);
ecore_shutdown();
}
END_TEST
void ecore_test_ecore_promise(TCase *tc EINA_UNUSED)
{
tcase_add_test(tc, ecore_test_promise);
tcase_add_test(tc, ecore_test_promise_error);
tcase_add_test(tc, ecore_test_promise_all);
tcase_add_test(tc, ecore_test_promise_all_then_then);
tcase_add_test(tc, ecore_test_promise_then_after_thread_finished);
tcase_add_test(tc, ecore_test_promise_then_after_thread_finished_all);
tcase_add_test(tc, ecore_test_promise_blocking_get);
tcase_add_test(tc, ecore_test_promise_blocking_get_all);
tcase_add_test(tc, ecore_test_promise_normal_lifetime);
tcase_add_test(tc, ecore_test_promise_normal_lifetime_all);
tcase_add_test(tc, ecore_test_promise_immediate_set_lifetime);
tcase_add_test(tc, ecore_test_promise_immediate_set_lifetime_all);
}