forked from enlightenment/efl
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:
parent
b7530726c8
commit
2bbaada66e
|
@ -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.
|
/// With a Promise you can attach futures to it, which will be used to notify of the value being available.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class Promise
|
public class Promise : IDisposable
|
||||||
{
|
{
|
||||||
internal IntPtr Handle;
|
internal IntPtr Handle;
|
||||||
private GCHandle CleanupHandle;
|
private GCHandle CleanupHandle;
|
||||||
|
@ -116,6 +116,28 @@ public class Promise
|
||||||
handle.Free();
|
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()
|
private void SanityChecks()
|
||||||
{
|
{
|
||||||
if (this.Handle == IntPtr.Zero)
|
if (this.Handle == IntPtr.Zero)
|
||||||
|
|
|
@ -230,6 +230,32 @@ class TestPromises
|
||||||
Test.Assert(callbackCalled, "Future callback should have been called.");
|
Test.Assert(callbackCalled, "Future callback should have been called.");
|
||||||
Test.AssertEquals(received_value, reference_value);
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue