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);
                }
            }
Exemple #3
0
        //---------------------------------------------------------------------------------------
        // 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);
        }
Exemple #4
0
 // 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));
 }