|
- using System;
- using System.Threading;
- using System.Threading.Tasks;
-
- namespace MQTTnet.Internal
- {
- // From Stephen Toub (https://blogs.msdn.microsoft.com/pfxteam/2012/02/12/building-async-coordination-primitives-part-6-asynclock/)
- public class AsyncLock : IDisposable
- {
- private readonly SemaphoreSlim _semaphore = new SemaphoreSlim(1, 1);
- private readonly Task<IDisposable> _releaser;
-
- public AsyncLock()
- {
- _releaser = Task.FromResult((IDisposable)new Releaser(this));
- }
-
- public Task<IDisposable> LockAsync(CancellationToken cancellationToken)
- {
- Task wait = _semaphore.WaitAsync(cancellationToken);
- return wait.IsCompleted ?
- _releaser :
- wait.ContinueWith((_, state) => (IDisposable)state,
- _releaser.Result, cancellationToken,
- TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default);
- }
-
- public void Dispose()
- {
- _semaphore?.Dispose();
- }
-
- private class Releaser : IDisposable
- {
- private readonly AsyncLock _toRelease;
-
- internal Releaser(AsyncLock toRelease)
- {
- _toRelease = toRelease;
- }
-
- public void Dispose()
- {
- _toRelease._semaphore.Release();
- }
- }
- }
- }
|