// This partitioner that is simpler than the general case (don't use a list) is called in the case // of initialPartitionSize == partitionMultiplier == 1 IEnumerator <KeyValuePair <long, T> > GetPartitionEnumeratorSimple(IEnumerator <T> src, PartitionerState state, bool last) { long index = -1; var value = default(T); try { do { lock (state.SyncLock) { if (!src.MoveNext()) { break; } index = state.Index++; value = src.Current; } yield return(new KeyValuePair <long, T> (index, value)); }while (true); } finally { if (last) { src.Dispose(); } } }
public override IList <IEnumerator <KeyValuePair <long, T> > > GetOrderablePartitions(int partitionCount) { if (partitionCount <= 0) { throw new ArgumentOutOfRangeException("partitionCount"); } IEnumerator <KeyValuePair <long, T> >[] enumerators = new IEnumerator <KeyValuePair <long, T> > [partitionCount]; PartitionerState state = new PartitionerState(); IEnumerator <T> src = source.GetEnumerator(); bool isSimple = initialPartitionSize == 1 && partitionMultiplier == 1; for (int i = 0; i < enumerators.Length; i++) { enumerators[i] = isSimple ? GetPartitionEnumeratorSimple(src, state, i == enumerators.Length - 1) : GetPartitionEnumerator(src, state); } return(enumerators); }
IEnumerator <KeyValuePair <long, T> > GetPartitionEnumerator(IEnumerator <T> src, PartitionerState state) { int count = initialPartitionSize; List <T> list = new List <T> (); while (true) { list.Clear(); long ind = -1; lock (state.SyncLock) { ind = state.Index; for (int i = 0; i < count; i++) { if (!src.MoveNext()) { if (list.Count == 0) { yield break; } else { break; } } list.Add(src.Current); state.Index++; } } for (int i = 0; i < list.Count; i++) { yield return(new KeyValuePair <long, T> (ind + i, list[i])); } count *= partitionMultiplier; } }