46 lines
1.1 KiB
C#
46 lines
1.1 KiB
C#
namespace CertMgr.Core.Utils;
|
|
|
|
using System;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
|
|
public sealed class AsyncLock
|
|
{
|
|
private readonly SemaphoreSlim _semaphore;
|
|
private readonly Task<IDisposable> _disposer;
|
|
|
|
public AsyncLock()
|
|
{
|
|
_semaphore = new SemaphoreSlim(1, 1);
|
|
_disposer = Task.FromResult((IDisposable)new AsyncLockDisposer(this));
|
|
}
|
|
|
|
public Task<IDisposable> LockAsync(CancellationToken cancellation = default)
|
|
{
|
|
Task wait = _semaphore.WaitAsync();
|
|
if (wait.IsCompleted)
|
|
{
|
|
return _disposer;
|
|
}
|
|
else
|
|
{
|
|
return wait.ContinueWith((_, state) => (IDisposable)state!, _disposer.Result, CancellationToken.None, TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default);
|
|
}
|
|
}
|
|
|
|
private sealed class AsyncLockDisposer : IDisposable
|
|
{
|
|
private readonly AsyncLock _owner;
|
|
|
|
internal AsyncLockDisposer(AsyncLock owner)
|
|
{
|
|
_owner = owner;
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
_owner._semaphore.Release();
|
|
}
|
|
}
|
|
}
|