using System.Collections.Generic;
using System.Threading;
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)
///
///
///
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();
}
}