using System; using System.Collections.Generic; using System.Threading; //note, rewrite like ThreadSafeQueue namespace Svelto.DataStructures { /// /// original code: http://devplanet.com/blogs/brianr/archive/2008/09/29/thread-safe-dictionary-update.aspx /// simplified (not an IDictionary) and apdated (uses FasterList) /// /// /// [Serializable] public class ThreadSafeDictionary { public ThreadSafeDictionary(int v) { dict = new Dictionary(v); } public ThreadSafeDictionary() { dict = new Dictionary(); } // setup the lock; public virtual int Count { get { LockQ.EnterReadLock(); try { return dict.Count; } finally { LockQ.ExitReadLock(); } } } public virtual bool IsReadOnly { get { LockQ.EnterReadLock(); try { return dict.IsReadOnly; } finally { LockQ.ExitReadLock(); } } } public virtual FasterList Keys { get { LockQ.EnterReadLock(); try { return new FasterList(dict.Keys); } finally { LockQ.ExitReadLock(); } } } public virtual FasterList Values { get { LockQ.EnterReadLock(); try { return new FasterList(dict.Values); } finally { LockQ.ExitReadLock(); } } } public virtual TValue this[TKey key] { get { LockQ.EnterReadLock(); try { return dict[key]; } finally { LockQ.ExitReadLock(); } } set { LockQ.EnterWriteLock(); try { dict[key] = value; } finally { LockQ.ExitWriteLock(); } } } public virtual void Add(KeyValuePair item) { LockQ.EnterWriteLock(); try { dict.Add(item); } finally { LockQ.ExitWriteLock(); } } public virtual void Clear() { LockQ.EnterWriteLock(); try { dict.Clear(); } finally { LockQ.ExitWriteLock(); } } public virtual bool Contains(KeyValuePair item) { LockQ.EnterReadLock(); try { return dict.Contains(item); } finally { LockQ.ExitReadLock(); } } public virtual void CopyTo(KeyValuePair[] array, int arrayIndex) { LockQ.EnterReadLock(); try { dict.CopyTo(array, arrayIndex); } finally { LockQ.ExitReadLock(); } } public virtual bool Remove(KeyValuePair item) { LockQ.EnterWriteLock(); try { return dict.Remove(item); } finally { LockQ.ExitWriteLock(); } } public virtual void Add(TKey key, TValue value) { LockQ.EnterWriteLock(); try { dict.Add(key, value); } finally { LockQ.ExitWriteLock(); } } public virtual bool ContainsKey(TKey key) { LockQ.EnterReadLock(); try { return dict.ContainsKey(key); } finally { LockQ.ExitReadLock(); } } public virtual bool Remove(TKey key) { LockQ.EnterWriteLock(); try { return dict.Remove(key); } finally { LockQ.ExitWriteLock(); } } public virtual bool TryGetValue(TKey key, out TValue value) { LockQ.EnterReadLock(); try { return dict.TryGetValue(key, out value); } finally { LockQ.ExitReadLock(); } } /// /// Merge does a blind remove, and then add. Basically a blind Upsert. /// /// Key to lookup /// New Value public void MergeSafe(TKey key, TValue newValue) { LockQ.EnterWriteLock(); try { // take a writelock immediately since we will always be writing if (dict.ContainsKey(key)) dict.Remove(key); dict.Add(key, newValue); } finally { LockQ.ExitWriteLock(); } } /// /// This is a blind remove. Prevents the need to check for existence first. /// /// Key to remove public void RemoveSafe(TKey key) { LockQ.EnterReadLock(); try { if (dict.ContainsKey(key)) LockQ.EnterWriteLock(); try { dict.Remove(key); } finally { LockQ.ExitWriteLock(); } } finally { LockQ.ExitReadLock(); } } // This is the internal dictionary that we are wrapping readonly IDictionary dict; readonly ReaderWriterLockSlim LockQ = new ReaderWriterLockSlim(); } }