mirror of
https://github.com/dotnet/MQTTnet.git
synced 2026-10-16 17:23:04 +08:00
49 lines
1.4 KiB
C#
49 lines
1.4 KiB
C#
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();
|
|
}
|
|
}
|
|
}
|
|
}
|