Created
October 8, 2025 11:22
-
-
Save yamamaya/d506eaa47921a470b46b88afa3571c89 to your computer and use it in GitHub Desktop.
A lightweight lock wrapper that allows SemaphoreSlim to be used with the using pattern.
This file contains hidden or 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.Diagnostics; | |
| namespace OaktreeLab.Utils.Common { | |
| /// <summary> | |
| /// A lightweight lock wrapper that allows <see cref="SemaphoreSlim"/> to be used with the <c>using</c> pattern. | |
| /// </summary> | |
| [DebuggerStepThrough] | |
| public sealed class SemaphoreSlimLock : IDisposable { | |
| private readonly SemaphoreSlim _semaphore; | |
| private bool _disposed; | |
| private SemaphoreSlimLock( SemaphoreSlim semaphore ) { | |
| _semaphore = semaphore; | |
| } | |
| /// <summary> | |
| /// Acquires the lock synchronously. | |
| /// </summary> | |
| public SemaphoreSlimLock( SemaphoreSlim semaphore, CancellationToken cancellationToken = default ) { | |
| ArgumentNullException.ThrowIfNull( semaphore ); | |
| semaphore.Wait( cancellationToken ); | |
| _semaphore = semaphore; | |
| } | |
| public void Dispose() { | |
| if ( !_disposed ) { | |
| _semaphore?.Release(); | |
| _disposed = true; | |
| } | |
| } | |
| /// <summary> | |
| /// Acquires the lock asynchronously. | |
| /// </summary> | |
| /// <returns>Returns an instance of <see cref="SemaphoreSlimLock"/> when the lock is acquired.</returns> | |
| public static async ValueTask<SemaphoreSlimLock> LockAsync( SemaphoreSlim semaphore, CancellationToken cancellationToken = default ) { | |
| ArgumentNullException.ThrowIfNull( semaphore ); | |
| await semaphore.WaitAsync( cancellationToken ).ConfigureAwait( false ); | |
| return new SemaphoreSlimLock( semaphore ); | |
| } | |
| /// <summary> | |
| /// Attempts to acquire the lock within the specified timeout. | |
| /// </summary> | |
| /// <returns>Returns an instance of <see cref="SemaphoreSlimLock"/> when the lock is acquired.</returns> | |
| /// <exception cref="TimeoutException">Thrown when the operation times out.</exception> | |
| public static async ValueTask<SemaphoreSlimLock> TryLockAsync( SemaphoreSlim semaphore, TimeSpan timeout, CancellationToken cancellationToken = default ) { | |
| ArgumentNullException.ThrowIfNull( semaphore ); | |
| if ( await semaphore.WaitAsync( timeout, cancellationToken ).ConfigureAwait( false ) ) { | |
| return new SemaphoreSlimLock( semaphore ); | |
| } | |
| throw new TimeoutException( "Failed to acquire the lock within the specified timeout." ); | |
| } | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment