Created
June 2, 2021 08:26
-
-
Save Pzixel/3576a23d0ca9ac52280f09869092993a to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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