summaryrefslogtreecommitdiff
path: root/src/SMAPI/Framework/Utilities
diff options
context:
space:
mode:
Diffstat (limited to 'src/SMAPI/Framework/Utilities')
-rw-r--r--src/SMAPI/Framework/Utilities/ContextHash.cs61
-rw-r--r--src/SMAPI/Framework/Utilities/Countdown.cs44
2 files changed, 105 insertions, 0 deletions
diff --git a/src/SMAPI/Framework/Utilities/ContextHash.cs b/src/SMAPI/Framework/Utilities/ContextHash.cs
new file mode 100644
index 00000000..6c0fdc90
--- /dev/null
+++ b/src/SMAPI/Framework/Utilities/ContextHash.cs
@@ -0,0 +1,61 @@
+using System;
+using System.Collections.Generic;
+
+namespace StardewModdingAPI.Framework.Utilities
+{
+ /// <summary>A <see cref="HashSet{T}"/> wrapper meant for tracking recursive contexts.</summary>
+ /// <typeparam name="T">The key type.</typeparam>
+ internal class ContextHash<T> : HashSet<T>
+ {
+ /*********
+ ** Public methods
+ *********/
+ /// <summary>Construct an instance.</summary>
+ public ContextHash() { }
+
+ /// <summary>Construct an instance.</summary>
+ /// <param name="comparer">The <see cref="IEqualityComparer{T}"/> implementation to use when comparing values in the set, or <c>null</c> to use the default comparer for the set type.</param>
+ public ContextHash(IEqualityComparer<T> comparer)
+ : base(comparer) { }
+
+ /// <summary>Add a key while an action is in progress, and remove it when it completes.</summary>
+ /// <param name="key">The key to add.</param>
+ /// <param name="action">The action to perform.</param>
+ /// <exception cref="InvalidOperationException">The specified key is already added.</exception>
+ public void Track(T key, Action action)
+ {
+ if (this.Contains(key))
+ throw new InvalidOperationException($"Can't track context for key {key} because it's already added.");
+
+ this.Add(key);
+ try
+ {
+ action();
+ }
+ finally
+ {
+ this.Remove(key);
+ }
+ }
+
+ /// <summary>Add a key while an action is in progress, and remove it when it completes.</summary>
+ /// <typeparam name="TResult">The value type returned by the method.</typeparam>
+ /// <param name="key">The key to add.</param>
+ /// <param name="action">The action to perform.</param>
+ public TResult Track<TResult>(T key, Func<TResult> action)
+ {
+ if (this.Contains(key))
+ throw new InvalidOperationException($"Can't track context for key {key} because it's already added.");
+
+ this.Add(key);
+ try
+ {
+ return action();
+ }
+ finally
+ {
+ this.Remove(key);
+ }
+ }
+ }
+}
diff --git a/src/SMAPI/Framework/Utilities/Countdown.cs b/src/SMAPI/Framework/Utilities/Countdown.cs
new file mode 100644
index 00000000..921a35ce
--- /dev/null
+++ b/src/SMAPI/Framework/Utilities/Countdown.cs
@@ -0,0 +1,44 @@
+namespace StardewModdingAPI.Framework.Utilities
+{
+ /// <summary>Counts down from a baseline value.</summary>
+ internal class Countdown
+ {
+ /*********
+ ** Accessors
+ *********/
+ /// <summary>The initial value from which to count down.</summary>
+ public int Initial { get; }
+
+ /// <summary>The current value.</summary>
+ public int Current { get; private set; }
+
+
+ /*********
+ ** Public methods
+ *********/
+ /// <summary>Construct an instance.</summary>
+ /// <param name="initial">The initial value from which to count down.</param>
+ public Countdown(int initial)
+ {
+ this.Initial = initial;
+ this.Current = initial;
+ }
+
+ /// <summary>Reduce the current value by one.</summary>
+ /// <returns>Returns whether the value was decremented (i.e. wasn't already zero).</returns>
+ public bool Decrement()
+ {
+ if (this.Current <= 0)
+ return false;
+
+ this.Current--;
+ return true;
+ }
+
+ /// <summary>Restart the countdown.</summary>
+ public void Reset()
+ {
+ this.Current = this.Initial;
+ }
+ }
+}