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