CountNotifier.cs 2.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Text;
  4. namespace UniRx
  5. {
  6. /// <summary>Event kind of CountNotifier.</summary>
  7. public enum CountChangedStatus
  8. {
  9. /// <summary>Count incremented.</summary>
  10. Increment,
  11. /// <summary>Count decremented.</summary>
  12. Decrement,
  13. /// <summary>Count is zero.</summary>
  14. Empty,
  15. /// <summary>Count arrived max.</summary>
  16. Max
  17. }
  18. /// <summary>
  19. /// Notify event of count flag.
  20. /// </summary>
  21. public class CountNotifier : IObservable<CountChangedStatus>
  22. {
  23. readonly object lockObject = new object();
  24. readonly Subject<CountChangedStatus> statusChanged = new Subject<CountChangedStatus>();
  25. readonly int max;
  26. public int Max { get { return max; } }
  27. public int Count { get; private set; }
  28. /// <summary>
  29. /// Setup max count of signal.
  30. /// </summary>
  31. public CountNotifier(int max = int.MaxValue)
  32. {
  33. if (max <= 0)
  34. {
  35. throw new ArgumentException("max");
  36. }
  37. this.max = max;
  38. }
  39. /// <summary>
  40. /// Increment count and notify status.
  41. /// </summary>
  42. public IDisposable Increment(int incrementCount = 1)
  43. {
  44. if (incrementCount < 0)
  45. {
  46. throw new ArgumentException("incrementCount");
  47. }
  48. lock (lockObject)
  49. {
  50. if (Count == Max) return Disposable.Empty;
  51. else if (incrementCount + Count > Max) Count = Max;
  52. else Count += incrementCount;
  53. statusChanged.OnNext(CountChangedStatus.Increment);
  54. if (Count == Max) statusChanged.OnNext(CountChangedStatus.Max);
  55. return Disposable.Create(() => this.Decrement(incrementCount));
  56. }
  57. }
  58. /// <summary>
  59. /// Decrement count and notify status.
  60. /// </summary>
  61. public void Decrement(int decrementCount = 1)
  62. {
  63. if (decrementCount < 0)
  64. {
  65. throw new ArgumentException("decrementCount");
  66. }
  67. lock (lockObject)
  68. {
  69. if (Count == 0) return;
  70. else if (Count - decrementCount < 0) Count = 0;
  71. else Count -= decrementCount;
  72. statusChanged.OnNext(CountChangedStatus.Decrement);
  73. if (Count == 0) statusChanged.OnNext(CountChangedStatus.Empty);
  74. }
  75. }
  76. /// <summary>
  77. /// Subscribe observer.
  78. /// </summary>
  79. public IDisposable Subscribe(IObserver<CountChangedStatus> observer)
  80. {
  81. return statusChanged.Subscribe(observer);
  82. }
  83. }
  84. }