using System; using System.Collections.Generic; using System.Linq; namespace Implab.Components { /// /// Component container, used to store track components in multi-threaded environmment. /// /// Instanses of this class are thread safe. public class ComponentContainer : Disposable, ICollection { List m_components = new List(); readonly object m_lock = new object(); /// /// Removes currently stored compoenents from the container and disposes them if possible. /// /// /// A new components may be added before this method completes. /// public void Clear() { List removed; lock (m_lock) { removed = m_components; m_components = new List(); } foreach (var item in removed.OfType()) item.Dispose(); } /// /// Checks whether the specified item in the collection. /// /// The item to check. public bool Contains(T item) { lock (m_lock) return m_components.Contains(item); } /// /// Copies currently stored components to the specified array. /// /// A destination array for components. /// A starting index in the destination array. public void CopyTo(T[] array, int arrayIndex) { lock (m_lock) m_components.CopyTo(array, arrayIndex); } /// /// Remove the specified item from the collection. /// /// The item to remove. public bool Remove(T item) { lock (m_lock) return m_components.Remove(item); } /// /// Gets the count of components in the collection. /// public int Count { get { lock (m_lock) return m_components.Count; } } /// /// Gets a value indicating whether this instance is read only. /// /// /// Always false. /// public bool IsReadOnly { get { return false; } } /// /// Gets the enumerator for components in the collection. /// /// The enumerator. public IEnumerator GetEnumerator() { T[] items = new T[m_components.Count]; lock (m_lock) { m_components.CopyTo(items); } return (IEnumerator)items.GetEnumerator(); } System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { return GetEnumerator(); } /// /// Add the specified item to the collection. /// /// The item to add. /// /// If the collection is alredy disposed, the item isn't added to the collection and disposed if possible. /// public void Add(T item) { Safe.ArgumentNotNull(item, "item"); bool dispose = false; lock (m_lock) { if (IsDisposed) dispose = true; else m_components.Add(item); } if (dispose) Safe.Dispose(item); } /// /// Disposes the components stored in the collection. /// /// If set to true the collection is disposing. protected override void Dispose(bool disposing) { if (disposing) Clear(); base.Dispose(disposing); } } }