#region Copyright 2011 by Roger Knapp, Licensed under the Apache License, Version 2.0
/* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#endregion
using System;
using System.Collections.Generic;
using CSharpTest.Net.Synchronization;
namespace CSharpTest.Net.Collections
{
///
/// Represents a thread-safe generic collection of key/value pairs.
///
public class SynchronizedDictionary : IDictionary, IDisposable
{
IDictionary _store;
readonly ILockStrategy _lock;
///
/// Constructs a thread-safe generic collection of key/value pairs using exclusive locking.
///
public SynchronizedDictionary()
: this(new Dictionary(), new ExclusiveLocking())
{ }
///
/// Constructs a thread-safe generic collection of key/value pairs using exclusive locking.
///
public SynchronizedDictionary(IEqualityComparer comparer)
: this(new Dictionary(comparer), new ExclusiveLocking())
{ }
///
/// Constructs a thread-safe generic collection of key/value pairs using the lock provided.
///
public SynchronizedDictionary(IEqualityComparer comparer, ILockStrategy locking)
: this(new Dictionary(comparer), locking)
{ }
///
/// Constructs a thread-safe generic collection of key/value pairs using the lock provided.
///
public SynchronizedDictionary(ILockStrategy locking)
: this(new Dictionary(), locking)
{ }
///
/// Constructs a thread-safe generic collection of key/value pairs using the default locking
/// type for exclusive access, akin to placing lock(this) around each call. If you want to
/// allow reader/writer locking provide one of those lock types from the Synchronization
/// namespace.
///
public SynchronizedDictionary(IDictionary storage)
: this(storage, new ExclusiveLocking())
{ }
///
/// Constructs a thread-safe generic collection of key/value pairs.
///
public SynchronizedDictionary(IDictionary storage, ILockStrategy locking)
{
_store = Check.NotNull(storage);
_lock = Check.NotNull(locking);
}
///
/// Defines a method to release allocated resources.
///
public void Dispose()
{
_lock.Dispose();
}
/// Exposes the interal lock so that you can syncronize several calls
public ILockStrategy Lock { get { return _lock; } }
///
/// Gets a value indicating whether the is read-only.
///
public bool IsReadOnly { get { return _store.IsReadOnly; } }
///
/// Gets the number of elements contained in the .
///
public int Count { get { using (_lock.Read()) return _store.Count; } }
///
/// Locks the collection and replaces the underlying storage dictionary.
///
public IDictionary ReplaceStorage(IDictionary newStorage)
{
using (_lock.Write())
{
IDictionary storage = _store;
_store = Check.NotNull(newStorage);
return storage;
}
}
///
/// Gets or sets the element with the specified key.
///
public TValue this[TKey key]
{
get
{
using (_lock.Read())
return _store[key];
}
set
{
using (_lock.Write())
_store[key] = value;
}
}
///
/// Adds an element with the provided key and value to the .
///
public void Add(TKey key, TValue value)
{
using (_lock.Write())
_store.Add(key, value);
}
void ICollection>.Add(KeyValuePair item)
{
using (_lock.Write())
_store.Add(item);
}
///
/// Removes the element with the specified key from the .
///
public bool Remove(TKey key)
{
using (_lock.Write())
return _store.Remove(key);
}
bool ICollection>.Remove(KeyValuePair item)
{
using (_lock.Write())
return _store.Remove(item);
}
///
/// Removes all items from the .
///
public void Clear()
{
using (_lock.Write())
_store.Clear();
}
bool ICollection>.Contains(KeyValuePair item)
{
using (_lock.Read())
return _store.Contains(item);
}
///
/// Determines whether the contains an element with the specified key.
///
public bool ContainsKey(TKey key)
{
using (_lock.Read())
return _store.ContainsKey(key);
}
///
/// Gets the value associated with the specified key.
///
public bool TryGetValue(TKey key, out TValue value)
{
using (_lock.Read())
return _store.TryGetValue(key, out value);
}
///
/// Gets an containing the keys of the .
///
public ICollection Keys
{
get
{
using (_lock.Read())
return new List(_store.Keys);
}
}
///
/// Gets an containing the values in the .
///
public ICollection Values
{
get
{
using (_lock.Read())
return new List(_store.Values);
}
}
///
/// Copies the elements of the to an , starting at a particular index.
///
public void CopyTo(KeyValuePair[] array, int arrayIndex)
{
using (_lock.Read())
_store.CopyTo(array, arrayIndex);
}
///
/// Returns an enumerator that iterates through the collection.
///
public IEnumerator> GetEnumerator()
{
using (_lock.Read())
{
foreach (KeyValuePair kv in _store)
yield return kv;
}
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{ return GetEnumerator(); }
}
}