Skip to content

Instantly share code, notes, and snippets.

@karno
Created August 19, 2010 11:05
Show Gist options
  • Save karno/537613 to your computer and use it in GitHub Desktop.
Save karno/537613 to your computer and use it in GitHub Desktop.
using System;
using System.Collections.Generic;
// *!* があるところが心配なところ。
namespace Azrael.Kernel.Base
{
/// <summary>
/// ストレージのベース実装
/// </summary>
public class SafeList<T> : IList<T>, ILockOperatable
{
/// <summary>
/// データ保持リスト
/// </summary>
private List<T> internalList;
/// <summary>
/// internalStorageのロックオブジェクト
/// </summary>
private object iLocker;
public SafeList()
{
internalList = new List<T>();
iLocker = new object();
}
/// <summary>
/// 保持しているアイテムの個数
/// </summary>
public int Count
{
// *!*
// Countプロパティはマルチスレッドでアクセスしても問題ない はず。
// 内部的にプロパティ持ってるんじゃないかな?
get { return internalList.Count; }
}
public T this[int index]
{
get { return internalList[index]; }
set { internalList[index] = value; }
}
/// <summary>
/// アイテムを追加します。
/// </summary>
/// <param name="item">追加アイテム</param>
public void Add(T item)
{
lock (iLocker)
{
internalList.Add(item);
}
}
/// <summary>
/// アイテム コレクションを追加します。<para />
/// 多重列挙に対応したコレクションを指定する必要があります。
/// </summary>
/// <param name="item">追加アイテム コレクション</param>
public void Add(IEnumerable<T> item)
{
lock (iLocker)
{
internalList.AddRange(item);
}
}
/// <summary>
/// アイテム コレクションを追加します。<para />
/// 一度だけ列挙動作を行います。
/// </summary>
/// <remarks>
/// 列挙操作中は内部ストレージがロックされるので、
/// コストの大きい操作は登録しないようにしてください。
/// </remarks>
/// <param name="item">アイテムの列挙</param>
public void AddOnce(IEnumerable<T> item)
{
lock (iLocker)
{
foreach (var i in item)
AddUnsafe(i);
}
}
/// <summary>
/// ストレージをロックせずにアイテムを追加します。<para />
/// マルチスレッド操作に対してロックされません。通常はAddメソッドを使用してください。
/// </summary>
public void AddUnsafe(T item)
{
internalList.Add(item);
}
/// <summary>
/// ストレージをロックせずにアイテムの列挙を追加します。<para />
/// マルチスレッド操作に対してロックされません。通常はAddメソッドを使用してください。
/// </summary>
public void AddUnsafe(IEnumerable<T> item)
{
internalList.AddRange(item);
}
/// <summary>
/// アイテム コレクションを追加します。<para />
/// 一度だけ列挙動作を行います。<para />
/// マルチスレッド操作に対してロックされません。通常はAddOnceメソッドを使用してください。
/// </summary>
/// <remarks>
/// 列挙操作中は内部ストレージがロックされるので、
/// コストの大きい操作は登録しないようにしてください。
/// </remarks>
/// <param name="item">アイテムの列挙</param>
public void AddOnceUnsafe(IEnumerable<T> item)
{
foreach (var i in item)
AddUnsafe(i);
}
/// <summary>
/// すべての要素を削除します。
/// </summary>
public void Clear()
{
lock (iLocker)
{
internalList.Clear();
}
}
/// <summary>
/// 指定したアイテムを取り除きます。
/// </summary>
public bool Remove(T item)
{
lock (iLocker)
{
return internalList.Remove(item);
}
}
/// <summary>
/// 指定したインデックスに存在するアイテムを取り除きます。
/// </summary>
public void RemoveAt(int index)
{
lock (iLocker)
{
if (internalList.Count <= index)
throw new ArgumentOutOfRangeException("index");
internalList.RemoveAt(index);
}
}
/// <summary>
/// 指定した述語条件に一致するすべての要素を取り除きます。
/// </summary>
public void RemoveAll(Predicate<T> match)
{
lock (iLocker)
{
internalList.RemoveAll(match);
}
}
/// <summary>
/// すべての要素を削除します。<para />
/// マルチスレッド操作に対してロックされません。通常はClearメソッドを使用してください。
/// </summary>
public void ClearUnsafe()
{
internalList.Clear();
}
/// <summary>
/// 指定したアイテムを取り除きます。<para />
/// マルチスレッド操作に対してロックされません。通常はRemoveメソッドを使用してください。
/// </summary>
public bool RemoveUnsafe(T item)
{
return internalList.Remove(item);
}
/// <summary>
/// 指定したインデックスに存在するアイテムを取り除きます。<para />
/// マルチスレッド操作に対してロックされません。通常はRemoveAtメソッドを使用してください。
/// </summary>
public void RemoveAtUnsafe(int index)
{
if (internalList.Count <= index)
throw new ArgumentOutOfRangeException("index");
internalList.RemoveAt(index);
}
/// <summary>
/// 指定した述語条件に一致するすべての要素を取り除きます。<para />
/// マルチスレッド操作に対してロックされません。通常はRemoveAllメソッドを使用してください。
/// </summary>
public void RemoveAllUnsafe(Predicate<T> match)
{
internalList.RemoveAll(match);
}
/// <summary>
/// 要素を配列化します。
/// </summary>
public T[] ToArray()
{
lock (iLocker)
{
return internalList.ToArray();
}
}
/// <summary>
/// 要素を配列化します。<para />
/// マルチスレッド操作に対してロックされません。通常はToArrayメソッドを使用してください。
/// </summary>
public T[] ToArrayUnsafe()
{
return internalList.ToArray();
}
#region IEnumerable メンバー
/// <summary>
/// 格納しているアイテムを取得します。
/// </summary>
public IEnumerable<T> Items
{
get { return internalList; }
}
public IEnumerator<T> GetEnumerator()
{
return internalList.GetEnumerator();
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
#endregion
#region ILockOperatable メンバー
public void LockOperate(Delegate operation, object arguments)
{
lock (iLocker)
{
operation.DynamicInvoke(arguments);
}
}
public TResult LockOperate<TResult>(Delegate operation, object arguments)
{
lock (iLocker)
{
return (TResult)operation.DynamicInvoke(arguments);
}
}
#endregion
#region IList<T> メンバー
public int IndexOf(T item)
{
lock (iLocker)
{
return internalList.IndexOf(item);
}
}
public void Insert(int index, T item)
{
lock (iLocker)
{
internalList.Insert(index, item);
}
}
public void InsertUnsafe(int index, T item)
{
internalList.Insert(index, item);
}
#endregion
#region ICollection<T> メンバー
public bool Contains(T item)
{
// *!*
return internalList.Contains(item);
}
public void CopyTo(T[] array, int arrayIndex)
{
lock (iLocker)
{
internalList.CopyTo(array, arrayIndex);
}
}
/// <summary>
/// 常に更新可能です。
/// </summary>
public bool IsReadOnly
{
get { return false; }
}
#endregion
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment