eina: Add support for eina_safepointer in promises

This commit is contained in:
Felipe Magno de Almeida 2016-06-10 22:32:07 -03:00
parent f6d20c839e
commit 949af55947
5 changed files with 166 additions and 110 deletions

View File

@ -20,10 +20,12 @@ typedef struct _Ecore_Thread_Data _Ecore_Thread_Data;
struct _Ecore_Thread_Promise_Owner
{
Eina_Promise_Owner owner_vtable;
Eina_Promise_Owner_VTable owner_vtable;
Eina_Promise_Owner* eina_owner;
Eina_Promise promise_vtable;
Eina_Promise_VTable promise_vtable;
Eina_Promise* eina_promise;
Eina_Promise_Owner* owner_pointer;
Eina_Promise* promise_pointer;
_Ecore_Thread_Data thread_callback_data;
int ref_count;
int then_count;
@ -40,9 +42,9 @@ static void _ecore_promise_ref_update(_Ecore_Thread_Promise_Owner* p)
}
if(!p->ref_count)
{
p->eina_promise->unref(p->eina_promise);
eina_promise_unref(p->eina_promise);
if (!p->then_count) // Whether we still own the initial eina_promise ref
p->eina_promise->unref(p->eina_promise);
eina_promise_unref(p->eina_promise);
p->eina_promise = NULL;
p->eina_owner = NULL;
p->thread_callback_data.thread = NULL;
@ -83,7 +85,7 @@ static void
_ecore_promise_thread_blocking(void* data, Ecore_Thread* thread EINA_UNUSED)
{
_Ecore_Thread_Promise_Owner* promise = data;
(promise->thread_callback_data.func_blocking)(promise->thread_callback_data.data, &promise->owner_vtable, thread);
(promise->thread_callback_data.func_blocking)(promise->thread_callback_data.data, promise->owner_pointer, thread);
}
static void _ecore_promise_thread_notify(void* data, Ecore_Thread* thread EINA_UNUSED, void* msg_data)
@ -95,7 +97,7 @@ static void _ecore_promise_thread_notify(void* data, Ecore_Thread* thread EINA_U
static void _ecore_promise_cancel_cb(void* data, Eina_Promise_Owner* promise EINA_UNUSED)
{
_Ecore_Thread_Promise_Owner* priv = data;
(priv->thread_callback_data.func_cancel)(priv->thread_callback_data.data, &priv->owner_vtable,
(priv->thread_callback_data.func_cancel)(priv->thread_callback_data.data, priv->owner_pointer,
priv->thread_callback_data.thread);
}
@ -110,23 +112,23 @@ static void _ecore_promise_thread_cancel(void* data, Ecore_Thread* thread EINA_U
static void _ecore_promise_owner_value_set(_Ecore_Thread_Promise_Owner* promise, void* data, Eina_Promise_Free_Cb free)
{
promise->eina_owner->value_set(promise->eina_owner, data, free);
eina_promise_owner_value_set(promise->eina_owner, data, free);
}
static void _ecore_promise_owner_error_set(_Ecore_Thread_Promise_Owner* promise, Eina_Error error)
{
promise->eina_owner->error_set(promise->eina_owner, error);
eina_promise_owner_error_set(promise->eina_owner, error);
}
static Eina_Bool _ecore_promise_owner_pending_is(_Ecore_Thread_Promise_Owner const* promise)
{
return promise->eina_owner->pending_is(promise->eina_owner);
return eina_promise_owner_pending_is(promise->eina_owner);
}
static Eina_Bool _ecore_promise_owner_cancelled_is(_Ecore_Thread_Promise_Owner const* promise)
{
return promise->eina_owner->cancelled_is(promise->eina_owner);
return eina_promise_owner_cancelled_is(promise->eina_owner);
}
static Eina_Promise* _ecore_thread_promise_owner_promise_get(_Ecore_Thread_Promise_Owner* promise)
{
return &promise->promise_vtable;
return promise->promise_pointer;
}
static void _ecore_thread_promise_owner_progress(_Ecore_Thread_Promise_Owner* promise, void* data)
{
@ -136,42 +138,42 @@ static void _ecore_thread_promise_owner_progress_notify(_Ecore_Thread_Promise_Ow
Eina_Promise_Progress_Notify_Cb progress_cb,
void* data, Eina_Promise_Free_Cb free_cb)
{
promise->eina_owner->progress_notify(promise->eina_owner, progress_cb, data, free_cb);
eina_promise_owner_progress_notify(promise->eina_owner, progress_cb, data, free_cb);
}
static void _ecore_promise_then(Eina_Promise* promise, Eina_Promise_Cb callback,
Eina_Promise_Error_Cb error_cb, void* data)
{
_Ecore_Thread_Promise_Owner* v = ECORE_PROMISE_GET_OWNER(promise);
v->eina_promise->then(v->eina_promise, callback, error_cb, data);
eina_promise_then(v->eina_promise, callback, error_cb, data);
v->ref_count++;
v->then_count++;
}
static void* _ecore_promise_value_get(Eina_Promise const* promise)
{
_Ecore_Thread_Promise_Owner* v = ECORE_PROMISE_GET_OWNER(promise);
return v->eina_promise->value_get(v->eina_promise);
return eina_promise_value_get(v->eina_promise);
}
static Eina_Error _ecore_promise_error_get(Eina_Promise const* promise)
{
_Ecore_Thread_Promise_Owner* v = ECORE_PROMISE_GET_OWNER(promise);
return v->eina_promise->error_get(v->eina_promise);
return eina_promise_error_get(v->eina_promise);
}
static Eina_Bool _ecore_promise_pending_is(Eina_Promise const* promise)
{
_Ecore_Thread_Promise_Owner* v = ECORE_PROMISE_GET_OWNER(promise);
return v->eina_promise->pending_is(v->eina_promise);
return eina_promise_pending_is(v->eina_promise);
}
static void _ecore_promise_progress_cb_add(Eina_Promise const* promise, Eina_Promise_Progress_Cb callback, void* data,
Eina_Promise_Free_Cb free_cb)
{
_Ecore_Thread_Promise_Owner* v = ECORE_PROMISE_GET_OWNER(promise);
v->eina_promise->progress_cb_add(v->eina_promise, callback, data, free_cb);
eina_promise_progress_cb_add(v->eina_promise, callback, data, free_cb);
}
static void _ecore_promise_cancel(Eina_Promise const* promise)
{
_Ecore_Thread_Promise_Owner* v = ECORE_PROMISE_GET_OWNER(promise);
v->eina_promise->cancel(v->eina_promise);
eina_promise_cancel(v->eina_promise);
}
static void _ecore_promise_ref(Eina_Promise const* promise)
{
@ -204,6 +206,7 @@ Ecore_Thread* ecore_thread_promise_run(Ecore_Thread_Promise_Cb func_blocking,
priv->owner_vtable.progress = EINA_FUNC_PROMISE_OWNER_PROGRESS(&_ecore_thread_promise_owner_progress);
priv->owner_vtable.progress_notify = EINA_FUNC_PROMISE_OWNER_PROGRESS_NOTIFY(&_ecore_thread_promise_owner_progress_notify);
EINA_MAGIC_SET(&priv->owner_vtable, EINA_MAGIC_PROMISE_OWNER);
priv->owner_pointer = eina_promise_owner_override(&priv->owner_vtable);
priv->promise_vtable.then = EINA_FUNC_PROMISE_THEN(&_ecore_promise_then);
priv->promise_vtable.value_get = EINA_FUNC_PROMISE_VALUE_GET(&_ecore_promise_value_get);
@ -214,14 +217,15 @@ Ecore_Thread* ecore_thread_promise_run(Ecore_Thread_Promise_Cb func_blocking,
priv->promise_vtable.ref = EINA_FUNC_PROMISE_REF(&_ecore_promise_ref);
priv->promise_vtable.unref = EINA_FUNC_PROMISE_UNREF(&_ecore_promise_unref);
EINA_MAGIC_SET(&priv->promise_vtable, EINA_MAGIC_PROMISE);
priv->promise_pointer = eina_promise_override(&priv->promise_vtable);
priv->thread_callback_data.data = data;
priv->thread_callback_data.func_blocking = func_blocking;
priv->thread_callback_data.func_cancel = func_cancel;
eina_promise_owner_default_manual_then_set(priv->eina_owner, EINA_TRUE);
priv->eina_promise = priv->eina_owner->promise_get(priv->eina_owner);
priv->eina_promise->ref(priv->eina_promise);
priv->eina_promise = eina_promise_owner_promise_get(priv->eina_owner);
eina_promise_ref(priv->eina_promise);
priv->ref_count = 0;
priv->then_count = 0;
@ -232,6 +236,6 @@ Ecore_Thread* ecore_thread_promise_run(Ecore_Thread_Promise_Cb func_blocking,
&_ecore_promise_thread_end, &_ecore_promise_thread_cancel, priv,
EINA_FALSE);
if(promise)
*promise = &priv->promise_vtable;
*promise = priv->promise_pointer;
return priv->thread_callback_data.thread;
}

View File

@ -154,8 +154,8 @@ EAPI Eina_Inlist *_eina_tracking = NULL;
S(cpu);
S(thread_queue);
S(rbtree);
S(promise);
S(safepointer);
S(promise);
/* no model for now
S(model);
*/
@ -203,8 +203,8 @@ static const struct eina_desc_setup _eina_desc_setup[] = {
S(cpu),
S(thread_queue),
S(rbtree),
S(promise),
S(safepointer)
S(safepointer),
S(promise)
/* no model for now
S(model)
*/

View File

@ -27,6 +27,9 @@ static int _eina_promise_log_dom = -1;
#define EINA_MAGIC_CHECK_PROMISE_OWNER(promise) \
do {if(!EINA_MAGIC_CHECK(promise, EINA_MAGIC_PROMISE_OWNER)) \
{EINA_MAGIC_FAIL(promise, EINA_MAGIC_PROMISE_OWNER);} } while(0)
#define EINA_PROMISE_SAFE_GET_OR_RETURN(x, y, v) \
x = eina_safepointer_get((Eina_Safepointer const*)y); \
if(!x) return v
typedef struct _Eina_Promise_Then_Cb _Eina_Promise_Then_Cb;
typedef struct _Eina_Promise_Progress_Cb _Eina_Promise_Progress_Cb;
@ -75,7 +78,7 @@ struct _Eina_Promise_Owner_Progress_Notify_Data
struct _Eina_Promise_Default
{
Eina_Promise vtable;
Eina_Promise_VTable vtable;
Eina_Error error;
size_t value_size;
@ -84,6 +87,7 @@ struct _Eina_Promise_Default
Eina_Inlist *cancel_callbacks;
Eina_Inlist *progress_notify_callbacks;
Eina_Promise_Free_Cb value_free_cb;
Eina_Promise* promise_pointer;
int ref;
@ -97,9 +101,9 @@ struct _Eina_Promise_Default
struct _Eina_Promise_Default_Owner
{
Eina_Promise_Owner owner_vtable;
Eina_Promise_Owner_VTable owner_vtable;
_Eina_Promise_Default promise;
Eina_Promise_Owner* owner_pointer;
void* pointer_value;
};
@ -290,7 +294,7 @@ _eina_promise_then(_Eina_Promise_Default* p, Eina_Promise_Cb callback,
EINA_INLIST_FOREACH(promise->promise.progress_notify_callbacks, notify_data)
{
(*notify_data->callback)(notify_data->data, &promise->owner_vtable);
(*notify_data->callback)(notify_data->data, promise->owner_pointer);
}
_eina_promise_free_callback_list(&promise->promise.progress_notify_callbacks, &free);
@ -372,7 +376,7 @@ _eina_promise_progress_cb_add(_Eina_Promise_Default* promise, Eina_Promise_Progr
promise->progress_callbacks = eina_inlist_append(promise->progress_callbacks, EINA_INLIST_GET(cb));
EINA_INLIST_FOREACH(owner->promise.progress_notify_callbacks, notify_data)
{
(*notify_data->callback)(notify_data->data, &owner->owner_vtable);
(*notify_data->callback)(notify_data->data, owner->owner_pointer);
}
_eina_promise_free_callback_list(&owner->promise.progress_notify_callbacks,
&_eina_promise_free_progress_notify_callback_node);
@ -417,19 +421,17 @@ _eina_promise_ref_get(_Eina_Promise_Default* p)
static Eina_Promise *
_eina_promise_owner_promise_get(_Eina_Promise_Default_Owner* p)
{
return &p->promise.vtable;
return p->promise.promise_pointer;
}
void
EAPI void
eina_promise_owner_default_cancel_cb_add(Eina_Promise_Owner* p,
Eina_Promise_Default_Cancel_Cb callback, void* data,
Eina_Promise_Free_Cb free_cb)
{
_Eina_Promise_Default_Owner *promise;
_Eina_Promise_Default_Owner* EINA_PROMISE_SAFE_GET_OR_RETURN(promise, p, );
_Eina_Promise_Cancel_Cb *cb;
promise = (_Eina_Promise_Default_Owner *)p;
cb = malloc(sizeof(struct _Eina_Promise_Cancel_Cb));
cb->callback = callback;
@ -486,6 +488,7 @@ static void eina_promise_add_internal(_Eina_Promise_Default_Owner* p)
p->promise.is_first_then = EINA_TRUE;
p->promise.ref = 1;
p->promise.promise_pointer = eina_promise_override(&p->promise.vtable);
p->owner_vtable.version = EINA_PROMISE_VERSION;
p->owner_vtable.value_set = EINA_FUNC_PROMISE_OWNER_VALUE_SET(_eina_promise_owner_value_set);
@ -496,6 +499,7 @@ static void eina_promise_add_internal(_Eina_Promise_Default_Owner* p)
p->owner_vtable.progress = EINA_FUNC_PROMISE_OWNER_PROGRESS(_eina_promise_owner_progress);
p->owner_vtable.progress_notify = EINA_FUNC_PROMISE_OWNER_PROGRESS_NOTIFY(_eina_promise_owner_progress_notify);
EINA_MAGIC_SET(&p->owner_vtable, EINA_MAGIC_PROMISE_OWNER);
p->owner_pointer = eina_promise_owner_override(&p->owner_vtable);
}
EAPI Eina_Promise_Owner *
@ -504,25 +508,28 @@ eina_promise_add()
_Eina_Promise_Default_Owner* p;
p = calloc(sizeof(_Eina_Promise_Default_Owner), 1);
eina_promise_add_internal(p);
return &p->owner_vtable;
return p->owner_pointer;
}
void
EAPI void
eina_promise_owner_default_manual_then_set(Eina_Promise_Owner* owner, Eina_Bool is_manual)
{
_Eina_Promise_Default_Owner* p = (_Eina_Promise_Default_Owner*)owner;
_Eina_Promise_Default_Owner* EINA_PROMISE_SAFE_GET_OR_RETURN(p, owner, );
EINA_MAGIC_CHECK_PROMISE_OWNER(&p->owner_vtable);
p->promise.is_manual_then = is_manual;
}
void
eina_promise_owner_default_call_then(Eina_Promise_Owner* promise)
EAPI void
eina_promise_owner_default_call_then(Eina_Promise_Owner* owner)
{
_Eina_Promise_Default_Owner* owner = (_Eina_Promise_Default_Owner*)promise;
_Eina_Promise_Default_Owner* EINA_PROMISE_SAFE_GET_OR_RETURN(p, owner, );
EINA_MAGIC_CHECK_PROMISE_OWNER(&p->owner_vtable);
_eina_promise_then_calls(owner);
_eina_promise_then_calls(p);
}
// eina_promise_all implementation
static void
_eina_promise_all_compose_then_cb(void *data, void* value EINA_UNUSED)
{
@ -538,7 +545,7 @@ _eina_promise_all_compose_then_cb(void *data, void* value EINA_UNUSED)
_eina_promise_finish(promise);
}
}
eina_promise_unref(&promise->promise.vtable);
eina_promise_unref(promise->promise.promise_pointer);
}
static void
@ -553,7 +560,7 @@ _eina_promise_all_compose_error_then_cb(void *data, Eina_Error error)
promise->promise.error = error;
_eina_promise_finish(promise);
}
eina_promise_unref(&promise->promise.vtable);
eina_promise_unref(promise->promise.promise_pointer);
}
static void
@ -572,6 +579,7 @@ _eina_promise_all_free(_Eina_Promise_Iterator* value)
Eina_Promise *
eina_promise_all(Eina_Iterator* it)
{
Eina_Promise_Owner *safe_promise;
_Eina_Promise_Default_Owner *promise;
Eina_Promise* current;
Eina_Array* promises;
@ -589,14 +597,12 @@ eina_promise_all(Eina_Iterator* it)
eina_iterator_free(it);
promise = (_Eina_Promise_Default_Owner*)eina_promise_add();
internal_it = malloc(sizeof(_Eina_Promise_Iterator) +
sizeof(_Eina_Promise_Default_Owner*) * eina_array_count_get(promises));
promise = eina_safepointer_get((Eina_Safepointer*)(safe_promise = eina_promise_add()));
internal_it = promise->pointer_value = malloc(sizeof(_Eina_Promise_Iterator) +
sizeof(_Eina_Promise_Default_Owner*) * eina_array_count_get(promises));
promise->promise.value_free_cb = (Eina_Promise_Free_Cb)&_eina_promise_all_free;
promise->pointer_value = (void*)internal_it;
_eina_promise_iterator_setup(internal_it, promises);
cur_promise = internal_it->data.promises;
@ -605,13 +611,13 @@ eina_promise_all(Eina_Iterator* it)
{
eina_promise_ref(*cur_promise); // We need to keep the value alive until this promise is freed
// We need to keep the all promise alive while there are callbacks registered to it
eina_promise_ref(&promise->promise.vtable);
eina_promise_ref(promise->promise.promise_pointer);
eina_promise_then(*cur_promise, &_eina_promise_all_compose_then_cb,
&_eina_promise_all_compose_error_then_cb, promise);
}
eina_array_free(promises);
return &promise->promise.vtable;
return promise->promise.promise_pointer;
}
static Eina_Bool
@ -686,19 +692,6 @@ _eina_promise_progress_notify_finish(void* data)
eina_promise_unref(eina_promise_owner_promise_get(owner));
}
EAPI Eina_Promise*
eina_promise_progress_notification(Eina_Promise_Owner* promise)
{
Eina_Promise_Owner* owner;
owner = eina_promise_add();
eina_promise_owner_progress_notify(promise, &_eina_promise_progress_notify_fulfilled, owner,
&_eina_promise_progress_notify_finish);
return eina_promise_owner_promise_get(owner);
}
// Race implementation
static void _eina_promise_race_unref(_Eina_Promise_Race* p)
{
@ -721,8 +714,8 @@ _eina_promise_race_compose_then_cb(void *data, void* value EINA_UNUSED)
_Eina_Promise_Race* race_promise = info->self;
if (!race_promise->promise_default.promise.has_finished)
eina_promise_owner_value_set(&race_promise->promise_default.owner_vtable, value, NULL);
eina_promise_unref(&race_promise->promise_default.promise.vtable);
eina_promise_owner_value_set(race_promise->promise_default.owner_pointer, value, NULL);
eina_promise_unref(race_promise->promise_default.promise.promise_pointer);
}
static void
@ -732,8 +725,8 @@ _eina_promise_race_compose_error_then_cb(void *data, Eina_Error error)
_Eina_Promise_Race* race_promise = info->self;
if (!race_promise->promise_default.promise.has_finished)
eina_promise_owner_error_set(&race_promise->promise_default.owner_vtable, error);
eina_promise_unref(&race_promise->promise_default.promise.vtable);
eina_promise_owner_error_set(race_promise->promise_default.owner_pointer, error);
eina_promise_unref(race_promise->promise_default.promise.promise_pointer);
}
Eina_Promise *
@ -771,21 +764,52 @@ eina_promise_race(Eina_Iterator* it)
cur_promise->self = promise;
eina_promise_ref(cur_promise->promise); // We need to keep the value alive until this promise is freed
// We need to keep the all promise alive while there are callbacks registered to it
eina_promise_ref(&promise->promise_default.promise.vtable);
eina_promise_ref(promise->promise_default.promise.promise_pointer);
eina_promise_then(cur_promise->promise, &_eina_promise_race_compose_then_cb,
&_eina_promise_race_compose_error_then_cb, cur_promise);
}
eina_array_free(promises);
return &promise->promise_default.promise.vtable;
return promise->promise_default.promise.promise_pointer;
}
// API functions
EAPI Eina_Promise_Owner* eina_promise_owner_override(Eina_Promise_Owner_VTable* owner)
{
_EINA_PROMISE_NULL_CHECK(owner, NULL);
EINA_MAGIC_CHECK_PROMISE_OWNER(owner);
Eina_Safepointer const* p = eina_safepointer_register(owner);
return (Eina_Promise_Owner*)p;
}
EAPI Eina_Promise* eina_promise_override(Eina_Promise_VTable* promise)
{
_EINA_PROMISE_NULL_CHECK(promise, NULL);
EINA_MAGIC_CHECK_PROMISE(promise);
Eina_Safepointer const* p = eina_safepointer_register(promise);
return (Eina_Promise*)p;
}
EAPI Eina_Promise*
eina_promise_progress_notification(Eina_Promise_Owner* safe_promise)
{
Eina_Promise_Owner_VTable* EINA_PROMISE_SAFE_GET_OR_RETURN(promise, safe_promise, NULL);
Eina_Promise_Owner* owner;
owner = eina_promise_add();
eina_promise_owner_progress_notify(safe_promise, &_eina_promise_progress_notify_fulfilled, owner,
&_eina_promise_progress_notify_finish);
return eina_promise_owner_promise_get(owner);
}
EAPI void
eina_promise_then(Eina_Promise* promise, Eina_Promise_Cb callback,
eina_promise_then(Eina_Promise* safe_promise, Eina_Promise_Cb callback,
Eina_Promise_Error_Cb error_cb, void* data)
{
if(!promise)
Eina_Promise_VTable* promise = eina_safepointer_get((void*)safe_promise);
if(!safe_promise || !promise)
{
if(!error_cb)
{
@ -801,122 +825,137 @@ eina_promise_then(Eina_Promise* promise, Eina_Promise_Cb callback,
}
EAPI void
eina_promise_owner_value_set(Eina_Promise_Owner* promise, const void* value, Eina_Promise_Free_Cb free)
eina_promise_owner_value_set(Eina_Promise_Owner* safe_promise, const void* value, Eina_Promise_Free_Cb free)
{
Eina_Promise_Owner_VTable* EINA_PROMISE_SAFE_GET_OR_RETURN(promise, safe_promise, );
_EINA_PROMISE_NULL_CHECK(promise, );
EINA_MAGIC_CHECK_PROMISE_OWNER(promise);
promise->value_set(promise, value, free);
}
EAPI void
eina_promise_owner_error_set(Eina_Promise_Owner* promise, Eina_Error error)
eina_promise_owner_error_set(Eina_Promise_Owner* safe_promise, Eina_Error error)
{
Eina_Promise_Owner_VTable* EINA_PROMISE_SAFE_GET_OR_RETURN(promise, safe_promise, );
_EINA_PROMISE_NULL_CHECK(promise, );
EINA_MAGIC_CHECK_PROMISE_OWNER(promise);
promise->error_set(promise, error);
}
EAPI void *
eina_promise_value_get(Eina_Promise const* promise)
eina_promise_value_get(Eina_Promise const* safe_promise)
{
Eina_Promise_VTable* EINA_PROMISE_SAFE_GET_OR_RETURN(promise, safe_promise, NULL);
_EINA_PROMISE_NULL_CHECK(promise, NULL);
EINA_MAGIC_CHECK_PROMISE(promise);
return promise->value_get(promise);
}
EAPI Eina_Error
eina_promise_error_get(Eina_Promise const* promise)
eina_promise_error_get(Eina_Promise const* safe_promise)
{
Eina_Promise_VTable* EINA_PROMISE_SAFE_GET_OR_RETURN(promise, safe_promise, 0);
_EINA_PROMISE_NULL_CHECK(promise, EINA_ERROR_PROMISE_NULL);
EINA_MAGIC_CHECK_PROMISE(promise);
return promise->error_get(promise);
}
EAPI Eina_Bool
eina_promise_pending_is(Eina_Promise const* promise)
eina_promise_pending_is(Eina_Promise const* safe_promise)
{
Eina_Promise_VTable* EINA_PROMISE_SAFE_GET_OR_RETURN(promise, safe_promise, EINA_FALSE);
_EINA_PROMISE_NULL_CHECK(promise, EINA_FALSE);
EINA_MAGIC_CHECK_PROMISE(promise);
return promise->pending_is(promise);
}
EAPI void
eina_promise_progress_cb_add(Eina_Promise* promise, Eina_Promise_Progress_Cb callback, void* data,
eina_promise_progress_cb_add(Eina_Promise* safe_promise, Eina_Promise_Progress_Cb callback, void* data,
Eina_Promise_Free_Cb free_cb)
{
Eina_Promise_VTable* EINA_PROMISE_SAFE_GET_OR_RETURN(promise, safe_promise, );
_EINA_PROMISE_NULL_CHECK(promise, );
EINA_MAGIC_CHECK_PROMISE(promise);
promise->progress_cb_add(promise, callback, data, free_cb);
}
EAPI void
eina_promise_cancel(Eina_Promise* promise)
eina_promise_cancel(Eina_Promise* safe_promise)
{
Eina_Promise_VTable* EINA_PROMISE_SAFE_GET_OR_RETURN(promise, safe_promise, );
_EINA_PROMISE_NULL_CHECK(promise, );
EINA_MAGIC_CHECK_PROMISE(promise);
promise->cancel(promise);
}
EAPI void
eina_promise_ref(Eina_Promise* promise)
eina_promise_ref(Eina_Promise* safe_promise)
{
Eina_Promise_VTable* EINA_PROMISE_SAFE_GET_OR_RETURN(promise, safe_promise, );
_EINA_PROMISE_NULL_CHECK(promise, );
EINA_MAGIC_CHECK_PROMISE(promise);
promise->ref(promise);
}
EAPI void
eina_promise_unref(Eina_Promise* promise)
eina_promise_unref(Eina_Promise* safe_promise)
{
Eina_Promise_VTable* EINA_PROMISE_SAFE_GET_OR_RETURN(promise, safe_promise, );
_EINA_PROMISE_NULL_CHECK(promise, );
EINA_MAGIC_CHECK_PROMISE(promise);
promise->unref(promise);
}
EAPI int
eina_promise_ref_get(Eina_Promise* promise)
eina_promise_ref_get(Eina_Promise* safe_promise)
{
Eina_Promise_VTable* EINA_PROMISE_SAFE_GET_OR_RETURN(promise, safe_promise, 0);
_EINA_PROMISE_NULL_CHECK(promise, 0);
EINA_MAGIC_CHECK_PROMISE(promise);
return promise->ref_get(promise);
}
EAPI Eina_Promise *
eina_promise_owner_promise_get(Eina_Promise_Owner* promise)
eina_promise_owner_promise_get(Eina_Promise_Owner* safe_promise)
{
Eina_Promise_Owner_VTable* EINA_PROMISE_SAFE_GET_OR_RETURN(promise, safe_promise, NULL);
_EINA_PROMISE_NULL_CHECK(promise, NULL);
EINA_MAGIC_CHECK_PROMISE_OWNER(promise);
return promise->promise_get(promise);
}
EAPI Eina_Bool
eina_promise_owner_pending_is(Eina_Promise_Owner const* promise)
eina_promise_owner_pending_is(Eina_Promise_Owner const* safe_promise)
{
Eina_Promise_Owner_VTable* EINA_PROMISE_SAFE_GET_OR_RETURN(promise, safe_promise, EINA_FALSE);
_EINA_PROMISE_NULL_CHECK(promise, EINA_FALSE);
EINA_MAGIC_CHECK_PROMISE_OWNER(promise);
return promise->pending_is(promise);
}
EAPI Eina_Bool
eina_promise_owner_cancelled_is(Eina_Promise_Owner const* promise)
eina_promise_owner_cancelled_is(Eina_Promise_Owner const* safe_promise)
{
Eina_Promise_Owner_VTable* EINA_PROMISE_SAFE_GET_OR_RETURN(promise, safe_promise, EINA_FALSE);
_EINA_PROMISE_NULL_CHECK(promise, EINA_FALSE);
EINA_MAGIC_CHECK_PROMISE_OWNER(promise);
return promise->cancelled_is(promise);
}
EAPI void
eina_promise_owner_progress(Eina_Promise_Owner const* promise, void* progress)
eina_promise_owner_progress(Eina_Promise_Owner const* safe_promise, void* progress)
{
Eina_Promise_Owner_VTable* EINA_PROMISE_SAFE_GET_OR_RETURN(promise, safe_promise, );
_EINA_PROMISE_NULL_CHECK(promise, );
EINA_MAGIC_CHECK_PROMISE_OWNER(promise);
promise->progress(promise, progress);
}
EAPI void
eina_promise_owner_progress_notify(Eina_Promise_Owner* promise, Eina_Promise_Progress_Notify_Cb progress_cb,
eina_promise_owner_progress_notify(Eina_Promise_Owner* safe_promise, Eina_Promise_Progress_Notify_Cb progress_cb,
void* data, Eina_Promise_Free_Cb free_cb)
{
Eina_Promise_Owner_VTable* EINA_PROMISE_SAFE_GET_OR_RETURN(promise, safe_promise, );
_EINA_PROMISE_NULL_CHECK(promise, );
EINA_MAGIC_CHECK_PROMISE_OWNER(promise);
promise->progress_notify(promise, progress_cb, data, free_cb);

View File

@ -3,19 +3,26 @@
#ifdef EFL_BETA_API_SUPPORT
struct _Eina_Promise;
struct _Eina_Promise_Default;
/*
* @def Eina_Promise
*/
typedef struct _Eina_Promise Eina_Promise;
/*
* @def Eina_Promise_VTable
*/
typedef struct _Eina_Promise_VTable Eina_Promise_VTable;
/*
* @def Eina_Promise
*/
typedef struct _Eina_Promise_Owner Eina_Promise_Owner;
/*
* @def Eina_Promise
*/
typedef struct _Eina_Promise_Owner_VTable Eina_Promise_Owner_VTable;
/*
* @brief Callback type for freeing Promise value and void* pointer data for callbacks
*/
@ -44,7 +51,7 @@ typedef void(*Eina_Promise_Progress_Cb)(void* data, void* value);
/*
* @brief Function callback type for then function override
*/
typedef void(*Eina_Promise_Then_Cb)(Eina_Promise* promise, Eina_Promise_Cb callback,
typedef void(*Eina_Promise_Then_Cb)(Eina_Promise_VTable* promise, Eina_Promise_Cb callback,
Eina_Promise_Error_Cb error_cb, void* data);
#define EINA_FUNC_PROMISE_THEN(Function) ((Eina_Promise_Then_Cb)Function)
@ -52,28 +59,28 @@ typedef void(*Eina_Promise_Then_Cb)(Eina_Promise* promise, Eina_Promise_Cb callb
/*
* @brief Function callback type for promise's value_get function override
*/
typedef void*(*Eina_Promise_Value_Get_Cb)(Eina_Promise const* promise);
typedef void*(*Eina_Promise_Value_Get_Cb)(Eina_Promise_VTable const* promise);
#define EINA_FUNC_PROMISE_VALUE_GET(Function) ((Eina_Promise_Value_Get_Cb)Function)
/*
* @brief Function callback type for promise's error_get function override
*/
typedef Eina_Error(*Eina_Promise_Error_Get_Cb)(Eina_Promise const* promise);
typedef Eina_Error(*Eina_Promise_Error_Get_Cb)(Eina_Promise_VTable const* promise);
#define EINA_FUNC_PROMISE_ERROR_GET(Function) ((Eina_Promise_Error_Get_Cb)Function)
/*
* @brief Function callback type for promise's pending function override
*/
typedef Eina_Bool(*Eina_Promise_Pending_Is_Cb)(Eina_Promise const* promise);
typedef Eina_Bool(*Eina_Promise_Pending_Is_Cb)(Eina_Promise_VTable const* promise);
#define EINA_FUNC_PROMISE_PENDING_IS(Function) ((Eina_Promise_Pending_Is_Cb)Function)
/*
* @brief Function callback type for promise's progress add function override
*/
typedef void(*Eina_Promise_Progress_Cb_Add_Cb)(Eina_Promise* promise, Eina_Promise_Progress_Cb callback, void* data
typedef void(*Eina_Promise_Progress_Cb_Add_Cb)(Eina_Promise_VTable* promise, Eina_Promise_Progress_Cb callback, void* data
, Eina_Promise_Free_Cb free_cb);
#define EINA_FUNC_PROMISE_PROGRESS_CB_ADD(Function) ((Eina_Promise_Progress_Cb_Add_Cb)Function)
@ -81,91 +88,91 @@ typedef void(*Eina_Promise_Progress_Cb_Add_Cb)(Eina_Promise* promise, Eina_Promi
/*
* @brief Function callback type for promise's cancel function override
*/
typedef void(*Eina_Promise_Cancel_Cb)(Eina_Promise* promise);
typedef void(*Eina_Promise_Cancel_Cb)(Eina_Promise_VTable* promise);
#define EINA_FUNC_PROMISE_CANCEL(Function) ((Eina_Promise_Cancel_Cb)Function)
/*
* @brief Function callback type for promise's ref function override
*/
typedef void(*Eina_Promise_Ref_Cb)(Eina_Promise* promise);
typedef void(*Eina_Promise_Ref_Cb)(Eina_Promise_VTable* promise);
#define EINA_FUNC_PROMISE_REF(Function) ((Eina_Promise_Ref_Cb)Function)
/*
* @brief Function callback type for promise's unref function override
*/
typedef void(*Eina_Promise_Unref_Cb)(Eina_Promise* promise);
typedef void(*Eina_Promise_Unref_Cb)(Eina_Promise_VTable* promise);
#define EINA_FUNC_PROMISE_UNREF(Function) ((Eina_Promise_Unref_Cb)Function)
/*
* @brief Function callback type for promise's ref_get function override
*/
typedef int(*Eina_Promise_Ref_Get_Cb)(Eina_Promise* promise);
typedef int(*Eina_Promise_Ref_Get_Cb)(Eina_Promise_VTable* promise);
#define EINA_FUNC_PROMISE_REF_GET(Function) ((Eina_Promise_Ref_Get_Cb)Function)
/*
* @brief Function callback type for promise's buffer_get function override
*/
typedef void*(*Eina_Promise_Buffer_Get_Cb)(Eina_Promise* promise);
typedef void*(*Eina_Promise_Buffer_Get_Cb)(Eina_Promise_VTable* promise);
#define EINA_FUNC_PROMISE_BUFFER_GET(Function) ((Eina_Promise_Buffer_Get_Cb)Function)
/*
* @brief Function callback type for promise owner's buffer_get function override
*/
typedef void*(*Eina_Promise_Owner_Buffer_Get_Cb)(Eina_Promise_Owner* promise);
typedef void*(*Eina_Promise_Owner_Buffer_Get_Cb)(Eina_Promise_Owner_VTable* promise);
#define EINA_FUNC_PROMISE_OWNER_BUFFER_GET(Function) ((Eina_Promise_Owner_Buffer_Get_Cb)Function)
/*
* @brief Function callback type for promise owner's promise_get function override
*/
typedef void*(*Eina_Promise_Owner_Promise_Get_Cb)(Eina_Promise_Owner const* promise);
typedef void*(*Eina_Promise_Owner_Promise_Get_Cb)(Eina_Promise_Owner_VTable const* promise);
#define EINA_FUNC_PROMISE_OWNER_PROMISE_GET(Function) ((Eina_Promise_Owner_Promise_Get_Cb)Function)
/*
* @brief Function callback type for promise owner's value_set function override
*/
typedef void(*Eina_Promise_Owner_Value_Set_Cb)(Eina_Promise_Owner* promise, const void* data, Eina_Promise_Free_Cb free_fun);
typedef void(*Eina_Promise_Owner_Value_Set_Cb)(Eina_Promise_Owner_VTable* promise, const void* data, Eina_Promise_Free_Cb free_fun);
#define EINA_FUNC_PROMISE_OWNER_VALUE_SET(Function) ((Eina_Promise_Owner_Value_Set_Cb)Function)
/*
* @brief Function callback type for promise owner's error_set function override
*/
typedef void(*Eina_Promise_Owner_Error_Set_Cb)(Eina_Promise_Owner* promise, Eina_Error error);
typedef void(*Eina_Promise_Owner_Error_Set_Cb)(Eina_Promise_Owner_VTable* promise, Eina_Error error);
#define EINA_FUNC_PROMISE_OWNER_ERROR_SET(Function) ((Eina_Promise_Owner_Error_Set_Cb)Function)
/*
* @brief Function callback type for promise owner's pending function override
*/
typedef Eina_Bool(*Eina_Promise_Owner_Pending_Is_Cb)(Eina_Promise_Owner const* promise);
typedef Eina_Bool(*Eina_Promise_Owner_Pending_Is_Cb)(Eina_Promise_Owner_VTable const* promise);
#define EINA_FUNC_PROMISE_OWNER_PENDING_IS(Function) ((Eina_Promise_Owner_Pending_Is_Cb)Function)
/*
* @brief Function callback type for promise owner's cancelled function override
*/
typedef Eina_Bool(*Eina_Promise_Owner_Cancelled_Is_Cb)(Eina_Promise_Owner const* promise);
typedef Eina_Bool(*Eina_Promise_Owner_Cancelled_Is_Cb)(Eina_Promise_Owner_VTable const* promise);
#define EINA_FUNC_PROMISE_OWNER_CANCELLED_IS(Function) ((Eina_Promise_Owner_Cancelled_Is_Cb)Function)
/*
* @brief Function callback type for promise owner's progress function override
*/
typedef Eina_Bool(*Eina_Promise_Owner_Progress_Cb)(Eina_Promise_Owner const* promise, void* progress);
typedef Eina_Bool(*Eina_Promise_Owner_Progress_Cb)(Eina_Promise_Owner_VTable const* promise, void* progress);
#define EINA_FUNC_PROMISE_OWNER_PROGRESS(Function) ((Eina_Promise_Owner_Progress_Cb)Function)
/*
* @brief Function callback type for promise owner's progress notify registration function override
*/
typedef Eina_Bool(*Eina_Promise_Owner_Progress_Notify_Cb)(Eina_Promise_Owner* promise,
typedef Eina_Bool(*Eina_Promise_Owner_Progress_Notify_Cb)(Eina_Promise_Owner_VTable* promise,
Eina_Promise_Progress_Notify_Cb progress_cb, void* data, Eina_Promise_Free_Cb free_cb);
#define EINA_FUNC_PROMISE_OWNER_PROGRESS_NOTIFY(Function) ((Eina_Promise_Owner_Progress_Notify_Cb)Function)
@ -173,7 +180,7 @@ typedef Eina_Bool(*Eina_Promise_Owner_Progress_Notify_Cb)(Eina_Promise_Owner* pr
#define EINA_PROMISE_VERSION 1
struct _Eina_Promise
struct _Eina_Promise_VTable
{
int version;
Eina_Promise_Then_Cb then;
@ -189,7 +196,7 @@ struct _Eina_Promise
EINA_MAGIC;
};
struct _Eina_Promise_Owner
struct _Eina_Promise_Owner_VTable
{
int version;
Eina_Promise_Owner_Value_Set_Cb value_set;
@ -203,6 +210,10 @@ struct _Eina_Promise_Owner
EINA_MAGIC;
};
EAPI Eina_Promise_Owner* eina_promise_owner_override(Eina_Promise_Owner_VTable* owner);
EAPI Eina_Promise* eina_promise_override(Eina_Promise_VTable* owner);
/*
* @brief Appends a callback to be called when the Eina_Promise is
* finished.

View File

@ -269,6 +269,7 @@ START_TEST(eina_test_pointer_promise_manual_then)
eina_promise_owner_default_manual_then_set(promise_owner, EINA_TRUE);
promise = eina_promise_owner_promise_get(promise_owner);
eina_promise_ref(promise);
eina_promise_then(promise, &_eina_test_promise_cb, NULL, &ran);
@ -277,6 +278,7 @@ START_TEST(eina_test_pointer_promise_manual_then)
ck_assert(!ran);
eina_promise_owner_default_call_then(promise_owner);
eina_promise_unref(promise);
ck_assert(ran);
@ -685,7 +687,7 @@ END_TEST
void
eina_test_promise(TCase *tc)
{
/* // pointer */
// pointer
tcase_add_test(tc, eina_test_pointer_promise_normal_lifetime);
tcase_add_test(tc, eina_test_pointer_promise_normal_lifetime_all);
tcase_add_test(tc, eina_test_pointer_promise_error_set);