private void InitializePartitions(IEnumerable <T> source, int partitionCount, bool useStriping) { ParallelEnumerableWrapper <T> wrapper = source as ParallelEnumerableWrapper <T>; if (wrapper != null) { source = wrapper.WrappedEnumerable; } IList <T> data = source as IList <T>; if (data != null) { QueryOperatorEnumerator <T, int>[] enumeratorArray = new QueryOperatorEnumerator <T, int> [partitionCount]; int count = data.Count; T[] localArray = source as T[]; int maxChunkSize = -1; if (useStriping) { maxChunkSize = Scheduling.GetDefaultChunkSize <T>(); if (maxChunkSize < 1) { maxChunkSize = 1; } } for (int i = 0; i < partitionCount; i++) { if (localArray != null) { if (useStriping) { enumeratorArray[i] = new ArrayIndexRangeEnumerator <T>(localArray, partitionCount, i, maxChunkSize); } else { enumeratorArray[i] = new ArrayContiguousIndexRangeEnumerator <T>(localArray, partitionCount, i); } } else if (useStriping) { enumeratorArray[i] = new ListIndexRangeEnumerator <T>(data, partitionCount, i, maxChunkSize); } else { enumeratorArray[i] = new ListContiguousIndexRangeEnumerator <T>(data, partitionCount, i); } } base.m_partitions = enumeratorArray; } else { base.m_partitions = PartitionedDataSource <T> .MakePartitions(source.GetEnumerator(), partitionCount); } }
//----------------------------------------------------------------------------------- // A factory method to construct a partitioned stream over a data source. // // Arguments: // source - the data source to be partitioned // partitionCount - the number of partitions desired // useOrdinalOrderPreservation - whether ordinal position must be tracked // useStriping - whether striped partitioning should be used instead of range partitioning // internal static PartitionedStream <T, int> PartitionDataSource <T>(IEnumerable <T> source, int partitionCount, bool useStriping) { // The partitioned stream to return. PartitionedStream <T, int> returnValue; IParallelPartitionable <T> sourceAsPartitionable = source as IParallelPartitionable <T>; if (sourceAsPartitionable != null) { // The type overrides the partitioning algorithm, so we will use it instead of the default. // The returned enumerator must be the same size that we requested, otherwise we throw. QueryOperatorEnumerator <T, int>[] enumerators = sourceAsPartitionable.GetPartitions(partitionCount); if (enumerators == null) { throw new InvalidOperationException(SR.GetString(SR.ParallelPartitionable_NullReturn)); } else if (enumerators.Length != partitionCount) { throw new InvalidOperationException(SR.GetString(SR.ParallelPartitionable_IncorretElementCount)); } // Now just copy the enumerators into the stream, validating that the result is non-null. PartitionedStream <T, int> stream = new PartitionedStream <T, int>(partitionCount, Util.GetDefaultComparer <int>(), OrdinalIndexState.Correct); for (int i = 0; i < partitionCount; i++) { QueryOperatorEnumerator <T, int> currentEnumerator = enumerators[i]; if (currentEnumerator == null) { throw new InvalidOperationException(SR.GetString(SR.ParallelPartitionable_NullElement)); } stream[i] = currentEnumerator; } returnValue = stream; } else { returnValue = new PartitionedDataSource <T>(source, partitionCount, useStriping); } Contract.Assert(returnValue.PartitionCount == partitionCount); return(returnValue); }