Partitioned stream recipient that will merge the results.
Inheritance: IPartitionedStreamRecipient
Esempio n. 1
0
        //---------------------------------------------------------------------------------------
        // Executes the query and returns the results in an array.
        //

        internal TOutput[] ExecuteAndGetResultsAsArray()
        {
            QuerySettings querySettings =
                SpecifiedQuerySettings
                .WithPerExecutionSettings()
                .WithDefaults();

            QueryLifecycle.LogicalQueryExecutionBegin(querySettings.QueryId);
            try
            {
                Debug.Assert(querySettings.ExecutionMode != null);
                if (querySettings.ExecutionMode.Value == ParallelExecutionMode.Default && LimitsParallelism)
                {
                    IEnumerable <TOutput> opSequential = AsSequentialQuery(querySettings.CancellationState.ExternalCancellationToken);
                    IEnumerable <TOutput> opSequentialWithCancelChecks = CancellableEnumerable.Wrap(opSequential, querySettings.CancellationState.ExternalCancellationToken);
                    return(ExceptionAggregator.WrapEnumerable(opSequentialWithCancelChecks, querySettings.CancellationState).ToArray());
                }

                QueryResults <TOutput> results = GetQueryResults(querySettings);

                // Top-level preemptive cancellation test.
                // This handles situations where cancellation has occurred before execution commences
                // The handling for in-execution occurs in QueryTaskGroupState.QueryEnd()

                if (querySettings.CancellationState.MergedCancellationToken.IsCancellationRequested)
                {
                    querySettings.CancellationState.ExternalCancellationToken.ThrowIfCancellationRequested();
                    throw new OperationCanceledException();
                }

                if (results.IsIndexible && OutputOrdered)
                {
                    // The special array-based merge performs better if the output is ordered, because
                    // it does not have to pay for ordering. In the unordered case, we it appears that
                    // the stop-and-go merge performs a little better.
                    ArrayMergeHelper <TOutput> merger = new ArrayMergeHelper <TOutput>(SpecifiedQuerySettings, results);
                    merger.Execute();
                    TOutput[] output = merger.GetResultsAsArray();
                    querySettings.CleanStateAtQueryEnd();
                    return(output);
                }
                else
                {
                    Debug.Assert(querySettings.TaskScheduler != null);
                    PartitionedStreamMerger <TOutput> merger =
                        new PartitionedStreamMerger <TOutput>(false, ParallelMergeOptions.FullyBuffered, querySettings.TaskScheduler,
                                                              OutputOrdered, querySettings.CancellationState, querySettings.QueryId);
                    results.GivePartitionedStream(merger);
                    Debug.Assert(merger.MergeExecutor != null);
                    TOutput[]? output = merger.MergeExecutor.GetResultsAsArray();
                    querySettings.CleanStateAtQueryEnd();
                    Debug.Assert(output != null);
                    return(output);
                }
            }
            finally
            {
                QueryLifecycle.LogicalQueryExecutionEnd(querySettings.QueryId);
            }
        }
Esempio n. 2
0
        //---------------------------------------------------------------------------------------
        // Just opens the current operator, including opening the children and wrapping them with
        // partitions as needed.
        //

        internal override QueryResults <TOutput> Open(QuerySettings settings, bool preferStriping)
        {
            // We just open our child operators, left and then right.
            QueryResults <TLeftInput>  leftChildResults  = _leftChild.Open(settings, preferStriping);
            QueryResults <TRightInput> rightChildResults = _rightChild.Open(settings, preferStriping);

            int partitionCount = settings.DegreeOfParallelism.Value;

            if (_prematureMergeLeft)
            {
                PartitionedStreamMerger <TLeftInput> merger = new PartitionedStreamMerger <TLeftInput>(
                    false, ParallelMergeOptions.FullyBuffered, settings.TaskScheduler, _leftChild.OutputOrdered,
                    settings.CancellationState, settings.QueryId);
                leftChildResults.GivePartitionedStream(merger);
                leftChildResults = new ListQueryResults <TLeftInput>(
                    merger.MergeExecutor.GetResultsAsArray(), partitionCount, preferStriping);
            }

            if (_prematureMergeRight)
            {
                PartitionedStreamMerger <TRightInput> merger = new PartitionedStreamMerger <TRightInput>(
                    false, ParallelMergeOptions.FullyBuffered, settings.TaskScheduler, _rightChild.OutputOrdered,
                    settings.CancellationState, settings.QueryId);
                rightChildResults.GivePartitionedStream(merger);
                rightChildResults = new ListQueryResults <TRightInput>(
                    merger.MergeExecutor.GetResultsAsArray(), partitionCount, preferStriping);
            }

            return(new ZipQueryOperatorResults(leftChildResults, rightChildResults, _resultSelector, partitionCount, preferStriping));
        }
        internal IEnumerator <TOutput> GetOpenedEnumerator(ParallelMergeOptions?mergeOptions, bool suppressOrder, bool forEffect, QuerySettings querySettings)
        {
            if ((((ParallelExecutionMode)querySettings.ExecutionMode.Value) == ParallelExecutionMode.Default) && this.LimitsParallelism)
            {
                return(ExceptionAggregator.WrapEnumerable <TOutput>(this.AsSequentialQuery(querySettings.CancellationState.ExternalCancellationToken), querySettings.CancellationState).GetEnumerator());
            }
            QueryResults <TOutput> queryResults = this.GetQueryResults(querySettings);

            if (!mergeOptions.HasValue)
            {
                mergeOptions = querySettings.MergeOptions;
            }
            if (querySettings.CancellationState.MergedCancellationToken.IsCancellationRequested)
            {
                if (querySettings.CancellationState.ExternalCancellationToken.IsCancellationRequested)
                {
                    throw new OperationCanceledException(querySettings.CancellationState.ExternalCancellationToken);
                }
                throw new OperationCanceledException();
            }
            bool outputOrdered = this.OutputOrdered && !suppressOrder;
            PartitionedStreamMerger <TOutput> recipient = new PartitionedStreamMerger <TOutput>(forEffect, mergeOptions.GetValueOrDefault(), querySettings.TaskScheduler, outputOrdered, querySettings.CancellationState, querySettings.QueryId);

            queryResults.GivePartitionedStream(recipient);
            if (forEffect)
            {
                return(null);
            }
            return(recipient.MergeExecutor.GetEnumerator());
        }
        internal TOutput[] ExecuteAndGetResultsAsArray()
        {
            TOutput[]     localArray3;
            QuerySettings querySettings = base.SpecifiedQuerySettings.WithPerExecutionSettings().WithDefaults();

            QueryLifecycle.LogicalQueryExecutionBegin(querySettings.QueryId);
            try
            {
                if ((((ParallelExecutionMode)querySettings.ExecutionMode.Value) == ParallelExecutionMode.Default) && this.LimitsParallelism)
                {
                    IEnumerable <TOutput> source       = this.AsSequentialQuery(querySettings.CancellationState.ExternalCancellationToken);
                    IEnumerable <TOutput> introduced13 = CancellableEnumerable.Wrap <TOutput>(source, querySettings.CancellationState.ExternalCancellationToken);
                    return(ExceptionAggregator.WrapEnumerable <TOutput>(introduced13, querySettings.CancellationState).ToArray <TOutput>());
                }
                QueryResults <TOutput> queryResults = this.GetQueryResults(querySettings);
                if (queryResults.IsIndexible && this.OutputOrdered)
                {
                    ArrayMergeHelper <TOutput> helper = new ArrayMergeHelper <TOutput>(base.SpecifiedQuerySettings, queryResults);
                    helper.Execute();
                    TOutput[] localArray = helper.GetResultsAsArray();
                    querySettings.CleanStateAtQueryEnd();
                    return(localArray);
                }
                PartitionedStreamMerger <TOutput> recipient = new PartitionedStreamMerger <TOutput>(false, ParallelMergeOptions.FullyBuffered, querySettings.TaskScheduler, this.OutputOrdered, querySettings.CancellationState, querySettings.QueryId);
                queryResults.GivePartitionedStream(recipient);
                TOutput[] resultsAsArray = recipient.MergeExecutor.GetResultsAsArray();
                querySettings.CleanStateAtQueryEnd();
                localArray3 = resultsAsArray;
            }
            finally
            {
                QueryLifecycle.LogicalQueryExecutionEnd(querySettings.QueryId);
            }
            return(localArray3);
        }
Esempio n. 5
0
        //---------------------------------------------------------------------------------------
        // The GetOpenedEnumerator method return an enumerator that walks the contents of a query.
        // The enumerator will be "opened", which means that PLINQ will start executing the query
        // immediately, even before the user calls MoveNext() for the first time.
        //
        internal IEnumerator <TOutput> GetOpenedEnumerator(ParallelMergeOptions?mergeOptions, bool suppressOrder, bool forEffect,
                                                           QuerySettings querySettings)
        {
            // If the top-level enumerator forces a premature merge, run the query sequentially.
            if (querySettings.ExecutionMode.Value == ParallelExecutionMode.Default && LimitsParallelism)
            {
                IEnumerable <TOutput> opSequential = AsSequentialQuery(querySettings.CancellationState.ExternalCancellationToken);
                return(ExceptionAggregator.WrapEnumerable(opSequential, querySettings.CancellationState).GetEnumerator());
            }

            QueryResults <TOutput> queryResults = GetQueryResults(querySettings);

            if (mergeOptions == null)
            {
                mergeOptions = querySettings.MergeOptions;
            }

            Contract.Assert(mergeOptions != null);

            // Top-level pre-emptive cancellation test.
            // This handles situations where cancellation has occured before execution commences
            // The handling for in-execution occurs in QueryTaskGroupState.QueryEnd()

            if (querySettings.CancellationState.MergedCancellationToken.IsCancellationRequested)
            {
                if (querySettings.CancellationState.ExternalCancellationToken.IsCancellationRequested)
                {
#if PFX_LEGACY_3_5
                    throw new OperationCanceledException2(querySettings.CancellationState.ExternalCancellationToken);
#else
                    throw new OperationCanceledException(querySettings.CancellationState.ExternalCancellationToken);
#endif
                }
                else
                {
                    throw new OperationCanceledException();
                }
            }

            bool orderedMerge = OutputOrdered && !suppressOrder;

            PartitionedStreamMerger <TOutput> merger = new PartitionedStreamMerger <TOutput>(forEffect, mergeOptions.GetValueOrDefault(),
                                                                                             querySettings.TaskScheduler,
                                                                                             orderedMerge,
                                                                                             querySettings.CancellationState,
                                                                                             querySettings.QueryId);

            queryResults.GivePartitionedStream(merger); // hook up the data flow between the operator-executors, starting from the merger.

            if (forEffect)
            {
                return(null);
            }

            return(merger.MergeExecutor.GetEnumerator());
        }
Esempio n. 6
0
        //---------------------------------------------------------------------------------------
        // Executes the query and returns the results in an array.
        //

        internal TOutput[] ExecuteAndGetResultsAsArray()
        {
            QuerySettings querySettings =
                SpecifiedQuerySettings
                .WithPerExecutionSettings()
                .WithDefaults();

            QueryLifecycle.LogicalQueryExecutionBegin(querySettings.QueryId);
            try
            {
                if (querySettings.ExecutionMode.Value == ParallelExecutionMode.Default && LimitsParallelism)
                {
                    IEnumerable <TOutput> opSequential = AsSequentialQuery(querySettings.CancellationState.ExternalCancellationToken);
                    IEnumerable <TOutput> opSequentialWithCancelChecks = CancellableEnumerable.Wrap(opSequential, querySettings.CancellationState.ExternalCancellationToken);
                    return(ExceptionAggregator.WrapEnumerable(opSequentialWithCancelChecks, querySettings.CancellationState).ToArray());
                }

                QueryResults <TOutput> results = GetQueryResults(querySettings);

                if (results.IsIndexible && OutputOrdered)
                {
                    // The special array-based merge performs better if the output is ordered, because
                    // it does not have to pay for ordering. In the unordered case, we it appears that
                    // the stop-and-go merge performs a little better.
                    ArrayMergeHelper <TOutput> merger = new ArrayMergeHelper <TOutput>(SpecifiedQuerySettings, results);
                    merger.Execute();
                    TOutput[] output = merger.GetResultsAsArray();
                    querySettings.CleanStateAtQueryEnd();
                    return(output);
                }
                else
                {
                    PartitionedStreamMerger <TOutput> merger =
                        new PartitionedStreamMerger <TOutput>(false, ParallelMergeOptions.FullyBuffered, querySettings.TaskScheduler,
                                                              OutputOrdered, querySettings.CancellationState, querySettings.QueryId);
                    results.GivePartitionedStream(merger);
                    TOutput[] output = merger.MergeExecutor.GetResultsAsArray();
                    querySettings.CleanStateAtQueryEnd();
                    return(output);
                }
            }
            finally
            {
                QueryLifecycle.LogicalQueryExecutionEnd(querySettings.QueryId);
            }
        }
Esempio n. 7
0
        internal override QueryResults <TOutput> Open(QuerySettings settings, bool preferStriping)
        {
            QueryResults <TLeftInput>  leftChildResults  = this.m_leftChild.Open(settings, preferStriping);
            QueryResults <TRightInput> rightChildResults = this.m_rightChild.Open(settings, preferStriping);
            int partitionCount = settings.DegreeOfParallelism.Value;

            if (this.m_prematureMergeLeft)
            {
                PartitionedStreamMerger <TLeftInput> recipient = new PartitionedStreamMerger <TLeftInput>(false, ParallelMergeOptions.FullyBuffered, settings.TaskScheduler, this.m_leftChild.OutputOrdered, settings.CancellationState, settings.QueryId);
                leftChildResults.GivePartitionedStream(recipient);
                leftChildResults = new ListQueryResults <TLeftInput>(recipient.MergeExecutor.GetResultsAsArray(), partitionCount, preferStriping);
            }
            if (this.m_prematureMergeRight)
            {
                PartitionedStreamMerger <TRightInput> merger2 = new PartitionedStreamMerger <TRightInput>(false, ParallelMergeOptions.FullyBuffered, settings.TaskScheduler, this.m_rightChild.OutputOrdered, settings.CancellationState, settings.QueryId);
                rightChildResults.GivePartitionedStream(merger2);
                rightChildResults = new ListQueryResults <TRightInput>(merger2.MergeExecutor.GetResultsAsArray(), partitionCount, preferStriping);
            }
            return(new ZipQueryOperatorResults <TLeftInput, TRightInput, TOutput>(leftChildResults, rightChildResults, this.m_resultSelector, partitionCount, preferStriping));
        }