using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Runtime.InteropServices; using System.Threading; using System.Threading.Tasks; #pragma warning disable 0649 namespace miew.Concurrency { static public class Tasks { static Tasks() { TaskCompletionSource<Object> tcs = new TaskCompletionSource<Object>(); tcs.SetResult(null); CompletedTask = tcs.Task; } static readonly public Task CompletedTask; static public Task<T> FromResult<T>(T result) { TaskCompletionSource<T> tcs = new TaskCompletionSource<T>(TaskCreationOptions.AttachedToParent); tcs.SetResult(result); return tcs.Task; } /// <summary> /// Caution: elements in the enumeration might be iterated more than once; beware of side-effects /// </summary> //static public Task WhenAllXX(IEnumerable<Task> iet) //{ // var c = iet as ICollection<Task>; // if ((c != null && c.Count > 0) || iet.GetEnumerator().MoveNext()) // return TaskEx.WhenAll(iet); // return CompletedTask; //} static public void RgtaskNop(Task[] rgt) { } public static Task Self { get { return Task.Factory.StartNew(Nop, CancellationToken.None, TaskCreationOptions.AttachedToParent, TaskScheduler.Default).Parent(); } } static void Nop() { } }; public class TimedTask<T> : Task<T> { public TimedTask(Func<T> f) : base(f) { } public long Milliseconds { get { return ms; } } protected long ms; public new void Start() { Stopwatch sw = Stopwatch.StartNew(); base.Start(); base.ContinueWith(t => ms = sw.ElapsedMilliseconds, TaskContinuationOptions.ExecuteSynchronously); } }; static public class Extensions { public static Task Parent(this Task t) { FieldInfo info = typeof(Task).GetField("m_parent", BindingFlags.NonPublic | BindingFlags.Instance); return info != null ? (Task)info.GetValue(t) : null; } public static bool HasAsAncestor(this Task t, Task parent) { Task walk = t; while ((walk = walk.Parent()) != null) if (walk == t) return true; return false; } public static bool AtomicStoreIfNull<T>(ref T pt, ref T in_out) where T : class { T actual = Interlocked.CompareExchange<T>(ref pt, in_out, null); if (actual == null) return true; in_out = actual; return false; } }; /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// /// </summary> /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public sealed class ConcurrentList<T> : List<T>//: ConcurrentContainer<T> { //readonly List<T> list = new List<T>(); SpinLock m_lock = new SpinLock(false); // do not make this 'readonly' public ConcurrentList() { } public ConcurrentList(T t) { this.Add(t); } public new /*override*/ void Clear() { bool entered = false; try { m_lock.Enter(ref entered); base.Clear(); } finally { if (entered) m_lock.Exit(false); } } public new /*override*/ bool Add(T item) { bool entered = false; try { m_lock.Enter(ref entered); base.Add(item); return true; } finally { if (entered) m_lock.Exit(false); } } public new void AddRange(IEnumerable<T> items) { bool entered = false; try { m_lock.Enter(ref entered); base.AddRange(items); } finally { if (entered) m_lock.Exit(false); } } /// <summary> /// (useless for concurrency) /// </summary> public new /*override*/ bool Contains(T item) { bool entered = false; try { m_lock.Enter(ref entered); return base.Contains(item); } finally { if (entered) m_lock.Exit(false); } } /// <summary> /// (useless for concurrency) /// </summary> public new /*override*/ int Count { get { bool entered = false; try { m_lock.Enter(ref entered); return base.Count; } finally { if (entered) m_lock.Exit(false); } } } public new /*override*/ IEnumerator<T> GetEnumerator() { while (true) { bool entered = false; try { m_lock.Enter(ref entered); return base.ToArray().AsEnumerable<T>().GetEnumerator(); } finally { if (entered) m_lock.Exit(false); } } } public IEnumerable<T> GetEnumerableUnsafe() { return base.ToArray().AsEnumerable<T>(); } public new T[] ToArray() { bool entered = false; try { m_lock.Enter(ref entered); return base.ToArray(); } finally { if (entered) m_lock.Exit(false); } } /// <summary> /// /// </summary> public new /*override*/ bool Remove(T item) { throw new NotImplementedException(); } }; /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// /// </summary> /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public sealed class ConcurrentHashSet<T> : ConcurrentContainer<T> { readonly HashSet<T> hs = new HashSet<T>(); SpinLock m_lock = new SpinLock(false); // 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(false); } } 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(false); } } public override void Clear() { bool entered = false; try { m_lock.Enter(ref entered); hs.Clear(); any = default(T); } finally { if (entered) m_lock.Exit(false); } } 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(false); } } public T[] ToArray() { bool entered = false; try { m_lock.Enter(ref entered); return hs.ToArray(); } finally { if (entered) m_lock.Exit(false); } } public override IEnumerator<T> GetEnumerator() { return ToArray().AsEnumerable<T>().GetEnumerator(); } public override int Count { get { return hs.Count; } } }; /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// /// </summary> /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public class ConcurrentStringBuilder { readonly System.Text.StringBuilder sb = new System.Text.StringBuilder(); SpinLock m_lock = new SpinLock(false); // 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(false); } } public ConcurrentStringBuilder Append(System.String s) { bool entered = false; try { m_lock.Enter(ref entered); sb.Append(s); return this; } finally { if (entered) m_lock.Exit(false); } } public ConcurrentStringBuilder AppendFormat(System.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(false); } } public override System.String ToString() { bool entered = false; try { m_lock.Enter(ref entered); return sb.ToString(); } finally { if (entered) m_lock.Exit(false); } } public int Length { get { bool entered = false; try { m_lock.Enter(ref entered); return sb.Length; } finally { if (entered) m_lock.Exit(false); } } set { bool entered = false; try { m_lock.Enter(ref entered); sb.Length = value; } finally { if (entered) m_lock.Exit(false); } } } }; /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// <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 sealed class ConcurrentSymmetricDictionary<K1, K2> { FalseSharing.Padding60 fsp1; SpinLock slock = new SpinLock(false); // do not make this 'readonly' FalseSharing.Padding60 fsp2; Dictionary<K1, K2> forward; Dictionary<K2, K1> reverse; public ConcurrentSymmetricDictionary(IEqualityComparer<K1> c) { forward = new Dictionary<K1, K2>(c); reverse = new Dictionary<K2, K1>(); Debugging.Nop.X(fsp1, fsp2); } public ConcurrentSymmetricDictionary(IEqualityComparer<K2> c) { forward = new Dictionary<K1, K2>(); reverse = new Dictionary<K2, K1>(c); Debugging.Nop.X(fsp1, fsp2); } public ConcurrentSymmetricDictionary() { forward = new Dictionary<K1, K2>(); reverse = new Dictionary<K2, K1>(); Debugging.Nop.X(fsp1, fsp2); } 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 bool ContainsKey(K1 k1) { bool _b = false; try { slock.Enter(ref _b); return forward.ContainsKey(k1); } finally { if (_b) slock.Exit(); } } public bool ContainsKey(K2 k2) { bool _b = false; try { slock.Enter(ref _b); return reverse.ContainsKey(k2); } finally { if (_b) slock.Exit(); } } public bool TryGetKey(K1 k1, out K2 k2) { bool _b = false; try { slock.Enter(ref _b); return forward.TryGetValue(k1, out k2); } finally { if (_b) slock.Exit(); } } 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(); } } public int Count { get { return forward.Count; } } public IEnumerable<KeyValuePair<K1, K2>> Enumerate() { return forward; } }; public static class FalseSharing { [StructLayout(LayoutKind.Explicit, Size = 56)] public struct Padding56 { }; [StructLayout(LayoutKind.Explicit, Size = 60)] public struct Padding60 { }; [StructLayout(LayoutKind.Explicit, Size = 64)] public struct Padding64 { }; [StructLayout(LayoutKind.Explicit, Size = 120)] public struct Padding120 { }; [StructLayout(LayoutKind.Explicit, Size = 124)] public struct Padding124 { }; [StructLayout(LayoutKind.Explicit, Size = 128)] public struct Padding128 { }; [StructLayout(LayoutKind.Explicit, Size = 248)] public struct Padding248 { }; [StructLayout(LayoutKind.Explicit, Size = 252)] public struct Padding252 { }; [StructLayout(LayoutKind.Explicit, Size = 256)] public struct Padding256 { }; [StructLayout(LayoutKind.Explicit, Size = 2048)] public struct Padding2048 { }; }; }