using SmartCoalApplication.SystemLayer; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; namespace SmartCoalApplication.Core.Threading { public class WaitableCounter { public static int MinimumCount { get { return WaitHandleArray.MinimumCount; } } public static int MaximumCount { get { return WaitHandleArray.MaximumCount; } } private sealed class CounterToken : IDisposable { private WaitableCounter parent; private int index; public int Index { get { return this.index; } } public CounterToken(WaitableCounter parent, int index) { this.parent = parent; this.index = index; } public void Dispose() { parent.Release(this); } } private WaitHandleArray freeEvents; private WaitHandleArray inUseEvents; private object theLock; public WaitableCounter(int maxCount) { if (maxCount < 1 || maxCount > 64) { throw new ArgumentOutOfRangeException("maxCount", "must be between 1 and 64, inclusive"); } this.freeEvents = new WaitHandleArray(maxCount); this.inUseEvents = new WaitHandleArray(maxCount); for (int i = 0; i < maxCount; ++i) { this.freeEvents[i] = new ManualResetEvent(true); this.inUseEvents[i] = new ManualResetEvent(false); } this.theLock = new object(); } private void Release(CounterToken token) { ((ManualResetEvent)this.inUseEvents[token.Index]).Reset(); ((ManualResetEvent)this.freeEvents[token.Index]).Set(); } public IDisposable AcquireToken() { lock (this.theLock) { int index = WaitForNotFull(); ((ManualResetEvent)this.freeEvents[index]).Reset(); ((ManualResetEvent)this.inUseEvents[index]).Set(); return new CounterToken(this, index); } } public bool IsEmpty() { return IsEmpty(0); } public bool IsEmpty(uint msTimeout) { return freeEvents.AreAllSignaled(msTimeout); } public void WaitForEmpty() { freeEvents.WaitAll(); } public int WaitForNotFull() { int returnVal = freeEvents.WaitAny(); return returnVal; } } }