You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
162 lines
3.9 KiB
162 lines
3.9 KiB
// <file>
|
|
// <copyright see="prj:///doc/copyright.txt"/>
|
|
// <license see="prj:///doc/license.txt"/>
|
|
// <author name="Daniel Grunwald"/>
|
|
// <version>$Revision$</version>
|
|
// </file>
|
|
|
|
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.Threading;
|
|
|
|
namespace ICSharpCode.TextEditor.Util
|
|
{
|
|
/// <summary>
|
|
/// A IList{T} that checks that it is only accessed on the thread that created it, and that
|
|
/// it is not modified while an enumerator is running.
|
|
/// </summary>
|
|
internal sealed class CheckedList<T> : IList<T>
|
|
{
|
|
private readonly IList<T> baseList;
|
|
private readonly int threadID;
|
|
private int enumeratorCount;
|
|
|
|
public CheckedList() : this(new List<T>())
|
|
{
|
|
}
|
|
|
|
public CheckedList(IList<T> baseList)
|
|
{
|
|
if (baseList == null)
|
|
throw new ArgumentNullException(nameof(baseList));
|
|
this.baseList = baseList;
|
|
threadID = Thread.CurrentThread.ManagedThreadId;
|
|
}
|
|
|
|
public T this[int index]
|
|
{
|
|
get
|
|
{
|
|
CheckRead();
|
|
return baseList[index];
|
|
}
|
|
set
|
|
{
|
|
CheckWrite();
|
|
baseList[index] = value;
|
|
}
|
|
}
|
|
|
|
public int Count
|
|
{
|
|
get
|
|
{
|
|
CheckRead();
|
|
return baseList.Count;
|
|
}
|
|
}
|
|
|
|
public bool IsReadOnly
|
|
{
|
|
get
|
|
{
|
|
CheckRead();
|
|
return baseList.IsReadOnly;
|
|
}
|
|
}
|
|
|
|
public int IndexOf(T item)
|
|
{
|
|
CheckRead();
|
|
return baseList.IndexOf(item);
|
|
}
|
|
|
|
public void Insert(int index, T item)
|
|
{
|
|
CheckWrite();
|
|
baseList.Insert(index, item);
|
|
}
|
|
|
|
public void RemoveAt(int index)
|
|
{
|
|
CheckWrite();
|
|
baseList.RemoveAt(index);
|
|
}
|
|
|
|
public void Add(T item)
|
|
{
|
|
CheckWrite();
|
|
baseList.Add(item);
|
|
}
|
|
|
|
public void Clear()
|
|
{
|
|
CheckWrite();
|
|
baseList.Clear();
|
|
}
|
|
|
|
public bool Contains(T item)
|
|
{
|
|
CheckRead();
|
|
return baseList.Contains(item);
|
|
}
|
|
|
|
public void CopyTo(T[] array, int arrayIndex)
|
|
{
|
|
CheckRead();
|
|
baseList.CopyTo(array, arrayIndex);
|
|
}
|
|
|
|
public bool Remove(T item)
|
|
{
|
|
CheckWrite();
|
|
return baseList.Remove(item);
|
|
}
|
|
|
|
public IEnumerator<T> GetEnumerator()
|
|
{
|
|
CheckRead();
|
|
return Enumerate();
|
|
}
|
|
|
|
IEnumerator IEnumerable.GetEnumerator()
|
|
{
|
|
CheckRead();
|
|
return Enumerate();
|
|
}
|
|
|
|
private void CheckRead()
|
|
{
|
|
if (Thread.CurrentThread.ManagedThreadId != threadID)
|
|
throw new InvalidOperationException("CheckList cannot be accessed from this thread!");
|
|
}
|
|
|
|
private void CheckWrite()
|
|
{
|
|
if (Thread.CurrentThread.ManagedThreadId != threadID)
|
|
throw new InvalidOperationException("CheckList cannot be accessed from this thread!");
|
|
if (enumeratorCount != 0)
|
|
throw new InvalidOperationException("CheckList cannot be written to while enumerators are active!");
|
|
}
|
|
|
|
private IEnumerator<T> Enumerate()
|
|
{
|
|
CheckRead();
|
|
try
|
|
{
|
|
enumeratorCount++;
|
|
foreach (var val in baseList)
|
|
{
|
|
yield return val;
|
|
CheckRead();
|
|
}
|
|
}
|
|
finally
|
|
{
|
|
enumeratorCount--;
|
|
CheckRead();
|
|
}
|
|
}
|
|
}
|
|
}
|