From de9be13d458f2739a536e5863aa8caddd3f7f715 Mon Sep 17 00:00:00 2001 From: Felipe Magno de Almeida Date: Wed, 25 May 2016 18:14:29 -0300 Subject: [PATCH] eina: Add promise parameter to then calllbacks Added promise parameter to then callbacks so callbacks can steal ownership of the value from the promise. --- src/lib/ecore/ecore_thread_promise.c | 9 ++++++++- src/lib/eina/eina_promise.c | 30 ++++++++++++++++++++++++---- src/lib/eina/eina_promise.h | 25 +++++++++++++++++++---- src/lib/elementary/elm_view_form.c | 8 ++++---- src/tests/ecore/ecore_test_promise.c | 14 ++++++------- src/tests/eina/eina_test_promise.c | 13 ++++++------ 6 files changed, 72 insertions(+), 27 deletions(-) diff --git a/src/lib/ecore/ecore_thread_promise.c b/src/lib/ecore/ecore_thread_promise.c index 1dea1bc79d..caf312cff3 100644 --- a/src/lib/ecore/ecore_thread_promise.c +++ b/src/lib/ecore/ecore_thread_promise.c @@ -47,7 +47,7 @@ static void _ecore_promise_ref_update(_Ecore_Thread_Promise_Owner* p) } } -static void _ecore_promise_thread_release_ref(void* data, void* value EINA_UNUSED) +static void _ecore_promise_thread_release_ref(void* data, void* value EINA_UNUSED, Eina_Promise* promise EINA_UNUSED) { _Ecore_Thread_Promise_Owner* p = data; p->ref_count -= p->then_count; @@ -197,6 +197,11 @@ static size_t _ecore_promise_value_size_get(Eina_Promise const* promise) _Ecore_Thread_Promise_Owner* v = ECORE_PROMISE_GET_OWNER(promise); return v->eina_promise->value_size_get(v->eina_promise); } +static void* _ecore_promise_release_value_ownership(Eina_Promise* promise) +{ + _Ecore_Thread_Promise_Owner* v = ECORE_PROMISE_GET_OWNER(promise); + return v->eina_promise->release_value_ownership(v->eina_promise); +} Ecore_Thread* ecore_thread_promise_run(Ecore_Thread_Promise_Cb func_blocking, Ecore_Thread_Promise_Cb func_cancel, @@ -230,6 +235,8 @@ Ecore_Thread* ecore_thread_promise_run(Ecore_Thread_Promise_Cb func_blocking, priv->promise_vtable.unref = EINA_FUNC_PROMISE_UNREF(&_ecore_promise_unref); priv->promise_vtable.value_size_get = EINA_FUNC_PROMISE_VALUE_SIZE_GET(&_ecore_promise_value_size_get); priv->promise_vtable.buffer_get = EINA_FUNC_PROMISE_BUFFER_GET(&_ecore_promise_buffer_get); + priv->promise_vtable.release_value_ownership = EINA_FUNC_PROMISE_RELEASE_VALUE_OWNERSHIP + (&_ecore_promise_release_value_ownership); priv->thread_callback_data.data = data; priv->thread_callback_data.func_blocking = func_blocking; diff --git a/src/lib/eina/eina_promise.c b/src/lib/eina/eina_promise.c index 93e70948e5..e8ef06d781 100644 --- a/src/lib/eina/eina_promise.c +++ b/src/lib/eina/eina_promise.c @@ -169,11 +169,11 @@ _eina_promise_then_calls(_Eina_Promise_Default_Owner* promise) if (error) { if (callback->error_cb) - (*callback->error_cb)(callback->data, &promise->promise.error); + (*callback->error_cb)(callback->data, promise->promise.error, &promise->promise.vtable); } else if (callback->callback) { - (*callback->callback)(callback->data, &promise->value[0]); + (*callback->callback)(callback->data, &promise->value[0], &promise->promise.vtable); } free(callback); _eina_promise_unref(&promise->promise); @@ -240,8 +240,23 @@ _eina_promise_value_get(_Eina_Promise_Default const* p) } } +static void * +_eina_promise_release_value_ownership(_Eina_Promise_Default* p) +{ + _Eina_Promise_Default_Owner* promise = EINA_PROMISE_GET_OWNER(p); + if (promise->promise.has_finished && !promise->promise.has_errored) + { + promise->promise.value_free_cb = NULL; + return (void*)&promise->value[0]; + } + else + { + return NULL; + } +} + static void -_eina_promise_owner_value_set(_Eina_Promise_Default_Owner* promise, void* data, Eina_Promise_Free_Cb free) +_eina_promise_owner_value_set(_Eina_Promise_Default_Owner* promise, const void* data, Eina_Promise_Free_Cb free) { if (data && promise->promise.value_size) { @@ -481,6 +496,7 @@ eina_promise_default_add(int value_size) p->promise.vtable.ref = EINA_FUNC_PROMISE_REF(_eina_promise_ref); p->promise.vtable.unref = EINA_FUNC_PROMISE_UNREF(_eina_promise_unref); p->promise.vtable.value_size_get = EINA_FUNC_PROMISE_VALUE_SIZE_GET(_eina_promise_value_size_get); + p->promise.vtable.release_value_ownership = EINA_FUNC_PROMISE_RELEASE_VALUE_OWNERSHIP(_eina_promise_release_value_ownership); p->promise.has_finished = p->promise.has_errored = p->promise.is_cancelled = p->promise.is_manual_then = EINA_FALSE; p->promise.is_first_then = EINA_TRUE; @@ -781,7 +797,7 @@ eina_promise_then(Eina_Promise* promise, Eina_Promise_Cb callback, } EAPI void -eina_promise_owner_value_set(Eina_Promise_Owner* promise, void* value, Eina_Promise_Free_Cb free) +eina_promise_owner_value_set(Eina_Promise_Owner* promise, const void* value, Eina_Promise_Free_Cb free) { promise->value_set(promise, value, free); } @@ -847,6 +863,12 @@ eina_promise_buffer_get(Eina_Promise* promise) return promise->buffer_get(promise); } +EAPI void * +eina_promise_release_value_ownership(Eina_Promise* promise) +{ + return promise->release_value_ownership(promise); +} + EAPI size_t eina_promise_value_size_get(Eina_Promise const* promise) { diff --git a/src/lib/eina/eina_promise.h b/src/lib/eina/eina_promise.h index 6921c6a8f4..8bba454107 100644 --- a/src/lib/eina/eina_promise.h +++ b/src/lib/eina/eina_promise.h @@ -29,12 +29,12 @@ typedef void(*Eina_Promise_Progress_Notify_Cb)(void* data, Eina_Promise_Owner* p /* * @brief Function callback type for when using eina_promise_then */ -typedef void(*Eina_Promise_Cb)(void* data, void* value); +typedef void(*Eina_Promise_Cb)(void* data, void* value, Eina_Promise* promise); /* * @brief Function callback type for when using eina_promise_then */ -typedef void(*Eina_Promise_Error_Cb)(void* data, Eina_Error const* error); +typedef void(*Eina_Promise_Error_Cb)(void* data, Eina_Error error, Eina_Promise* promise); /* * @brief Function callback type for progress information @@ -106,6 +106,13 @@ typedef void*(*Eina_Promise_Buffer_Get_Cb)(Eina_Promise* promise); #define EINA_FUNC_PROMISE_BUFFER_GET(Function) ((Eina_Promise_Buffer_Get_Cb)Function) +/* + * @brief Function callback type for promise's release_value_ownership function override + */ +typedef void*(*Eina_Promise_Release_Value_Ownership_Cb)(Eina_Promise* promise); + +#define EINA_FUNC_PROMISE_RELEASE_VALUE_OWNERSHIP(Function) ((Eina_Promise_Release_Value_Ownership_Cb)Function) + /* * @brief Function callback type for promise's value_size_get function override */ @@ -138,7 +145,7 @@ typedef void*(*Eina_Promise_Owner_Promise_Get_Cb)(Eina_Promise_Owner const* prom /* * @brief Function callback type for promise owner's value_set function override */ -typedef void(*Eina_Promise_Owner_Value_Set_Cb)(Eina_Promise_Owner* promise, void* data, Eina_Promise_Free_Cb free_fun); +typedef void(*Eina_Promise_Owner_Value_Set_Cb)(Eina_Promise_Owner* 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) @@ -194,6 +201,7 @@ struct _Eina_Promise Eina_Promise_Unref_Cb unref; Eina_Promise_Value_Size_Get_Cb value_size_get; Eina_Promise_Buffer_Get_Cb buffer_get; + Eina_Promise_Release_Value_Ownership_Cb release_value_ownership; #define EINA_MAGIC_PROMISE 0x07932A5B EINA_MAGIC; }; @@ -269,7 +277,7 @@ EAPI Eina_Promise* eina_promise_progress_notification(Eina_Promise_Owner* promis * @param value The pointer to the value that is going to be copied, or NULL. * @param free_cb Callback function to be used to free the value copied */ -EAPI void eina_promise_owner_value_set(Eina_Promise_Owner* promise, void* value, Eina_Promise_Free_Cb free_cb); +EAPI void eina_promise_owner_value_set(Eina_Promise_Owner* promise, const void* value, Eina_Promise_Free_Cb free_cb); /* * @brief Returns the pointer to the value @@ -295,6 +303,15 @@ EAPI void* eina_promise_value_get(Eina_Promise const* promise); */ EAPI void* eina_promise_buffer_get(Eina_Promise* promise); +/* + * @brief Returns the pointer to the value and releases ownership of + * the value by the promise. + * + * @param promise The promise for which to release value ownership + * @return Pointer to value + */ +EAPI void* eina_promise_release_value_ownership(Eina_Promise* promise); + /* * @brief Returns the pointer to the buffer that holds the value. * diff --git a/src/lib/elementary/elm_view_form.c b/src/lib/elementary/elm_view_form.c index 612165f045..8f2fb85f88 100644 --- a/src/lib/elementary/elm_view_form.c +++ b/src/lib/elementary/elm_view_form.c @@ -46,18 +46,18 @@ struct _Elm_View_Form_Promise static void -_efl_promise_then_widget(Elm_View_Form_Widget *w, Eina_Value *value) +_efl_promise_then_widget(Elm_View_Form_Widget *w, Eina_Value *value, Eina_Promise* promise EINA_UNUSED) { w->widget_obj_set_cb(w->widget_obj, value, w->widget_propname); } static void -_efl_promise_error_widget(void *data EINA_UNUSED, const Eina_Error *err EINA_UNUSED) +_efl_promise_error_widget(void *data EINA_UNUSED, Eina_Error err EINA_UNUSED, Eina_Promise* promise EINA_UNUSED) { } static void -_efl_model_promise_then_cb(Elm_View_Form_Promise *p, Eina_Value *value) +_efl_model_promise_then_cb(Elm_View_Form_Promise *p, Eina_Value *value, Eina_Promise* promise EINA_UNUSED) { EINA_SAFETY_ON_NULL_RETURN(p); @@ -78,7 +78,7 @@ _efl_model_promise_then_cb(Elm_View_Form_Promise *p, Eina_Value *value) } static void -_efl_model_promise_error_cb(Elm_View_Form_Promise *p, const Eina_Error *error EINA_UNUSED) +_efl_model_promise_error_cb(Elm_View_Form_Promise *p, Eina_Error error EINA_UNUSED, Eina_Promise* promise EINA_UNUSED) { EINA_SAFETY_ON_NULL_RETURN(p); diff --git a/src/tests/ecore/ecore_test_promise.c b/src/tests/ecore/ecore_test_promise.c index 5a54281a33..bf2a16076a 100644 --- a/src/tests/ecore/ecore_test_promise.c +++ b/src/tests/ecore/ecore_test_promise.c @@ -11,7 +11,7 @@ void promised_thread(const void* data EINA_UNUSED, Eina_Promise_Owner* promise, eina_promise_owner_value_set(promise, NULL, NULL); } -void promise_callback(void* data EINA_UNUSED, void* value EINA_UNUSED) +void promise_callback(void* data EINA_UNUSED, void* value EINA_UNUSED, Eina_Promise* promise EINA_UNUSED) { ecore_main_loop_quit(); } @@ -36,9 +36,9 @@ void promise_error_thread(const void* data EINA_UNUSED, Eina_Promise_Owner* prom eina_promise_owner_error_set(promise, EINA_ERROR_OUT_OF_MEMORY); } -void promise_error_callback(void* data EINA_UNUSED, Eina_Error const* error) +void promise_error_callback(void* data EINA_UNUSED, Eina_Error error, Eina_Promise* promise EINA_UNUSED) { - ck_assert(*error == EINA_ERROR_OUT_OF_MEMORY); + ck_assert(error == EINA_ERROR_OUT_OF_MEMORY); ecore_main_loop_quit(); } @@ -74,7 +74,7 @@ START_TEST(ecore_test_promise_all) } END_TEST -void promise_callback2(void* data, void* value EINA_UNUSED) +void promise_callback2(void* data, void* value EINA_UNUSED, Eina_Promise* promise EINA_UNUSED) { if(++(*(int*)data) == 2) ecore_main_loop_quit(); @@ -201,7 +201,7 @@ void promised_block_thread(const void* data EINA_UNUSED, Eina_Promise_Owner* pro } static void -_ecore_test_promise_normal_lifetime_cb(void* data EINA_UNUSED, void* value EINA_UNUSED) +_ecore_test_promise_normal_lifetime_cb(void* data EINA_UNUSED, void* value EINA_UNUSED, Eina_Promise* promise EINA_UNUSED) { ecore_main_loop_quit(); } @@ -254,7 +254,7 @@ START_TEST(ecore_test_promise_normal_lifetime_all) END_TEST static void -_ecore_test_promise_immediate_set_lifetime_cb(void* data EINA_UNUSED, void* value EINA_UNUSED) +_ecore_test_promise_immediate_set_lifetime_cb(void* data EINA_UNUSED, void* value EINA_UNUSED, Eina_Promise* promise EINA_UNUSED) { ecore_main_loop_quit(); } @@ -327,7 +327,7 @@ static void _cancel_callback(const void* data, Eina_Promise_Owner* promise EINA_ eina_lock_release(&v->lock); } -static void _cancel_promise_callback(void* data EINA_UNUSED, Eina_Error const* value) +static void _cancel_promise_callback(void* data EINA_UNUSED, Eina_Error value, Eina_Promise* promise EINA_UNUSED) { ck_assert(!!value); ecore_main_loop_quit(); diff --git a/src/tests/eina/eina_test_promise.c b/src/tests/eina/eina_test_promise.c index 2932e1c792..cc7aa88ea2 100644 --- a/src/tests/eina/eina_test_promise.c +++ b/src/tests/eina/eina_test_promise.c @@ -32,7 +32,7 @@ #include "eina_suite.h" static void -_eina_test_promise_cb(void* data, void* value EINA_UNUSED) +_eina_test_promise_cb(void* data, void* value EINA_UNUSED, Eina_Promise* promise EINA_UNUSED) { *(Eina_Bool*)data = EINA_TRUE; } @@ -122,7 +122,7 @@ START_TEST(eina_test_promise_immediate_set_lifetime_all) } END_TEST -static void _eina_test_promise_value_all_cb(void* data, void* value) +static void _eina_test_promise_value_all_cb(void* data, void* value, Eina_Promise* promise EINA_UNUSED) { Eina_Iterator** iterator = value; int *i, *j; @@ -178,9 +178,8 @@ static void cancel_callback(void* data, Eina_Promise_Owner* promise EINA_UNUSED) *(Eina_Bool*)data = EINA_TRUE; } -static void _cancel_promise_callback(void* data EINA_UNUSED, Eina_Error const* value) +static void _cancel_promise_callback(void* data EINA_UNUSED, Eina_Error error, Eina_Promise* promise EINA_UNUSED) { - ck_assert(!!value); *(Eina_Bool*)data = EINA_TRUE; } @@ -207,7 +206,7 @@ START_TEST(eina_test_promise_cancel_promise) } END_TEST -void progress_callback(void* data, void* value) +void progress_callback(void* data, void* value, Eina_Promise* promise EINA_UNUSED) { int* i = value; ck_assert(*i == 1); @@ -285,13 +284,13 @@ START_TEST(eina_test_promise_progress_notify2) END_TEST static void -_eina_promise_progress_notify_fulfilled(void* data, void* value EINA_UNUSED) +_eina_promise_progress_notify_fulfilled(void* data, void* value EINA_UNUSED, Eina_Promise* promise EINA_UNUSED) { *(Eina_Bool*)data = EINA_TRUE; } static void -_eina_promise_progress_notify_error(void* data EINA_UNUSED, Eina_Error const* error EINA_UNUSED) +_eina_promise_progress_notify_error(void* data EINA_UNUSED, Eina_Error error EINA_UNUSED, Eina_Promise* promise EINA_UNUSED) { ck_assert(EINA_FALSE); }