#region Copyright 2011-2014 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.Collections.Generic; using CSharpTest.Net.Synchronization; namespace CSharpTest.Net.Collections { /// /// Represents a collection of objects that can be individually accessed by index. /// public class SynchronizedList : IList { IList _store; readonly ILockStrategy _lock; /// /// Constructs a thread-safe generic collection of key/value pairs using exclusive locking. /// public SynchronizedList() : this(new List(), new ExclusiveLocking()) { } /// /// Constructs a thread-safe generic collection of key/value pairs using the lock provided. /// public SynchronizedList(ILockStrategy locking) : this(new List(), locking) { } /// /// Constructs a thread-safe generic collection of T, wrapped around the instance in storage /// 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 SynchronizedList(IList storage) : this(storage, new ExclusiveLocking()) { } /// /// Constructs a thread-safe generic collection of T, wrapped around the instance in storage /// public SynchronizedList(IList 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 IList ReplaceStorage(IList newStorage) { using (_lock.Write()) { IList storage = _store; _store = Check.NotNull(newStorage); return storage; } } /// /// Gets or sets the element at the specified index. /// public T this[int index] { get { using (_lock.Read()) return _store[index]; } set { using (_lock.Write()) _store[index] = value; } } /// /// Adds an item to the . /// public int Add(T item) { using (_lock.Write()) { _store.Add(item); return _store.Count - 1; } } /// /// Added the public version to return the ordinal since you cannot depend upon the collection being /// unmodified to determine the index either before or after the Add() call. /// void ICollection.Add(T item) { using (_lock.Write()) _store.Add(item); } /// /// Inserts an item to the at the specified index. /// public void Insert(int index, T item) { using (_lock.Write()) _store.Insert(index, item); } /// /// Removes the first occurrence of a specific object from the . /// public bool Remove(T item) { using (_lock.Write()) return _store.Remove(item); } /// /// Removes the item at the specified index. /// public void RemoveAt(int index) { using (_lock.Write()) _store.RemoveAt(index); } /// /// Removes all items from the . /// public void Clear() { using (_lock.Write()) _store.Clear(); } /// /// Determines whether the contains the element specified. /// public bool Contains(T item) { using (_lock.Read()) return _store.Contains(item); } /// /// Determines the index of a specific item in the . /// public int IndexOf(T item) { using (_lock.Read()) return _store.IndexOf(item); } /// /// Copies the elements of the to an , starting at a particular index. /// public void CopyTo(T[] 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 (T value in _store) yield return value; } } System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { return GetEnumerator(); } } }