97 lines
2.7 KiB
C#
97 lines
2.7 KiB
C#
using System;
|
||
using System.Collections.Generic;
|
||
using System.Text;
|
||
|
||
namespace UniRx
|
||
{
|
||
/// <summary>Event kind of CountNotifier.</summary>
|
||
public enum CountChangedStatus
|
||
{
|
||
/// <summary>Count incremented.</summary>
|
||
Increment,
|
||
/// <summary>Count decremented.</summary>
|
||
Decrement,
|
||
/// <summary>Count is zero.</summary>
|
||
Empty,
|
||
/// <summary>Count arrived max.</summary>
|
||
Max
|
||
}
|
||
|
||
/// <summary>
|
||
/// Notify event of count flag.
|
||
/// </summary>
|
||
public class CountNotifier : IObservable<CountChangedStatus>
|
||
{
|
||
readonly object lockObject = new object();
|
||
readonly Subject<CountChangedStatus> statusChanged = new Subject<CountChangedStatus>();
|
||
readonly int max;
|
||
|
||
public int Max { get { return max; } }
|
||
public int Count { get; private set; }
|
||
|
||
/// <summary>
|
||
/// Setup max count of signal.
|
||
/// </summary>
|
||
public CountNotifier(int max = int.MaxValue)
|
||
{
|
||
if (max <= 0)
|
||
{
|
||
throw new ArgumentException("max");
|
||
}
|
||
|
||
this.max = max;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Increment count and notify status.
|
||
/// </summary>
|
||
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));
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Decrement count and notify status.
|
||
/// </summary>
|
||
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);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Subscribe observer.
|
||
/// </summary>
|
||
public IDisposable Subscribe(IObserver<CountChangedStatus> observer)
|
||
{
|
||
return statusChanged.Subscribe(observer);
|
||
}
|
||
}
|
||
} |