public override bool TryGetValue(THashKey key, ref HashLookupValueList <IEnumerable <TElement>, TOrderKey> value) { Pair <IEnumerable <TElement>, TOrderKey> valueList = GetValueList(key); value = new HashLookupValueList <IEnumerable <TElement>, TOrderKey>(valueList.First, valueList.Second); return(true); }
public bool Add(THashKey hashKey, TElement element, TOrderKey orderKey) { HashLookupValueList <TElement, TOrderKey> currentValue = default(HashLookupValueList <TElement, TOrderKey>); if (!_base.TryGetValue(hashKey, ref currentValue)) { currentValue = new HashLookupValueList <TElement, TOrderKey>(element, orderKey); _base.Add(hashKey, currentValue); return(false); } else { if (currentValue.Add(element, orderKey)) { // We need to re-store this element because the pair is a value type. _base[hashKey] = currentValue; } return(true); } }
//--------------------------------------------------------------------------------------- // MoveNext implements all the hash-join logic noted earlier. When it is called first, it // will execute the entire inner query tree, and build a hash-table lookup. This is the // Building phase. Then for the first call and all subsequent calls to MoveNext, we will // incrementally perform the Probing phase. We'll keep getting elements from the outer // data source, looking into the hash-table we built, and enumerating the full results. // // This routine supports both inner and outer (group) joins. An outer join will yield a // (possibly empty) list of matching elements from the inner instead of one-at-a-time, // as we do for inner joins. // internal override bool MoveNext(ref TOutput currentElement, ref TOutputKey currentKey) { Debug.Assert(_resultSelector != null, "expected a compiled result selector"); Debug.Assert(_leftSource != null); Debug.Assert(_rightLookupBuilder != null); // BUILD phase: If we haven't built the hash-table yet, create that first. Mutables mutables = _mutables; if (mutables == null) { mutables = _mutables = new Mutables(); mutables._rightHashLookup = _rightLookupBuilder.BuildHashLookup(_cancellationToken); } // PROBE phase: So long as the source has a next element, return the match. ListChunk <Pair <TRightInput, TRightKey> > currentRightChunk = mutables._currentRightMatches; if (currentRightChunk != null && mutables._currentRightMatchesIndex == currentRightChunk.Count) { mutables._currentRightMatches = currentRightChunk.Next; mutables._currentRightMatchesIndex = 0; } if (mutables._currentRightMatches == null) { // We have to look up the next list of matches in the hash-table. Pair <TLeftInput, THashKey> leftPair = default(Pair <TLeftInput, THashKey>); TLeftKey leftKey = default(TLeftKey); while (_leftSource.MoveNext(ref leftPair, ref leftKey)) { if ((mutables._outputLoopCount++ & CancellationState.POLL_INTERVAL) == 0) { CancellationState.ThrowIfCanceled(_cancellationToken); } // Find the match in the hash table. HashLookupValueList <TRightInput, TRightKey> matchValue = default(HashLookupValueList <TRightInput, TRightKey>); TLeftInput leftElement = leftPair.First; THashKey leftHashKey = leftPair.Second; // Ignore null keys. if (leftHashKey != null) { if (mutables._rightHashLookup.TryGetValue(leftHashKey, ref matchValue)) { // We found a new match. We remember the list in case there are multiple // values under this same key -- the next iteration will pick them up. mutables._currentRightMatches = matchValue.Tail; Debug.Assert(mutables._currentRightMatches == null || mutables._currentRightMatches.Count > 0, "we were expecting that the list would be either null or empty"); mutables._currentRightMatchesIndex = 0; // Yield the value. currentElement = _resultSelector(leftElement, matchValue.Head.First); currentKey = _outputKeyBuilder.Combine(leftKey, matchValue.Head.Second); // If there is a list of matches, remember the left values for next time. if (matchValue.Tail != null) { mutables._currentLeft = leftElement; mutables._currentLeftKey = leftKey; } return(true); } } } // If we've reached the end of the data source, we're done. return(false); } // Produce the next element. Debug.Assert(mutables._currentRightMatches != null); Debug.Assert(0 <= mutables._currentRightMatchesIndex && mutables._currentRightMatchesIndex < mutables._currentRightMatches.Count); Pair <TRightInput, TRightKey> rightMatch = mutables._currentRightMatches._chunk[mutables._currentRightMatchesIndex]; currentElement = _resultSelector(mutables._currentLeft, rightMatch.First); currentKey = _outputKeyBuilder.Combine(mutables._currentLeftKey, rightMatch.Second); mutables._currentRightMatchesIndex++; return(true); }
// get the current value if it exists. public abstract bool TryGetValue(THashKey key, ref HashLookupValueList <TElement, TOrderKey> value);
public override bool TryGetValue(THashKey key, ref HashLookupValueList <TElement, TOrderKey> value) { return(_base.TryGetValue(key, ref value)); }