|
|
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;
|
|
|
}
|
|
|
|
|
|
public HandlerDescriptor(Action success, Action<Exception> error, Action<Exception> cancel) {
|
|
|
m_handler = success;
|
|
|
m_error = error;
|
|
|
m_cancel = cancel;
|
|
|
m_mask = PromiseEventType.Success;
|
|
|
}
|
|
|
|
|
|
public HandlerDescriptor(Action handler, PromiseEventType mask) {
|
|
|
m_handler = handler;
|
|
|
m_mask = mask;
|
|
|
}
|
|
|
|
|
|
public void SignalSuccess(T result) {
|
|
|
if (m_success != null) {
|
|
|
try {
|
|
|
m_success(result);
|
|
|
} catch(Exception err) {
|
|
|
SignalError(err);
|
|
|
}
|
|
|
} else if (m_mask & PromiseEventType.Success && 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 && 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 && m_handler != null) {
|
|
|
try {
|
|
|
m_handler();
|
|
|
// Analysis disable once EmptyGeneralCatchClause
|
|
|
} catch {
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public Type PromiseType {
|
|
|
get {
|
|
|
return typeof(T);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
public new T Join() {
|
|
|
WaitResult(-1);
|
|
|
return m_result;
|
|
|
}
|
|
|
public new T Join(int timeout) {
|
|
|
WaitResult(timeout);
|
|
|
return m_result;
|
|
|
}
|
|
|
|
|
|
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;
|
|
|
}
|
|
|
|
|
|
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 SignalSuccess(HandlerDescriptor handler) {
|
|
|
handler.SignalSuccess(m_result);
|
|
|
}
|
|
|
|
|
|
protected override void SignalError(HandlerDescriptor handler, Exception error) {
|
|
|
handler.SignalError(error);
|
|
|
}
|
|
|
|
|
|
protected override void SignalCancelled(HandlerDescriptor handler, Exception reason) {
|
|
|
handler.SignalCancel(reason);
|
|
|
}
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
T m_result;
|
|
|
|
|
|
protected void SetResult(T value) {
|
|
|
if (BeginSetResult()) {
|
|
|
m_result = value;
|
|
|
EndSetResult();
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|