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