#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(); } } }