-
-
Notifications
You must be signed in to change notification settings - Fork 9
/
Counter.cs
109 lines (92 loc) · 3.18 KB
/
Counter.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
namespace SharedCounter
{
using System;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Hosting;
using SharpDeck.Connectivity;
/// <summary>
/// Provides methods for monitoring and persisting the shared count.
/// </summary>
public class Counter : IHostedService
{
/// <summary>
/// The synchronization root.
/// </summary>
private readonly SemaphoreSlim _syncRoot = new SemaphoreSlim(1);
/// <summary>
/// Initializes a new instance of the <see cref="Counter"/> class.
/// </summary>
/// <param name="connection">The connection.</param>
public Counter(IStreamDeckConnection connection)
=> this.Connection = connection;
/// <summary>
/// Occurs when the value has changed.
/// </summary>
public event EventHandler<int> Changed;
/// <summary>
/// Gets the connection to the Stream Deck.
/// </summary>
private IStreamDeckConnection Connection { get; }
/// <summary>
/// Gets or sets the value.
/// </summary>
private int Value { get; set; }
/// <summary>
/// Gets the task responsible for indicating this instance is ready.
/// </summary>
private TaskCompletionSource<object> Started { get; } = new TaskCompletionSource<object>();
/// <summary>
/// Gets the value asynchronously.
/// </summary>
/// <returns>The value of the counter.</returns>
public async ValueTask<int> GetValueAsync()
{
await this.Started.Task;
return this.Value;
}
/// <summary>
/// Increments the count asynchronously.
/// </summary>
public ValueTask IncrementAsync()
=> this.UpdateAsync(() => this.Value++);
/// <summary>
/// Resets the count asynchronously.
/// </summary>
public ValueTask ResetAsync()
=> this.UpdateAsync(() => this.Value = 0);
/// <inheritdoc/>
public async Task StartAsync(CancellationToken cancellationToken)
{
var settings = await this.Connection.GetGlobalSettingsAsync<GlobalSettings>();
this.Value = settings.Count;
this.Changed?.Invoke(this, this.Value);
this.Started.TrySetResult(true);
}
/// <inheritdoc/>
public Task StopAsync(CancellationToken cancellationToken)
=> Task.CompletedTask;
/// <summary>
/// Updates the value asynchronous.
/// </summary>
/// <param name="action">The action to apply.</param>
private async ValueTask UpdateAsync(Action action)
{
await this.Started.Task;
try
{
await this._syncRoot.WaitAsync();
action();
await this.Connection.SetGlobalSettingsAsync(new GlobalSettings
{
Count = this.Value
});
}
finally
{
this._syncRoot.Release();
}
this.Changed?.Invoke(this, this.Value);
}
}
}