##// END OF EJS Templates
Reworked cancelation handling, if the cancel handler isn't specified the OperationCanceledException will be handled by the error handler...
Reworked cancelation handling, if the cancel handler isn't specified the OperationCanceledException will be handled by the error handler Any unhandled OperationCanceledException will cause the promise cancelation

File last commit:

r156:97fbbf816844 v2
r187:dd4a3590f9c6 ref20160224
Show More
AbstractPromiseT.cs
206 lines | 6.7 KiB | text/x-csharp | CSharpLexer
using System;
using Implab.Parallels;
namespace Implab {
public abstract class AbstractPromise<T> : AbstractEvent<AbstractPromise<T>.HandlerDescriptor>, IPromise<T> {
public struct HandlerDescriptor {
readonly Action m_handler;
readonly Action<T> m_success;
readonly Action<Exception> m_error;
readonly Action<Exception> m_cancel;
readonly PromiseEventType m_mask;
public HandlerDescriptor(Action<T> success, Action<Exception> error, Action<Exception> cancel) {
m_success = success;
m_error = error;
m_cancel = cancel;
m_handler = null;
m_mask = 0;
}
public HandlerDescriptor(Action success, Action<Exception> error, Action<Exception> cancel) {
m_handler = success;
m_success = null;
m_error = error;
m_cancel = cancel;
m_mask = PromiseEventType.Success;
}
public HandlerDescriptor(Action handler, PromiseEventType mask) {
m_handler = handler;
m_mask = mask;
m_success = null;
m_error = null;
m_cancel = null;
}
public void SignalSuccess(T result) {
if (m_success != null) {
try {
m_success(result);
} catch(Exception err) {
SignalError(err);
}
} else if ((m_mask & PromiseEventType.Success) != 0 && m_handler != null) {
try {
m_handler();
} catch(Exception err) {
// avoid calling handler twice in case of error
if (m_error != null)
SignalError(err);
}
}
}
public void SignalError(Exception err) {
if (m_error != null) {
try {
m_error(err);
// Analysis disable once EmptyGeneralCatchClause
} catch {
}
} else if ((m_mask & PromiseEventType.Error) != 0 && m_handler != null) {
try {
m_handler();
// Analysis disable once EmptyGeneralCatchClause
} catch {
}
}
}
public void SignalCancel(Exception reason) {
if (m_cancel != null) {
try {
m_cancel(reason);
} catch (Exception err) {
SignalError(err);
}
} else if ((m_mask & PromiseEventType.Cancelled) != 0 && m_handler != null) {
try {
m_handler();
// Analysis disable once EmptyGeneralCatchClause
} catch {
}
}
}
}
public Type PromiseType {
get {
return typeof(T);
}
}
public T Join() {
WaitResult(-1);
return m_result;
}
public T Join(int timeout) {
WaitResult(timeout);
return m_result;
}
void IPromise.Join() {
WaitResult(-1);
}
void IPromise.Join(int timeout) {
WaitResult(timeout);
}
public IPromise<T> On(Action<T> success, Action<Exception> error, Action<Exception> cancel) {
AddHandler(new HandlerDescriptor(success, error, cancel));
return this;
}
public IPromise<T> On(Action<T> success, Action<Exception> error) {
AddHandler(new HandlerDescriptor(success, error, null));
return this;
}
public IPromise<T> On(Action<T> success) {
AddHandler(new HandlerDescriptor(success, null, null));
return this;
}
public IPromise<T> On(Action handler, PromiseEventType events) {
AddHandler(new HandlerDescriptor(handler, events));
return this;
}
public IPromise<T> On(Action success, Action<Exception> error, Action<Exception> cancel) {
AddHandler(new HandlerDescriptor(success, error, cancel));
return this;
}
public IPromise<T> On(Action success, Action<Exception> error) {
AddHandler(new HandlerDescriptor(success, error, null));
return this;
}
public IPromise<T> On(Action success) {
AddHandler(new HandlerDescriptor(success, null, null));
return this;
}
IPromise IPromise.On(Action success, Action<Exception> error, Action<Exception> cancel) {
AddHandler(new HandlerDescriptor(success, error, cancel));
return this;
}
IPromise IPromise.On(Action success, Action<Exception> error) {
AddHandler(new HandlerDescriptor(success, error, null));
return this;
}
IPromise IPromise.On(Action success) {
AddHandler(new HandlerDescriptor(success, null, null));
return this;
}
IPromise IPromise.On(Action handler, PromiseEventType events) {
AddHandler(new HandlerDescriptor(handler, events));
return this;
}
public IPromise<T2> Cast<T2>() {
return (IPromise<T2>)this;
}
#region implemented abstract members of AbstractPromise
protected override Signal GetResolveSignal() {
var signal = new Signal();
AddHandler(new HandlerDescriptor(signal.Set, PromiseEventType.All));
return signal;
}
protected override void SignalHandler(HandlerDescriptor handler, int signal) {
switch (signal) {
case SUCCEEDED_STATE:
handler.SignalSuccess(m_result);
break;
case REJECTED_STATE:
handler.SignalError(Error);
break;
case CANCELLED_STATE:
handler.SignalCancel(CancellationReason);
break;
default:
throw new InvalidOperationException(String.Format("Invalid promise signal: {0}", signal));
}
}
#endregion
T m_result;
protected void SetResult(T value) {
if (BeginSetResult()) {
m_result = value;
EndSetResult();
}
}
}
}