AbstractPromiseT.cs
206 lines
| 6.7 KiB
| text/x-csharp
|
CSharpLexer
/ Implab / AbstractPromiseT.cs
cin
|
r144 | 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; | ||||
cin
|
r145 | |||
m_handler = null; | ||||
m_mask = 0; | ||||
cin
|
r144 | } | ||
public HandlerDescriptor(Action success, Action<Exception> error, Action<Exception> cancel) { | ||||
m_handler = success; | ||||
cin
|
r145 | m_success = null; | ||
cin
|
r144 | m_error = error; | ||
m_cancel = cancel; | ||||
m_mask = PromiseEventType.Success; | ||||
} | ||||
public HandlerDescriptor(Action handler, PromiseEventType mask) { | ||||
m_handler = handler; | ||||
m_mask = mask; | ||||
cin
|
r145 | m_success = null; | ||
m_error = null; | ||||
m_cancel = null; | ||||
cin
|
r144 | } | ||
public void SignalSuccess(T result) { | ||||
if (m_success != null) { | ||||
try { | ||||
m_success(result); | ||||
} catch(Exception err) { | ||||
SignalError(err); | ||||
} | ||||
cin
|
r145 | } else if ((m_mask & PromiseEventType.Success) != 0 && m_handler != null) { | ||
cin
|
r144 | 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 { | ||||
} | ||||
cin
|
r145 | } else if ((m_mask & PromiseEventType.Error) != 0 && m_handler != null) { | ||
cin
|
r144 | 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); | ||||
} | ||||
cin
|
r145 | } else if ((m_mask & PromiseEventType.Cancelled) != 0 && m_handler != null) { | ||
cin
|
r144 | try { | ||
m_handler(); | ||||
// Analysis disable once EmptyGeneralCatchClause | ||||
} catch { | ||||
} | ||||
} | ||||
} | ||||
} | ||||
public Type PromiseType { | ||||
get { | ||||
return typeof(T); | ||||
} | ||||
} | ||||
cin
|
r145 | public T Join() { | ||
cin
|
r144 | WaitResult(-1); | ||
return m_result; | ||||
} | ||||
cin
|
r145 | public T Join(int timeout) { | ||
cin
|
r144 | WaitResult(timeout); | ||
return m_result; | ||||
} | ||||
cin
|
r145 | void IPromise.Join() { | ||
WaitResult(-1); | ||||
} | ||||
void IPromise.Join(int timeout) { | ||||
WaitResult(timeout); | ||||
} | ||||
cin
|
r144 | 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; | ||||
} | ||||
cin
|
r145 | IPromise IPromise.On(Action handler, PromiseEventType events) { | ||
AddHandler(new HandlerDescriptor(handler, events)); | ||||
return this; | ||||
} | ||||
cin
|
r144 | 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; | ||||
} | ||||
cin
|
r156 | 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)); | ||||
} | ||||
cin
|
r144 | } | ||
#endregion | ||||
T m_result; | ||||
protected void SetResult(T value) { | ||||
if (BeginSetResult()) { | ||||
m_result = value; | ||||
EndSetResult(); | ||||
} | ||||
} | ||||
} | ||||
} | ||||