You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
78 lines
2.3 KiB
78 lines
2.3 KiB
// Copyright (c) Microsoft. All rights reserved. |
|
// Licensed under the MIT license. See LICENSE file in the project root for full license information. |
|
#if !NET_4_6 |
|
using System.Threading; |
|
using LinqInternal.Core; |
|
|
|
namespace System.Dynamic.Utils |
|
{ |
|
internal class CacheDict<TKey, TValue> |
|
{ |
|
// cache size is always ^2. |
|
// items are placed at [hash ^ mask] |
|
// new item will displace previous one at the same location. |
|
private readonly int _mask; |
|
|
|
private readonly Entry[] _entries; |
|
|
|
// class, to ensure atomic updates. |
|
private sealed class Entry |
|
{ |
|
internal readonly int Hash; |
|
internal readonly TKey Key; |
|
internal readonly TValue Value; |
|
|
|
internal Entry(int hash, TKey key, TValue value) |
|
{ |
|
Hash = hash; |
|
Key = key; |
|
Value = value; |
|
} |
|
} |
|
|
|
/// <summary> |
|
/// Creates a dictionary-like object used for caches. |
|
/// </summary> |
|
/// <param name="size">The maximum number of elements to store will be this number aligned to next ^2.</param> |
|
internal CacheDict(int size) |
|
{ |
|
var alignedSize = NumericHelper.NextPowerOf2(size - 1); |
|
_mask = alignedSize - 1; |
|
_entries = new Entry[alignedSize]; |
|
} |
|
|
|
internal bool TryGetValue(TKey key, out TValue value) |
|
{ |
|
var hash = key.GetHashCode(); |
|
var idx = hash & _mask; |
|
|
|
var entry = Volatile.Read(ref _entries[idx]); |
|
if (entry != null && entry.Hash == hash && entry.Key.Equals(key)) |
|
{ |
|
value = entry.Value; |
|
return true; |
|
} |
|
|
|
value = default(TValue); |
|
return false; |
|
} |
|
|
|
internal void Add(TKey key, TValue value) |
|
{ |
|
var hash = key.GetHashCode(); |
|
var idx = hash & _mask; |
|
|
|
var entry = Volatile.Read(ref _entries[idx]); |
|
if (entry == null || entry.Hash != hash || !entry.Key.Equals(key)) |
|
{ |
|
Volatile.Write(ref _entries[idx], new Entry(hash, key, value)); |
|
} |
|
} |
|
|
|
internal TValue this[TKey key] |
|
{ |
|
set { Add(key, value); } |
|
} |
|
} |
|
} |
|
#endif |