-
Notifications
You must be signed in to change notification settings - Fork 83
Expand file tree
/
Copy pathAsyncMutex.cs
More file actions
211 lines (185 loc) · 6.55 KB
/
AsyncMutex.cs
File metadata and controls
211 lines (185 loc) · 6.55 KB
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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
using System;
using System.Threading;
using System.Threading.Tasks;
namespace Waher.Runtime.Threading.Sync
{
/// <summary>
/// Asynchronous mutex class.
/// </summary>
public class AsyncMutex : IDisposable
{
private readonly object synchObj = new object();
private ThreadExecutor executor = null;
private Mutex mutex;
/// <summary>
/// Asynchronous mutex class.
/// </summary>
public AsyncMutex()
: this(new Mutex())
{
}
/// <summary>
/// Asynchronous mutex class.
/// </summary>
/// <param name="InitiallyOwned">if mutex is initially owned by caller.</param>
public AsyncMutex(bool InitiallyOwned)
: this(new Mutex(InitiallyOwned))
{
}
/// <summary>
/// Asynchronous mutex class.
/// </summary>
/// <param name="InitiallyOwned">if mutex is initially owned by caller.</param>
/// <param name="Name">Name of mutex.</param>
public AsyncMutex(bool InitiallyOwned, string Name)
: this(new Mutex(InitiallyOwned, Name))
{
}
/// <summary>
/// Asynchronous mutex class.
/// </summary>
/// <param name="InitiallyOwned">if mutex is initially owned by caller.</param>
/// <param name="Name">Name of mutex.</param>
/// <param name="CreatedNew">If a new mutex was created.</param>
public AsyncMutex(bool InitiallyOwned, string Name, out bool CreatedNew)
: this(new Mutex(InitiallyOwned, Name, out CreatedNew))
{
}
/// <summary>
/// Asynchronous mutex class.
/// </summary>
/// <param name="Mutex">Mutex object</param>
public AsyncMutex(Mutex Mutex)
: base()
{
this.mutex = Mutex;
}
/// <summary>
/// Opens an existing Mutex.
/// </summary>
/// <param name="Name">Name of mutex.</param>
/// <returns>Asynchronous Mutex.</returns>
public static AsyncMutex OpenExisting(string Name)
{
return new AsyncMutex(Mutex.OpenExisting(Name));
}
/// <summary>
/// Tries to open an existing Mutex.
/// </summary>
/// <param name="Name">Name of Mutex.</param>
/// <param name="Result">Asychronous Mutex, if found.</param>
/// <returns>If able to open Mutex.</returns>
public static bool TryOpenExisting(string Name, out AsyncMutex Result)
{
if (!Mutex.TryOpenExisting(Name, out Mutex MutexObj))
{
Result = null;
return false;
}
Result = new AsyncMutex(MutexObj);
return true;
}
private ThreadExecutor Executor
{
get
{
lock (this.synchObj)
{
if (this.executor is null)
this.executor = new ThreadExecutor();
return this.executor;
}
}
}
/// <summary>
/// <see cref="IDisposable.Dispose"/>
/// </summary>
public void Dispose()
{
this.executor?.Dispose();
this.executor = null;
this.mutex?.Dispose();
this.mutex = null;
}
/// <summary>
/// Waits for the Mutex to be free, and locks it.
/// </summary>
/// <returns>If successful.</returns>
public Task<bool> WaitOne()
{
return this.Executor.Execute(this.WaitOneSync);
}
private bool WaitOneSync()
{
return this.mutex.WaitOne();
}
/// <summary>
/// Waits for the Mutex to be free, and locks it.
/// </summary>
/// <param name="MillisecondsTimeout">Timeout, in milliseconds.</param>
/// <returns>If successful.</returns>
public Task<bool> WaitOne(int MillisecondsTimeout)
{
return this.Executor.Execute(this.WaitOneSync, MillisecondsTimeout);
}
private bool WaitOneSync(int MillisecondsTimeout)
{
return this.mutex.WaitOne(MillisecondsTimeout);
}
/// <summary>
/// Waits for the Mutex to be free, and locks it.
/// </summary>
/// <param name="MillisecondsTimeout">Timeout, in milliseconds.</param>
/// <param name="ExitContext">true to exit the synchronization domain for the context before the wait
/// (if in a synchronized context), and reacquire it afterward; otherwise, false.</param>
/// <returns>If successful.</returns>
public Task<bool> WaitOne(int MillisecondsTimeout, bool ExitContext)
{
return this.Executor.Execute(this.WaitOneSync, MillisecondsTimeout, ExitContext);
}
private bool WaitOneSync(int MillisecondsTimeout, bool ExitContext)
{
return this.mutex.WaitOne(MillisecondsTimeout, ExitContext);
}
/// <summary>
/// Waits for the Mutex to be free, and locks it.
/// </summary>
/// <param name="Timeout">Timeout.</param>
/// <returns>If successful.</returns>
public Task<bool> WaitOne(TimeSpan Timeout)
{
return this.Executor.Execute<bool, TimeSpan>(this.WaitOneSync, Timeout);
}
private bool WaitOneSync(TimeSpan Timeout)
{
return this.mutex.WaitOne(Timeout);
}
/// <summary>
/// Waits for the Mutex to be free, and locks it.
/// </summary>
/// <param name="Timeout">Timeout.</param>
/// <param name="ExitContext">true to exit the synchronization domain for the context before the wait
/// (if in a synchronized context), and reacquire it afterward; otherwise, false.</param>
/// <returns>If successful.</returns>
public Task<bool> WaitOne(TimeSpan Timeout, bool ExitContext)
{
return this.Executor.Execute(this.WaitOneSync, Timeout, ExitContext);
}
private bool WaitOneSync(TimeSpan Timeout, bool ExitContext)
{
return this.mutex.WaitOne(Timeout, ExitContext);
}
/// <summary>
/// Releases the mutex earlier aquired via a call to WaitOne.
/// </summary>
public async Task ReleaseMutex()
{
await this.Executor.Execute(this.ReleaseMutexSync);
}
private bool ReleaseMutexSync()
{
this.mutex.ReleaseMutex();
return true;
}
}
}