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; } }
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); }
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; } }
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); }