protected internal ForEachOrderedTask(PipelineHelper <T> helper, Spliterator <S> spliterator, Sink <T> action) : base(null) { this.Helper = helper; this.Spliterator = spliterator; this.TargetSize = AbstractTask.SuggestTargetSize(spliterator.EstimateSize()); // Size map to avoid concurrent re-sizes this.CompletionMap = new ConcurrentDictionary <>(System.Math.Max(16, AbstractTask.LEAF_TARGET << 1)); this.Action = action; this.LeftPredecessor = null; }
// Similar to AbstractTask but doesn't need to track child tasks public void Compute() { Spliterator <S> rightSplit = Spliterator, leftSplit; long sizeEstimate = rightSplit.EstimateSize(), sizeThreshold; if ((sizeThreshold = TargetSize) == 0L) { TargetSize = sizeThreshold = AbstractTask.SuggestTargetSize(sizeEstimate); } bool isShortCircuit = StreamOpFlag.SHORT_CIRCUIT.isKnown(Helper.StreamAndOpFlags); bool forkRight = false; Sink <S> taskSink = Sink; ForEachTask <S, T> task = this; while (!isShortCircuit || !taskSink.cancellationRequested()) { if (sizeEstimate <= sizeThreshold || (leftSplit = rightSplit.TrySplit()) == null) { task.Helper.CopyInto(taskSink, rightSplit); break; } ForEachTask <S, T> leftTask = new ForEachTask <S, T>(task, leftSplit); task.AddToPendingCount(1); ForEachTask <S, T> taskToFork; if (forkRight) { forkRight = false; rightSplit = leftSplit; taskToFork = task; task = leftTask; } else { forkRight = true; taskToFork = leftTask; } taskToFork.Fork(); sizeEstimate = rightSplit.EstimateSize(); } task.Spliterator = null; task.PropagateCompletion(); }