efl_mono: Reject the promise when it's disposed.

Summary:
As futures are tied to a given promises and are usually handled in
a 'attach and forget' scheme, we can't cancel them as it would cancel
the whole chain.

Reviewers: felipealmeida, vitor.sousa

Reviewed By: vitor.sousa

Subscribers: cedric, #committers, zmike

Tags: #efl

Differential Revision: https://phab.enlightenment.org/D6189
This commit is contained in:
Lauro Moura 2018-05-17 19:46:57 -03:00 committed by Vitor Sousa
parent b7530726c8
commit 2bbaada66e
2 changed files with 49 additions and 1 deletions

View File

@ -66,7 +66,7 @@ static internal class PromiseNativeMethods
///
/// With a Promise you can attach futures to it, which will be used to notify of the value being available.
/// </summary>
public class Promise
public class Promise : IDisposable
{
internal IntPtr Handle;
private GCHandle CleanupHandle;
@ -116,6 +116,28 @@ public class Promise
handle.Free();
}
/// <summary>Dispose this promise, causing its cancellation if it isn't already fulfilled.</summary>
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
/// <summary>Finalizer to be called from the Garbage Collector.</summary>
~Promise()
{
Dispose(false);
}
protected virtual void Dispose(bool disposing)
{
if (Handle != IntPtr.Zero)
{
eina_promise_reject(Handle, eina.Error.ECANCELED);
Handle = IntPtr.Zero;
}
}
private void SanityChecks()
{
if (this.Handle == IntPtr.Zero)

View File

@ -230,6 +230,32 @@ class TestPromises
Test.Assert(callbackCalled, "Future callback should have been called.");
Test.AssertEquals(received_value, reference_value);
}
public static void test_reject_on_disposal()
{
bool callbackCalled = false;
eina.Error received_error = eina.Error.NO_ERROR;
efl.ILoop loop = efl.App.GetLoopMain();
eina.Promise promise = new eina.Promise();
eina.Future future = new eina.Future(promise);
future = future.Then((eina.Value value) => {
callbackCalled = true;
value.Get(out received_error);
return value;
});
promise.Dispose();
loop.Iterate();
Test.Assert(callbackCalled, "Future callback should have been called.");
Test.AssertEquals(received_error, eina.Error.ECANCELED);
Test.AssertRaises<ObjectDisposedException>(() => { promise.Resolve(null); });
Test.AssertRaises<ObjectDisposedException>(future.Cancel);
}
}
}