using System; using System.Collections.Generic; using System.Text; namespace UniRx { /// Event kind of CountNotifier. public enum CountChangedStatus { /// Count incremented. Increment, /// Count decremented. Decrement, /// Count is zero. Empty, /// Count arrived max. Max } /// /// Notify event of count flag. /// public class CountNotifier : IObservable { readonly object lockObject = new object(); readonly Subject statusChanged = new Subject(); readonly int max; public int Max { get { return max; } } public int Count { get; private set; } /// /// Setup max count of signal. /// public CountNotifier(int max = int.MaxValue) { if (max <= 0) { throw new ArgumentException("max"); } this.max = max; } /// /// Increment count and notify status. /// public IDisposable Increment(int incrementCount = 1) { if (incrementCount < 0) { throw new ArgumentException("incrementCount"); } lock (lockObject) { if (Count == Max) return Disposable.Empty; else if (incrementCount + Count > Max) Count = Max; else Count += incrementCount; statusChanged.OnNext(CountChangedStatus.Increment); if (Count == Max) statusChanged.OnNext(CountChangedStatus.Max); return Disposable.Create(() => this.Decrement(incrementCount)); } } /// /// Decrement count and notify status. /// public void Decrement(int decrementCount = 1) { if (decrementCount < 0) { throw new ArgumentException("decrementCount"); } lock (lockObject) { if (Count == 0) return; else if (Count - decrementCount < 0) Count = 0; else Count -= decrementCount; statusChanged.OnNext(CountChangedStatus.Decrement); if (Count == 0) statusChanged.OnNext(CountChangedStatus.Empty); } } /// /// Subscribe observer. /// public IDisposable Subscribe(IObserver observer) { return statusChanged.Subscribe(observer); } } }