private static QueryOperatorEnumerator <T, int>[] MakePartitions(IEnumerator <T> source, int partitionCount) { QueryOperatorEnumerator <T, int>[] enumeratorArray = new QueryOperatorEnumerator <T, int> [partitionCount]; object sourceSyncLock = new object(); Shared <int> currentIndex = new Shared <int>(0); Shared <int> degreeOfParallelism = new Shared <int>(partitionCount); Shared <bool> exceptionTracker = new Shared <bool>(false); for (int i = 0; i < partitionCount; i++) { enumeratorArray[i] = new ContiguousChunkLazyEnumerator <T>(source, exceptionTracker, sourceSyncLock, currentIndex, degreeOfParallelism); } return(enumeratorArray); }
//--------------------------------------------------------------------------------------- // This method just creates the individual partitions given a data source. See the base // class for more details on this method's contracts. This version takes an enumerator, // and so it can't actually do an in-place partition. We'll instead create enumerators // that coordinate with one another to lazily (on demand) grab chunks from the enumerator. // This clearly is much less efficient than the fast path above since it requires // synchronization. We try to amortize that cost by retrieving many elements at once // instead of just one-at-a-time. // private static QueryOperatorEnumerator <T, int>[] MakePartitions(IEnumerator <T> source, int partitionCount) { Contract.Assert(source != null); Contract.Assert(partitionCount > 0); // At this point we were unable to efficiently partition the data source. Instead, we // will return enumerators that lazily partition the data source. QueryOperatorEnumerator <T, int>[] partitions = new QueryOperatorEnumerator <T, int> [partitionCount]; // The following is used for synchronization between threads. object sharedSyncLock = new object(); Shared <int> sharedCurrentIndex = new Shared <int>(0); Shared <int> sharedPartitionCount = new Shared <int>(partitionCount); Shared <bool> sharedExeceptionTracker = new Shared <bool>(false); // Create a new lazy chunking enumerator per partition, sharing the same lock. for (int i = 0; i < partitionCount; i++) { partitions[i] = new ContiguousChunkLazyEnumerator( source, sharedExeceptionTracker, sharedSyncLock, sharedCurrentIndex, sharedPartitionCount); } return(partitions); }