Ejemplo n.º 1
0
        private bool FindTagMaybeTentativeInternal(long hash, ushort tag, ref HashBucket *bucket, ref int slot)
        {
            var target_entry_word = default(long);
            var entry_slot_bucket = default(HashBucket *);

            do
            {
                // Search through the bucket looking for our key. Last entry is reserved
                // for the overflow pointer.
                for (int index = 0; index < Constants.kOverflowBucketIndex; ++index)
                {
                    target_entry_word = *(((long *)bucket) + index);
                    if (0 == target_entry_word)
                    {
                        continue;
                    }

                    HashBucketEntry entry = default(HashBucketEntry);
                    entry.word = target_entry_word;
                    if (tag == entry.Tag)
                    {
                        slot = index;
                        return(true);
                    }
                }

                target_entry_word = *(((long *)bucket) + Constants.kOverflowBucketIndex) & Constants.kAddressMask;
                // Go to next bucket in the chain


                if (target_entry_word == 0)
                {
                    return(false);
                }
                bucket = (HashBucket *)overflowBucketsAllocator.GetPhysicalAddress(target_entry_word);
            } while (true);
        }
Ejemplo n.º 2
0
        private bool FindTagOrFreeInternal(long hash, ushort tag, ref HashBucket *bucket, ref int slot, ref HashBucketEntry entry, long BeginAddress = 0)
        {
            var target_entry_word = default(long);
            var recordExists      = false;
            var entry_slot_bucket = default(HashBucket *);

            do
            {
                // Search through the bucket looking for our key. Last entry is reserved
                // for the overflow pointer.
                for (int index = 0; index < Constants.kOverflowBucketIndex; ++index)
                {
                    target_entry_word = *(((long *)bucket) + index);
                    if (0 == target_entry_word)
                    {
                        if (slot == Constants.kInvalidEntrySlot)
                        {
                            slot = index;
                            entry_slot_bucket = bucket;
                        }
                        continue;
                    }

                    entry.word = target_entry_word;
                    if (entry.Address < BeginAddress && entry.Address != Constants.kTempInvalidAddress)
                    {
                        if (entry.word == Interlocked.CompareExchange(ref bucket->bucket_entries[index], Constants.kInvalidAddress, target_entry_word))
                        {
                            if (slot == Constants.kInvalidEntrySlot)
                            {
                                slot = index;
                                entry_slot_bucket = bucket;
                            }
                            continue;
                        }
                    }
                    if (tag == entry.Tag && !entry.Tentative)
                    {
                        slot         = index;
                        recordExists = true;
                        return(recordExists);
                    }
                }

                target_entry_word = *(((long *)bucket) + Constants.kOverflowBucketIndex);
                // Go to next bucket in the chain


                if ((target_entry_word & Constants.kAddressMask) == 0)
                {
                    if (slot == Constants.kInvalidEntrySlot)
                    {
                        // Allocate new bucket
                        var  logicalBucketAddress  = overflowBucketsAllocator.Allocate();
                        var  physicalBucketAddress = (HashBucket *)overflowBucketsAllocator.GetPhysicalAddress(logicalBucketAddress);
                        long compare_word          = target_entry_word;
                        target_entry_word  = logicalBucketAddress;
                        target_entry_word |= (compare_word & ~Constants.kAddressMask);

                        long result_word = Interlocked.CompareExchange(
                            ref bucket->bucket_entries[Constants.kOverflowBucketIndex],
                            target_entry_word,
                            compare_word);

                        if (compare_word != result_word)
                        {
                            // Install failed, undo allocation; use the winner's entry
                            overflowBucketsAllocator.Free(logicalBucketAddress);
                            target_entry_word = result_word;
                        }
                        else
                        {
                            // Install succeeded
                            bucket = physicalBucketAddress;
                            slot   = 0;
                            entry  = default(HashBucketEntry);
                            return(recordExists);
                        }
                    }
                    else
                    {
                        if (!recordExists)
                        {
                            bucket = entry_slot_bucket;
                        }
                        entry = default(HashBucketEntry);
                        break;
                    }
                }

                bucket = (HashBucket *)overflowBucketsAllocator.GetPhysicalAddress(target_entry_word & Constants.kAddressMask);
            } while (true);

            return(recordExists);
        }
Ejemplo n.º 3
0
        internal void FindOrCreateTag(long hash, ushort tag, ref HashBucket *bucket, ref int slot, ref HashBucketEntry entry, long BeginAddress)
        {
            var version           = resizeInfo.version;
            var masked_entry_word = hash & state[version].size_mask;

            while (true)
            {
                bucket = state[version].tableAligned + masked_entry_word;
                slot   = Constants.kInvalidEntrySlot;

                if (FindTagOrFreeInternal(hash, tag, ref bucket, ref slot, ref entry, BeginAddress))
                {
                    return;
                }


                // Install tentative tag in free slot
                entry           = default(HashBucketEntry);
                entry.Tag       = tag;
                entry.Address   = Constants.kTempInvalidAddress;
                entry.Pending   = false;
                entry.Tentative = true;

                if (0 == Interlocked.CompareExchange(ref bucket->bucket_entries[slot], entry.word, 0))
                {
                    var orig_bucket = state[version].tableAligned + masked_entry_word;
                    var orig_slot   = Constants.kInvalidEntrySlot;

                    if (FindOtherTagMaybeTentativeInternal(hash, tag, ref orig_bucket, ref orig_slot, bucket, slot))
                    {
                        bucket->bucket_entries[slot] = 0;
                    }
                    else
                    {
                        entry.Tentative          = false;
                        *((long *)bucket + slot) = entry.word;
                        break;
                    }
                }
            }
        }
Ejemplo n.º 4
0
        internal bool FindTag(long hash, ushort tag, ref HashBucket *bucket, ref int slot, ref HashBucketEntry entry)
        {
            var target_entry_word = default(long);
            var entry_slot_bucket = default(HashBucket *);
            var version           = resizeInfo.version;
            var masked_entry_word = hash & state[version].size_mask;

            bucket = state[version].tableAligned + masked_entry_word;
            slot   = Constants.kInvalidEntrySlot;

            do
            {
                // Search through the bucket looking for our key. Last entry is reserved
                // for the overflow pointer.
                for (int index = 0; index < Constants.kOverflowBucketIndex; ++index)
                {
                    target_entry_word = *(((long *)bucket) + index);
                    if (0 == target_entry_word)
                    {
                        continue;
                    }

                    entry.word = target_entry_word;
                    if (tag == entry.Tag)
                    {
                        slot = index;
                        if (!entry.Tentative)
                        {
                            return(true);
                        }
                    }
                }

                target_entry_word = *(((long *)bucket) + Constants.kOverflowBucketIndex) & Constants.kAddressMask;
                // Go to next bucket in the chain


                if (target_entry_word == 0)
                {
                    entry = default(HashBucketEntry);
                    return(false);
                }
                bucket = (HashBucket *)overflowBucketsAllocator.GetPhysicalAddress(target_entry_word);
            } while (true);
        }