view 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 source

using System;
using System.Diagnostics;
using System.Reflection;
using Implab.Parallels;

namespace Implab {
    public class AbstractPromise : AbstractEvent<IResolvable>, IPromise {

        class ResolvableSignal : IResolvable {
            public Signal Signal { get; private set; }
            public ResolvableSignal() {
                Signal = new Signal();
            }


            public void Reject(Exception error) {
                Signal.Set();
            }

            public void Resolve() {
                Signal.Set();
            }
        }

        PromiseState m_state;

        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() {
            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 handler) {
            switch (m_state) {
                case PromiseState.Fulfilled:
                    handler.Resolve();
                    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 next) {
            AddHandler(next);
        }

        public IPromise<T> Cast<T>() {
            throw new InvalidCastException();
        }

        public void Join() {
            WaitResult(-1);
            if (IsRejected)
                Rethrow();
        }

        public void Join(int timeout) {
            WaitResult(timeout);
        }
    }
}