diff Implab/AbstractPromise.cs @ 244:eee3e49dd1ff v3

working on promises
author cin
date Thu, 25 Jan 2018 19:09:16 +0300
parents b1e0ffdf3451
children fb70574741a1
line wrap: on
line diff
--- a/Implab/AbstractPromise.cs	Wed Jan 24 19:24:10 2018 +0300
+++ b/Implab/AbstractPromise.cs	Thu Jan 25 19:09:16 2018 +0300
@@ -4,36 +4,21 @@
 using Implab.Parallels;
 
 namespace Implab {
-    public abstract class AbstractPromise : AbstractEvent<AbstractPromise.HandlerDescriptor>, IPromise {
-        public class HandlerDescriptor {
-            readonly Action m_resolve;
-            readonly Action<Exception> m_reject;
+    public class AbstractPromise : AbstractEvent<IResolvable>, IPromise {
 
-            readonly IDeferred m_deferred;
-            public HandlerDescriptor(Action success, Action<Exception> 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 @@
             }
         }
 
-        public bool IsResolved {
+        public bool IsFulfilled {
             get {
-                return m_state == PromiseState.Resolved;
+                return m_state == PromiseState.Fulfilled;
             }
         }
 
@@ -60,15 +45,29 @@
         }
 
 
+        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 @@
         }
 
         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 @@
             }
         }
 
-        /// <summary>
-        /// Выполняет обещание, сообщая об ошибке
-        /// </summary>
-        /// <remarks>
-        /// Поскольку обещание должно работать в многопточной среде, при его выполнении сразу несколько потоков
-        /// могу вернуть ошибку, при этом только первая будет использована в качестве результата, остальные
-        /// будут проигнорированы.
-        /// </remarks>
-        /// <param name="error">Исключение возникшее при выполнении операции</param>
-        /// <exception cref="InvalidOperationException">Данное обещание уже выполнено</exception>
-        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 @@
                 throw new TargetInvocationException(m_error);
         }
 
-        public void On(Action success, Action<Exception> error) {
-            AddHandler(new HandlerDescriptor(success, error));
+        public void Then(IResolvable next) {
+            AddHandler(next);
         }
 
         public IPromise<T> Cast<T>() {