felipealmeida pushed a commit to branch master. http://git.enlightenment.org/core/efl.git/commit/?id=949af55947407de97165dab25814ea63045a28e7
commit 949af55947407de97165dab25814ea63045a28e7 Author: Felipe Magno de Almeida <fel...@expertisesolutions.com.br> Date: Fri Jun 10 22:32:07 2016 -0300 eina: Add support for eina_safepointer in promises --- src/lib/ecore/ecore_thread_promise.c | 46 +++++----- src/lib/eina/eina_main.c | 6 +- src/lib/eina/eina_promise.c | 163 ++++++++++++++++++++++------------- src/lib/eina/eina_promise.h | 57 +++++++----- src/tests/eina/eina_test_promise.c | 4 +- 5 files changed, 166 insertions(+), 110 deletions(-) diff --git a/src/lib/ecore/ecore_thread_promise.c b/src/lib/ecore/ecore_thread_promise.c index 5e4fa11..9531978 100644 --- a/src/lib/ecore/ecore_thread_promise.c +++ b/src/lib/ecore/ecore_thread_promise.c @@ -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; } diff --git a/src/lib/eina/eina_main.c b/src/lib/eina/eina_main.c index 4cdb406..7238002 100644 --- a/src/lib/eina/eina_main.c +++ b/src/lib/eina/eina_main.c @@ -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) */ diff --git a/src/lib/eina/eina_promise.c b/src/lib/eina/eina_promise.c index 1006f84..7664020 100644 --- a/src/lib/eina/eina_promise.c +++ b/src/lib/eina/eina_promise.c @@ -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); diff --git a/src/lib/eina/eina_promise.h b/src/lib/eina/eina_promise.h index f012046..0d6f779 100644 --- a/src/lib/eina/eina_promise.h +++ b/src/lib/eina/eina_promise.h @@ -3,20 +3,27 @@ #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 */ typedef void(*Eina_Promise_Free_Cb)(void* value); @@ -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. diff --git a/src/tests/eina/eina_test_promise.c b/src/tests/eina/eina_test_promise.c index 5c73dba..a236aad 100644 --- a/src/tests/eina/eina_test_promise.c +++ b/src/tests/eina/eina_test_promise.c @@ -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); --