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);

-- 


Reply via email to