using System;
using System.Collections.Generic;
using System.Collections.Concurrent;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
/// http://download.microsoft.com/download/B/C/F/BCFD4868-1354-45E3-B71B-B851CD78733D/PerformanceCharacteristicsOfThreadSafeCollection.pdf
namespace tgcs.Util.Concurrency
{
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary>
///
/// </summary>
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public class ConcurrentList<T> : ConcurrentContainer<T>
{
readonly List<T> list = new List<T>();
SpinLock m_lock = new SpinLock(); // do not make this 'readonly'
int c_inert = 0;
public override void Clear()
{
bool entered = false;
try
{
m_lock.Enter(ref entered);
list.Clear();
}
finally
{
if (entered)
m_lock.Exit();
}
}
public override bool Add(T item)
{
bool entered = false;
try
{
m_lock.Enter(ref entered);
list.Add(item);
return true;
}
finally
{
if (entered)
m_lock.Exit();
}
}
/// <summary>
/// (useless for concurrency)
/// </summary>
public override bool Contains(T item)
{
bool entered = false;
try
{
m_lock.Enter(ref entered);
return list.Contains(item);
}
finally
{
if (entered)
m_lock.Exit();
}
}
/// <summary>
/// (useless for concurrency)
/// </summary>
public override int Count
{
get
{
bool entered = false;
try
{
m_lock.Enter(ref entered);
return list.Count - c_inert;
}
finally
{
if (entered)
m_lock.Exit();
}
}
}
public override IEnumerator<T> GetEnumerator()
{
int i = 0;
while (true)
{
bool entered = false;
try
{
m_lock.Enter(ref entered);
while (true)
{
if (i >= list.Count)
yield break;
else
{
T item = list[i++];
// exiting a 'try' block with 'yield return' does not execute 'finally' each time
// http://blogs.msdn.com/b/oldnewthing/archive/2008/08/14/8862242.aspx
entered = false;
m_lock.Exit();
yield return item;
m_lock.Enter(ref entered);
break;
}
}
}
finally
{
if (entered)
m_lock.Exit();
}
}
}
public T[] ToArray()
{
bool entered = false;
try
{
m_lock.Enter(ref entered);
return list.ToArray();
}
finally
{
if (entered)
m_lock.Exit();
}
}
/// <summary>
/// Would interfere with in-situ enumeration
/// </summary>
public override bool Remove(T item) { throw new NotSupportedException(); }
};
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary>
///
/// </summary>
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public class ConcurrentHashSet<T> : ConcurrentContainer<T>
{
readonly HashSet<T> hs = new HashSet<T>();
SpinLock m_lock = new SpinLock(); // do not make this 'readonly'
T any = default(T);
public T Peek() { return any; }
public override bool Add(T item)
{
bool entered = false;
try
{
m_lock.Enter(ref entered);
bool b = hs.Add(item);
if (b)
any = item;
return b;
}
finally
{
if (entered)
m_lock.Exit();
}
}
public override bool Remove(T item)
{
bool entered = false;
try
{
m_lock.Enter(ref entered);
bool b = hs.Remove(item);
if (b && any.Equals(item))
{
if (hs.Count == 0)
any = default(T);
else
{
var e = hs.GetEnumerator();
e.MoveNext();
any = e.Current;
}
}
return b;
}
finally
{
if (entered)
m_lock.Exit();
}
}
public override void Clear()
{
bool entered = false;
try
{
m_lock.Enter(ref entered);
hs.Clear();
any = default(T);
}
finally
{
if (entered)
m_lock.Exit();
}
}
public override bool Contains(T item)
{
bool entered = false;
try
{
m_lock.Enter(ref entered);
return hs.Contains(item);
}
finally
{
if (entered)
m_lock.Exit();
}
}
public T[] ToArray()
{
bool entered = false;
try
{
m_lock.Enter(ref entered);
return hs.ToArray();
}
finally
{
if (entered)
m_lock.Exit();
}
}
public override int Count { get { return hs.Count; } }
};
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary>
///
/// </summary>
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public class ConcurrentStringBuilder
{
readonly StringBuilder sb = new StringBuilder();
SpinLock m_lock = new SpinLock(); // do not make this 'readonly'
public void Clear()
{
bool entered = false;
try
{
m_lock.Enter(ref entered);
sb.Clear();
}
finally
{
if (entered)
m_lock.Exit();
}
}
public ConcurrentStringBuilder Append(String s)
{
bool entered = false;
try
{
m_lock.Enter(ref entered);
sb.Append(s);
return this;
}
finally
{
if (entered)
m_lock.Exit();
}
}
public ConcurrentStringBuilder AppendFormat(String fmt, params Object[] args)
{
bool entered = false;
try
{
m_lock.Enter(ref entered);
sb.AppendFormat(fmt, args);
return this;
}
finally
{
if (entered)
m_lock.Exit();
}
}
public override String ToString()
{
bool entered = false;
try
{
m_lock.Enter(ref entered);
return sb.ToString();
}
finally
{
if (entered)
m_lock.Exit();
}
}
public int Length
{
get
{
bool entered = false;
try
{
m_lock.Enter(ref entered);
return sb.Length;
}
finally
{
if (entered)
m_lock.Exit();
}
}
set
{
bool entered = false;
try
{
m_lock.Enter(ref entered);
sb.Length = value;
}
finally
{
if (entered)
m_lock.Exit();
}
}
}
};
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary>
///
/// </summary>
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public abstract class ConcurrentContainer<T> : ISet<T>
{
public abstract bool Add(T item);
public abstract void Clear();
public abstract bool Contains(T item);
public abstract int Count { get; }
public abstract bool Remove(T item);
public virtual IEnumerator<T> GetEnumerator() { throw new NotImplementedException(); }
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { return GetEnumerator(); }
void ICollection<T>.Add(T item) { Add(item); }
public bool IsReadOnly { get { return false; } }
public void CopyTo(T[] array, int arrayIndex) { throw new NotSupportedException(); }
public void ExceptWith(IEnumerable<T> other) { throw new NotSupportedException(); }
public void IntersectWith(IEnumerable<T> other) { throw new NotSupportedException(); }
public bool IsProperSubsetOf(IEnumerable<T> other) { throw new NotSupportedException(); }
public bool IsProperSupersetOf(IEnumerable<T> other) { throw new NotSupportedException(); }
public bool IsSubsetOf(IEnumerable<T> other) { throw new NotSupportedException(); }
public bool IsSupersetOf(IEnumerable<T> other) { throw new NotSupportedException(); }
public bool Overlaps(IEnumerable<T> other) { throw new NotSupportedException(); }
public bool SetEquals(IEnumerable<T> other) { throw new NotSupportedException(); }
public void SymmetricExceptWith(IEnumerable<T> other) { throw new NotSupportedException(); }
public void UnionWith(IEnumerable<T> other) { throw new NotSupportedException(); }
};
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary>
///
/// </summary>
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public class ConcurrentSymmetricDictionary<K1, K2>
{
SpinLock slock = new SpinLock(false); // do not make this 'readonly'
Dictionary<K1, K2> forward;
Dictionary<K2, K1> reverse;
public ConcurrentSymmetricDictionary(IEqualityComparer<K1> c)
{
forward = new Dictionary<K1, K2>(c);
reverse = new Dictionary<K2, K1>();
}
public ConcurrentSymmetricDictionary(IEqualityComparer<K2> c)
{
forward = new Dictionary<K1, K2>();
reverse = new Dictionary<K2, K1>(c);
}
public ConcurrentSymmetricDictionary()
{
forward = new Dictionary<K1, K2>();
reverse = new Dictionary<K2, K1>();
}
public K2 this[K1 k1]
{
get
{
return forward[k1];
}
set
{
bool _b = false;
try
{
slock.Enter(ref _b);
forward[k1] = value;
reverse[value] = k1;
}
finally
{
if (_b) slock.Exit();
}
}
}
public K1 this[K2 k2]
{
get
{
return reverse[k2];
}
set
{
bool _b = false;
try
{
slock.Enter(ref _b);
reverse[k2] = value;
forward[value] = k2;
}
finally
{
if (_b) slock.Exit();
}
}
}
public void Add(K1 k1, K2 k2)
{
bool _b = false;
try
{
slock.Enter(ref _b);
forward.Add(k1, k2);
reverse.Add(k2, k1);
}
finally
{
if (_b) slock.Exit();
}
}
public bool Remove(K1 k1)
{
bool _b = false;
try
{
slock.Enter(ref _b);
K2 k2;
if (!forward.TryGetValue(k1, out k2))
return false;
forward.Remove(k1);
reverse.Remove(k2);
return true;
}
finally
{
if (_b) slock.Exit();
}
}
public bool Remove(K2 k2)
{
bool _b = false;
try
{
slock.Enter(ref _b);
K1 k1;
if (!reverse.TryGetValue(k2, out k1))
return false;
reverse.Remove(k2);
forward.Remove(k1);
}
finally
{
if (_b) slock.Exit();
}
return true;
}
public void Clear()
{
bool _b = false;
try
{
slock.Enter(ref _b);
forward.Clear();
reverse.Clear();
}
finally
{
if (_b) slock.Exit();
}
}
public bool TryGetValue(K2 k2, out K1 k1)
{
return reverse.TryGetValue(k2, out k1);
}
public bool TryGetValue(K1 k1, out K2 k2)
{
return forward.TryGetValue(k1, out k2);
}
public K2 GetOrAdd(K1 k1, K2 k2)
{
bool _b = false;
try
{
slock.Enter(ref _b);
K2 v;
if (!forward.TryGetValue(k1, out v))
{
v = k2;
forward.Add(k1, v);
reverse.Add(v, k1);
}
return v;
}
finally
{
if (_b) slock.Exit();
}
}
};
}