Beispiel #1
0
            public override void onCompletion <T1>(CountedCompleter <T1> caller)
            {
                if (Node != null)
                {
                    // Dump buffered elements from this leaf into the sink
                    Node.ForEach(Action);
                    Node = null;
                }
                else if (Spliterator != null)
                {
                    // Dump elements output from this leaf's pipeline into the sink
                    Helper.WrapAndCopyInto(Action, Spliterator);
                    Spliterator = null;
                }

                // The completion of this task *and* the dumping of elements
                // "happens-before" completion of the associated left-most leaf task
                // of right subtree (if any, which can be this task's right sibling)
                //
                ForEachOrderedTask <S, T> leftDescendant = CompletionMap.Remove(this);

                if (leftDescendant != null)
                {
                    leftDescendant.TryComplete();
                }
            }
Beispiel #2
0
 internal ForEachOrderedTask(ForEachOrderedTask <S, T> parent, Spliterator <S> spliterator, ForEachOrderedTask <S, T> leftPredecessor) : base(parent)
 {
     this.Helper          = parent.Helper;
     this.Spliterator     = spliterator;
     this.TargetSize      = parent.TargetSize;
     this.CompletionMap   = parent.CompletionMap;
     this.Action          = parent.Action;
     this.LeftPredecessor = leftPredecessor;
 }
Beispiel #3
0
 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;
 }
Beispiel #4
0
            internal static void doCompute <S, T>(ForEachOrderedTask <S, T> task)
            {
                Spliterator <S> rightSplit = task.Spliterator, leftSplit;
                long            sizeThreshold = task.TargetSize;
                bool            forkRight     = false;

                while (rightSplit.EstimateSize() > sizeThreshold && (leftSplit = rightSplit.TrySplit()) != null)
                {
                    ForEachOrderedTask <S, T> leftChild  = new ForEachOrderedTask <S, T>(task, leftSplit, task.LeftPredecessor);
                    ForEachOrderedTask <S, T> rightChild = new ForEachOrderedTask <S, T>(task, rightSplit, leftChild);

                    // Fork the parent task
                    // Completion of the left and right children "happens-before"
                    // completion of the parent
                    task.AddToPendingCount(1);
                    // Completion of the left child "happens-before" completion of
                    // the right child
                    rightChild.AddToPendingCount(1);
                    task.CompletionMap[leftChild] = rightChild;

                    // If task is not on the left spine
                    if (task.LeftPredecessor != null)
                    {
                        /*
                         * Completion of left-predecessor, or left subtree,
                         * "happens-before" completion of left-most leaf node of
                         * right subtree.
                         * The left child's pending count needs to be updated before
                         * it is associated in the completion map, otherwise the
                         * left child can complete prematurely and violate the
                         * "happens-before" constraint.
                         */
                        leftChild.AddToPendingCount(1);
                        // Update association of left-predecessor to left-most
                        // leaf node of right subtree
                        if (task.CompletionMap.replace(task.LeftPredecessor, task, leftChild))
                        {
                            // If replaced, adjust the pending count of the parent
                            // to complete when its children complete
                            task.AddToPendingCount(-1);
                        }
                        else
                        {
                            // Left-predecessor has already completed, parent's
                            // pending count is adjusted by left-predecessor;
                            // left child is ready to complete
                            leftChild.AddToPendingCount(-1);
                        }
                    }

                    ForEachOrderedTask <S, T> taskToFork;
                    if (forkRight)
                    {
                        forkRight  = false;
                        rightSplit = leftSplit;
                        task       = leftChild;
                        taskToFork = rightChild;
                    }
                    else
                    {
                        forkRight  = true;
                        task       = rightChild;
                        taskToFork = leftChild;
                    }
                    taskToFork.Fork();
                }

                /*
                 * Task's pending count is either 0 or 1.  If 1 then the completion
                 * map will contain a value that is task, and two calls to
                 * tryComplete are required for completion, one below and one
                 * triggered by the completion of task's left-predecessor in
                 * onCompletion.  Therefore there is no data race within the if
                 * block.
                 */
                if (task.PendingCount > 0)
                {
                    // Cannot complete just yet so buffer elements into a Node
                    // for use when completion occurs
//JAVA TO C# CONVERTER TODO TASK: Most Java annotations will not have direct .NET equivalent attributes:
//ORIGINAL LINE: @SuppressWarnings("unchecked") java.util.function.IntFunction<T[]> generator = size -> (T[]) new Object[size];
//JAVA TO C# CONVERTER TODO TASK: Java lambdas satisfy functional interfaces, while .NET lambdas satisfy delegates - change the appropriate interface to a delegate:
                    IntFunction <T[]> generator = size => (T[])new Object[size];
                    Node_Builder <T>  nb        = task.Helper.MakeNodeBuilder(task.Helper.ExactOutputSizeIfKnown(rightSplit), generator);
                    task.Node        = task.Helper.WrapAndCopyInto(nb, rightSplit).build();
                    task.Spliterator = null;
                }
                task.TryComplete();
            }