protected static void ExchangePassthroughs(ref ValueLinkedStack <Internal.PromisePassThrough> from, ref ValueLinkedStack <Internal.PromisePassThrough> to)
 {
     // Remove this.passThroughs before adding to passThroughs. They are re-added by the caller.
     while (from.IsNotEmpty)
     {
         var passThrough = from.Pop();
         if (passThrough.Owner != null && passThrough.Owner._state != State.Pending)
         {
             // The owner already completed.
             passThrough.Release();
         }
         else
         {
             to.Push(passThrough);
         }
     }
 }
        private static void SubscribeProgressToBranchesAndRoots(Promise promise, Internal.IProgressListener progressListener)
        {
            // This allows us to subscribe progress to AllPromises and RacePromises iteratively instead of recursively
            ValueLinkedStack <Internal.PromisePassThrough> passThroughs = new ValueLinkedStack <Internal.PromisePassThrough>();

Repeat:
            SubscribeProgressToChain(promise, progressListener, ref passThroughs);

            if (passThroughs.IsNotEmpty)
            {
                // passThroughs are removed from their targets before adding to passThroughs. Add them back here.
                var passThrough = passThroughs.Pop();
                promise          = passThrough.Owner;
                progressListener = passThrough;
                passThrough.Target.ReAdd(passThrough);
                goto Repeat;
            }
        }
Пример #3
0
                public static Promise GetOrCreate(ValueLinkedStack <PromisePassThrough> promisePassThroughs, int count, int skipFrames)
                {
                    var promise = _pool.IsNotEmpty ? (RacePromise0)_pool.Pop() : new RacePromise0();

                    promise._passThroughs = promisePassThroughs;

                    promise._waitCount = (uint)count;
                    promise.Reset(skipFrames + 1);
                    // Retain this until all promises resolve/reject/cancel.
                    promise.RetainInternal();

                    foreach (var passThrough in promisePassThroughs)
                    {
                        passThrough.SetTargetAndAddToOwner(promise);
                    }

                    return(promise);
                }
Пример #4
0
        partial void ValidateReturn(Promise other)
        {
            if (other == null)
            {
                // Returning a null from the callback is not allowed.
                throw new InvalidReturnException("A null promise was returned.");
            }

            // Validate returned promise as not disposed.
            if (IsDisposed(other._valueOrPrevious))
            {
                throw new InvalidReturnException("A disposed promise was returned.", Internal.GetFormattedStacktrace(other));
            }

            // A promise cannot wait on itself.

            // This allows us to check All/Race/First Promises iteratively.
            ValueLinkedStack <InternalProtected.PromisePassThrough> passThroughs = new ValueLinkedStack <InternalProtected.PromisePassThrough>();
            var prev = other;

Repeat:
            for (; prev != null; prev = prev._valueOrPrevious as Promise)
            {
                if (prev == this)
                {
                    throw new InvalidReturnException("Circular Promise chain detected.", Internal.GetFormattedStacktrace(other));
                }
                prev.BorrowPassthroughs(ref passThroughs);
            }

            if (passThroughs.IsNotEmpty)
            {
                // passThroughs are removed from their targets before adding to passThroughs. Add them back here.
                var passThrough = passThroughs.Pop();
                prev = passThrough.Owner;
                passThrough.Target.ReAdd(passThrough);
                goto Repeat;
            }
        }
Пример #5
0
                public static MergePromise <T> GetOrCreate(ValueLinkedStack <PromisePassThrough> promisePassThroughs, ref T value, Action <Internal.IValueContainer, Internal.ResolveContainer <T>, int> onPromiseResolved, int count)
                {
                    var promise = _pool.IsNotEmpty ? (MergePromise <T>)_pool.Pop() : new MergePromise <T>();

                    promise._passThroughs      = promisePassThroughs;
                    promise._onPromiseResolved = onPromiseResolved;

                    promise._waitCount = (uint)count;
                    promise.Reset();
                    promise._pending = true;
                    // Retain this until all promises resolve/reject/cancel.
                    promise.RetainInternal();

                    var container = Internal.ResolveContainer <T> .GetOrCreate(ref value);

                    container.Retain();
                    promise._valueOrPrevious = container;

                    foreach (var passThrough in promisePassThroughs)
                    {
                        passThrough.SetTargetAndAddToOwner(promise);
                    }
                    return(promise);
                }
 protected override bool SubscribeProgressIfWaiterAndContinueLoop(ref IProgressListener progressListener, out Promise previous, ref ValueLinkedStack <PromisePassThrough> passThroughs)
 {
     if (_state != State.Pending)
     {
         previous = null;
         return(false);
     }
     return(SubscribeProgressAndContinueLoop(ref progressListener, out previous));
 }
 protected override void BorrowPassthroughs(ref ValueLinkedStack <PromisePassThrough> borrower)
 {
     ExchangePassthroughs(ref _passThroughs, ref borrower);
 }
 protected virtual void BorrowPassthroughs(ref ValueLinkedStack <Internal.PromisePassThrough> borrower)
 {
 }
        private static void SubscribeProgressToChain(Promise promise, Internal.IProgressListener progressListener, ref ValueLinkedStack <Internal.PromisePassThrough> passThroughs)
        {
            Promise next;

            // If the promise is not waiting on another promise (is the root), it sets next to null, does not add the listener, and returns false.
            // If the promise is waiting on another promise that is not its previous, it adds the listener, transforms progresslistener, sets next to the one it's waiting on, and returns true.
            // Otherwise, it sets next to its previous, adds the listener only if it is a WaitPromise, and returns true.
            while (promise.SubscribeProgressIfWaiterAndContinueLoop(ref progressListener, out next, ref passThroughs))
            {
                promise = next;
            }

            // promise is the root of the promise tree.
            switch (promise._state)
            {
            case State.Pending:
            {
                progressListener.SetInitialAmount(promise._waitDepthAndProgress);
                break;
            }

            case State.Resolved:
            {
                progressListener.SetInitialAmount(promise._waitDepthAndProgress.GetIncrementedWholeTruncated());
                break;
            }

            default:     // Rejected or Canceled:
            {
                progressListener.Retain();
                progressListener.CancelOrIncrementProgress(promise, promise._waitDepthAndProgress.GetIncrementedWholeTruncated().ToUInt32());
                break;
            }
            }
        }
 protected virtual bool SubscribeProgressIfWaiterAndContinueLoop(ref Internal.IProgressListener progressListener, out Promise previous, ref ValueLinkedStack <Internal.PromisePassThrough> passThroughs)
 {
     return((previous = _valueOrPrevious as Promise) != null);
 }