using System; using Implab.Parallels; namespace Implab { public abstract class AbstractPromise : AbstractEvent.HandlerDescriptor>, IPromise { public struct HandlerDescriptor { readonly Action m_handler; readonly Action m_success; readonly Action m_error; readonly Action m_cancel; readonly PromiseEventType m_mask; public HandlerDescriptor(Action success, Action error, Action cancel) { m_success = success; m_error = error; m_cancel = cancel; m_handler = null; m_mask = 0; } public HandlerDescriptor(Action success, Action error, Action 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); // Analysis disable once EmptyGeneralCatchClause } catch { } } else if ((m_mask & PromiseEventType.Success) != 0 && m_handler != null) { try { m_handler(); // Analysis disable once EmptyGeneralCatchClause } catch { } } } 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); // Analysis disable once EmptyGeneralCatchClause } catch { } } else if ((m_mask & PromiseEventType.Cancelled) != 0 && m_handler != null) { try { m_handler(); // Analysis disable once EmptyGeneralCatchClause } catch { } } } } public Type ResultType { 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 On(Action success, Action error, Action cancel) { AddHandler(new HandlerDescriptor(success, error, cancel)); return this; } public IPromise On(Action success, Action error) { AddHandler(new HandlerDescriptor(success, error, null)); return this; } public IPromise On(Action success) { AddHandler(new HandlerDescriptor(success, null, null)); return this; } public IPromise On(Action handler, PromiseEventType events) { AddHandler(new HandlerDescriptor(handler, events)); return this; } public IPromise On(Action success, Action error, Action cancel) { AddHandler(new HandlerDescriptor(success, error, cancel)); return this; } public IPromise On(Action success, Action error) { AddHandler(new HandlerDescriptor(success, error, null)); return this; } public IPromise On(Action success) { AddHandler(new HandlerDescriptor(success, null, null)); return this; } IPromise IPromise.On(Action success, Action error, Action cancel) { AddHandler(new HandlerDescriptor(success, error, cancel)); return this; } IPromise IPromise.On(Action success, Action 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 Cast() { return (IPromise)this; } #region implemented abstract members of AbstractPromise protected override Signal GetFulfillSignal() { 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(RejectReason); 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(); } } } }