//--------------------------------------------------------------------------------------- // Tallies up the min/max of the underlying data source, walking the entire thing the first // time MoveNext is called on this object. // protected override bool MoveNextCore(ref int currentElement) { // Based on the sign, do either a min or max reduction. QueryOperatorEnumerator <int, TKey> source = m_source; TKey keyUnused = default(TKey); if (source.MoveNext(ref currentElement, ref keyUnused)) { int i = 0; // We just scroll through the enumerator and find the min or max. if (m_sign == -1) { int elem = default(int); while (source.MoveNext(ref elem, ref keyUnused)) { if ((i++ & CancellationState.POLL_INTERVAL) == 0) { CancellationState.ThrowIfCanceled(m_cancellationToken); } if (elem < currentElement) { currentElement = elem; } } } else { int elem = default(int); while (source.MoveNext(ref elem, ref keyUnused)) { if ((i++ & CancellationState.POLL_INTERVAL) == 0) { CancellationState.ThrowIfCanceled(m_cancellationToken); } if (elem > currentElement) { currentElement = elem; } } } // The sum has been calculated. Now just return. return(true); } return(false); }
//----------------------------------------------------------------------------------- // Builds the hash lookup, transforming from TSource to TElement through whatever means is appropriate. // protected override HashLookup <Wrapper <TGroupKey>, GroupKeyData> BuildHashLookup() { HashLookup <Wrapper <TGroupKey>, GroupKeyData> hashLookup = new HashLookup <Wrapper <TGroupKey>, GroupKeyData>( new WrapperEqualityComparer <TGroupKey>(_keyComparer)); Pair <TSource, TGroupKey> sourceElement = default(Pair <TSource, TGroupKey>); TOrderKey sourceOrderKey = default(TOrderKey); int i = 0; while (_source.MoveNext(ref sourceElement, ref sourceOrderKey)) { if ((i++ & CancellationState.POLL_INTERVAL) == 0) { CancellationState.ThrowIfCanceled(_cancellationToken); } // Generate a key and place it into the hashtable. Wrapper <TGroupKey> key = new Wrapper <TGroupKey>(sourceElement.Second); // If the key already exists, we just append it to the existing list -- // otherwise we will create a new one and add it to that instead. GroupKeyData currentValue = null; if (hashLookup.TryGetValue(key, ref currentValue)) { if (_orderComparer.Compare(sourceOrderKey, currentValue._orderKey) < 0) { currentValue._orderKey = sourceOrderKey; } } else { currentValue = new GroupKeyData(sourceOrderKey, key.Value, _orderComparer); hashLookup.Add(key, currentValue); } Debug.Assert(currentValue != null); currentValue._grouping.Add(sourceElement.First, sourceOrderKey); } // Sort the elements within each group for (int j = 0; j < hashLookup.Count; j++) { hashLookup[j].Value._grouping.DoneAdding(); } return(hashLookup); }
internal override bool MoveNext(ref TInputOutput currentElement, ref int currentKey) { if (this.m_hashLookup == null) { this.m_hashLookup = new System.Linq.Parallel.Set <TInputOutput>(this.m_comparer); this.m_outputLoopCount = new Shared <int>(0); } if (this.m_leftSource != null) { TLeftKey local = default(TLeftKey); Pair <TInputOutput, NoKeyMemoizationRequired> pair = new Pair <TInputOutput, NoKeyMemoizationRequired>(); int num = 0; while (this.m_leftSource.MoveNext(ref pair, ref local)) { if ((num++ & 0x3f) == 0) { CancellationState.ThrowIfCanceled(this.m_cancellationToken); } if (this.m_hashLookup.Add(pair.First)) { currentElement = pair.First; return(true); } } this.m_leftSource.Dispose(); this.m_leftSource = null; } if (this.m_rightSource != null) { TRightKey local2 = default(TRightKey); Pair <TInputOutput, NoKeyMemoizationRequired> pair2 = new Pair <TInputOutput, NoKeyMemoizationRequired>(); while (this.m_rightSource.MoveNext(ref pair2, ref local2)) { if ((this.m_outputLoopCount.Value++ & 0x3f) == 0) { CancellationState.ThrowIfCanceled(this.m_cancellationToken); } if (this.m_hashLookup.Add(pair2.First)) { currentElement = pair2.First; return(true); } } this.m_rightSource.Dispose(); this.m_rightSource = null; } return(false); }
private void EnumerateAndRedistributeElements() { Mutables <TInputOutput, THashKey, TOrderKey> mutables = this.m_mutables; ListChunk <Pair <TInputOutput, THashKey> >[] chunkArray = new ListChunk <Pair <TInputOutput, THashKey> > [this.m_partitionCount]; ListChunk <TOrderKey>[] chunkArray2 = new ListChunk <TOrderKey> [this.m_partitionCount]; TInputOutput currentElement = default(TInputOutput); TOrderKey currentKey = default(TOrderKey); int num = 0; while (this.m_source.MoveNext(ref currentElement, ref currentKey)) { int num2; if ((num++ & 0x3f) == 0) { CancellationState.ThrowIfCanceled(this.m_cancellationToken); } THashKey key = default(THashKey); if (this.m_keySelector != null) { key = this.m_keySelector(currentElement); num2 = this.m_repartitionStream.GetHashCode(key) % this.m_partitionCount; } else { num2 = this.m_repartitionStream.GetHashCode(currentElement) % this.m_partitionCount; } ListChunk <Pair <TInputOutput, THashKey> > chunk = chunkArray[num2]; ListChunk <TOrderKey> chunk2 = chunkArray2[num2]; if (chunk == null) { chunkArray[num2] = chunk = new ListChunk <Pair <TInputOutput, THashKey> >(0x80); chunkArray2[num2] = chunk2 = new ListChunk <TOrderKey>(0x80); } chunk.Add(new Pair <TInputOutput, THashKey>(currentElement, key)); chunk2.Add(currentKey); } for (int i = 0; i < this.m_partitionCount; i++) { this.m_valueExchangeMatrix[this.m_partitionIndex, i] = chunkArray[i]; this.m_keyExchangeMatrix[this.m_partitionIndex, i] = chunkArray2[i]; } this.m_barrier.Signal(); mutables.m_currentBufferIndex = this.m_partitionIndex; mutables.m_currentBuffer = chunkArray[this.m_partitionIndex]; mutables.m_currentKeyBuffer = chunkArray2[this.m_partitionIndex]; mutables.m_currentIndex = -1; }
internal override bool MoveNext(ref TInput currentElement, ref int currentKey) { TInput local = default(TInput); TKey local2 = default(TKey); int num = 0; while (this.m_source.MoveNext(ref local, ref local2)) { if ((num++ & 0x3f) == 0) { CancellationState.ThrowIfCanceled(this.m_cancellationToken); } this.m_elementAction(local); } return(false); }
//--------------------------------------------------------------------------------------- // Walks the single data source, skipping elements it has already seen. // internal override bool MoveNext(ref TInputOutput currentElement, ref TKey currentKey) { Debug.Assert(_source != null); Debug.Assert(_hashLookup != null); if (_hashLookupEnumerator == null) { Pair <TInputOutput, NoKeyMemoizationRequired> elem = default(Pair <TInputOutput, NoKeyMemoizationRequired>); TKey orderKey = default(TKey); int i = 0; while (_source.MoveNext(ref elem, ref orderKey)) { if ((i++ & CancellationState.POLL_INTERVAL) == 0) { CancellationState.ThrowIfCanceled(_cancellationToken); } // For each element, we track the smallest order key for that element that we saw so far TKey oldEntry; Wrapper <TInputOutput> wrappedElem = new Wrapper <TInputOutput>(elem.First); // If this is the first occurrence of this element, or the order key is lower than all keys we saw previously, // update the order key for this element. if (!_hashLookup.TryGetValue(wrappedElem, out oldEntry) || _keyComparer.Compare(orderKey, oldEntry) < 0) { // For each "elem" value, we store the smallest key, and the element value that had that key. // Note that even though two element values are "equal" according to the EqualityComparer, // we still cannot choose arbitrarily which of the two to yield. _hashLookup[wrappedElem] = orderKey; } } _hashLookupEnumerator = _hashLookup.GetEnumerator(); } if (_hashLookupEnumerator.MoveNext()) { KeyValuePair <Wrapper <TInputOutput>, TKey> currentPair = _hashLookupEnumerator.Current; currentElement = currentPair.Key.Value; currentKey = currentPair.Value; return(true); } return(false); }
protected void BuildBaseHashLookup <TBaseBuilder, TBaseElement, TBaseOrderKey>( QueryOperatorEnumerator <Pair <TBaseElement, THashKey>, TBaseOrderKey> dataSource, TBaseBuilder baseHashBuilder, CancellationToken cancellationToken) where TBaseBuilder : IBaseHashBuilder <TBaseElement, TBaseOrderKey> { Debug.Assert(dataSource != null); #if DEBUG int hashLookupCount = 0; int hashKeyCollisions = 0; #endif Pair <TBaseElement, THashKey> currentPair = default(Pair <TBaseElement, THashKey>); TBaseOrderKey orderKey = default(TBaseOrderKey); int i = 0; while (dataSource.MoveNext(ref currentPair, ref orderKey)) { if ((i++ & CancellationState.POLL_INTERVAL) == 0) { CancellationState.ThrowIfCanceled(cancellationToken); } TBaseElement element = currentPair.First; THashKey hashKey = currentPair.Second; // We ignore null keys. if (hashKey != null) { #if DEBUG hashLookupCount++; #endif if (baseHashBuilder.Add(hashKey, element, orderKey)) { #if DEBUG hashKeyCollisions++; #endif } } } #if DEBUG TraceHelpers.TraceInfo("HashLookupBuilder::BuildBaseHashLookup - built hash table [count = {0}, collisions = {1}]", hashLookupCount, hashKeyCollisions); #endif }
internal override bool MoveNext(ref TInputOutput currentElement, ref TLeftKey currentKey) { if (this.m_outputEnumerator == null) { System.Linq.Parallel.Set <TInputOutput> set = new System.Linq.Parallel.Set <TInputOutput>(this.m_comparer); Pair <TInputOutput, NoKeyMemoizationRequired> pair = new Pair <TInputOutput, NoKeyMemoizationRequired>(); int num = 0; int num2 = 0; while (this.m_rightSource.MoveNext(ref pair, ref num)) { if ((num2++ & 0x3f) == 0) { CancellationState.ThrowIfCanceled(this.m_cancellationToken); } set.Add(pair.First); } Dictionary <Wrapper <TInputOutput>, Pair <TInputOutput, TLeftKey> > dictionary = new Dictionary <Wrapper <TInputOutput>, Pair <TInputOutput, TLeftKey> >(new WrapperEqualityComparer <TInputOutput>(this.m_comparer)); Pair <TInputOutput, NoKeyMemoizationRequired> pair2 = new Pair <TInputOutput, NoKeyMemoizationRequired>(); TLeftKey local = default(TLeftKey); while (this.m_leftSource.MoveNext(ref pair2, ref local)) { if ((num2++ & 0x3f) == 0) { CancellationState.ThrowIfCanceled(this.m_cancellationToken); } if (!set.Contains(pair2.First)) { Pair <TInputOutput, TLeftKey> pair3; Wrapper <TInputOutput> key = new Wrapper <TInputOutput>(pair2.First); if (!dictionary.TryGetValue(key, out pair3) || (this.m_leftKeyComparer.Compare(local, pair3.Second) < 0)) { dictionary[key] = new Pair <TInputOutput, TLeftKey>(pair2.First, local); } } } this.m_outputEnumerator = dictionary.GetEnumerator(); } if (this.m_outputEnumerator.MoveNext()) { Pair <TInputOutput, TLeftKey> pair4 = this.m_outputEnumerator.Current.Value; currentElement = pair4.First; currentKey = pair4.Second; return(true); } return(false); }
internal override bool MoveNext(ref TInputOutput currentElement, ref TLeftKey currentKey) { int num = 0; if (this.m_hashLookup == null) { this.m_hashLookup = new Dictionary <Wrapper <TInputOutput>, Pair <TInputOutput, TLeftKey> >(this.m_comparer); Pair <TInputOutput, NoKeyMemoizationRequired> pair = new Pair <TInputOutput, NoKeyMemoizationRequired>(); TLeftKey local = default(TLeftKey); while (this.m_leftSource.MoveNext(ref pair, ref local)) { Pair <TInputOutput, TLeftKey> pair2; if ((num++ & 0x3f) == 0) { CancellationState.ThrowIfCanceled(this.m_cancellationToken); } Wrapper <TInputOutput> key = new Wrapper <TInputOutput>(pair.First); if (!this.m_hashLookup.TryGetValue(key, out pair2) || (this.m_leftKeyComparer.Compare(local, pair2.Second) < 0)) { this.m_hashLookup[key] = new Pair <TInputOutput, TLeftKey>(pair.First, local); } } } Pair <TInputOutput, NoKeyMemoizationRequired> pair3 = new Pair <TInputOutput, NoKeyMemoizationRequired>(); int num2 = 0; while (this.m_rightSource.MoveNext(ref pair3, ref num2)) { Pair <TInputOutput, TLeftKey> pair4; if ((num++ & 0x3f) == 0) { CancellationState.ThrowIfCanceled(this.m_cancellationToken); } Wrapper <TInputOutput> wrapper2 = new Wrapper <TInputOutput>(pair3.First); if (this.m_hashLookup.TryGetValue(wrapper2, out pair4)) { currentElement = pair4.First; currentKey = pair4.Second; this.m_hashLookup.Remove(new Wrapper <TInputOutput>(pair4.First)); return(true); } } return(false); }
internal override bool MoveNext(ref TInputOutput currentElement, ref TKey currentKey) { if (this.m_outputLoopCount == null) { this.m_outputLoopCount = new Shared <int>(0); } while (this.m_source.MoveNext(ref currentElement, ref currentKey)) { if ((this.m_outputLoopCount.Value++ & 0x3f) == 0) { CancellationState.ThrowIfCanceled(this.m_cancellationToken); } if (this.m_predicate(currentElement)) { return(true); } } return(false); }
internal override bool MoveNext(ref TIntermediate currentElement, ref int currentKey) { if (!this.m_accumulated) { this.m_accumulated = true; bool flag = false; TIntermediate local = default(TIntermediate); if (this.m_reduceOperator.m_seedIsSpecified) { local = (this.m_reduceOperator.m_seedFactory == null) ? this.m_reduceOperator.m_seed : this.m_reduceOperator.m_seedFactory(); } else { TInput local2 = default(TInput); TKey local3 = default(TKey); if (!this.m_source.MoveNext(ref local2, ref local3)) { return(false); } flag = true; local = (TIntermediate)local2; } TInput local4 = default(TInput); TKey local5 = default(TKey); int num = 0; while (this.m_source.MoveNext(ref local4, ref local5)) { if ((num++ & 0x3f) == 0) { CancellationState.ThrowIfCanceled(this.m_cancellationToken); } flag = true; local = this.m_reduceOperator.m_intermediateReduce(local, local4); } if (flag) { currentElement = local; currentKey = this.m_partitionIndex; return(true); } } return(false); }
protected override bool MoveNextCore(ref float currentElement) { QueryOperatorEnumerator <float, TKey> source = this.m_source; TKey currentKey = default(TKey); if (!source.MoveNext(ref currentElement, ref currentKey)) { return(false); } int num = 0; if (this.m_sign == -1) { float num2 = 0f; while (source.MoveNext(ref num2, ref currentKey)) { if ((num++ & 0x3f) == 0) { CancellationState.ThrowIfCanceled(base.m_cancellationToken); } if ((num2 < currentElement) || float.IsNaN(num2)) { currentElement = num2; } } } else { float num3 = 0f; while (source.MoveNext(ref num3, ref currentKey)) { if ((num++ & 0x3f) == 0) { CancellationState.ThrowIfCanceled(base.m_cancellationToken); } if ((num3 > currentElement) || float.IsNaN(currentElement)) { currentElement = num3; } } } return(true); }
internal override bool MoveNext(ref TOutput currentElement, ref Pair <TLeftKey, int> currentKey) { while (true) { if (this.m_currentRightSource == null) { this.m_mutables = new Mutables <TLeftInput, TRightInput, TOutput, TLeftKey>(); if ((this.m_mutables.m_lhsCount++ & 0x3f) == 0) { CancellationState.ThrowIfCanceled(this.m_cancellationToken); } if (!this.m_leftSource.MoveNext(ref this.m_mutables.m_currentLeftElement, ref this.m_mutables.m_currentLeftKey)) { return(false); } this.m_currentRightSource = this.m_selectManyOperator.m_rightChildSelector(this.m_mutables.m_currentLeftElement).GetEnumerator(); if (this.m_selectManyOperator.m_resultSelector == null) { this.m_currentRightSourceAsOutput = (IEnumerator <TOutput>) this.m_currentRightSource; } } if (this.m_currentRightSource.MoveNext()) { this.m_mutables.m_currentRightSourceIndex++; if (this.m_selectManyOperator.m_resultSelector != null) { currentElement = this.m_selectManyOperator.m_resultSelector(this.m_mutables.m_currentLeftElement, this.m_currentRightSource.Current); } else { currentElement = this.m_currentRightSourceAsOutput.Current; } currentKey = new Pair <TLeftKey, int>(this.m_mutables.m_currentLeftKey, this.m_mutables.m_currentRightSourceIndex); return(true); } this.m_currentRightSource.Dispose(); this.m_currentRightSource = null; this.m_currentRightSourceAsOutput = null; } }
internal override bool MoveNext(ref TSource currentElement, ref int currentKey) { int num = 0; while (this.m_source.MoveNext(ref currentElement, ref currentKey)) { if ((num++ & 0x3f) == 0) { CancellationState.ThrowIfCanceled(this.m_cancellationToken); } if (this.m_resultFoundFlag.Value) { break; } if (currentKey == this.m_index) { this.m_resultFoundFlag.Value = true; return(true); } } return(false); }
internal override bool MoveNext(ref TInputOutput currentElement, ref int currentKey) { TKey local = default(TKey); Pair <TInputOutput, NoKeyMemoizationRequired> pair = new Pair <TInputOutput, NoKeyMemoizationRequired>(); if (this.m_outputLoopCount == null) { this.m_outputLoopCount = new Shared <int>(0); } while (this.m_source.MoveNext(ref pair, ref local)) { if ((this.m_outputLoopCount.Value++ & 0x3f) == 0) { CancellationState.ThrowIfCanceled(this.m_cancellationToken); } if (this.m_hashLookup.Add(pair.First)) { currentElement = pair.First; return(true); } } return(false); }
protected override HashLookup <Wrapper <TGroupKey>, OrderedGroupByQueryOperatorEnumerator <TSource, TGroupKey, TSource, TOrderKey> .GroupKeyData> BuildHashLookup() { HashLookup <Wrapper <TGroupKey>, OrderedGroupByQueryOperatorEnumerator <TSource, TGroupKey, TSource, TOrderKey> .GroupKeyData> lookup = new HashLookup <Wrapper <TGroupKey>, OrderedGroupByQueryOperatorEnumerator <TSource, TGroupKey, TSource, TOrderKey> .GroupKeyData>(new WrapperEqualityComparer <TGroupKey>(base.m_keyComparer)); Pair <TSource, TGroupKey> currentElement = new Pair <TSource, TGroupKey>(); TOrderKey currentKey = default(TOrderKey); int num = 0; while (base.m_source.MoveNext(ref currentElement, ref currentKey)) { if ((num++ & 0x3f) == 0) { CancellationState.ThrowIfCanceled(base.m_cancellationToken); } Wrapper <TGroupKey> key = new Wrapper <TGroupKey>(currentElement.Second); OrderedGroupByQueryOperatorEnumerator <TSource, TGroupKey, TSource, TOrderKey> .GroupKeyData data = null; if (lookup.TryGetValue(key, ref data)) { if (base.m_orderComparer.Compare(currentKey, data.m_orderKey) < 0) { data.m_orderKey = currentKey; } } else { data = new OrderedGroupByQueryOperatorEnumerator <TSource, TGroupKey, TSource, TOrderKey> .GroupKeyData(currentKey, key.Value, base.m_orderComparer); lookup.Add(key, data); } data.m_grouping.Add(currentElement.First, currentKey); } for (int i = 0; i < lookup.Count; i++) { KeyValuePair <Wrapper <TGroupKey>, OrderedGroupByQueryOperatorEnumerator <TSource, TGroupKey, TSource, TOrderKey> .GroupKeyData> pair2 = lookup[i]; pair2.Value.m_grouping.DoneAdding(); } return(lookup); }
protected override bool MoveNextCore(ref Pair <decimal, long> currentElement) { decimal first = 0.0M; long second = 0L; QueryOperatorEnumerator <decimal?, TKey> source = this.m_source; decimal?nullable = null; TKey currentKey = default(TKey); int num3 = 0; while (source.MoveNext(ref nullable, ref currentKey)) { if ((num3++ & 0x3f) == 0) { CancellationState.ThrowIfCanceled(base.m_cancellationToken); } if (nullable.HasValue) { first += nullable.GetValueOrDefault(); second += 1L; } } currentElement = new Pair <decimal, long>(first, second); return(second > 0L); }
//--------------------------------------------------------------------------------------- // Walks the two data sources, left and then right, to produce the union. // internal override bool MoveNext([MaybeNullWhen(false), AllowNull] ref TInputOutput currentElement, ref ConcatKey <TLeftKey, TRightKey> currentKey) { Debug.Assert(_leftSource != null); Debug.Assert(_rightSource != null); if (_outputEnumerator == null) { IEqualityComparer <Wrapper <TInputOutput> > wrapperComparer = new WrapperEqualityComparer <TInputOutput>(_comparer); Dictionary <Wrapper <TInputOutput>, Pair <TInputOutput, ConcatKey <TLeftKey, TRightKey> > > union = new Dictionary <Wrapper <TInputOutput>, Pair <TInputOutput, ConcatKey <TLeftKey, TRightKey> > >(wrapperComparer); Pair <TInputOutput, NoKeyMemoizationRequired> elem = default(Pair <TInputOutput, NoKeyMemoizationRequired>); TLeftKey leftKey = default(TLeftKey) !; int i = 0; while (_leftSource.MoveNext(ref elem, ref leftKey)) { if ((i++ & CancellationState.POLL_INTERVAL) == 0) { CancellationState.ThrowIfCanceled(_cancellationToken); } ConcatKey <TLeftKey, TRightKey> key = ConcatKey <TLeftKey, TRightKey> .MakeLeft(_leftOrdered?leftKey : default);
//--------------------------------------------------------------------------------------- // Just walks the entire data source upon its first invocation, performing the per- // element action for each element. // internal override bool MoveNext([MaybeNullWhen(false), AllowNull] ref TInput currentElement, ref int currentKey) { Debug.Assert(_elementAction != null, "expected a compiled operator"); // We just scroll through the enumerator and execute the action. Because we execute // "in place", we actually never even produce a single value. // Cancellation testing must be performed here as full enumeration occurs within this method. // We only need to throw a simple exception here.. marshalling logic handled via QueryTaskGroupState.QueryEnd (called by ForAllSpoolingTask) TInput element = default(TInput) !; TKey keyUnused = default(TKey) !; int i = 0; while (_source.MoveNext(ref element, ref keyUnused)) { if ((i++ & CancellationState.POLL_INTERVAL) == 0) { CancellationState.ThrowIfCanceled(_cancellationToken); } _elementAction(element); } return(false); }
protected override bool MoveNextCore(ref double currentElement) { float num = 0f; TKey currentKey = default(TKey); QueryOperatorEnumerator <float, TKey> source = this.m_source; if (!source.MoveNext(ref num, ref currentKey)) { return(false); } double num2 = 0.0; int num3 = 0; do { if ((num3++ & 0x3f) == 0) { CancellationState.ThrowIfCanceled(base.m_cancellationToken); } num2 += num; }while (source.MoveNext(ref num, ref currentKey)); currentElement = num2; return(true); }
protected override bool MoveNextCore(ref long currentElement) { TSource local = default(TSource); TKey currentKey = default(TKey); QueryOperatorEnumerator <TSource, TKey> source = this.m_source; if (!source.MoveNext(ref local, ref currentKey)) { return(false); } long num = 0L; int num2 = 0; do { if ((num2++ & 0x3f) == 0) { CancellationState.ThrowIfCanceled(base.m_cancellationToken); } num += 1L; }while (source.MoveNext(ref local, ref currentKey)); currentElement = num; return(true); }
protected override HashLookup <Wrapper <TGroupKey>, ListChunk <TSource> > BuildHashLookup() { HashLookup <Wrapper <TGroupKey>, ListChunk <TSource> > lookup = new HashLookup <Wrapper <TGroupKey>, ListChunk <TSource> >(new WrapperEqualityComparer <TGroupKey>(base.m_keyComparer)); Pair <TSource, TGroupKey> currentElement = new Pair <TSource, TGroupKey>(); TOrderKey currentKey = default(TOrderKey); int num = 0; while (base.m_source.MoveNext(ref currentElement, ref currentKey)) { if ((num++ & 0x3f) == 0) { CancellationState.ThrowIfCanceled(base.m_cancellationToken); } Wrapper <TGroupKey> key = new Wrapper <TGroupKey>(currentElement.Second); ListChunk <TSource> chunk = null; if (!lookup.TryGetValue(key, ref chunk)) { chunk = new ListChunk <TSource>(2); lookup.Add(key, chunk); } chunk.Add(currentElement.First); } return(lookup); }
internal override bool MoveNext(ref bool currentElement, ref int currentKey) { if (this.m_resultFoundFlag.Value) { return(false); } TInput local = default(TInput); TKey local2 = default(TKey); if (!this.m_source.MoveNext(ref local, ref local2)) { return(false); } currentElement = false; currentKey = this.m_partitionIndex; int num = 0; do { if ((num++ & 0x3f) == 0) { CancellationState.ThrowIfCanceled(this.m_cancellationToken); } if (this.m_resultFoundFlag.Value) { return(false); } if (this.m_comparer.Equals(local, this.m_searchValue)) { this.m_resultFoundFlag.Value = true; currentElement = true; break; } }while (this.m_source.MoveNext(ref local, ref local2)); return(true); }
protected override bool MoveNextCore(ref double?currentElement) { float?nullable = null; TKey currentKey = default(TKey); QueryOperatorEnumerator <float?, TKey> source = this.m_source; if (!source.MoveNext(ref nullable, ref currentKey)) { return(false); } float num = 0f; int num2 = 0; do { if ((num2++ & 0x3f) == 0) { CancellationState.ThrowIfCanceled(base.m_cancellationToken); } num += nullable.GetValueOrDefault(); }while (source.MoveNext(ref nullable, ref currentKey)); currentElement = new double?((double)num); return(true); }
//----------------------------------------------------------------------------------- // Builds the hash lookup, transforming from TSource to TElement through whatever means is appropriate. // protected override HashLookup <Wrapper <TGroupKey>, ListChunk <TElement> > BuildHashLookup() { HashLookup <Wrapper <TGroupKey>, ListChunk <TElement> > hashlookup = new HashLookup <Wrapper <TGroupKey>, ListChunk <TElement> >(new WrapperEqualityComparer <TGroupKey>(_keyComparer)); Pair <TSource, TGroupKey> sourceElement = default(Pair <TSource, TGroupKey>); TOrderKey sourceKeyUnused = default(TOrderKey); int i = 0; while (_source.MoveNext(ref sourceElement, ref sourceKeyUnused)) { if ((i++ & CancellationState.POLL_INTERVAL) == 0) { CancellationState.ThrowIfCanceled(_cancellationToken); } // Generate a key and place it into the hashtable. Wrapper <TGroupKey> key = new Wrapper <TGroupKey>(sourceElement.Second); // If the key already exists, we just append it to the existing list -- // otherwise we will create a new one and add it to that instead. ListChunk <TElement> currentValue = null; if (!hashlookup.TryGetValue(key, ref currentValue)) { const int INITIAL_CHUNK_SIZE = 2; currentValue = new ListChunk <TElement>(INITIAL_CHUNK_SIZE); hashlookup.Add(key, currentValue); } Debug.Assert(currentValue != null); // Call to the base class to yield the current value. currentValue.Add(_elementSelector(sourceElement.First)); } return(hashlookup); }
//--------------------------------------------------------------------------------------- // Walks the two data sources, left and then right, to produce the intersection. // internal override bool MoveNext(ref TInputOutput currentElement, ref TLeftKey currentKey) { Debug.Assert(_leftSource != null); Debug.Assert(_rightSource != null); // Build the set out of the left data source, if we haven't already. int i = 0; if (_hashLookup == null) { _hashLookup = new Dictionary <Wrapper <TInputOutput>, Pair <TInputOutput, TLeftKey> >(_comparer); Pair <TInputOutput, NoKeyMemoizationRequired> leftElement = default(Pair <TInputOutput, NoKeyMemoizationRequired>); TLeftKey leftKey = default(TLeftKey); while (_leftSource.MoveNext(ref leftElement, ref leftKey)) { if ((i++ & CancellationState.POLL_INTERVAL) == 0) { CancellationState.ThrowIfCanceled(_cancellationToken); } // For each element, we track the smallest order key for that element that we saw so far Pair <TInputOutput, TLeftKey> oldEntry; Wrapper <TInputOutput> wrappedLeftElem = new Wrapper <TInputOutput>(leftElement.First); // If this is the first occurrence of this element, or the order key is lower than all keys we saw previously, // update the order key for this element. if (!_hashLookup.TryGetValue(wrappedLeftElem, out oldEntry) || _leftKeyComparer.Compare(leftKey, oldEntry.Second) < 0) { // For each "elem" value, we store the smallest key, and the element value that had that key. // Note that even though two element values are "equal" according to the EqualityComparer, // we still cannot choose arbitrarily which of the two to yield. _hashLookup[wrappedLeftElem] = new Pair <TInputOutput, TLeftKey>(leftElement.First, leftKey); } } } // Now iterate over the right data source, looking for matches. Pair <TInputOutput, NoKeyMemoizationRequired> rightElement = default(Pair <TInputOutput, NoKeyMemoizationRequired>); int rightKeyUnused = default(int); while (_rightSource.MoveNext(ref rightElement, ref rightKeyUnused)) { if ((i++ & CancellationState.POLL_INTERVAL) == 0) { CancellationState.ThrowIfCanceled(_cancellationToken); } // If we found the element in our set, and if we haven't returned it yet, // we can yield it to the caller. We also mark it so we know we've returned // it once already and never will again. Pair <TInputOutput, TLeftKey> entry; Wrapper <TInputOutput> wrappedRightElem = new Wrapper <TInputOutput>(rightElement.First); if (_hashLookup.TryGetValue(wrappedRightElem, out entry)) { currentElement = entry.First; currentKey = entry.Second; _hashLookup.Remove(new Wrapper <TInputOutput>(entry.First)); return(true); } } return(false); }
//--------------------------------------------------------------------------------------- // Walks the two data sources, left and then right, to produce the distinct set // internal override bool MoveNext(ref TInputOutput currentElement, ref TLeftKey currentKey) { Contract.Assert(_leftSource != null); Contract.Assert(_rightSource != null); // Build the set out of the left data source, if we haven't already. if (_outputEnumerator == null) { Set <TInputOutput> rightLookup = new Set <TInputOutput>(_comparer); Pair rightElement = new Pair(default(TInputOutput), default(NoKeyMemoizationRequired)); int rightKeyUnused = default(int); int i = 0; while (_rightSource.MoveNext(ref rightElement, ref rightKeyUnused)) { if ((i++ & CancellationState.POLL_INTERVAL) == 0) { CancellationState.ThrowIfCanceled(_cancellationToken); } rightLookup.Add((TInputOutput)rightElement.First); } var leftLookup = new Dictionary <Wrapper <TInputOutput>, Pair>( new WrapperEqualityComparer <TInputOutput>(_comparer)); Pair leftElement = new Pair(default(TInputOutput), default(NoKeyMemoizationRequired)); TLeftKey leftKey = default(TLeftKey); while (_leftSource.MoveNext(ref leftElement, ref leftKey)) { if ((i++ & CancellationState.POLL_INTERVAL) == 0) { CancellationState.ThrowIfCanceled(_cancellationToken); } if (rightLookup.Contains((TInputOutput)leftElement.First)) { continue; } Pair oldEntry; Wrapper <TInputOutput> wrappedLeftElement = new Wrapper <TInputOutput>((TInputOutput)leftElement.First); if (!leftLookup.TryGetValue(wrappedLeftElement, out oldEntry) || _leftKeyComparer.Compare(leftKey, (TLeftKey)oldEntry.Second) < 0) { // For each "elem" value, we store the smallest key, and the element value that had that key. // Note that even though two element values are "equal" according to the EqualityComparer, // we still cannot choose arbitrarily which of the two to yield. leftLookup[wrappedLeftElement] = new Pair(leftElement.First, leftKey); } } _outputEnumerator = leftLookup.GetEnumerator(); } if (_outputEnumerator.MoveNext()) { Pair currentPair = _outputEnumerator.Current.Value; currentElement = (TInputOutput)currentPair.First; currentKey = (TLeftKey)currentPair.Second; return(true); } return(false); }
//--------------------------------------------------------------------------------------- // Straightforward IEnumerator<T> methods. // internal override bool MoveNext(ref TOutput currentElement, ref Pair <TLeftKey, int> currentKey) { while (true) { if (_currentRightSource == null) { _mutables = new Mutables(); // Check cancellation every few lhs-enumerations in case none of them are producing // any outputs. Otherwise, we rely on the consumer of this operator to be performing the checks. if ((_mutables._lhsCount++ & CancellationState.POLL_INTERVAL) == 0) { CancellationState.ThrowIfCanceled(_cancellationToken); } // We don't have a "current" right enumerator to use. We have to fetch the next // one. If the left has run out of elements, however, we're done and just return // false right away. if (!_leftSource.MoveNext(ref _mutables._currentLeftElement, ref _mutables._currentLeftKey)) { return(false); } // Use the source selection routine to create a right child. IEnumerable <TRightInput> rightChild = _selectManyOperator._rightChildSelector(_mutables._currentLeftElement); Debug.Assert(rightChild != null); _currentRightSource = rightChild.GetEnumerator(); Debug.Assert(_currentRightSource != null); // If we have no result selector, we will need to access the Current element of the right // data source as though it is a TOutput. Unfortunately, we know that TRightInput must // equal TOutput (we check it during operator construction), but the type system doesn't. // Thus we would have to cast the result of invoking Current from type TRightInput to // TOutput. This is no good, since the results could be value types. Instead, we save the // enumerator object as an IEnumerator<TOutput> and access that later on. if (_selectManyOperator._resultSelector == null) { _currentRightSourceAsOutput = (IEnumerator <TOutput>)_currentRightSource; Debug.Assert(_currentRightSourceAsOutput == _currentRightSource, "these must be equal, otherwise the surrounding logic will be broken"); } } if (_currentRightSource.MoveNext()) { _mutables._currentRightSourceIndex++; // If the inner data source has an element, we can yield it. if (_selectManyOperator._resultSelector != null) { // In the case of a selection function, use that to yield the next element. currentElement = _selectManyOperator._resultSelector(_mutables._currentLeftElement, _currentRightSource.Current); } else { // Otherwise, the right input and output types must be the same. We use the // casted copy of the current right source and just return its current element. Debug.Assert(_currentRightSourceAsOutput != null); currentElement = _currentRightSourceAsOutput.Current; } currentKey = new Pair <TLeftKey, int>(_mutables._currentLeftKey, _mutables._currentRightSourceIndex); return(true); } else { // Otherwise, we have exhausted the right data source. Loop back around and try // to get the next left element, then its right, and so on. _currentRightSource.Dispose(); _currentRightSource = null; _currentRightSourceAsOutput = null; } } }
//--------------------------------------------------------------------------------------- // Called when this enumerator is first enumerated; it must walk through the source // and redistribute elements to their slot in the exchange matrix. // private void EnumerateAndRedistributeElements() { Mutables mutables = m_mutables; Contract.Assert(mutables != null); ListChunk <Pair <TInputOutput, THashKey> >[] privateBuffers = new ListChunk <Pair <TInputOutput, THashKey> > [m_partitionCount]; ListChunk <TOrderKey>[] privateKeyBuffers = new ListChunk <TOrderKey> [m_partitionCount]; TInputOutput element = default(TInputOutput); TOrderKey key = default(TOrderKey); int loopCount = 0; while (m_source.MoveNext(ref element, ref key)) { if ((loopCount++ & CancellationState.POLL_INTERVAL) == 0) { CancellationState.ThrowIfCanceled(m_cancellationToken); } // Calculate the element's destination partition index, placing it into the // appropriate buffer from which partitions will later enumerate. int destinationIndex; THashKey elementHashKey = default(THashKey); if (m_keySelector != null) { elementHashKey = m_keySelector(element); destinationIndex = m_repartitionStream.GetHashCode(elementHashKey) % m_partitionCount; } else { Contract.Assert(typeof(THashKey) == typeof(NoKeyMemoizationRequired)); destinationIndex = m_repartitionStream.GetHashCode(element) % m_partitionCount; } Contract.Assert(0 <= destinationIndex && destinationIndex < m_partitionCount, "destination partition outside of the legal range of partitions"); // Get the buffer for the destnation partition, lazily allocating if needed. We maintain // this list in our own private cache so that we avoid accessing shared memory locations // too much. In the original implementation, we'd access the buffer in the matrix ([N,M], // where N is the current partition and M is the destination), but some rudimentary // performance profiling indicates copying at the end performs better. ListChunk <Pair <TInputOutput, THashKey> > buffer = privateBuffers[destinationIndex]; ListChunk <TOrderKey> keyBuffer = privateKeyBuffers[destinationIndex]; if (buffer == null) { const int INITIAL_PRIVATE_BUFFER_SIZE = 128; Contract.Assert(keyBuffer == null); privateBuffers[destinationIndex] = buffer = new ListChunk <Pair <TInputOutput, THashKey> >(INITIAL_PRIVATE_BUFFER_SIZE); privateKeyBuffers[destinationIndex] = keyBuffer = new ListChunk <TOrderKey>(INITIAL_PRIVATE_BUFFER_SIZE); } buffer.Add(new Pair <TInputOutput, THashKey>(element, elementHashKey)); keyBuffer.Add(key); } // Copy the local buffers to the shared space and then signal to other threads that // we are done. We can then immediately move on to enumerating the elements we found // for the current partition before waiting at the barrier. If we found a lot, we will // hopefully never have to physically wait. for (int i = 0; i < m_partitionCount; i++) { m_valueExchangeMatrix[m_partitionIndex, i] = privateBuffers[i]; m_keyExchangeMatrix[m_partitionIndex, i] = privateKeyBuffers[i]; } m_barrier.Signal(); // Begin at our own buffer. mutables.m_currentBufferIndex = m_partitionIndex; mutables.m_currentBuffer = privateBuffers[m_partitionIndex]; mutables.m_currentKeyBuffer = privateKeyBuffers[m_partitionIndex]; mutables.m_currentIndex = ENUMERATION_NOT_STARTED; }
//--------------------------------------------------------------------------------------- // This API, upon the first time calling it, walks the entire source query tree. It begins // with an accumulator value set to the aggregation operator's seed, and always passes // the accumulator along with the current element from the data source to the binary // intermediary aggregation operator. The return value is kept in the accumulator. At // the end, we will have our intermediate result, ready for final aggregation. // internal override bool MoveNext(ref TIntermediate currentElement, ref int currentKey) { Contract.Assert(_reduceOperator != null); Contract.Assert(_reduceOperator._intermediateReduce != null, "expected a compiled operator"); // Only produce a single element. Return false if MoveNext() was already called before. if (_accumulated) { return(false); } _accumulated = true; bool hadNext = false; TIntermediate accumulator = default(TIntermediate); // Initialize the accumulator. if (_reduceOperator._seedIsSpecified) { // If the seed is specified, initialize accumulator to the seed value. accumulator = _reduceOperator._seedFactory == null ? _reduceOperator._seed : _reduceOperator._seedFactory(); } else { // If the seed is not specified, then we take the first element as the seed. // Seed may be unspecified only if TInput is the same as TIntermediate. Contract.Assert(typeof(TInput) == typeof(TIntermediate)); TInput acc = default(TInput); TKey accKeyUnused = default(TKey); if (!_source.MoveNext(ref acc, ref accKeyUnused)) { return(false); } hadNext = true; accumulator = (TIntermediate)((object)acc); } // Scan through the source and accumulate the result. TInput input = default(TInput); TKey keyUnused = default(TKey); int i = 0; while (_source.MoveNext(ref input, ref keyUnused)) { if ((i++ & CancellationState.POLL_INTERVAL) == 0) { CancellationState.ThrowIfCanceled(_cancellationToken); } hadNext = true; accumulator = _reduceOperator._intermediateReduce(accumulator, input); } if (hadNext) { currentElement = accumulator; currentKey = _partitionIndex; // A reduction's "index" is just its partition number. return(true); } return(false); }