felipealmeida pushed a commit to branch master.

http://git.enlightenment.org/core/efl.git/commit/?id=47dea6abc184823df29f4ce0bcdac59aac637bf8

commit 47dea6abc184823df29f4ce0bcdac59aac637bf8
Author: Lauro Moura <lauromo...@expertisesolutions.com.br>
Date:   Mon Jun 6 02:54:18 2016 -0300

    eina: Avoid promise early deletion when cancelled.
    
    Cancelling a promise will fulfill it but won't actually free the memory. 
This
    memory is under custody of the owner, who must either call value_set or
    error_set to finish it.
---
 src/lib/eina/eina_promise.c          |  6 +++++-
 src/tests/ecore/ecore_test_promise.c |  4 +++-
 src/tests/eina/eina_test_promise.c   | 16 ++++++++++++++++
 3 files changed, 24 insertions(+), 2 deletions(-)

diff --git a/src/lib/eina/eina_promise.c b/src/lib/eina/eina_promise.c
index 3410048..9e34481 100644
--- a/src/lib/eina/eina_promise.c
+++ b/src/lib/eina/eina_promise.c
@@ -76,6 +76,7 @@ struct _Eina_Promise_Default
 
    Eina_Bool has_finished : 1;
    Eina_Bool has_errored : 1;
+   Eina_Bool can_be_deleted : 1;
    Eina_Bool is_cancelled : 1;
    Eina_Bool is_manual_then : 1;
    Eina_Bool is_first_then : 1;
@@ -359,6 +360,7 @@ static void
 _eina_promise_finish(_Eina_Promise_Default_Owner* promise)
 {
    promise->promise.has_finished = EINA_TRUE;
+   promise->promise.can_be_deleted = EINA_TRUE;
    if (!promise->promise.is_manual_then)
      {
         _eina_promise_then_calls(promise);
@@ -453,7 +455,7 @@ _eina_promise_ref(_Eina_Promise_Default* p)
 static void
 _eina_promise_unref(_Eina_Promise_Default* p)
 {
-   if (p->ref == 1 && p->has_finished)
+   if (p->ref <= 1 && p->has_finished && p->can_be_deleted)
      {
         _eina_promise_del(EINA_PROMISE_GET_OWNER(p));
      }
@@ -540,6 +542,7 @@ eina_promise_value_add(int value_size)
    
    p->promise.has_finished = p->promise.has_errored =
      p->promise.is_cancelled = p->promise.is_manual_then = 
p->promise.is_pointer = EINA_FALSE;
+   p->promise.can_be_deleted = EINA_FALSE;
    p->promise.is_first_then = EINA_TRUE;
    p->promise.ref = 1;
    memset(&p->promise.then_callbacks, 0, sizeof(p->promise.then_callbacks));
@@ -587,6 +590,7 @@ eina_promise_add()
    p->promise.has_finished = p->promise.has_errored =
      p->promise.is_cancelled = p->promise.is_manual_then = EINA_FALSE;
    p->promise.is_first_then = p->promise.is_pointer = EINA_TRUE;
+   p->promise.can_be_deleted = EINA_FALSE;
    p->promise.ref = 1;
    memset(&p->promise.then_callbacks, 0, sizeof(p->promise.then_callbacks));
    memset(&p->promise.progress_callbacks, 0, 
sizeof(p->promise.progress_callbacks));
diff --git a/src/tests/ecore/ecore_test_promise.c 
b/src/tests/ecore/ecore_test_promise.c
index 5f2a754..cf9c33f 100644
--- a/src/tests/ecore/ecore_test_promise.c
+++ b/src/tests/ecore/ecore_test_promise.c
@@ -303,7 +303,7 @@ static void promise_cancel_thread(const void* data, 
Eina_Promise_Owner* promise
   eina_lock_release(&v->lock);
 }
 
-static void _cancel_callback(const void* data, Eina_Promise_Owner* promise 
EINA_UNUSED, Ecore_Thread* thread EINA_UNUSED)
+static void _cancel_callback(const void* data, Eina_Promise_Owner* promise, 
Ecore_Thread* thread EINA_UNUSED)
 {
   _condition_var* v = (void*)data;
   
@@ -311,6 +311,8 @@ static void _cancel_callback(const void* data, 
Eina_Promise_Owner* promise EINA_
   v->boolean = EINA_TRUE;
   eina_condition_broadcast(&v->condvar);
   eina_lock_release(&v->lock);
+
+  eina_promise_owner_value_set(promise, NULL, NULL);
 }
 
 static void _cancel_promise_callback(void* data EINA_UNUSED, Eina_Error value)
diff --git a/src/tests/eina/eina_test_promise.c 
b/src/tests/eina/eina_test_promise.c
index e2ef1f3..4629869 100644
--- a/src/tests/eina/eina_test_promise.c
+++ b/src/tests/eina/eina_test_promise.c
@@ -201,6 +201,14 @@ START_TEST(eina_test_promise_cancel_promise)
    eina_promise_cancel(promise);
 
    ck_assert(cancel_ran && ran);
+   ck_assert(eina_promise_owner_cancelled_is(owner));
+   ck_assert(!eina_promise_pending_is(promise));
+   ck_assert_int_eq(EINA_ERROR_PROMISE_CANCEL, 
eina_promise_error_get(promise));
+
+   // Finally free the owner
+   eina_promise_owner_value_set(owner, NULL, NULL);
+
+   ck_assert(ran);
 
    eina_shutdown();
 }
@@ -505,6 +513,14 @@ START_TEST(eina_test_pointer_promise_cancel_promise)
    eina_promise_cancel(promise);
 
    ck_assert(cancel_ran && ran);
+   ck_assert(eina_promise_owner_cancelled_is(owner));
+   ck_assert(!eina_promise_pending_is(promise));
+   ck_assert_int_eq(EINA_ERROR_PROMISE_CANCEL, 
eina_promise_error_get(promise));
+
+   // Free the owner
+   eina_promise_owner_value_set(owner, NULL, NULL);
+
+   ck_assert(ran);
 
    eina_shutdown();
 }

-- 


Reply via email to