# HG changeset patch # User cin # Date 2018-01-25 16:09:16 # Node ID eee3e49dd1ff5124cded2637ae947b669b357c48 # Parent b1e0ffdf34514bbebd7c80df2ca39256fb63670c working on promises diff --git a/Implab/AbstractEvent.cs b/Implab/AbstractEvent.cs --- a/Implab/AbstractEvent.cs +++ b/Implab/AbstractEvent.cs @@ -35,31 +35,31 @@ namespace Implab { /// /// public abstract class AbstractEvent where THandler : class { - const int PENDING_SATE = 0; + const int PendingState = 0; - const int TRANSITIONAL_STATE = 1; + const int TransitionalState = 1; - const int FULFILLED_STATE = 2; + const int ResolvedState = 2; volatile int m_state; THandler m_handler; SimpleAsyncQueue m_extraHandlers; - public bool IsFulfilled { + public bool IsResolved { get { - return m_state > TRANSITIONAL_STATE; + return m_state > TransitionalState; } } #region state managment protected bool BeginTransit() { - return PENDING_SATE == Interlocked.CompareExchange(ref m_state, TRANSITIONAL_STATE, PENDING_SATE); + return PendingState == Interlocked.CompareExchange(ref m_state, TransitionalState, PendingState); } protected void CompleteTransit() { #if DEBUG - if (TRANSITIONAL_STATE != Interlocked.CompareExchange(ref m_state, FULFILLED_STATE, TRANSITIONAL_STATE)) + if (TransitionalState != Interlocked.CompareExchange(ref m_state, ResolvedState, TransitionalState)) throw new InvalidOperationException("Can't complete transition when the object isn't in the transitional state"); #else m_state = state; @@ -68,11 +68,11 @@ namespace Implab { } protected void WaitTransition() { - if (m_state == TRANSITIONAL_STATE) { + if (m_state == TransitionalState) { SpinWait spin; do { spin.SpinOnce(); - } while (m_state == TRANSITIONAL_STATE); + } while (m_state == TransitionalState); } } @@ -91,7 +91,7 @@ namespace Implab { #region synchronization traits protected void WaitResult(int timeout) { - if (!(IsFulfilled || GetFulfillSignal().Wait(timeout))) + if (!(IsResolved || GetFulfillSignal().Wait(timeout))) throw new TimeoutException(); } @@ -102,13 +102,13 @@ namespace Implab { protected void AddHandler(THandler handler) { - if (IsFulfilled) { + if (IsResolved) { // the promise is in the resolved state, just invoke the handler SignalHandler(handler); } else { EnqueueHandler(handler); - if (IsFulfilled && TryDequeueHandler(out handler)) + if (IsResolved && TryDequeueHandler(out handler)) // if the promise have been resolved while we was adding the handler to the queue // we can't guarantee that someone is still processing it // therefore we need to fetch a handler from the queue and execute it diff --git a/Implab/AbstractPromise.cs b/Implab/AbstractPromise.cs --- a/Implab/AbstractPromise.cs +++ b/Implab/AbstractPromise.cs @@ -4,36 +4,21 @@ using System.Reflection; using Implab.Parallels; namespace Implab { - public abstract class AbstractPromise : AbstractEvent, IPromise { - public class HandlerDescriptor { - readonly Action m_resolve; - readonly Action m_reject; + public class AbstractPromise : AbstractEvent, IPromise { - readonly IDeferred m_deferred; - public HandlerDescriptor(Action success, Action error) { - m_resolve = success; - m_reject = error; + class ResolvableSignal : IResolvable { + public Signal Signal { get; private set; } + public ResolvableSignal() { + Signal = new Signal(); } - public void SignalSuccess() { - try { - if (m_resolve != null) - m_resolve(); - m_deferred.Resolve(); - } catch (Exception ex) { - m_deferred.Reject(ex); - } + + public void Reject(Exception error) { + Signal.Set(); } - public void SignalError(Exception err) { - if (m_reject != null) { - try { - m_reject(err); - m_deferred.Resolve(); - } catch (Exception ex) { - m_deferred.Reject(ex); - } - } + public void Resolve() { + Signal.Set(); } } @@ -47,9 +32,9 @@ namespace Implab { } } - public bool IsResolved { + public bool IsFulfilled { get { - return m_state == PromiseState.Resolved; + return m_state == PromiseState.Fulfilled; } } @@ -60,15 +45,29 @@ namespace Implab { } + internal void Resolve() { + if (BeginTransit()) + CompleteResolve(); + } + + internal void Reject(Exception reason) { + if (BeginTransit()) { + m_error = reason; + m_state = PromiseState.Rejected; + CompleteTransit(); + } + } + + #region implemented abstract members of AbstractPromise - protected override void SignalHandler(HandlerDescriptor handler) { + protected override void SignalHandler(IResolvable handler) { switch (m_state) { - case PromiseState.Resolved: - handler.SignalSuccess(); + case PromiseState.Fulfilled: + handler.Resolve(); break; case PromiseState.Rejected: - handler.SignalError(RejectReason); + handler.Reject(RejectReason); break; default: throw new InvalidOperationException(String.Format("Invalid promise signal: {0}", m_state)); @@ -76,15 +75,15 @@ namespace Implab { } protected override Signal GetFulfillSignal() { - var signal = new Signal(); - On(signal.Set, e => signal.Set()); - return signal; + var next = new ResolvableSignal(); + Then(next); + return next.Signal; } #endregion protected void CompleteResolve() { - m_state = PromiseState.Resolved; + m_state = PromiseState.Fulfilled; CompleteTransit(); } @@ -94,27 +93,6 @@ namespace Implab { } } - /// - /// Выполняет обещание, сообщая об ошибке - /// - /// - /// Поскольку обещание должно работать в многопточной среде, при его выполнении сразу несколько потоков - /// могу вернуть ошибку, при этом только первая будет использована в качестве результата, остальные - /// будут проигнорированы. - /// - /// Исключение возникшее при выполнении операции - /// Данное обещание уже выполнено - protected void SetError(Exception error) { - if (BeginTransit()) { - m_error = error; - m_state = PromiseState.Rejected; - CompleteTransit(); - } else { - WaitTransition(); - if (m_state == PromiseState.Resolved) - throw new InvalidOperationException("The promise is already resolved"); - } - } protected void Rethrow() { Debug.Assert(m_error != null); @@ -124,8 +102,8 @@ namespace Implab { throw new TargetInvocationException(m_error); } - public void On(Action success, Action error) { - AddHandler(new HandlerDescriptor(success, error)); + public void Then(IResolvable next) { + AddHandler(next); } public IPromise Cast() { diff --git a/Implab/ActionChainTask.cs b/Implab/ActionChainTask.cs --- a/Implab/ActionChainTask.cs +++ b/Implab/ActionChainTask.cs @@ -1,7 +1,7 @@ using System; namespace Implab { - public class ActionChainTask : ActionChainTaskBase, IDeferred { + public class ActionChainTask : ActionChainTaskBase, IResolvable { readonly Func m_task; /// diff --git a/Implab/ActionTask.cs b/Implab/ActionTask.cs --- a/Implab/ActionTask.cs +++ b/Implab/ActionTask.cs @@ -1,7 +1,7 @@ using System; namespace Implab { - public class ActionTask : ActionTaskBase, IDeferred { + public class ActionTask : ActionTaskBase, IResolvable { readonly Action m_task; public ActionTask(Action task, Action error, Action cancel, bool autoCancellable) : base(error,cancel, autoCancellable) { m_task = task; diff --git a/Implab/Components/RunnableComponent.cs b/Implab/Components/RunnableComponent.cs --- a/Implab/Components/RunnableComponent.cs +++ b/Implab/Components/RunnableComponent.cs @@ -1,6 +1,6 @@ using System; -using System.Diagnostics.CodeAnalysis; - +using System.Diagnostics.CodeAnalysis; + namespace Implab.Components { public abstract class RunnableComponent : IDisposable, IRunnable, IInitializable { enum Commands { @@ -18,28 +18,28 @@ namespace Implab.Components { public static readonly ExecutionState[,] ReusableTransitions; public static readonly ExecutionState[,] NonreusableTransitions; - class StateBuilder { - readonly ExecutionState[,] m_states; - - public ExecutionState[,] States { - get { return m_states; } - } - public StateBuilder(ExecutionState[,] states) { - m_states = states; - } - - public StateBuilder() { - m_states = new ExecutionState[(int)ExecutionState.Last + 1, (int)Commands.Last + 1]; - } - - public StateBuilder Edge(ExecutionState s1, ExecutionState s2, Commands cmd) { - m_states[(int)s1, (int)cmd] = s2; - return this; - } - - public StateBuilder Clone() { - return new StateBuilder((ExecutionState[,])m_states.Clone()); - } + class StateBuilder { + readonly ExecutionState[,] m_states; + + public ExecutionState[,] States { + get { return m_states; } + } + public StateBuilder(ExecutionState[,] states) { + m_states = states; + } + + public StateBuilder() { + m_states = new ExecutionState[(int)ExecutionState.Last + 1, (int)Commands.Last + 1]; + } + + public StateBuilder Edge(ExecutionState s1, ExecutionState s2, Commands cmd) { + m_states[(int)s1, (int)cmd] = s2; + return this; + } + + public StateBuilder Clone() { + return new StateBuilder((ExecutionState[,])m_states.Clone()); + } } static StateMachine() { @@ -65,8 +65,8 @@ namespace Implab.Components { .Edge(ExecutionState.Running, ExecutionState.Disposed, Commands.Dispose) .Edge(ExecutionState.Failed, ExecutionState.Disposed, Commands.Dispose) - .Edge(ExecutionState.Failed, ExecutionState.Initializing, Commands.Reset) - + .Edge(ExecutionState.Failed, ExecutionState.Initializing, Commands.Reset) + .Edge(ExecutionState.Stopping, ExecutionState.Failed, Commands.Fail) .Edge(ExecutionState.Stopping, ExecutionState.Disposed, Commands.Dispose) @@ -74,11 +74,11 @@ namespace Implab.Components { var reusable = common .Clone() - .Edge(ExecutionState.Stopping, ExecutionState.Ready, Commands.Ok); - - var nonreusable = common - .Clone() - .Edge(ExecutionState.Stopping, ExecutionState.Disposed, Commands.Ok); + .Edge(ExecutionState.Stopping, ExecutionState.Ready, Commands.Ok); + + var nonreusable = common + .Clone() + .Edge(ExecutionState.Stopping, ExecutionState.Disposed, Commands.Ok); NonreusableTransitions = nonreusable.States; ReusableTransitions = reusable.States; @@ -109,45 +109,45 @@ namespace Implab.Components { IPromise m_pending; Exception m_lastError; - readonly StateMachine m_stateMachine; - readonly bool m_reusable; - public event EventHandler StateChanged; - - /// - /// Initializes component state. - /// - /// If set, the component initial state is and the component is ready to start, otherwise initialization is required. - /// If set, the component may start after it has been stopped, otherwise the component is disposed after being stopped. - protected RunnableComponent(bool initialized, bool reusable) { + readonly StateMachine m_stateMachine; + readonly bool m_reusable; + public event EventHandler StateChanged; + + /// + /// Initializes component state. + /// + /// If set, the component initial state is and the component is ready to start, otherwise initialization is required. + /// If set, the component may start after it has been stopped, otherwise the component is disposed after being stopped. + protected RunnableComponent(bool initialized, bool reusable) { m_stateMachine = new StateMachine( reusable ? StateMachine.ReusableTransitions : StateMachine.NonreusableTransitions, initialized ? ExecutionState.Ready : ExecutionState.Created ); m_reusable = reusable; - } - - /// - /// Initializes component state. The component created with this constructor is not reusable, i.e. it will be disposed after stop. - /// - /// If set, the component initial state is and the component is ready to start, otherwise initialization is required. + } + + /// + /// Initializes component state. The component created with this constructor is not reusable, i.e. it will be disposed after stop. + /// + /// If set, the component initial state is and the component is ready to start, otherwise initialization is required. protected RunnableComponent(bool initialized) : this(initialized, false) { } void ThrowInvalidCommand(Commands cmd) { if (m_stateMachine.State == ExecutionState.Disposed) - throw new ObjectDisposedException(ToString()); - + throw new ObjectDisposedException(ToString()); + throw new InvalidOperationException(String.Format("Command {0} is not allowed in the state {1}", cmd, m_stateMachine.State)); } bool MoveIfInState(Commands cmd, IPromise pending, Exception error, ExecutionState state) { ExecutionState prev, current; - lock (m_stateMachine) { - if (m_stateMachine.State != state) - return false; - - prev = m_stateMachine.State; - if (!m_stateMachine.Move(cmd)) + lock (m_stateMachine) { + if (m_stateMachine.State != state) + return false; + + prev = m_stateMachine.State; + if (!m_stateMachine.Move(cmd)) ThrowInvalidCommand(cmd); current = m_stateMachine.State; @@ -161,46 +161,46 @@ namespace Implab.Components { bool MoveIfPending(Commands cmd, IPromise pending, Exception error, IPromise expected) { ExecutionState prev, current; - lock (m_stateMachine) { - if (m_pending != expected) - return false; - prev = m_stateMachine.State; - if (!m_stateMachine.Move(cmd)) + lock (m_stateMachine) { + if (m_pending != expected) + return false; + prev = m_stateMachine.State; + if (!m_stateMachine.Move(cmd)) ThrowInvalidCommand(cmd); current = m_stateMachine.State; m_pending = pending; m_lastError = error; - } + } if (prev != current) - OnStateChanged(prev, current, error); + OnStateChanged(prev, current, error); return true; } IPromise Move(Commands cmd, IPromise pending, Exception error) { ExecutionState prev, current; IPromise ret; - lock (m_stateMachine) { - prev = m_stateMachine.State; - if (!m_stateMachine.Move(cmd)) + lock (m_stateMachine) { + prev = m_stateMachine.State; + if (!m_stateMachine.Move(cmd)) ThrowInvalidCommand(cmd); current = m_stateMachine.State; ret = m_pending; m_pending = pending; - m_lastError = error; - + m_lastError = error; + } if (prev != current) OnStateChanged(prev, current, error); return ret; } - /// - /// Handles the state of the component change event, raises the event, handles - /// the transition to the state (calls method). - /// - /// The previous state - /// The current state + /// + /// Handles the state of the component change event, raises the event, handles + /// the transition to the state (calls method). + /// + /// The previous state + /// The current state /// The last error if any. /// /// @@ -212,31 +212,31 @@ namespace Implab.Components { /// the wrong behavior of the component. /// /// - protected virtual void OnStateChanged(ExecutionState previous, ExecutionState current, Exception error) { - StateChanged.DispatchEvent( - this, - new StateChangeEventArgs { - State = current, - LastError = error - } - ); - if (current == ExecutionState.Disposed) { - GC.SuppressFinalize(this); - Dispose(true); - } + protected virtual void OnStateChanged(ExecutionState previous, ExecutionState current, Exception error) { + StateChanged.DispatchEvent( + this, + new StateChangeEventArgs { + State = current, + LastError = error + } + ); + if (current == ExecutionState.Disposed) { + GC.SuppressFinalize(this); + Dispose(true); + } } /// /// Moves the component from running to failed state. /// /// The exception which is describing the error. - protected bool Fail(Exception error) { - return MoveIfInState(Commands.Fail, null, error, ExecutionState.Running); + protected bool Fail(Exception error) { + return MoveIfInState(Commands.Fail, null, error, ExecutionState.Running); } - /// - /// Tries to reset state to . - /// + /// + /// Tries to reset state to . + /// /// True if component is reset to , false if the componet wasn't /// in state. /// @@ -246,10 +246,10 @@ namespace Implab.Components { /// to state, otherwise the component is moved to /// state. If throws an exception it will be propagated by this method to the caller. /// - protected bool ResetState() { - if (!MoveIfInState(Commands.Reset, null, null, ExecutionState.Failed)) - return false; - + protected bool ResetState() { + if (!MoveIfInState(Commands.Reset, null, null, ExecutionState.Failed)) + return false; + try { OnResetState(); Move(Commands.Ok, null, null); @@ -257,38 +257,38 @@ namespace Implab.Components { } catch (Exception err) { Move(Commands.Fail, null, err); throw; - } + } } - /// - /// This method is called by to reinitialize component in the failed state. + /// + /// This method is called by to reinitialize component in the failed state. /// /// /// Default implementation throws which will cause the component /// fail to reset it's state and it left in state. /// If this method doesn't throw exceptions the component is moved to state. /// - protected virtual void OnResetState() { - throw new NotImplementedException(); + protected virtual void OnResetState() { + throw new NotImplementedException(); } - IPromise InvokeAsync(Commands cmd, Func action, Action chain) { + IPromise InvokeAsync(Commands cmd, Func action, Action chain) { IPromise promise = null; IPromise prev; var task = new ActionChainTask(action, null, null, true); - Action errorOrCancel = e => { - if (e == null) - e = new OperationCanceledException(); - MoveIfPending(Commands.Fail, null, e, promise); - throw new PromiseTransientException(e); + Action errorOrCancel = e => { + if (e == null) + e = new OperationCanceledException(); + MoveIfPending(Commands.Fail, null, e, promise); + throw new PromiseTransientException(e); }; promise = task.Then( () => MoveIfPending(Commands.Ok, null, null, promise), errorOrCancel, - errorOrCancel + errorOrCancel ); prev = Move(cmd, promise, null); @@ -305,8 +305,8 @@ namespace Implab.Components { #region IInitializable implementation public void Initialize() { - Move(Commands.Init, null, null); - + Move(Commands.Init, null, null); + try { OnInitialize(); Move(Commands.Ok, null, null); @@ -344,7 +344,7 @@ namespace Implab.Components { /// /// Current. /// Stop. - protected virtual void StopPending(IPromise current, IDeferred stop) { + protected virtual void StopPending(IPromise current, IResolvable stop) { if (current == null) { stop.Resolve(); } else { @@ -398,11 +398,11 @@ namespace Implab.Components { #endregion - /// - /// Releases all resources used by the component, called automatically, override this method to implement your cleanup. - /// - /// true if this method is called during normal dispose process. - /// The operation which is currenty pending + /// + /// Releases all resources used by the component, called automatically, override this method to implement your cleanup. + /// + /// true if this method is called during normal dispose process. + /// The operation which is currenty pending protected virtual void Dispose(bool disposing) { } diff --git a/Implab/Deferred.cs b/Implab/Deferred.cs new file mode 100644 --- /dev/null +++ b/Implab/Deferred.cs @@ -0,0 +1,52 @@ +using System; +using System.Diagnostics; + +namespace Implab { + /// + /// This class is responsible for the promise resolution, dispatching and chaining + /// + public class Deferred : IResolvable { + + readonly AbstractPromise m_promise; + readonly IDispatcher m_dispatcher; + + internal Deferred(AbstractPromise promise, IDispatcher dispatcher) { + Debug.Assert(promise != null); + m_promise = promise; + m_dispatcher = dispatcher; + } + + public IPromise Promise { + get { return m_promise; } + } + + public void Reject(Exception error) { + m_promise.Reject(error); + } + + public void Resolve() { + m_promise.Resolve(); + } + + public void Resolve(IPromise thenable) { + if (thenable == null) + Reject(new Exception("The promise or task are expected")); + if (thenable == m_promise) + Reject(new Exception("The promise cannot be resolved with oneself")); + + else if (m_dispatcher != null) + // dispatch (see ecma-262/6.0: 25.4.1.3.2 Promise Resolve Functions) + m_dispatcher.Enqueue(() => thenable.Then(this)); + else + thenable.Then(this); + } + + void Chain(IPromise thenable) { + try { + thenable.Then(this); + } catch (Exception err) { + Reject(err); + } + } + } +} \ No newline at end of file diff --git a/Implab/FuncChainTask.cs b/Implab/FuncChainTask.cs --- a/Implab/FuncChainTask.cs +++ b/Implab/FuncChainTask.cs @@ -1,7 +1,7 @@ using System; namespace Implab { - public class FuncChainTask : FuncChainTaskBase, IDeferred { + public class FuncChainTask : FuncChainTaskBase, IResolvable { readonly Func> m_task; public FuncChainTask(Func> task, Func> error, Func> cancel, bool autoCancellable) diff --git a/Implab/FuncTask.cs b/Implab/FuncTask.cs --- a/Implab/FuncTask.cs +++ b/Implab/FuncTask.cs @@ -2,7 +2,7 @@ using System.Threading; namespace Implab { - public class FuncTask : FuncTaskBase, IDeferred { + public class FuncTask : FuncTaskBase, IResolvable { readonly Func m_task; public FuncTask(Func task, Func error, Func cancel, bool autoCancellable) : base(error, cancel, autoCancellable) { diff --git a/Implab/IDeferred.cs b/Implab/IDeferred.cs deleted file mode 100644 --- a/Implab/IDeferred.cs +++ /dev/null @@ -1,31 +0,0 @@ -using System; - -namespace Implab { - /// - /// Deferred result, usually used by asynchronous services as the service part of the promise. - /// - public interface IDeferred { - - void Resolve(); - - /// - /// Reject the promise with the specified error. - /// - /// The reason why the promise is rejected. - /// - /// Some exceptions are treated in a special case: - /// is interpreted as call to method, - /// and is always unwrapped and its - /// is used as the reason to reject promise. - /// - void Reject(Exception error); - - /// - /// Marks current instance as cencelled with the specified reason. - /// - /// The reason for the operation cancellation, - /// if not specified the new will be created - void SetCancelled(Exception reason); - } -} - diff --git a/Implab/IDispatcher.cs b/Implab/IDispatcher.cs new file mode 100644 --- /dev/null +++ b/Implab/IDispatcher.cs @@ -0,0 +1,7 @@ +using System; + +namespace Implab { + public interface IDispatcher { + void Enqueue(Action job); + } +} \ No newline at end of file diff --git a/Implab/IPromise.cs b/Implab/IPromise.cs --- a/Implab/IPromise.cs +++ b/Implab/IPromise.cs @@ -14,11 +14,11 @@ namespace Implab { /// /// Обещание является выполненым, либо успешно, либо с ошибкой, либо отменено. /// - bool IsFulfilled { get; } + bool IsResolved { get; } bool IsRejected { get; } - bool IsResolved { get; } + bool IsFulfilled { get; } /// /// Исключение возникшее в результате выполнения обещания, либо причина отмены. @@ -31,23 +31,11 @@ namespace Implab { /// The handler called on the successful promise completion. /// The handler is called if an error while completing the promise occurred. /// The current promise. - void On(Action success, Action error); + void Then(IResolvable next); /// /// Преобразует результат обещания к заданному типу и возвращает новое обещание. /// IPromise Cast(); - - /// - /// Синхронизирует текущий поток с обещанием. - /// - void Join(); - /// - /// Синхронизирует текущий поток с обещанием. - /// - /// Время ожидания, по его истечению возникнет исключение. - /// Превышено время ожидания. - void Join(int timeout); - } } diff --git a/Implab/IResolvable.cs b/Implab/IResolvable.cs new file mode 100644 --- /dev/null +++ b/Implab/IResolvable.cs @@ -0,0 +1,26 @@ +using System; + +namespace Implab { + /// + /// Deferred result, usually used by asynchronous services as the service part of the promise. + /// + public interface IResolvable { + + void Resolve(); + + void Resolve(IPromise thenable); + + /// + /// Reject the promise with the specified error. + /// + /// The reason why the promise is rejected. + /// + /// Some exceptions are treated in a special case: + /// is interpreted as call to method, + /// and is always unwrapped and its + /// is used as the reason to reject promise. + /// + void Reject(Exception error); + } +} + diff --git a/Implab/Implab.old.csproj b/Implab/Implab.old.csproj deleted file mode 100644 --- a/Implab/Implab.old.csproj +++ /dev/null @@ -1,189 +0,0 @@ - - - - Debug - AnyCPU - {F550F1F8-8746-4AD0-9614-855F4C4B7F05} - Library - Implab - Implab - v4.5 - - - - true - full - true - bin\Debug - TRACE;DEBUG;NET_4_5 - prompt - 4 - false - true - - - full - true - bin\Release - NET_4_5 - prompt - 4 - false - - - false - - - implab.snk - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Designer - - - - - - - \ No newline at end of file diff --git a/Implab/Promise.cs b/Implab/Promise.cs deleted file mode 100644 --- a/Implab/Promise.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System; -using Implab.Parallels; - -namespace Implab { - public class Promise : AbstractPromise { - public static readonly IPromise Success; - - static Promise() { - Success = new SuccessPromise(); - } - - internal void ResolvePromise() { - SetResult(); - } - - internal void RejectPromise(Exception error) { - SetError(error); - } - - public static IPromise Reject(Exception exception) { - return new FailedPromise(exception); - } - } -} - diff --git a/Implab/PromiseState.cs b/Implab/PromiseState.cs --- a/Implab/PromiseState.cs +++ b/Implab/PromiseState.cs @@ -2,7 +2,7 @@ namespace Implab { public enum PromiseState { Pending, - Resolved, + Fulfilled, Rejected }