Code:
/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / Core / System / Linq / Parallel / QueryOperators / Unary / ConcatQueryOperator.cs / 1305376 / ConcatQueryOperator.cs
// ==++==
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// ==--==
// =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
//
// ConcatQueryOperator.cs
//
// [....]
//
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.Threading;
namespace System.Linq.Parallel
{
///
/// Concatenates one data source with another. Order preservation is used to ensure
/// the output is actually a concatenation -- i.e. one after the other. The only
/// special synchronization required is to find the largest index N in the first data
/// source so that the indices of elements in the second data source can be offset
/// by adding N+1. This makes it appear to the order preservation infrastructure as
/// though all elements in the second came after all elements in the first, which is
/// precisely what we want.
///
///
internal sealed class ConcatQueryOperator : BinaryQueryOperator
{
private readonly bool m_prematureMergeLeft = false; // Whether to prematurely merge the left data source
private readonly bool m_prematureMergeRight = false; // Whether to prematurely merge the right data source
//----------------------------------------------------------------------------------------
// Initializes a new concatenation operator.
//
// Arguments:
// child - the child whose data we will reverse
//
internal ConcatQueryOperator(ParallelQuery firstChild, ParallelQuery secondChild)
: base(firstChild, secondChild)
{
Contract.Assert(firstChild != null, "first child data source cannot be null");
Contract.Assert(secondChild != null, "second child data source cannot be null");
m_outputOrdered = LeftChild.OutputOrdered || RightChild.OutputOrdered;
m_prematureMergeLeft = LeftChild.OrdinalIndexState.IsWorseThan(OrdinalIndexState.Increasing);
m_prematureMergeRight = RightChild.OrdinalIndexState.IsWorseThan(OrdinalIndexState.Increasing);
if ((LeftChild.OrdinalIndexState == OrdinalIndexState.Indexible)
&& (RightChild.OrdinalIndexState == OrdinalIndexState.Indexible))
{
SetOrdinalIndex(OrdinalIndexState.Indexible);
}
else
{
SetOrdinalIndex(OrdinalIndexState.Shuffled);
}
}
//---------------------------------------------------------------------------------------
// Just opens the current operator, including opening the child and wrapping it with
// partitions as needed.
//
internal override QueryResults Open(QuerySettings settings, bool preferStriping)
{
// We just open the children operators.
QueryResults leftChildResults = LeftChild.Open(settings, preferStriping);
QueryResults rightChildResults = RightChild.Open(settings, preferStriping);
return ConcatQueryOperatorResults.NewResults(leftChildResults, rightChildResults, this, settings, preferStriping);
}
public override void WrapPartitionedStream(
PartitionedStream leftStream, PartitionedStream rightStream,
IPartitionedStreamRecipient outputRecipient, bool preferStriping, QuerySettings settings)
{
OrdinalIndexState leftChildIndexState = leftStream.OrdinalIndexState;
int partitionCount = leftStream.PartitionCount;
PartitionedStream leftStreamInc;
PartitionedStream rightStreamInc;
// Prematurely merge the left results, if necessary
if (m_prematureMergeLeft)
{
ListQueryResults leftStreamResults =
ExecuteAndCollectResults(leftStream, partitionCount, LeftChild.OutputOrdered, preferStriping, settings);
leftStreamInc = leftStreamResults.GetPartitionedStream();
}
else
{
Contract.Assert(!ExchangeUtilities.IsWorseThan(leftStream.OrdinalIndexState, OrdinalIndexState.Increasing));
leftStreamInc = (PartitionedStream)(object)leftStream;
}
// Prematurely merge the right results, if necessary
if (m_prematureMergeRight)
{
ListQueryResults rightStreamResults =
ExecuteAndCollectResults(rightStream, partitionCount, LeftChild.OutputOrdered, preferStriping, settings);
rightStreamInc = rightStreamResults.GetPartitionedStream();
}
else
{
Contract.Assert(!ExchangeUtilities.IsWorseThan(rightStream.OrdinalIndexState, OrdinalIndexState.Increasing));
rightStreamInc = (PartitionedStream)(object)rightStream;
}
// Generate the shared data.
IComparer> comparer = ConcatKey.MakeComparer(
leftStreamInc.KeyComparer, rightStreamInc.KeyComparer);
var outputStream = new PartitionedStream>(partitionCount, comparer, OrdinalIndexState);
for (int i = 0; i < partitionCount; i++)
{
outputStream[i] = new ConcatQueryOperatorEnumerator(leftStreamInc[i], rightStreamInc[i]);
}
outputRecipient.Receive(outputStream);
}
//---------------------------------------------------------------------------------------
// Returns an enumerable that represents the query executing sequentially.
//
internal override IEnumerable AsSequentialQuery(CancellationToken token)
{
return LeftChild.AsSequentialQuery(token).Concat(RightChild.AsSequentialQuery(token));
}
//---------------------------------------------------------------------------------------
// Whether this operator performs a premature merge.
//
internal override bool LimitsParallelism
{
get
{
return m_prematureMergeLeft || m_prematureMergeLeft;
}
}
//----------------------------------------------------------------------------------------
// The enumerator type responsible for concatenating two data sources.
//
class ConcatQueryOperatorEnumerator : QueryOperatorEnumerator>
{
private QueryOperatorEnumerator m_firstSource; // The first data source to enumerate.
private QueryOperatorEnumerator m_secondSource; // The second data source to enumerate.
private bool m_begunSecond; // Whether this partition has begun enumerating the second source yet.
//---------------------------------------------------------------------------------------
// Instantiates a new select enumerator.
//
internal ConcatQueryOperatorEnumerator(
QueryOperatorEnumerator firstSource,
QueryOperatorEnumerator secondSource)
{
Contract.Assert(firstSource != null);
Contract.Assert(secondSource != null);
m_firstSource = firstSource;
m_secondSource = secondSource;
}
//----------------------------------------------------------------------------------------
// MoveNext advances to the next element in the output. While the first data source has
// elements, this consists of just advancing through it. After this, all partitions must
// synchronize at a barrier and publish the maximum index N. Finally, all partitions can
// move on to the second data source, adding N+1 to indices in order to get the correct
// index offset.
//
internal override bool MoveNext(ref TSource currentElement, ref ConcatKey currentKey)
{
Contract.Assert(m_firstSource != null);
Contract.Assert(m_secondSource != null);
// If we are still enumerating the first source, fetch the next item.
if (!m_begunSecond)
{
// If elements remain, just return true and continue enumerating the left.
TLeftKey leftKey = default(TLeftKey);
if (m_firstSource.MoveNext(ref currentElement, ref leftKey))
{
currentKey = ConcatKey.MakeLeft(leftKey);
return true;
}
m_begunSecond = true;
}
// Now either move on to, or continue, enumerating the right data source.
TRightKey rightKey = default(TRightKey);
if (m_secondSource.MoveNext(ref currentElement, ref rightKey))
{
currentKey = ConcatKey.MakeRight(rightKey);
return true;
}
return false;
}
protected override void Dispose(bool disposing)
{
m_firstSource.Dispose();
m_secondSource.Dispose();
}
}
//------------------------------------------------------------------------------------
// Query results for a Concat operator. The results are indexible if the child
// results were indexible.
//
class ConcatQueryOperatorResults : BinaryQueryOperatorResults
{
ConcatQueryOperator m_concatOp; // Operator that generated the results
int m_leftChildCount; // The number of elements in the left child result set
int m_rightChildCount; // The number of elements in the right child result set
public static QueryResults NewResults(
QueryResults leftChildQueryResults, QueryResults rightChildQueryResults,
ConcatQueryOperator op, QuerySettings settings,
bool preferStriping)
{
if (leftChildQueryResults.IsIndexible && rightChildQueryResults.IsIndexible)
{
return new ConcatQueryOperatorResults(
leftChildQueryResults, rightChildQueryResults, op, settings, preferStriping);
}
else
{
return new BinaryQueryOperatorResults(
leftChildQueryResults, rightChildQueryResults, op, settings, preferStriping);
}
}
private ConcatQueryOperatorResults(
QueryResults leftChildQueryResults, QueryResults rightChildQueryResults,
ConcatQueryOperator concatOp, QuerySettings settings,
bool preferStriping)
: base(leftChildQueryResults, rightChildQueryResults, concatOp, settings, preferStriping)
{
m_concatOp = concatOp;
Contract.Assert(leftChildQueryResults.IsIndexible && rightChildQueryResults.IsIndexible);
m_leftChildCount = leftChildQueryResults.ElementsCount;
m_rightChildCount = rightChildQueryResults.ElementsCount;
}
internal override bool IsIndexible
{
get { return true; }
}
internal override int ElementsCount
{
get
{
Contract.Assert(m_leftChildCount >= 0 && m_rightChildCount >= 0);
return m_leftChildCount + m_rightChildCount;
}
}
internal override TSource GetElement(int index)
{
if (index < m_leftChildCount)
{
return m_leftChildQueryResults.GetElement(index);
}
else
{
return m_rightChildQueryResults.GetElement(index - m_leftChildCount);
}
}
}
}
//---------------------------------------------------------------------------------------
// ConcatKey represents an ordering key for the Concat operator. It knows whether the
// element it is associated with is from the left source or the right source, and also
// the elements ordering key.
//
internal struct ConcatKey
{
private readonly TLeftKey m_leftKey;
private readonly TRightKey m_rightKey;
private readonly bool m_isLeft;
private ConcatKey(TLeftKey leftKey, TRightKey rightKey, bool isLeft)
{
m_leftKey = leftKey;
m_rightKey = rightKey;
m_isLeft = isLeft;
}
internal static ConcatKey MakeLeft(TLeftKey leftKey)
{
return new ConcatKey(leftKey, default(TRightKey), true);
}
internal static ConcatKey MakeRight(TRightKey rightKey)
{
return new ConcatKey(default(TLeftKey), rightKey, false);
}
internal static IComparer> MakeComparer(
IComparer leftComparer, IComparer rightComparer)
{
return new ConcatKeyComparer(leftComparer, rightComparer);
}
//----------------------------------------------------------------------------------------
// ConcatKeyComparer compares ConcatKeys, so that elements from the left source come
// before elements from the right source, and elements within each source are ordered
// according to the corresponding order key.
//
private class ConcatKeyComparer : IComparer>
{
private IComparer m_leftComparer;
private IComparer m_rightComparer;
internal ConcatKeyComparer(IComparer leftComparer, IComparer rightComparer)
{
m_leftComparer = leftComparer;
m_rightComparer = rightComparer;
}
public int Compare(ConcatKey x, ConcatKey y)
{
// If one element is from the left source and the other not, the element from the left source
// comes earlier.
if (x.m_isLeft != y.m_isLeft)
{
return x.m_isLeft ? -1 : 1;
}
// Elements are from the same source (left or right). Compare the corresponding keys.
if (x.m_isLeft)
{
return m_leftComparer.Compare(x.m_leftKey, y.m_leftKey);
}
return m_rightComparer.Compare(x.m_rightKey, y.m_rightKey);
}
}
}
}
// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- XmlCharCheckingReader.cs
- RelatedPropertyManager.cs
- MenuItemAutomationPeer.cs
- Page.cs
- ComponentCollection.cs
- storepermissionattribute.cs
- CompressStream.cs
- EntryWrittenEventArgs.cs
- Errors.cs
- XmlReader.cs
- BezierSegment.cs
- MimeXmlImporter.cs
- Span.cs
- XmlLoader.cs
- SequentialUshortCollection.cs
- ContainerControl.cs
- Utility.cs
- AbsoluteQuery.cs
- GlobalProxySelection.cs
- ExpressionTextBoxAutomationPeer.cs
- VirtualPath.cs
- MDIClient.cs
- SqlNodeTypeOperators.cs
- Animatable.cs
- DataBoundLiteralControl.cs
- SchemaNamespaceManager.cs
- TreeViewTemplateSelector.cs
- StyleModeStack.cs
- NeutralResourcesLanguageAttribute.cs
- LinqDataSource.cs
- TableProviderWrapper.cs
- AnchoredBlock.cs
- ProxyFragment.cs
- FieldMetadata.cs
- DbQueryCommandTree.cs
- TextWriterTraceListener.cs
- ListViewCancelEventArgs.cs
- HMACRIPEMD160.cs
- VirtualizingStackPanel.cs
- DataSourceXmlTextReader.cs
- BaseAsyncResult.cs
- DesignerTransactionCloseEvent.cs
- RepeatBehaviorConverter.cs
- AudioDeviceOut.cs
- XmlUrlResolver.cs
- CapabilitiesPattern.cs
- CircleHotSpot.cs
- HashAlgorithm.cs
- ManagementBaseObject.cs
- TextServicesContext.cs
- Msmq4SubqueuePoisonHandler.cs
- SchemaMapping.cs
- DbCommandDefinition.cs
- HelloMessageApril2005.cs
- SupportsPreviewControlAttribute.cs
- ChannelManager.cs
- _Connection.cs
- ContractMapping.cs
- webclient.cs
- _FixedSizeReader.cs
- CacheDict.cs
- RegexCharClass.cs
- StreamGeometry.cs
- CounterSetInstanceCounterDataSet.cs
- WmpBitmapDecoder.cs
- CodeDOMUtility.cs
- Win32PrintDialog.cs
- FileIOPermission.cs
- WindowsEditBox.cs
- XmlSchemaType.cs
- DataPager.cs
- SpecialFolderEnumConverter.cs
- printdlgexmarshaler.cs
- Cloud.cs
- Attribute.cs
- SimpleTableProvider.cs
- KeyPressEvent.cs
- Translator.cs
- ConnectorDragDropGlyph.cs
- CultureTable.cs
- DirectoryObjectSecurity.cs
- updatecommandorderer.cs
- StringUtil.cs
- DesignerLoader.cs
- FilterEventArgs.cs
- SqlStream.cs
- HttpServerVarsCollection.cs
- InputBindingCollection.cs
- Clipboard.cs
- RelationshipFixer.cs
- EditorZone.cs
- StatusBar.cs
- ModifierKeysValueSerializer.cs
- RecordsAffectedEventArgs.cs
- ComponentChangedEvent.cs
- DescendantQuery.cs
- FileLogRecordHeader.cs
- TrackingQueryElement.cs
- ServiceNameCollection.cs
- LoginCancelEventArgs.cs