##// END OF EJS Templates
Fixed promise rejection when there is not specified error handler in the reaction....
Fixed promise rejection when there is not specified error handler in the reaction. FIXED SPELLING IN THE XML CONTAINER CONFIGURATION signleton->singleton Code cleanup Update tests make them working on dotnet core

File last commit:

r295:28af686e24f7 default
r295:28af686e24f7 default
Show More
Promise`1.cs
158 lines | 3.9 KiB | text/x-csharp | CSharpLexer
using System;
using System.Reflection;
using Implab.Parallels;
namespace Implab {
public class Promise<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) {
m_resolvable = 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 ResolvePromise(T result) {
if (BeginTransit()) {
m_result = result;
m_state = PromiseState.Fulfilled;
CompleteTransit();
}
}
internal void RejectPromise(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 void WaitResult(int timeout) {
if (!(IsResolved || GetFulfillSignal().Wait(timeout)))
throw new TimeoutException();
}
protected Signal GetFulfillSignal() {
var next = new ResolvableSignal();
Then(next);
return next.Signal;
}
#endregion
public Type ResultType {
get {
return typeof(void);
}
}
protected void Rethrow() {
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() {
Join();
}
void IPromise.Join(int timeout) {
Join(timeout);
}
public T Join() {
WaitResult(-1);
if (IsRejected)
Rethrow();
return m_result;
}
public T Join(int timeout) {
WaitResult(timeout);
if (IsRejected)
Rethrow();
return m_result;
}
}
}