using System.Collections.Generic;
using System.Diagnostics;
namespace System.Collections.Concurrent;
[DebuggerTypeProxy(typeof(CollectionDebuggerView<, >))]
[DebuggerDisplay("Count={Count}")]
public class ConcurrentDictionary<TKey, TValue> : IDictionary<TKey, TValue>, ICollection<KeyValuePair<TKey, TValue>>, IEnumerable<KeyValuePair<TKey, TValue>>, IDictionary, ICollection, IEnumerable
{
private class ConcurrentDictionaryEnumerator : IDictionaryEnumerator, IEnumerator
{
private IEnumerator<KeyValuePair<TKey, TValue>> internalEnum;
public object Current => Entry;
public DictionaryEntry Entry
{
get
{
KeyValuePair<TKey, TValue> current = internalEnum.Current;
return new DictionaryEntry(current.Key, current.Value);
}
}
public object Key => internalEnum.Current.Key;
public object Value => internalEnum.Current.Value;
public ConcurrentDictionaryEnumerator(IEnumerator<KeyValuePair<TKey, TValue>> internalEnum)
{
this.internalEnum = internalEnum;
}
public bool MoveNext()
{
return internalEnum.MoveNext();
}
public void Reset()
{
internalEnum.Reset();
}
}
private IEqualityComparer<TKey> comparer;
private SplitOrderedList<TKey, KeyValuePair<TKey, TValue>> internalDictionary;
public TValue this[TKey key]
{
get
{
return GetValue(key);
}
set
{
AddOrUpdate(key, value, value);
}
}
object IDictionary.this[object key]
{
get
{
if (!(key is TKey))
{
throw new ArgumentException("key isn't of correct type", "key");
}
return this[(TKey)key];
}
set
{
if (!(key is TKey) || !(value is TValue))
{
throw new ArgumentException("key or value aren't of correct type");
}
this[(TKey)key] = (TValue)value;
}
}
public int Count => internalDictionary.Count;
public bool IsEmpty => Count == 0;
bool ICollection<KeyValuePair<TKey, TValue>>.IsReadOnly => false;
bool IDictionary.IsReadOnly => false;
public ICollection<TKey> Keys => GetPart((KeyValuePair<TKey, TValue> kvp) => kvp.Key);
public ICollection<TValue> Values => GetPart((KeyValuePair<TKey, TValue> kvp) => kvp.Value);
ICollection IDictionary.Keys => (ICollection)Keys;
ICollection IDictionary.Values => (ICollection)Values;
object ICollection.SyncRoot => this;
bool IDictionary.IsFixedSize => false;
bool ICollection.IsSynchronized => true;
public ConcurrentDictionary()
: this((IEqualityComparer<TKey>)EqualityComparer<TKey>.Default)
{
}
public ConcurrentDictionary(IEnumerable<KeyValuePair<TKey, TValue>> collection)
: this(collection, (IEqualityComparer<TKey>)EqualityComparer<TKey>.Default)
{
}
public ConcurrentDictionary(IEqualityComparer<TKey> comparer)
{
this.comparer = comparer;
internalDictionary = new SplitOrderedList<TKey, KeyValuePair<TKey, TValue>>(comparer);
}
public ConcurrentDictionary(IEnumerable<KeyValuePair<TKey, TValue>> collection, IEqualityComparer<TKey> comparer)
: this(comparer)
{
foreach (KeyValuePair<TKey, TValue> item in collection)
{
Add(item.Key, item.Value);
}
}
public ConcurrentDictionary(int concurrencyLevel, int capacity)
: this((IEqualityComparer<TKey>)EqualityComparer<TKey>.Default)
{
}
public ConcurrentDictionary(int concurrencyLevel, IEnumerable<KeyValuePair<TKey, TValue>> collection, IEqualityComparer<TKey> comparer)
: this(collection, comparer)
{
}
public ConcurrentDictionary(int concurrencyLevel, int capacity, IEqualityComparer<TKey> comparer)
: this(comparer)
{
}
private void Add(TKey key, TValue value)
{
while (!TryAdd(key, value))
{
}
}
void IDictionary<TKey, TValue>.Add(TKey key, TValue value)
{
Add(key, value);
}
public bool TryAdd(TKey key, TValue value)
{
return internalDictionary.Insert(Hash(key), key, Make(key, value));
}
void ICollection<KeyValuePair<TKey, TValue>>.Add(KeyValuePair<TKey, TValue> pair)
{
Add(pair.Key, pair.Value);
}
public TValue AddOrUpdate(TKey key, Func<TKey, TValue> addValueFactory, Func<TKey, TValue, TValue> updateValueFactory)
{
return internalDictionary.InsertOrUpdate(Hash(key), key, () => Make(key, addValueFactory(key)), (KeyValuePair<TKey, TValue> e) => Make(key, updateValueFactory(key, e.Value))).Value;
}
public TValue AddOrUpdate(TKey key, TValue addValue, Func<TKey, TValue, TValue> updateValueFactory)
{
return AddOrUpdate(key, (TKey _) => addValue, updateValueFactory);
}
private TValue AddOrUpdate(TKey key, TValue addValue, TValue updateValue)
{
return internalDictionary.InsertOrUpdate(Hash(key), key, Make(key, addValue), Make(key, updateValue)).Value;
}
private TValue GetValue(TKey key)
{
if (!TryGetValue(key, out var value))
{
throw new KeyNotFoundException(key.ToString());
}
return value;
}
public bool TryGetValue(TKey key, out TValue value)
{
KeyValuePair<TKey, TValue> data;
bool result = internalDictionary.Find(Hash(key), key, out data);
value = data.Value;
return result;
}
public bool TryUpdate(TKey key, TValue newValue, TValue comparisonValue)
{
return internalDictionary.CompareExchange(Hash(key), key, Make(key, newValue), (KeyValuePair<TKey, TValue> e) => e.Value.Equals(comparisonValue));
}
public TValue GetOrAdd(TKey key, Func<TKey, TValue> valueFactory)
{
return internalDictionary.InsertOrGet(Hash(key), key, Make(key, default(TValue)), () => Make(key, valueFactory(key))).Value;
}
public TValue GetOrAdd(TKey key, TValue value)
{
return internalDictionary.InsertOrGet(Hash(key), key, Make(key, value), null).Value;
}
public bool TryRemove(TKey key, out TValue value)
{
KeyValuePair<TKey, TValue> data;
bool result = internalDictionary.Delete(Hash(key), key, out data);
value = data.Value;
return result;
}
private bool Remove(TKey key)
{
TValue value;
return TryRemove(key, out value);
}
bool IDictionary<TKey, TValue>.Remove(TKey key)
{
return Remove(key);
}
bool ICollection<KeyValuePair<TKey, TValue>>.Remove(KeyValuePair<TKey, TValue> pair)
{
return Remove(pair.Key);
}
public bool ContainsKey(TKey key)
{
KeyValuePair<TKey, TValue> data;
return internalDictionary.Find(Hash(key), key, out data);
}
bool IDictionary.Contains(object key)
{
if (!(key is TKey))
{
return false;
}
return ContainsKey((TKey)key);
}
void IDictionary.Remove(object key)
{
if (key is TKey)
{
Remove((TKey)key);
}
}
void IDictionary.Add(object key, object value)
{
if (!(key is TKey) || !(value is TValue))
{
throw new ArgumentException("key or value aren't of correct type");
}
Add((TKey)key, (TValue)value);
}
bool ICollection<KeyValuePair<TKey, TValue>>.Contains(KeyValuePair<TKey, TValue> pair)
{
return ContainsKey(pair.Key);
}
public KeyValuePair<TKey, TValue>[] ToArray()
{
return new List<KeyValuePair<TKey, TValue>>(this).ToArray();
}
public void Clear()
{
internalDictionary = new SplitOrderedList<TKey, KeyValuePair<TKey, TValue>>(comparer);
}
private ICollection<T> GetPart<T>(Func<KeyValuePair<TKey, TValue>, T> extractor)
{
List<T> list = new List<T>();
using (IEnumerator<KeyValuePair<TKey, TValue>> enumerator = GetEnumerator())
{
while (enumerator.MoveNext())
{
KeyValuePair<TKey, TValue> current = enumerator.Current;
list.Add(extractor(current));
}
}
return list.AsReadOnly();
}
void ICollection.CopyTo(Array array, int startIndex)
{
if (array is KeyValuePair<TKey, TValue>[] array2)
{
CopyTo(array2, startIndex, Count);
}
}
private void CopyTo(KeyValuePair<TKey, TValue>[] array, int startIndex)
{
CopyTo(array, startIndex, Count);
}
void ICollection<KeyValuePair<TKey, TValue>>.CopyTo(KeyValuePair<TKey, TValue>[] array, int startIndex)
{
CopyTo(array, startIndex);
}
private void CopyTo(KeyValuePair<TKey, TValue>[] array, int startIndex, int num)
{
using IEnumerator<KeyValuePair<TKey, TValue>> enumerator = GetEnumerator();
while (enumerator.MoveNext())
{
KeyValuePair<TKey, TValue> current = enumerator.Current;
array[startIndex++] = current;
if (--num <= 0)
{
break;
}
}
}
public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
{
return GetEnumeratorInternal();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumeratorInternal();
}
private IEnumerator<KeyValuePair<TKey, TValue>> GetEnumeratorInternal()
{
return internalDictionary.GetEnumerator();
}
IDictionaryEnumerator IDictionary.GetEnumerator()
{
return new ConcurrentDictionaryEnumerator(GetEnumeratorInternal());
}
private static KeyValuePair<U, V> Make<U, V>(U key, V value)
{
return new KeyValuePair<U, V>(key, value);
}
private uint Hash(TKey key)
{
return (uint)comparer.GetHashCode(key);
}
}
|