using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Runtime.Serialization; namespace NitroxModel.DataStructures { [DebuggerDisplay($"Items = {{{nameof(Entries)}}}")] [DataContract] public class ThreadSafeDictionary : IDictionary { [DebuggerBrowsable(DebuggerBrowsableState.Never)] [IgnoreDataMember] private readonly IDictionary dictionary; [DebuggerBrowsable(DebuggerBrowsableState.Never)] [IgnoreDataMember] private readonly object locker = new(); [IgnoreDataMember] public ICollection Keys { get { lock (locker) { return new List(dictionary.Keys); } } } [IgnoreDataMember] public ICollection Values { get { lock (locker) { return new List(dictionary.Values); } } } [DebuggerBrowsable(DebuggerBrowsableState.Never)] [IgnoreDataMember] public ICollection> Entries { get { lock (locker) { return dictionary.ToList(); } } } public TValue this[TKey key] { get { lock (locker) { return dictionary[key]; } } set { lock (locker) { dictionary[key] = value; } } } public int Count { get { lock (locker) { return dictionary.Count; } } } public bool IsReadOnly { get; } = false; public ThreadSafeDictionary() { dictionary = new Dictionary(); } public ThreadSafeDictionary(IDictionary dictionary, bool createCopy = true) { this.dictionary = createCopy ? new Dictionary(dictionary) : dictionary; } public void Add(KeyValuePair item) { lock (locker) { dictionary.Add(item); } } public void Clear() { lock (locker) { dictionary.Clear(); } } public bool Contains(KeyValuePair item) { lock (locker) { return dictionary.Contains(item); } } public void CopyTo(KeyValuePair[] array, int arrayIndex) { lock (locker) { dictionary.CopyTo(array, arrayIndex); } } public bool Remove(KeyValuePair item) { lock (locker) { return dictionary.Remove(item); } } public bool ContainsKey(TKey key) { lock (locker) { return dictionary.ContainsKey(key); } } public void Add(TKey key, TValue value) { lock (locker) { dictionary.Add(key, value); } } public bool Remove(TKey key) { lock (locker) { return dictionary.Remove(key); } } public bool TryGetValue(TKey key, out TValue value) { lock (locker) { return dictionary.TryGetValue(key, out value); } } public IEnumerator> GetEnumerator() { lock (locker) { return new Dictionary(dictionary).GetEnumerator(); } } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } }