You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
97 lines
2.7 KiB
97 lines
2.7 KiB
1 year ago
|
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);
|
||
|
}
|
||
|
}
|
||
|
}
|