| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657 |
- 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> WaitAsync()
- {
- return WaitAsync(CancellationToken.None);
- }
- public Task<IDisposable> WaitAsync(CancellationToken cancellationToken)
- {
- var task = _semaphore.WaitAsync(cancellationToken);
- if (task.Status == TaskStatus.RanToCompletion)
- {
- return _releaser;
- }
- return task.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();
- }
- }
- }
- }
|