//-----------------------------------------------------------------------
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// A list with locking semantics so it can be used cross-thread.
//
//-----------------------------------------------------------------------
namespace Microsoft.Kinect.Toolkit
{
using System;
using System.Collections;
using System.Collections.Generic;
///
/// IList implementation with locking on all operations.
///
/// Type of generic IList to implement.
public sealed class ThreadSafeCollection : IList
{
///
/// Lock object to use for all operations.
///
private readonly object lockObject;
///
/// Wrapped collection object.
///
private readonly List list = new List();
///
/// Initializes a new instance of the ThreadSafeCollection class with a new lock.
///
public ThreadSafeCollection() : this(new object())
{
}
///
/// Initializes a new instance of the ThreadSafeCollection class with an existing new lock.
///
/// Existing lock to use for this collection.
public ThreadSafeCollection(object existingLock)
{
this.lockObject = existingLock;
}
///
/// Gets the number of elements actually contained in the ThreadSafeCollection<T>.
///
public int Count
{
get
{
lock (this.lockObject)
{
return list.Count;
}
}
}
///
/// Gets a value indicating whether the collection is read only. Returns true.
///
public bool IsReadOnly
{
get
{
lock (this.lockObject)
{
return false;
}
}
}
///
/// Gets or sets the element at the specified index.
///
/// The zero-based index of the element to get or set.
/// The element at the specified index.
public T this[int index]
{
get
{
lock (this.lockObject)
{
return list[index];
}
}
set
{
lock (this.lockObject)
{
list[index] = value;
}
}
}
///
/// Adds an object to the end of the ThreadSafeCollection<T>.
///
///
/// The object to be added to the end of the ThreadSafeCollection<T>.
/// The value can be null for reference types.
///
public void Add(T item)
{
lock (this.lockObject)
{
list.Add(item);
}
}
///
/// Removes all elements from the ThreadSafeCollection<T>.
///
public void Clear()
{
lock (this.lockObject)
{
list.Clear();
}
}
///
/// Determines whether an element is in the ThreadSafeCollection<T>.
///
///
/// The object to locate in the ThreadSafeCollection<T>. The value
/// can be null for reference types.
///
///
/// true if item is found in the ThreadSafeCollection<T>; otherwise,
/// false.
///
public bool Contains(T item)
{
lock (this.lockObject)
{
return list.Contains(item);
}
}
///
/// Copies the entire ThreadSafeCollection<T> to a compatible one-dimensional
/// array, starting at the beginning of the target array.
///
///
/// The one-dimensional System.Array that is the destination of the elements
/// copied from ThreadSafeCollection<T>. The System.Array must have
/// zero-based indexing.
///
///
/// The zero-based index in array at which copying begins.
///
/// Array is null.
/// ArrayIndex is less than 0.
///
/// The number of elements in the source ThreadSafeCollection<T> is
/// greater than the available space from arrayIndex to the end of the destination
/// array.
///
public void CopyTo(T[] array, int arrayIndex)
{
lock (this.lockObject)
{
list.CopyTo(array, arrayIndex);
}
}
///
/// Copies the entire ThreadSafeCollection<Tgt; to a compatible one-dimensional
/// array, starting at the beginning of the target array.
///
///
/// The one-dimensional System.Array that is the destination of the elements
/// copied from System.Collections.Generic.List<Tgt;. The System.Array must have
/// zero-based indexing.
///
/// Array is null.
///
/// The number of elements in the source ThreadSafeCollection<Tgt; is
/// greater than the number of elements that the destination array can contain.
///
public void CopyTo(T[] array)
{
lock (this.lockObject)
{
list.CopyTo(array);
}
}
///
/// Adds the elements of the specified collection to the end of the ThreadSafeCollection<T>.
///
///
/// The collection whose elements should be added to the end of the ThreadSafeCollection<T>.
/// The collection itself cannot be null, but it can contain elements that are
/// null, if type T is a reference type.
///
/// Collection is null.
public void AddRange(IEnumerable collection)
{
lock (this.lockObject)
{
list.AddRange(collection);
}
}
///
/// Searches for the specified object and returns the zero-based index of the
/// first occurrence within the entire ThreadSafeCollection<T>.
///
///
/// The object to locate in the ThreadSafeCollection<T>. The value
/// can be null for reference types.
///
///
/// The zero-based index of the first occurrence of item within the entire ThreadSafeCollection<T>,
/// if found; otherwise, –1.
///
public int IndexOf(T item)
{
lock (this.lockObject)
{
return list.IndexOf(item);
}
}
///
/// Inserts an element into the ThreadSafeCollection<T> at the specified
/// index.
///
///
/// The zero-based index at which item should be inserted.
///
///
/// The object to insert. The value can be null for reference types.
///
/// Index is less than 0.-or-index is greater than ThreadSafeCollection<T>.Count.
public void Insert(int index, T item)
{
lock (this.lockObject)
{
list.Insert(index, item);
}
}
///
/// Removes the element at the specified index of the ThreadSafeCollection<T>.
///
/// The zero-based index of the element to remove.
/// Index is less than 0.-or-index is equal to or greater than ThreadSafeCollection<T>.Count.
public void RemoveAt(int index)
{
lock (this.lockObject)
{
list.RemoveAt(index);
}
}
///
/// Removes the first occurrence of a specific object from the ThreadSafeCollection<T>.
///
///
/// The object to remove from the ThreadSafeCollection<T>. The value
/// can be null for reference types.
///
///
/// true if item is successfully removed; otherwise, false. This method also
/// returns false if item was not found in the ThreadSafeCollection<T>.
///
public bool Remove(T item)
{
lock (this.lockObject)
{
return list.Remove(item);
}
}
///
/// Returns an enumerator that iterates through the ThreadSafeCollection<T>.
///
/// This enumerator is a SNAPSHOT of the collection. Keep this in mind when using this enumerator.
/// A ThreadSafeCollection<T>.Enumerator for the ThreadSafeCollection<T>.
IEnumerator IEnumerable.GetEnumerator()
{
lock (this.lockObject)
{
return NewEnumerator();
}
}
///
/// Returns an enumerator that iterates through the ThreadSafeCollection<T>.
///
/// This enumerator is a SNAPSHOT of the collection. Keep this in mind when using this enumerator.
/// A ThreadSafeCollection<T>.Enumerator for the ThreadSafeCollection<T>.
IEnumerator IEnumerable.GetEnumerator()
{
lock (this.lockObject)
{
return NewEnumerator();
}
}
///
/// Returns an enumerator that iterates through the ThreadSafeCollection<T>.
///
/// This support function exists to satisfy code quality warning CA2000. Otherwise, it would be in-line.
/// A ThreadSafeCollection<T>.Enumerator for the ThreadSafeCollection<T>.
private IEnumerator NewEnumerator()
{
return new ThreadSafeEnumerator(this);
}
///
/// Provides a SNAPSHOT enumerator of the collection. Keep this in mind when using this enumerator.
///
private class ThreadSafeEnumerator : IEnumerator
{
///
/// Snapshot to enumerate.
///
private readonly ThreadSafeCollection collection;
///
/// Internal enumerator of the snapshot.
///
private readonly IEnumerator enumerator;
///
/// Initializes a new instance of the ThreadSafeEnumerator class, creating a snapshot of the given collection.
///
/// List to snapshot.
public ThreadSafeEnumerator(ThreadSafeCollection collection)
{
lock (collection.lockObject)
{
// Make snapshot of passed in collection.
this.collection = new ThreadSafeCollection();
this.collection.AddRange(collection);
// Wrapped enumerator.
enumerator = this.collection.list.GetEnumerator();
}
}
///
/// Gets the element in the collection at the current position of the enumerator.
///
/// The element in the collection at the current position of the enumerator.
public T Current
{
get
{
lock (this.collection.lockObject)
{
return enumerator.Current;
}
}
}
///
/// Gets the element in the collection at the current position of the enumerator.
///
/// The element in the collection at the current position of the enumerator.
object IEnumerator.Current
{
get
{
lock (this.collection.lockObject)
{
return enumerator.Current;
}
}
}
///
/// Disposes the underlying enumerator. Does not set collection or enumerator to null so calls will still
/// proxy to the disposed instance (and throw the proper exception).
///
public void Dispose()
{
lock (this.collection.lockObject)
{
enumerator.Dispose();
}
}
///
/// Advances the enumerator to the next element of the collection.
///
///
/// true if the enumerator was successfully advanced to the next element; false
/// if the enumerator has passed the end of the collection.
///
/// The collection was modified after the enumerator was created.
public bool MoveNext()
{
lock (this.collection.lockObject)
{
return enumerator.MoveNext();
}
}
///
/// Sets the enumerator to its initial position, which is before the first element
/// in the collection.
///
/// The collection was modified after the enumerator was created.
public void Reset()
{
lock (this.collection.lockObject)
{
enumerator.Reset();
}
}
}
}
}