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);
}
}
}