diff Implab/AbstractPromise`1.cs @ 247:fb70574741a1 v3

working on promises
author cin
date Fri, 26 Jan 2018 18:46:27 +0300
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Implab/AbstractPromise`1.cs	Fri Jan 26 18:46:27 2018 +0300
@@ -0,0 +1,161 @@
+using System;
+using System.Diagnostics;
+using System.Reflection;
+using Implab.Parallels;
+
+namespace Implab {
+    public class AbstractPromise<T> : AbstractEvent<IResolvable<T>>, IPromise<T> {
+
+        class ResolvableSignal : IResolvable<T> {
+            public Signal Signal { get; private set; }
+            public ResolvableSignal() {
+                Signal = new Signal();
+            }
+
+
+            public void Reject(Exception error) {
+                Signal.Set();
+            }
+
+            public void Resolve(T result) {
+                Signal.Set();
+            }
+        }
+
+        class ResolvableWrapper : IResolvable<T> {
+            readonly IResolvable m_resolvable;
+            public ResolvableWrapper(IResolvable resolvable) {
+
+            }
+
+            public void Reject(Exception reason) {
+                m_resolvable.Reject(reason);
+            }
+
+            public void Resolve(T value) {
+                m_resolvable.Resolve();
+            }
+        }
+
+        PromiseState m_state;
+
+        T m_result;
+
+        Exception m_error;
+
+        public bool IsRejected {
+            get {
+                return m_state == PromiseState.Rejected;
+            }
+        }
+
+        public bool IsFulfilled {
+            get {
+                return m_state == PromiseState.Fulfilled;
+            }
+        }
+
+        public Exception RejectReason {
+            get {
+                return m_error;
+            }
+        }
+
+
+        internal void Resolve(T result) {
+            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(IResolvable<T> handler) {
+            switch (m_state) {
+                case PromiseState.Fulfilled:
+                    handler.Resolve(m_result);
+                    break;
+                case PromiseState.Rejected:
+                    handler.Reject(RejectReason);
+                    break;
+                default:
+                    throw new InvalidOperationException(String.Format("Invalid promise signal: {0}", m_state));
+            }
+        }
+
+        protected override Signal GetFulfillSignal() {
+            var next = new ResolvableSignal();
+            Then(next);
+            return next.Signal;
+        }
+
+        #endregion
+
+        protected void CompleteResolve() {
+            m_state = PromiseState.Fulfilled;
+            CompleteTransit();
+        }
+
+        public Type ResultType {
+            get {
+                return typeof(void);
+            }
+        }
+
+
+        protected void Rethrow() {
+            Debug.Assert(m_error != null);
+            if (m_error is OperationCanceledException)
+                throw new OperationCanceledException("Operation cancelled", m_error);
+            else
+                throw new TargetInvocationException(m_error);
+        }
+
+        public void Then(IResolvable<T> next) {
+            AddHandler(next);
+        }
+
+        public void Then(IResolvable next) {
+            AddHandler(new ResolvableWrapper(next));
+        }
+
+        public IPromise<T2> Cast<T2>() {
+            return (IPromise<T2>)this;
+        }
+
+        void IPromise.Join() {
+            WaitResult(-1);
+            if (IsRejected)
+                Rethrow();
+        }
+
+        void IPromise.Join(int timeout) {
+            WaitResult(timeout);
+            if (IsRejected)
+                Rethrow();
+        }
+
+        public T Join() {
+            WaitResult(-1);
+            if (IsRejected)
+                Rethrow();
+            return m_result;
+        }
+
+        public T Join(int timeout) {
+            WaitResult(timeout);
+            if (IsRejected)
+                Rethrow();
+            return m_result;
+        }
+    }
+}
+