Skip to content

Instantly share code, notes, and snippets.

@Pzixel
Created June 2, 2021 08:26
Show Gist options
  • Save Pzixel/3576a23d0ca9ac52280f09869092993a to your computer and use it in GitHub Desktop.
Save Pzixel/3576a23d0ca9ac52280f09869092993a to your computer and use it in GitHub Desktop.
using System;
using System.Threading;
using System.Threading.Tasks;
namespace Utils
{
public class AsyncLock<T> where T : class
{
public bool IsDeconstructed { get; private set; }
private readonly SemaphoreSlim _semaphore;
private readonly SemaphoreSlimReleaser _semaphoreReleaser;
public AsyncLock(T value)
{
_semaphore = new SemaphoreSlim(1);
_semaphoreReleaser = new SemaphoreSlimReleaser(_semaphore, value);
}
public async Task<ISemaphoreReleaser<T>> AcquireAsync()
{
if (IsDeconstructed)
{
throw new InvalidOperationException("AsyncLock was deconstructed");
}
await _semaphore.WaitAsync().ConfigureAwait(false);
if (IsDeconstructed)
{
throw new InvalidOperationException("AsyncLock was deconstructed");
}
return _semaphoreReleaser;
}
public T? Deconstruct()
{
if (!IsDeconstructed)
{
_semaphore.Wait();
if (!IsDeconstructed)
{
IsDeconstructed = true;
return _semaphoreReleaser.Value;
}
}
return null;
}
private readonly struct SemaphoreSlimReleaser : ISemaphoreReleaser<T>
{
private readonly SemaphoreSlim _semaphore;
public T Value { get; }
public SemaphoreSlimReleaser(SemaphoreSlim semaphore, T value)
{
_semaphore = semaphore;
Value = value;
}
public void Dispose()
{
_semaphore.Release();
}
}
}
public interface ISemaphoreReleaser<out T> : IDisposable
{
public T Value { get; }
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment