forked from enlightenment/efl
eina: Fix memory leaks in promise
This commit is contained in:
parent
ba1e70278e
commit
6d43adaaf4
|
@ -7,6 +7,8 @@
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
|
#include <ecore_private.h>
|
||||||
|
|
||||||
struct _Ecore_Thread_Data
|
struct _Ecore_Thread_Data
|
||||||
{
|
{
|
||||||
Ecore_Thread_Promise_Cb func_blocking;
|
Ecore_Thread_Promise_Cb func_blocking;
|
||||||
|
@ -20,10 +22,38 @@ struct _Ecore_Thread_Promise_Owner
|
||||||
{
|
{
|
||||||
Eina_Promise_Owner owner_vtable;
|
Eina_Promise_Owner owner_vtable;
|
||||||
Eina_Promise_Owner* eina_owner;
|
Eina_Promise_Owner* eina_owner;
|
||||||
|
Eina_Promise promise_vtable;
|
||||||
|
Eina_Promise* eina_promise;
|
||||||
_Ecore_Thread_Data thread_callback_data;
|
_Ecore_Thread_Data thread_callback_data;
|
||||||
|
int ref_count;
|
||||||
|
int then_count;
|
||||||
};
|
};
|
||||||
typedef struct _Ecore_Thread_Promise_Owner _Ecore_Thread_Promise_Owner;
|
typedef struct _Ecore_Thread_Promise_Owner _Ecore_Thread_Promise_Owner;
|
||||||
|
|
||||||
|
#define ECORE_PROMISE_GET_OWNER(p) (_Ecore_Thread_Promise_Owner*)((unsigned char*)p - offsetof(struct _Ecore_Thread_Promise_Owner, promise_vtable))
|
||||||
|
|
||||||
|
static void _ecore_promise_ref_update(_Ecore_Thread_Promise_Owner* p)
|
||||||
|
{
|
||||||
|
if(p->ref_count < 0)
|
||||||
|
{
|
||||||
|
ERR("Reference count is negative for promise %p\n", p);
|
||||||
|
}
|
||||||
|
if(!p->ref_count)
|
||||||
|
{
|
||||||
|
p->eina_promise->unref(p->eina_promise);
|
||||||
|
p->eina_promise = NULL;
|
||||||
|
p->eina_owner = NULL;
|
||||||
|
p->thread_callback_data.thread = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _ecore_promise_thread_release_ref(void* data, void* value EINA_UNUSED)
|
||||||
|
{
|
||||||
|
_Ecore_Thread_Promise_Owner* p = data;
|
||||||
|
p->ref_count -= p->then_count;
|
||||||
|
_ecore_promise_ref_update(p);
|
||||||
|
}
|
||||||
|
|
||||||
static void _ecore_promise_thread_end(void* data, Ecore_Thread* thread EINA_UNUSED)
|
static void _ecore_promise_thread_end(void* data, Ecore_Thread* thread EINA_UNUSED)
|
||||||
{
|
{
|
||||||
_Ecore_Thread_Promise_Owner* p = data;
|
_Ecore_Thread_Promise_Owner* p = data;
|
||||||
|
@ -31,10 +61,14 @@ static void _ecore_promise_thread_end(void* data, Ecore_Thread* thread EINA_UNUS
|
||||||
{
|
{
|
||||||
eina_promise_owner_default_manual_then_set(p->eina_owner, EINA_FALSE);
|
eina_promise_owner_default_manual_then_set(p->eina_owner, EINA_FALSE);
|
||||||
eina_promise_owner_default_call_then(p->eina_owner);
|
eina_promise_owner_default_call_then(p->eina_owner);
|
||||||
|
p->ref_count -= p->then_count;
|
||||||
|
_ecore_promise_ref_update(p);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
eina_promise_owner_default_manual_then_set(p->eina_owner, EINA_FALSE);
|
eina_promise_owner_default_manual_then_set(p->eina_owner, EINA_FALSE);
|
||||||
|
eina_promise_then(p->eina_promise, &_ecore_promise_thread_release_ref,
|
||||||
|
(Eina_Promise_Error_Cb)&_ecore_promise_thread_release_ref, p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,7 +85,7 @@ static void _ecore_promise_thread_notify(void* data, Ecore_Thread* thread EINA_U
|
||||||
eina_promise_owner_progress(promise->eina_owner, msg_data);
|
eina_promise_owner_progress(promise->eina_owner, msg_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _ecore_promise_cancel(void* data, Eina_Promise_Owner* promise EINA_UNUSED)
|
static void _ecore_promise_cancel_cb(void* data, Eina_Promise_Owner* promise EINA_UNUSED)
|
||||||
{
|
{
|
||||||
_Ecore_Thread_Promise_Owner* priv = data;
|
_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_vtable,
|
||||||
|
@ -93,12 +127,76 @@ static Eina_Bool _ecore_promise_owner_cancelled_is(_Ecore_Thread_Promise_Owner c
|
||||||
}
|
}
|
||||||
static Eina_Promise* _ecore_thread_promise_owner_promise_get(_Ecore_Thread_Promise_Owner* promise)
|
static Eina_Promise* _ecore_thread_promise_owner_promise_get(_Ecore_Thread_Promise_Owner* promise)
|
||||||
{
|
{
|
||||||
return promise->eina_owner->promise_get(promise->eina_owner);
|
return &promise->promise_vtable;
|
||||||
}
|
}
|
||||||
static void _ecore_thread_promise_owner_progress(_Ecore_Thread_Promise_Owner* promise, void* data)
|
static void _ecore_thread_promise_owner_progress(_Ecore_Thread_Promise_Owner* promise, void* data)
|
||||||
{
|
{
|
||||||
ecore_thread_feedback(promise->thread_callback_data.thread, data);
|
ecore_thread_feedback(promise->thread_callback_data.thread, data);
|
||||||
}
|
}
|
||||||
|
static void _ecore_thread_promise_owner_progress_notify(_Ecore_Thread_Promise_Owner* promise,
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
if(v->then_count)
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
static void _ecore_promise_ref(Eina_Promise const* promise)
|
||||||
|
{
|
||||||
|
_Ecore_Thread_Promise_Owner* v = ECORE_PROMISE_GET_OWNER(promise);
|
||||||
|
++v->ref_count;
|
||||||
|
}
|
||||||
|
static void _ecore_promise_unref(Eina_Promise const* promise)
|
||||||
|
{
|
||||||
|
_Ecore_Thread_Promise_Owner* v = ECORE_PROMISE_GET_OWNER(promise);
|
||||||
|
--v->ref_count;
|
||||||
|
}
|
||||||
|
static void* _ecore_promise_buffer_get(Eina_Promise const* promise)
|
||||||
|
{
|
||||||
|
_Ecore_Thread_Promise_Owner* v = ECORE_PROMISE_GET_OWNER(promise);
|
||||||
|
return v->eina_promise->buffer_get(v->eina_promise);
|
||||||
|
}
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
Ecore_Thread* ecore_thread_promise_run(Ecore_Thread_Promise_Cb func_blocking,
|
Ecore_Thread* ecore_thread_promise_run(Ecore_Thread_Promise_Cb func_blocking,
|
||||||
Ecore_Thread_Promise_Cb func_cancel,
|
Ecore_Thread_Promise_Cb func_cancel,
|
||||||
|
@ -120,18 +218,36 @@ Ecore_Thread* ecore_thread_promise_run(Ecore_Thread_Promise_Cb func_blocking,
|
||||||
priv->owner_vtable.pending_is = EINA_FUNC_PROMISE_OWNER_PENDING_IS(&_ecore_promise_owner_pending_is);
|
priv->owner_vtable.pending_is = EINA_FUNC_PROMISE_OWNER_PENDING_IS(&_ecore_promise_owner_pending_is);
|
||||||
priv->owner_vtable.cancelled_is = EINA_FUNC_PROMISE_OWNER_CANCELLED_IS(&_ecore_promise_owner_cancelled_is);
|
priv->owner_vtable.cancelled_is = EINA_FUNC_PROMISE_OWNER_CANCELLED_IS(&_ecore_promise_owner_cancelled_is);
|
||||||
priv->owner_vtable.progress = EINA_FUNC_PROMISE_OWNER_PROGRESS(&_ecore_thread_promise_owner_progress);
|
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);
|
||||||
|
|
||||||
|
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);
|
||||||
|
priv->promise_vtable.error_get = EINA_FUNC_PROMISE_ERROR_GET(&_ecore_promise_error_get);
|
||||||
|
priv->promise_vtable.pending_is = EINA_FUNC_PROMISE_PENDING_IS(&_ecore_promise_pending_is);
|
||||||
|
priv->promise_vtable.progress_cb_add = EINA_FUNC_PROMISE_PROGRESS_CB_ADD(&_ecore_promise_progress_cb_add);
|
||||||
|
priv->promise_vtable.cancel = EINA_FUNC_PROMISE_CANCEL(&_ecore_promise_cancel);
|
||||||
|
priv->promise_vtable.ref = EINA_FUNC_PROMISE_REF(&_ecore_promise_ref);
|
||||||
|
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->thread_callback_data.data = data;
|
priv->thread_callback_data.data = data;
|
||||||
priv->thread_callback_data.func_blocking = func_blocking;
|
priv->thread_callback_data.func_blocking = func_blocking;
|
||||||
priv->thread_callback_data.func_cancel = func_cancel;
|
priv->thread_callback_data.func_cancel = func_cancel;
|
||||||
eina_promise_owner_default_manual_then_set(priv->eina_owner, EINA_TRUE);
|
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->ref_count = 0;
|
||||||
|
priv->then_count = 0;
|
||||||
|
|
||||||
if(func_cancel)
|
if(func_cancel)
|
||||||
eina_promise_owner_default_cancel_cb_add(priv->eina_owner, &_ecore_promise_cancel, priv, NULL);
|
eina_promise_owner_default_cancel_cb_add(priv->eina_owner, &_ecore_promise_cancel_cb, priv, NULL);
|
||||||
priv->thread_callback_data.thread =
|
priv->thread_callback_data.thread =
|
||||||
ecore_thread_feedback_run(&_ecore_promise_thread_blocking, &_ecore_promise_thread_notify,
|
ecore_thread_feedback_run(&_ecore_promise_thread_blocking, &_ecore_promise_thread_notify,
|
||||||
&_ecore_promise_thread_end, &_ecore_promise_thread_cancel, priv,
|
&_ecore_promise_thread_end, &_ecore_promise_thread_cancel, priv,
|
||||||
EINA_FALSE);
|
EINA_FALSE);
|
||||||
if(promise)
|
if(promise)
|
||||||
*promise = priv->eina_owner->promise_get(priv->eina_owner);
|
*promise = priv->eina_promise;
|
||||||
return priv->thread_callback_data.thread;
|
return priv->thread_callback_data.thread;
|
||||||
}
|
}
|
||||||
|
|
|
@ -87,7 +87,6 @@ static int _eina_main_count = 0;
|
||||||
static int _eina_main_thread_count = 0;
|
static int _eina_main_thread_count = 0;
|
||||||
#endif
|
#endif
|
||||||
static int _eina_log_dom = -1;
|
static int _eina_log_dom = -1;
|
||||||
void _eina_promise_init(void);
|
|
||||||
|
|
||||||
#ifdef ERR
|
#ifdef ERR
|
||||||
#undef ERR
|
#undef ERR
|
||||||
|
@ -155,6 +154,7 @@ EAPI Eina_Inlist *_eina_tracking = NULL;
|
||||||
S(cpu);
|
S(cpu);
|
||||||
S(thread_queue);
|
S(thread_queue);
|
||||||
S(rbtree);
|
S(rbtree);
|
||||||
|
S(promise);
|
||||||
/* no model for now
|
/* no model for now
|
||||||
S(model);
|
S(model);
|
||||||
*/
|
*/
|
||||||
|
@ -201,7 +201,8 @@ static const struct eina_desc_setup _eina_desc_setup[] = {
|
||||||
S(cow),
|
S(cow),
|
||||||
S(cpu),
|
S(cpu),
|
||||||
S(thread_queue),
|
S(thread_queue),
|
||||||
S(rbtree)
|
S(rbtree),
|
||||||
|
S(promise)
|
||||||
/* no model for now
|
/* no model for now
|
||||||
S(model)
|
S(model)
|
||||||
*/
|
*/
|
||||||
|
@ -300,8 +301,6 @@ eina_init(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_eina_promise_init();
|
|
||||||
|
|
||||||
eina_cpu_count_internal();
|
eina_cpu_count_internal();
|
||||||
|
|
||||||
eina_log_timing(_eina_log_dom, EINA_LOG_STATE_STOP, EINA_LOG_STATE_INIT);
|
eina_log_timing(_eina_log_dom, EINA_LOG_STATE_STOP, EINA_LOG_STATE_INIT);
|
||||||
|
|
|
@ -4,8 +4,17 @@
|
||||||
|
|
||||||
#include <Eina.h>
|
#include <Eina.h>
|
||||||
|
|
||||||
|
#include <eina_private.h>
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
|
static int _eina_promise_log_dom = -1;
|
||||||
|
|
||||||
|
#ifdef ERR
|
||||||
|
#undef ERR
|
||||||
|
#endif
|
||||||
|
#define ERR(...) EINA_LOG_DOM_ERR(_eina_promise_log_dom, __VA_ARGS__)
|
||||||
|
|
||||||
typedef struct _Eina_Promise_Then_Cb _Eina_Promise_Then_Cb;
|
typedef struct _Eina_Promise_Then_Cb _Eina_Promise_Then_Cb;
|
||||||
typedef struct _Eina_Promise_Progress_Cb _Eina_Promise_Progress_Cb;
|
typedef struct _Eina_Promise_Progress_Cb _Eina_Promise_Progress_Cb;
|
||||||
typedef struct _Eina_Promise_Cancel_Cb _Eina_Promise_Cancel_Cb;
|
typedef struct _Eina_Promise_Cancel_Cb _Eina_Promise_Cancel_Cb;
|
||||||
|
@ -29,6 +38,7 @@ struct _Eina_Promise_Progress_Cb
|
||||||
EINA_INLIST;
|
EINA_INLIST;
|
||||||
|
|
||||||
Eina_Promise_Progress_Cb callback;
|
Eina_Promise_Progress_Cb callback;
|
||||||
|
Eina_Promise_Free_Cb free;
|
||||||
void* data;
|
void* data;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -94,6 +104,22 @@ struct _Eina_Promise_Iterator
|
||||||
} data;
|
} data;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static void _eina_promise_free_progress_callback_node(void* node)
|
||||||
|
{
|
||||||
|
_Eina_Promise_Progress_Cb *progress_cb = node;
|
||||||
|
if(progress_cb->free)
|
||||||
|
progress_cb->free(progress_cb->data);
|
||||||
|
free(progress_cb);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _eina_promise_free_progress_notify_callback_node(void* node)
|
||||||
|
{
|
||||||
|
_Eina_Promise_Owner_Progress_Notify_Data *progress_notify_cb = node;
|
||||||
|
if(progress_notify_cb->free_cb)
|
||||||
|
progress_notify_cb->free_cb(progress_notify_cb->data);
|
||||||
|
free(progress_notify_cb);
|
||||||
|
}
|
||||||
|
|
||||||
static void _eina_promise_finish(_Eina_Promise_Default_Owner* promise);
|
static void _eina_promise_finish(_Eina_Promise_Default_Owner* promise);
|
||||||
static void _eina_promise_ref(_Eina_Promise_Default* promise);
|
static void _eina_promise_ref(_Eina_Promise_Default* promise);
|
||||||
static void _eina_promise_unref(_Eina_Promise_Default* promise);
|
static void _eina_promise_unref(_Eina_Promise_Default* promise);
|
||||||
|
@ -119,14 +145,14 @@ static void
|
||||||
_eina_promise_then_calls(_Eina_Promise_Default_Owner* promise)
|
_eina_promise_then_calls(_Eina_Promise_Default_Owner* promise)
|
||||||
{
|
{
|
||||||
_Eina_Promise_Then_Cb* callback;
|
_Eina_Promise_Then_Cb* callback;
|
||||||
Eina_Inlist* list2;
|
|
||||||
Eina_Bool error;
|
Eina_Bool error;
|
||||||
|
|
||||||
_eina_promise_ref(&promise->promise);
|
_eina_promise_ref(&promise->promise);
|
||||||
error = promise->promise.has_errored;
|
error = promise->promise.has_errored;
|
||||||
|
|
||||||
EINA_INLIST_FOREACH_SAFE(promise->promise.then_callbacks, list2, callback)
|
EINA_INLIST_FREE(promise->promise.then_callbacks, callback)
|
||||||
{
|
{
|
||||||
|
promise->promise.then_callbacks = eina_inlist_remove(promise->promise.then_callbacks, EINA_INLIST_GET(callback));
|
||||||
if (error)
|
if (error)
|
||||||
{
|
{
|
||||||
if (callback->error_cb)
|
if (callback->error_cb)
|
||||||
|
@ -136,6 +162,7 @@ _eina_promise_then_calls(_Eina_Promise_Default_Owner* promise)
|
||||||
{
|
{
|
||||||
(*callback->callback)(callback->data, &promise->value[0]);
|
(*callback->callback)(callback->data, &promise->value[0]);
|
||||||
}
|
}
|
||||||
|
free(callback);
|
||||||
_eina_promise_unref(&promise->promise);
|
_eina_promise_unref(&promise->promise);
|
||||||
}
|
}
|
||||||
_eina_promise_unref(&promise->promise);
|
_eina_promise_unref(&promise->promise);
|
||||||
|
@ -145,14 +172,15 @@ static void
|
||||||
_eina_promise_cancel_calls(_Eina_Promise_Default_Owner* promise, Eina_Bool call_cancel EINA_UNUSED)
|
_eina_promise_cancel_calls(_Eina_Promise_Default_Owner* promise, Eina_Bool call_cancel EINA_UNUSED)
|
||||||
{
|
{
|
||||||
_Eina_Promise_Cancel_Cb* callback;
|
_Eina_Promise_Cancel_Cb* callback;
|
||||||
Eina_Inlist* list2;
|
|
||||||
|
|
||||||
EINA_INLIST_FOREACH_SAFE(promise->promise.cancel_callbacks, list2, callback)
|
EINA_INLIST_FREE(promise->promise.cancel_callbacks, callback)
|
||||||
{
|
{
|
||||||
if (callback->callback)
|
promise->promise.cancel_callbacks = eina_inlist_remove(promise->promise.cancel_callbacks, EINA_INLIST_GET(callback));
|
||||||
{
|
if (callback->callback)
|
||||||
(*callback->callback)(callback->data, (Eina_Promise_Owner*)promise);
|
{
|
||||||
}
|
(*callback->callback)(callback->data, (Eina_Promise_Owner*)promise);
|
||||||
|
}
|
||||||
|
free(callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!promise->promise.is_manual_then)
|
if (!promise->promise.is_manual_then)
|
||||||
|
@ -164,15 +192,19 @@ _eina_promise_cancel_calls(_Eina_Promise_Default_Owner* promise, Eina_Bool call_
|
||||||
static void
|
static void
|
||||||
_eina_promise_del(_Eina_Promise_Default_Owner* promise)
|
_eina_promise_del(_Eina_Promise_Default_Owner* promise)
|
||||||
{
|
{
|
||||||
if (promise->promise.has_finished)
|
if (!promise->promise.has_finished)
|
||||||
{
|
{
|
||||||
if (promise->promise.value_free_cb)
|
ERR("Promise is being deleted, despite not being finished yet. This will cause intermitent crashes");
|
||||||
promise->promise.value_free_cb((void*)&promise->value[0]);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_eina_promise_cancel_calls(promise, EINA_TRUE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (promise->promise.value_free_cb)
|
||||||
|
promise->promise.value_free_cb((void*)&promise->value[0]);
|
||||||
|
|
||||||
|
_eina_promise_free_callback_list(&promise->promise.progress_callbacks,
|
||||||
|
&_eina_promise_free_progress_callback_node);
|
||||||
|
_eina_promise_free_callback_list(&promise->promise.progress_notify_callbacks,
|
||||||
|
&_eina_promise_free_progress_notify_callback_node);
|
||||||
|
free(promise);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void *
|
static void *
|
||||||
|
@ -234,8 +266,9 @@ _eina_promise_then(_Eina_Promise_Default* p, Eina_Promise_Cb callback,
|
||||||
if (!promise->promise.is_first_then)
|
if (!promise->promise.is_first_then)
|
||||||
{
|
{
|
||||||
_eina_promise_ref(p);
|
_eina_promise_ref(p);
|
||||||
promise->promise.is_first_then = EINA_FALSE;
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
promise->promise.is_first_then = EINA_FALSE;
|
||||||
if (promise->promise.has_finished)
|
if (promise->promise.has_finished)
|
||||||
{
|
{
|
||||||
_eina_promise_then_calls(promise);
|
_eina_promise_then_calls(promise);
|
||||||
|
@ -259,6 +292,10 @@ _eina_promise_finish(_Eina_Promise_Default_Owner* promise)
|
||||||
{
|
{
|
||||||
_eina_promise_then_calls(promise);
|
_eina_promise_then_calls(promise);
|
||||||
}
|
}
|
||||||
|
if(promise->promise.ref == 0)
|
||||||
|
{
|
||||||
|
_eina_promise_del(promise);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static Eina_Error
|
static Eina_Error
|
||||||
|
@ -293,7 +330,8 @@ _eina_promise_owner_cancelled_is(_Eina_Promise_Default_Owner const* promise)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_eina_promise_progress_cb_add(_Eina_Promise_Default* promise, Eina_Promise_Progress_Cb callback, void* data)
|
_eina_promise_progress_cb_add(_Eina_Promise_Default* promise, Eina_Promise_Progress_Cb callback, void* data,
|
||||||
|
Eina_Promise_Free_Cb free_cb)
|
||||||
{
|
{
|
||||||
_Eina_Promise_Progress_Cb* cb;
|
_Eina_Promise_Progress_Cb* cb;
|
||||||
_Eina_Promise_Owner_Progress_Notify_Data* notify_data;
|
_Eina_Promise_Owner_Progress_Notify_Data* notify_data;
|
||||||
|
@ -302,13 +340,15 @@ _eina_promise_progress_cb_add(_Eina_Promise_Default* promise, Eina_Promise_Progr
|
||||||
cb = malloc(sizeof(struct _Eina_Promise_Progress_Cb));
|
cb = malloc(sizeof(struct _Eina_Promise_Progress_Cb));
|
||||||
cb->callback = callback;
|
cb->callback = callback;
|
||||||
cb->data = data;
|
cb->data = data;
|
||||||
|
cb->free = free_cb;
|
||||||
promise->progress_callbacks = eina_inlist_append(promise->progress_callbacks, EINA_INLIST_GET(cb));
|
promise->progress_callbacks = eina_inlist_append(promise->progress_callbacks, EINA_INLIST_GET(cb));
|
||||||
|
|
||||||
EINA_INLIST_FOREACH(owner->promise.progress_notify_callbacks, notify_data)
|
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_vtable);
|
||||||
}
|
}
|
||||||
_eina_promise_free_callback_list(&owner->promise.progress_notify_callbacks, &free);
|
_eina_promise_free_callback_list(&owner->promise.progress_notify_callbacks,
|
||||||
|
&_eina_promise_free_progress_notify_callback_node);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -393,7 +433,8 @@ _eina_promise_owner_progress(_Eina_Promise_Default_Owner* promise, void* data)
|
||||||
|
|
||||||
EINA_INLIST_FOREACH_SAFE(promise->promise.progress_callbacks, list2, callback)
|
EINA_INLIST_FOREACH_SAFE(promise->promise.progress_callbacks, list2, callback)
|
||||||
{
|
{
|
||||||
(*callback->callback)(callback->data, data);
|
if(callback->callback)
|
||||||
|
(*callback->callback)(callback->data, data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -605,6 +646,7 @@ _eina_promise_progress_notify_fulfilled(void* data, Eina_Promise_Owner* p EINA_U
|
||||||
}
|
}
|
||||||
|
|
||||||
EAPI Eina_Error EINA_ERROR_PROMISE_NO_NOTIFY;
|
EAPI Eina_Error EINA_ERROR_PROMISE_NO_NOTIFY;
|
||||||
|
EAPI Eina_Error EINA_ERROR_PROMISE_CANCEL;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_eina_promise_progress_notify_failed(void* data)
|
_eina_promise_progress_notify_failed(void* data)
|
||||||
|
@ -666,9 +708,10 @@ eina_promise_pending_is(Eina_Promise const* promise)
|
||||||
}
|
}
|
||||||
|
|
||||||
EAPI void
|
EAPI void
|
||||||
eina_promise_progress_cb_add(Eina_Promise* promise, Eina_Promise_Progress_Cb callback, void* data)
|
eina_promise_progress_cb_add(Eina_Promise* promise, Eina_Promise_Progress_Cb callback, void* data,
|
||||||
|
Eina_Promise_Free_Cb free_cb)
|
||||||
{
|
{
|
||||||
promise->progress_cb_add(promise, callback, data);
|
promise->progress_cb_add(promise, callback, data, free_cb);
|
||||||
}
|
}
|
||||||
|
|
||||||
EAPI void
|
EAPI void
|
||||||
|
@ -739,8 +782,27 @@ eina_promise_owner_progress_notify(Eina_Promise_Owner* promise, Eina_Promise_Pro
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char EINA_ERROR_PROMISE_NO_NOTIFY_STR[] = "Out of memory";
|
static const char EINA_ERROR_PROMISE_NO_NOTIFY_STR[] = "Out of memory";
|
||||||
|
static const char EINA_ERROR_PROMISE_CANCEL_STR[] = "Promise cancelled";
|
||||||
|
|
||||||
void _eina_promise_init()
|
Eina_Bool eina_promise_init()
|
||||||
{
|
{
|
||||||
EINA_ERROR_PROMISE_NO_NOTIFY = eina_error_msg_static_register(EINA_ERROR_PROMISE_NO_NOTIFY_STR);
|
EINA_ERROR_PROMISE_NO_NOTIFY = eina_error_msg_static_register(EINA_ERROR_PROMISE_NO_NOTIFY_STR);
|
||||||
|
EINA_ERROR_PROMISE_CANCEL = eina_error_msg_static_register(EINA_ERROR_PROMISE_CANCEL_STR);
|
||||||
|
|
||||||
|
_eina_promise_log_dom = eina_log_domain_register("eina_promise",
|
||||||
|
EINA_LOG_COLOR_DEFAULT);
|
||||||
|
if (_eina_promise_log_dom < 0)
|
||||||
|
{
|
||||||
|
EINA_LOG_ERR("Could not register log domain: eina_promise");
|
||||||
|
return EINA_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return EINA_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
Eina_Bool eina_promise_shutdown()
|
||||||
|
{
|
||||||
|
eina_log_domain_unregister(_eina_promise_log_dom);
|
||||||
|
_eina_promise_log_dom = -1;
|
||||||
|
return EINA_TRUE;
|
||||||
}
|
}
|
||||||
|
|
|
@ -71,7 +71,8 @@ typedef Eina_Bool(*Eina_Promise_Pending_Is_Cb)(Eina_Promise const* promise);
|
||||||
/*
|
/*
|
||||||
* @brief Function callback type for promise's progress add function override
|
* @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* 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)
|
#define EINA_FUNC_PROMISE_PROGRESS_CB_ADD(Function) ((Eina_Promise_Progress_Cb_Add_Cb)Function)
|
||||||
|
|
||||||
|
@ -338,7 +339,8 @@ EAPI Eina_Bool eina_promise_pending_is(Eina_Promise const* promise);
|
||||||
* @param progress The callback to be called when progress is made
|
* @param progress The callback to be called when progress is made
|
||||||
* @param data The private data that will be passed to the progress callback
|
* @param data The private data that will be passed to the progress callback
|
||||||
*/
|
*/
|
||||||
EAPI void eina_promise_progress_cb_add(Eina_Promise* promise, Eina_Promise_Progress_Cb progress, void* data);
|
EAPI void eina_promise_progress_cb_add(Eina_Promise* promise, Eina_Promise_Progress_Cb progress, void* data,
|
||||||
|
Eina_Promise_Free_Cb free_cb);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @brief Increments the reference count for the Eina_Promise
|
* @brief Increments the reference count for the Eina_Promise
|
||||||
|
@ -483,6 +485,14 @@ EAPI void eina_promise_owner_default_call_then(Eina_Promise_Owner* promise);
|
||||||
*/
|
*/
|
||||||
EAPI extern Eina_Error EINA_ERROR_PROMISE_NO_NOTIFY;
|
EAPI extern Eina_Error EINA_ERROR_PROMISE_NO_NOTIFY;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var EINA_ERROR_PROMISE_CANCEL
|
||||||
|
*
|
||||||
|
* @brief The error identifier corresponding to when a promise was
|
||||||
|
* cancelled before the callback can be called
|
||||||
|
*/
|
||||||
|
EAPI extern Eina_Error EINA_ERROR_PROMISE_CANCEL;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @internal
|
* @internal
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -378,7 +378,7 @@ START_TEST(ecore_test_promise_progress_promise)
|
||||||
|
|
||||||
ecore_thread_promise_run(&promise_progress_thread, NULL, NULL, 0, &promise);
|
ecore_thread_promise_run(&promise_progress_thread, NULL, NULL, 0, &promise);
|
||||||
|
|
||||||
eina_promise_progress_cb_add(promise, &_progress_callback, NULL);
|
eina_promise_progress_cb_add(promise, &_progress_callback, NULL, NULL);
|
||||||
|
|
||||||
ecore_main_loop_begin();
|
ecore_main_loop_begin();
|
||||||
|
|
||||||
|
|
|
@ -226,7 +226,7 @@ START_TEST(eina_test_promise_progress)
|
||||||
owner = eina_promise_default_add(0);
|
owner = eina_promise_default_add(0);
|
||||||
|
|
||||||
promise = eina_promise_owner_promise_get(owner);
|
promise = eina_promise_owner_promise_get(owner);
|
||||||
eina_promise_progress_cb_add(promise, &progress_callback, &progress_ran);
|
eina_promise_progress_cb_add(promise, &progress_callback, &progress_ran, NULL);
|
||||||
|
|
||||||
eina_promise_owner_progress(owner, &i);
|
eina_promise_owner_progress(owner, &i);
|
||||||
|
|
||||||
|
@ -254,8 +254,8 @@ START_TEST(eina_test_promise_progress_notify1)
|
||||||
eina_promise_owner_progress_notify(owner, &progress_notify, &progress_notify_ran, NULL);
|
eina_promise_owner_progress_notify(owner, &progress_notify, &progress_notify_ran, NULL);
|
||||||
|
|
||||||
promise = eina_promise_owner_promise_get(owner);
|
promise = eina_promise_owner_promise_get(owner);
|
||||||
eina_promise_progress_cb_add(promise, &progress_callback, NULL); // never run
|
eina_promise_progress_cb_add(promise, &progress_callback, NULL, NULL); // never run
|
||||||
eina_promise_progress_cb_add(promise, &progress_callback, NULL); // never run
|
eina_promise_progress_cb_add(promise, &progress_callback, NULL, NULL); // never run
|
||||||
|
|
||||||
ck_assert(progress_notify_ran);
|
ck_assert(progress_notify_ran);
|
||||||
|
|
||||||
|
@ -311,8 +311,8 @@ START_TEST(eina_test_promise_progress_notify3)
|
||||||
&_eina_promise_progress_notify_error, &progress_notify_ran);
|
&_eina_promise_progress_notify_error, &progress_notify_ran);
|
||||||
|
|
||||||
promise = eina_promise_owner_promise_get(owner);
|
promise = eina_promise_owner_promise_get(owner);
|
||||||
eina_promise_progress_cb_add(promise, &progress_callback, NULL); // never run
|
eina_promise_progress_cb_add(promise, &progress_callback, NULL, NULL); // never run
|
||||||
eina_promise_progress_cb_add(promise, &progress_callback, NULL); // never run
|
eina_promise_progress_cb_add(promise, &progress_callback, NULL, NULL); // never run
|
||||||
|
|
||||||
ck_assert(progress_notify_ran);
|
ck_assert(progress_notify_ran);
|
||||||
|
|
||||||
|
@ -320,6 +320,22 @@ START_TEST(eina_test_promise_progress_notify3)
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
|
START_TEST(eina_test_promise_ignored)
|
||||||
|
{
|
||||||
|
Eina_Promise_Owner* owner;
|
||||||
|
Eina_Promise* promise;
|
||||||
|
|
||||||
|
eina_init();
|
||||||
|
|
||||||
|
owner = eina_promise_default_add(0);
|
||||||
|
promise = eina_promise_owner_promise_get(owner);
|
||||||
|
eina_promise_unref(promise);
|
||||||
|
eina_promise_owner_value_set(owner, NULL, NULL);
|
||||||
|
|
||||||
|
eina_shutdown();
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
void
|
void
|
||||||
eina_test_promise(TCase *tc)
|
eina_test_promise(TCase *tc)
|
||||||
{
|
{
|
||||||
|
@ -333,4 +349,5 @@ eina_test_promise(TCase *tc)
|
||||||
tcase_add_test(tc, eina_test_promise_progress_notify1);
|
tcase_add_test(tc, eina_test_promise_progress_notify1);
|
||||||
tcase_add_test(tc, eina_test_promise_progress_notify2);
|
tcase_add_test(tc, eina_test_promise_progress_notify2);
|
||||||
tcase_add_test(tc, eina_test_promise_progress_notify3);
|
tcase_add_test(tc, eina_test_promise_progress_notify3);
|
||||||
|
tcase_add_test(tc, eina_test_promise_ignored);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue