//--------------------------------------------------------------------------------------- // 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 double currentElement) { // Based on the sign, do either a min or max reduction. QueryOperatorEnumerator <double, TKey> source = _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 (_sign == -1) { double elem = default(double); while (source.MoveNext(ref elem, ref keyUnused)) { if ((i++ & CancellationState.POLL_INTERVAL) == 0) { _cancellationToken.ThrowIfCancellationRequested(); } ; if (elem < currentElement || double.IsNaN(elem)) { currentElement = elem; } } } else { double elem = default(double); while (source.MoveNext(ref elem, ref keyUnused)) { if ((i++ & CancellationState.POLL_INTERVAL) == 0) { _cancellationToken.ThrowIfCancellationRequested(); } ; if (elem > currentElement || double.IsNaN(currentElement)) { currentElement = elem; } } } // The sum has been calculated. Now just return. return(true); } return(false); }
//--------------------------------------------------------------------------------------- // This enumerates the entire input source to perform the search. If another peer // partition finds an answer before us, we will voluntarily return (propagating the // peer's result). // internal override bool MoveNext(ref bool currentElement, ref int currentKey) { Debug.Assert(_comparer != null); // Avoid enumerating if we've already found an answer. if (_resultFoundFlag.Value) { return(false); } // We just scroll through the enumerator and accumulate the result. TInput element = default(TInput); TKey keyUnused = default(TKey); if (_source.MoveNext(ref element, ref keyUnused)) { currentElement = false; currentKey = _partitionIndex; // Continue walking the data so long as we haven't found an item that satisfies // the condition we are searching for. int i = 0; do { if ((i++ & CancellationState.POLL_INTERVAL) == 0) { CancellationState.ThrowIfCanceled(_cancellationToken); } if (_resultFoundFlag.Value) { // If cancellation occurred, it's because a successful answer was found. return(false); } if (_comparer.Equals(element, _searchValue)) { // We have found an item that satisfies the search. Cancel other // workers that are concurrently searching, and return. _resultFoundFlag.Value = true; currentElement = true; break; } }while (_source.MoveNext(ref element, ref keyUnused)); return(true); } return(false); }
//--------------------------------------------------------------------------------------- // 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 decimal?currentElement) { // Based on the sign, do either a min or max reduction. QueryOperatorEnumerator <decimal?, TKey> source = _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 (_sign == -1) { decimal?elem = default(decimal?); while (source.MoveNext(ref elem, ref keyUnused)) { if ((i++ & CancellationState.POLL_INTERVAL) == 0) { CancellationState.ThrowIfCanceled(_cancellationToken); } if (currentElement == null || elem < currentElement) { currentElement = elem; } } } else { decimal?elem = default(decimal?); while (source.MoveNext(ref elem, ref keyUnused)) { if ((i++ & CancellationState.POLL_INTERVAL) == 0) { CancellationState.ThrowIfCanceled(_cancellationToken); } if (currentElement == null || elem > currentElement) { currentElement = elem; } } } // The sum has been calculated. Now just return. return(true); } return(false); }
//----------------------------------------------------------------------------------- // Moves to the next matching element in the underlying data stream. // internal override bool MoveNext(ref TInputOutput currentElement, ref TKey currentKey) { Debug.Assert(_predicate != null, "expected a compiled operator"); // Iterate through the input until we reach the end of the sequence or find // an element matching the predicate. if (_outputLoopCount == null) { _outputLoopCount = new Shared <int>(0); } while (_source.MoveNext(ref currentElement, ref currentKey)) { if ((_outputLoopCount.Value++ & CancellationState.POLL_INTERVAL) == 0) { CancellationState.ThrowIfCanceled(_cancellationToken); } if (_predicate(currentElement)) { return(true); } } return(false); }
//--------------------------------------------------------------------------------------- // Enumerates the entire input until the element with the specified is found or another // partition has signaled that it found the element. // internal override bool MoveNext(ref TSource currentElement, ref int currentKey) { // Just walk the enumerator until we've found the element. int i = 0; while (_source.MoveNext(ref currentElement, ref currentKey)) { if ((i++ & CancellationState.POLL_INTERVAL) == 0) { CancellationState.ThrowIfCanceled(_cancellationToken); } if (_resultFoundFlag.Value) { // Another partition found the element. break; } if (currentKey == _index) { // We have found the element. Cancel other searches and return true. _resultFoundFlag.Value = true; return(true); } } return(false); }
//--------------------------------------------------------------------------------------- // 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) { _cancellationToken.ThrowIfCancellationRequested(); } ; 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) { _cancellationToken.ThrowIfCancellationRequested(); } ; _elementAction(element); } return(false); }
//--------------------------------------------------------------------------------------- // 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 <TLeftKey, TRightKey> 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 <TLeftKey, TRightKey> .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 <TLeftKey, TRightKey> .MakeRight(rightKey); return(true); } return(false); }
/// <summary> /// A variant of WrapEnumerable that accepts a QueryOperatorEnumerator{,} instead of an IEnumerable{}. /// The code duplication is necessary to avoid extra virtual method calls that would otherwise be needed to /// convert the QueryOperatorEnumerator{,} to an IEnumerator{}. /// </summary> internal static IEnumerable <TElement> WrapQueryEnumerator <TElement, TIgnoreKey>(QueryOperatorEnumerator <TElement, TIgnoreKey> source, CancellationState cancellationState) { TElement elem = default(TElement); TIgnoreKey ignoreKey = default(TIgnoreKey); try { while (true) { try { if (!source.MoveNext(ref elem, ref ignoreKey)) { yield break; } } catch (ThreadAbortException) { // Do not wrap ThreadAbortExceptions throw; } catch (Exception ex) { ThrowOCEorAggregateException(ex, cancellationState); } yield return(elem); } } finally { source.Dispose(); } }
internal static IEnumerable <TElement> WrapQueryEnumerator <TElement, TIgnoreKey>(QueryOperatorEnumerator <TElement, TIgnoreKey> source, CancellationState cancellationState) { TElement currentElement = default(TElement); TIgnoreKey currentKey = default(TIgnoreKey); while (true) { try { if (!source.MoveNext(ref currentElement, ref currentKey)) { break; } } catch (ThreadAbortException) { throw; } catch (Exception exception) { ThrowOCEorAggregateException(exception, cancellationState); } yield return(currentElement); } }
//--------------------------------------------------------------------------------------- // Tallies up the average of the underlying data source, walking the entire thing the first // time MoveNext is called on this object. // protected override bool MoveNextCore(ref Pair <decimal, long> currentElement) { // The temporary result contains the running sum and count, respectively. decimal sum = 0.0m; long count = 0; QueryOperatorEnumerator <decimal?, TKey> source = _source; decimal?current = default(decimal?); TKey currentKey = default(TKey) !; int i = 0; while (source.MoveNext(ref current, ref currentKey)) { if ((i++ & CancellationState.POLL_INTERVAL) == 0) { _cancellationToken.ThrowIfCancellationRequested(); } ; if (current.HasValue) { checked { sum += current.GetValueOrDefault(); count++; } } } currentElement = new Pair <decimal, long>(sum, count); return(count > 0); }
//--------------------------------------------------------------------------------------- // Straightforward IEnumerator<T> methods. // internal override bool MoveNext(ref TSource currentElement, ref int currentKey) { Contract.Assert(m_source != null); if (m_alreadySearched) { // If we've already searched, we will "fake out" the caller by returning an extra // element at the end in the case that we've found more than one element. if (m_yieldExtra) { m_yieldExtra = false; currentElement = default(TSource); currentKey = 0; return(true); } return(false); } // Scan our input, looking for a match. bool found = false; TSource current = default(TSource); TKey keyUnused = default(TKey); while (m_source.MoveNext(ref current, ref keyUnused)) { // If the predicate is null or the current element satisfies it, we will remember // it so that we can yield it later. We then proceed with scanning the input // in case there are multiple such elements. if (m_predicate == null || m_predicate(current)) { // Notify other partitions. Interlocked.Increment(ref m_totalElementCount.Value); currentElement = current; currentKey = 0; if (found) { // Already found an element previously, we can exit. m_yieldExtra = true; break; } else { found = true; } } // If we've already determined there is more than one matching element in the // data source, we can exit right away. if (Volatile.Read(ref m_totalElementCount.Value) > 1) { break; } } m_alreadySearched = true; return(found); }
//--------------------------------------------------------------------------------------- // Tallies up the average of the underlying data source, walking the entire thing the first // time MoveNext is called on this object. // protected override bool MoveNextCore(ref Pair <long, long> currentElement) { // The temporary result contains the running sum and count, respectively. long sum = 0; long count = 0; QueryOperatorEnumerator <int?, TKey> source = _source; int? current = default(int?); TKey keyUnused = default(TKey); int i = 0; while (source.MoveNext(ref current, ref keyUnused)) { if ((i++ & CancellationState.POLL_INTERVAL) == 0) { CancellationState.ThrowIfCanceled(_cancellationToken); } if (current.HasValue) { sum += current.GetValueOrDefault(); count++; } } currentElement = new Pair <long, long>(sum, count); return(count > 0); }
//--------------------------------------------------------------------------------------- // Walks the two data sources, left and then right, to produce the distinct set // internal override bool MoveNext([MaybeNullWhen(false), AllowNull] ref TInputOutput currentElement, ref int currentKey) { Debug.Assert(_leftSource != null); Debug.Assert(_rightSource != null); // Build the set out of the left data source, if we haven't already. if (_hashLookup == null) { _outputLoopCount = new Shared <int>(0); _hashLookup = new HashSet <TInputOutput>(_comparer); Pair <TInputOutput, NoKeyMemoizationRequired> rightElement = default(Pair <TInputOutput, NoKeyMemoizationRequired>); int rightKeyUnused = default(int); int i = 0; while (_rightSource.MoveNext(ref rightElement, ref rightKeyUnused)) { if ((i++ & CancellationState.POLL_INTERVAL) == 0) { _cancellationToken.ThrowIfCancellationRequested(); } ; _hashLookup.Add(rightElement.First); } } // Now iterate over the right data source, looking for matches. Pair <TInputOutput, NoKeyMemoizationRequired> leftElement = default(Pair <TInputOutput, NoKeyMemoizationRequired>); TLeftKey leftKeyUnused = default !;
//----------------------------------------------------------------------------------- // This method is responsible for enumerating results and enqueueing them to // the output channel(s) as appropriate. Each base class implements its own. // protected override void SpoolingWork() { // We just enumerate over the entire source data stream, placing each element // into the destination channel. TInputOutput current = default(TInputOutput); TIgnoreKey keyUnused = default(TIgnoreKey); QueryOperatorEnumerator <TInputOutput, TIgnoreKey> source = _source; AsynchronousChannel <TInputOutput> destination = _destination; CancellationToken cancelToken = _groupState.CancellationState.MergedCancellationToken; while (source.MoveNext(ref current, ref keyUnused)) { // If an abort has been requested, stop this worker immediately. if (cancelToken.IsCancellationRequested) { break; } destination.Enqueue(current); } // Flush remaining data to the query consumer in preparation for channel shutdown. destination.FlushBuffers(); }
//--------------------------------------------------------------------------------------- // Straightforward IEnumerator<T> methods. // internal override bool MoveNext(ref TSource currentElement, ref TKey currentKey) { // If the buffer has not been created, we will generate it lazily on demand. if (_buffer == null) { _bufferIndex = new Shared <int>(0); // Buffer all of our data. _buffer = new List <Pair>(); TSource current = default(TSource); TKey key = default(TKey); int i = 0; while (_source.MoveNext(ref current, ref key)) { if ((i++ & CancellationState.POLL_INTERVAL) == 0) { CancellationState.ThrowIfCanceled(_cancellationToken); } _buffer.Add(new Pair(current, key)); _bufferIndex.Value++; } } // Continue yielding elements from our buffer. if (--_bufferIndex.Value >= 0) { currentElement = (TSource)_buffer[_bufferIndex.Value].First; currentKey = (TKey)_buffer[_bufferIndex.Value].Second; return(true); } return(false); }
//--------------------------------------------------------------------------------------- // Walks the single data source, skipping elements it has already seen. // internal override bool MoveNext(ref TInputOutput currentElement, ref int currentKey) { Debug.Assert(_source != null); Debug.Assert(_hashLookup != null); // Iterate over this set's elements until we find a unique element. TKey keyUnused = default(TKey); Pair <TInputOutput, NoKeyMemoizationRequired> current = default(Pair <TInputOutput, NoKeyMemoizationRequired>); if (_outputLoopCount == null) { _outputLoopCount = new Shared <int>(0); } while (_source.MoveNext(ref current, ref keyUnused)) { if ((_outputLoopCount.Value++ & CancellationState.POLL_INTERVAL) == 0) { CancellationState.ThrowIfCanceled(_cancellationToken); } // We ensure we never return duplicates by tracking them in our set. if (_hashLookup.Add(current.First)) { #if DEBUG currentKey = unchecked ((int)0xdeadbeef); #endif currentElement = current.First; return(true); } } return(false); }
//--------------------------------------------------------------------------------------- // Walks the two data sources, left and then right, to produce the intersection. // internal override bool MoveNext(ref TInputOutput currentElement, ref int currentKey) { Contract.Assert(m_leftSource != null); Contract.Assert(m_rightSource != null); // Build the set out of the right data source, if we haven't already. if (m_hashLookup == null) { m_outputLoopCount = new Shared <int>(0); // @TODO: @PERF: @BUG#594: different implementation of set operations. Consider a treap. m_hashLookup = new Set <TInputOutput>(m_comparer); Pair <TInputOutput, NoKeyMemoizationRequired> rightElement = default(Pair <TInputOutput, NoKeyMemoizationRequired>); int rightKeyUnused = default(int); int i = 0; while (m_rightSource.MoveNext(ref rightElement, ref rightKeyUnused)) { if ((i++ & CancellationState.POLL_INTERVAL) == 0) { CancellationState.ThrowIfCanceled(m_cancellationToken); } m_hashLookup.Add(rightElement.First); } } // Now iterate over the left data source, looking for matches. Pair <TInputOutput, NoKeyMemoizationRequired> leftElement = default(Pair <TInputOutput, NoKeyMemoizationRequired>); TLeftKey keyUnused = default(TLeftKey); while (m_leftSource.MoveNext(ref leftElement, ref keyUnused)) { if ((m_outputLoopCount.Value++ & CancellationState.POLL_INTERVAL) == 0) { CancellationState.ThrowIfCanceled(m_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. if (m_hashLookup.Contains(leftElement.First)) { // @TODO: @PERF: avoid the double lookup required to remove the element // we have already found in the hashtable. m_hashLookup.Remove(leftElement.First); currentElement = leftElement.First; #if DEBUG currentKey = unchecked ((int)0xdeadbeef); #endif return(true); } } return(false); }
//--------------------------------------------------------------------------------------- // Walks the two data sources, left and then right, to produce the intersection. // internal override bool MoveNext([MaybeNullWhen(false), AllowNull] ref TInputOutput currentElement, ref int currentKey) { Debug.Assert(_leftSource != null); Debug.Assert(_rightSource != null); // Build the set out of the right data source, if we haven't already. if (_hashLookup == null) { _outputLoopCount = new Shared <int>(0); _hashLookup = new Set <TInputOutput>(_comparer); Pair <TInputOutput, NoKeyMemoizationRequired> rightElement = default(Pair <TInputOutput, NoKeyMemoizationRequired>); int rightKeyUnused = default(int); int i = 0; while (_rightSource.MoveNext(ref rightElement, ref rightKeyUnused)) { if ((i++ & CancellationState.POLL_INTERVAL) == 0) { _cancellationToken.ThrowIfCancellationRequested(); } ; _hashLookup.Add(rightElement.First); } } // Now iterate over the left data source, looking for matches. Pair <TInputOutput, NoKeyMemoizationRequired> leftElement = default(Pair <TInputOutput, NoKeyMemoizationRequired>); TLeftKey keyUnused = default(TLeftKey) !; while (_leftSource.MoveNext(ref leftElement, ref keyUnused)) { Debug.Assert(_outputLoopCount != null); if ((_outputLoopCount.Value++ & CancellationState.POLL_INTERVAL) == 0) { _cancellationToken.ThrowIfCancellationRequested(); } ; // 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. if (_hashLookup.Remove(leftElement.First)) { currentElement = leftElement.First; #if DEBUG currentKey = unchecked ((int)0xdeadbeef); #endif 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); }
//--------------------------------------------------------------------------------------- // Straightforward IEnumerator<T> methods. // internal override bool MoveNext(ref TSource currentElement, ref TKey currentKey) { Contract.Assert(m_source != null); bool moveNextResult = m_source.MoveNext(ref currentElement, ref currentKey); // There is special logic the first time this function is called. if (!m_lookedForEmpty) { // Ensure we don't enter this loop again. m_lookedForEmpty = true; if (!moveNextResult) { if (m_partitionIndex == 0) { // If this is the 0th partition, we must wait for all others. Note: we could // actually do a wait-any here: if at least one other partition finds an element, // there is strictly no need to wait. But this would require extra coordination // which may or may not be worth the trouble. m_sharedLatch.Wait(m_cancelToken); m_sharedLatch.Dispose(); // Now see if there were any other partitions with data. if (m_sharedEmptyCount.Value == m_partitionCount - 1) { // No data, we will yield the default value. currentElement = m_defaultValue; currentKey = default(TKey); return(true); } else { // Another partition has data, we are done. return(false); } } else { // Not the 0th partition, we will increment the shared empty counter. Interlocked.Increment(ref m_sharedEmptyCount.Value); } } // Every partition (but the 0th) will signal the latch the first time. if (m_partitionIndex != 0) { m_sharedLatch.Signal(); } } return(moveNextResult); }
//----------------------------------------------------------------------------------- // This method is responsible for enumerating results and enqueueing them to // the output channel(s) as appropriate. Each base class implements its own. // protected override void SpoolingWork() { // We just enumerate over the entire source data stream for effect. TInputOutput currentUnused = default(TInputOutput); TIgnoreKey keyUnused = default(TIgnoreKey); //Note: this only ever runs with a ForAll operator, and ForAllEnumerator performs cancellation checks while (_source.MoveNext(ref currentUnused, ref keyUnused)) { ; } }
//--------------------------------------------------------------------------------------- // Walks the two data sources, left and then right, to produce the distinct set // internal override bool MoveNext(ref TInputOutput currentElement, ref int currentKey) { Contract.Assert(m_leftSource != null); Contract.Assert(m_rightSource != null); // Build the set out of the left data source, if we haven't already. if (m_hashLookup == null) { m_outputLoopCount = new Shared <int>(0); // @TODO: @PERF: @BUG#594: different implementation of set operations. Consider a treap. m_hashLookup = new Set <TInputOutput>(m_comparer); Pair <TInputOutput, NoKeyMemoizationRequired> rightElement = default(Pair <TInputOutput, NoKeyMemoizationRequired>); int rightKeyUnused = default(int); int i = 0; while (m_rightSource.MoveNext(ref rightElement, ref rightKeyUnused)) { if ((i++ & CancellationState.POLL_INTERVAL) == 0) { CancellationState.ThrowIfCanceled(m_cancellationToken); } m_hashLookup.Add(rightElement.First); } } // Now iterate over the right data source, looking for matches. Pair <TInputOutput, NoKeyMemoizationRequired> leftElement = default(Pair <TInputOutput, NoKeyMemoizationRequired>); TLeftKey leftKeyUnused = default(TLeftKey); while (m_leftSource.MoveNext(ref leftElement, ref leftKeyUnused)) { if ((m_outputLoopCount.Value++ & CancellationState.POLL_INTERVAL) == 0) { CancellationState.ThrowIfCanceled(m_cancellationToken); } if (m_hashLookup.Add(leftElement.First)) { // This element has never been seen. Return it. currentElement = leftElement.First; #if DEBUG currentKey = unchecked ((int)0xdeadbeef); #endif 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 int currentKey) { Contract.Assert(_leftSource != null); Contract.Assert(_rightSource != null); // Build the set out of the left data source, if we haven't already. if (_hashLookup == null) { _outputLoopCount = new Shared <int>(0); _hashLookup = 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); } _hashLookup.Add((TInputOutput)rightElement.First); } } // Now iterate over the right data source, looking for matches. Pair leftElement = new Pair(default(TInputOutput), default(NoKeyMemoizationRequired)); TLeftKey leftKeyUnused = default(TLeftKey); while (_leftSource.MoveNext(ref leftElement, ref leftKeyUnused)) { if ((_outputLoopCount.Value++ & CancellationState.POLL_INTERVAL) == 0) { CancellationState.ThrowIfCanceled(_cancellationToken); } if (_hashLookup.Add((TInputOutput)leftElement.First)) { // This element has never been seen. Return it. currentElement = (TInputOutput)leftElement.First; #if DEBUG currentKey = unchecked ((int)0xdeadbeef); #endif return(true); } } return(false); }
//--------------------------------------------------------------------------------------- // Straightforward IEnumerator<T> methods. // internal override bool MoveNext(ref TOutput currentElement, ref int currentKey) { // So long as the source has a next element, we have an element. TInput element = default(TInput); if (m_source.MoveNext(ref element, ref currentKey)) { Contract.Assert(m_selector != null, "expected a compiled selection function"); currentElement = m_selector(element, currentKey); return(true); } return(false); }
//--------------------------------------------------------------------------------------- // Straightforward IEnumerator<T> methods. // internal override bool MoveNext(ref TOutput currentElement, ref TKey currentKey) { // So long as the source has a next element, we have an element. TInput element = default(TInput); if (_source.MoveNext(ref element, ref currentKey)) { Debug.Assert(_selector != null, "expected a compiled operator"); currentElement = _selector(element); return(true); } return(false); }
//--------------------------------------------------------------------------------------- // Moves to the next element in the sorted output. When called for the first time, the // descendents in the sort's child tree are executed entirely, the results accumulated // in memory, and the data sorted. // internal override bool MoveNext(ref TInputOutput currentElement, ref TSortKey currentKey) { Debug.Assert(_source != null); TKey keyUnused = default(TKey); if (!_source.MoveNext(ref currentElement, ref keyUnused)) { return(false); } currentKey = _keySelector(currentElement); 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 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 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); }