Mercurial > pub > ImplabNet
diff Implab/AbstractPromise`1.cs @ 247:fb70574741a1 v3
working on promises
author | cin |
---|---|
date | Fri, 26 Jan 2018 18:46:27 +0300 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Implab/AbstractPromise`1.cs Fri Jan 26 18:46:27 2018 +0300 @@ -0,0 +1,161 @@ +using System; +using System.Diagnostics; +using System.Reflection; +using Implab.Parallels; + +namespace Implab { + public class AbstractPromise<T> : AbstractEvent<IResolvable<T>>, IPromise<T> { + + class ResolvableSignal : IResolvable<T> { + public Signal Signal { get; private set; } + public ResolvableSignal() { + Signal = new Signal(); + } + + + public void Reject(Exception error) { + Signal.Set(); + } + + public void Resolve(T result) { + Signal.Set(); + } + } + + class ResolvableWrapper : IResolvable<T> { + readonly IResolvable m_resolvable; + public ResolvableWrapper(IResolvable resolvable) { + + } + + public void Reject(Exception reason) { + m_resolvable.Reject(reason); + } + + public void Resolve(T value) { + m_resolvable.Resolve(); + } + } + + PromiseState m_state; + + T m_result; + + Exception m_error; + + public bool IsRejected { + get { + return m_state == PromiseState.Rejected; + } + } + + public bool IsFulfilled { + get { + return m_state == PromiseState.Fulfilled; + } + } + + public Exception RejectReason { + get { + return m_error; + } + } + + + internal void Resolve(T result) { + if (BeginTransit()) + CompleteResolve(); + } + + internal void Reject(Exception reason) { + if (BeginTransit()) { + m_error = reason; + m_state = PromiseState.Rejected; + CompleteTransit(); + } + } + + + #region implemented abstract members of AbstractPromise + + protected override void SignalHandler(IResolvable<T> handler) { + switch (m_state) { + case PromiseState.Fulfilled: + handler.Resolve(m_result); + break; + case PromiseState.Rejected: + handler.Reject(RejectReason); + break; + default: + throw new InvalidOperationException(String.Format("Invalid promise signal: {0}", m_state)); + } + } + + protected override Signal GetFulfillSignal() { + var next = new ResolvableSignal(); + Then(next); + return next.Signal; + } + + #endregion + + protected void CompleteResolve() { + m_state = PromiseState.Fulfilled; + CompleteTransit(); + } + + public Type ResultType { + get { + return typeof(void); + } + } + + + protected void Rethrow() { + Debug.Assert(m_error != null); + if (m_error is OperationCanceledException) + throw new OperationCanceledException("Operation cancelled", m_error); + else + throw new TargetInvocationException(m_error); + } + + public void Then(IResolvable<T> next) { + AddHandler(next); + } + + public void Then(IResolvable next) { + AddHandler(new ResolvableWrapper(next)); + } + + public IPromise<T2> Cast<T2>() { + return (IPromise<T2>)this; + } + + void IPromise.Join() { + WaitResult(-1); + if (IsRejected) + Rethrow(); + } + + void IPromise.Join(int timeout) { + WaitResult(timeout); + if (IsRejected) + Rethrow(); + } + + public T Join() { + WaitResult(-1); + if (IsRejected) + Rethrow(); + return m_result; + } + + public T Join(int timeout) { + WaitResult(timeout); + if (IsRejected) + Rethrow(); + return m_result; + } + } +} +