Class AsyncReentrantLock
- Namespace
- CryptoHives.Foundation.Threading.Async.Pooled
- Assembly
- CryptoHives.Foundation.Threading.dll
An experimental async lock that a nested call on the same logical async flow can re-acquire without deadlocking, unlike AsyncLock.
public sealed class AsyncReentrantLock
- Inheritance
-
AsyncReentrantLock
- Inherited Members
Remarks
Reentrancy is tracked through ExecutionContext, so an async method that awaits LockAsync(CancellationToken) and returns the releaser hides the hold from its caller, and the caller's next nested acquisition deadlocks. Releasing returns at once, but the lock stays held while nested holders such as fire-and-forget work are still running, until the last of them releases.
Constructors
AsyncReentrantLock(int, int)
Constructs a new AsyncReentrantLock.
public AsyncReentrantLock(int defaultDepthLocksCapacity = 4, int maxDepthLocksCapacity = 32)
Parameters
defaultDepthLocksCapacityintThe initial capacity of the depth table; it grows on demand up to
maxDepthLocksCapacity.maxDepthLocksCapacityintThe maximum nesting depth; a call that would nest deeper throws InvalidOperationException.
Exceptions
- ArgumentOutOfRangeException
Thrown when either capacity is below DefaultDepthLocksCapacity, or
defaultDepthLocksCapacityexceedsmaxDepthLocksCapacity.
Fields
DefaultDepthLocksCapacity
The default initial capacity of the depth table, and the smallest capacity accepted.
public const int DefaultDepthLocksCapacity = 4
Field Value
MaxDepthLocksCapacity
The default maximum nesting depth.
public const int MaxDepthLocksCapacity = 32
Field Value
Properties
DepthsCreated
Gets the number of distinct nesting depths this instance has reached; at least 1. Diagnostic only.
public int DepthsCreated { get; }
Property Value
Methods
LockAsync(CancellationToken)
Asynchronously acquires the lock. A call nested inside a hold on the same logical flow acquires the next depth instead of deadlocking; concurrent siblings at the same depth serialize.
public ValueTask<AsyncReentrantLock.Releaser> LockAsync(CancellationToken cancellationToken = default)
Parameters
cancellationTokenCancellationTokenThe cancellation token.
Returns
- ValueTask<AsyncReentrantLock.Releaser>
A ValueTask<TResult> that completes when the lock is acquired. Dispose the returned releaser to release the lock.
Exceptions
- OperationCanceledException
Thrown when
cancellationTokenis cancelled before the lock can be acquired.- InvalidOperationException
Thrown when the call would nest deeper than the maximum depth set at construction.
LockAsync(TimeSpan, CancellationToken)
Asynchronously acquires the lock, or throws if it cannot be acquired before the timeout elapses.
public ValueTask<AsyncReentrantLock.Releaser> LockAsync(TimeSpan timeout, CancellationToken cancellationToken = default)
Parameters
timeoutTimeSpanThe maximum time to wait. Use InfiniteTimeSpan to wait indefinitely.
cancellationTokenCancellationTokenThe cancellation token used to cancel the wait.
Returns
- ValueTask<AsyncReentrantLock.Releaser>
A ValueTask<TResult> that completes when the lock is acquired. Dispose the returned releaser to release the lock.
Exceptions
- ArgumentOutOfRangeException
Thrown when
timeoutis negative and not equal to InfiniteTimeSpan.- TimeoutException
Thrown when the timeout elapses before the lock can be acquired.
- OperationCanceledException
Thrown when
cancellationTokenis cancelled before the lock can be acquired.- InvalidOperationException
Thrown when the call would nest deeper than the maximum depth set at construction.
LockLeafAsync(CancellationToken)
Asynchronously acquires the lock at the same depth as LockAsync(CancellationToken), but without recording the hold for further nesting, which makes it cheaper.
public ValueTask<AsyncReentrantLock.Releaser> LockLeafAsync(CancellationToken cancellationToken = default)
Parameters
cancellationTokenCancellationTokenThe cancellation token.
Returns
- ValueTask<AsyncReentrantLock.Releaser>
A ValueTask<TResult> that completes when the lock is acquired. Dispose the returned releaser to release the lock.
Remarks
Use it only for innermost regions that never call back into this lock: a LockAsync(CancellationToken) or LockLeafAsync(CancellationToken) call made inside the hold deadlocks, as with AsyncLock.
Exceptions
- OperationCanceledException
Thrown when
cancellationTokenis cancelled before the lock can be acquired.- InvalidOperationException
Thrown when the call would nest deeper than the maximum depth set at construction.
LockLeafAsync(TimeSpan, CancellationToken)
Asynchronously acquires the lock like LockLeafAsync(CancellationToken), or throws if it cannot be acquired before the timeout elapses.
public ValueTask<AsyncReentrantLock.Releaser> LockLeafAsync(TimeSpan timeout, CancellationToken cancellationToken = default)
Parameters
timeoutTimeSpanThe maximum time to wait. Use InfiniteTimeSpan to wait indefinitely.
cancellationTokenCancellationTokenThe cancellation token used to cancel the wait.
Returns
- ValueTask<AsyncReentrantLock.Releaser>
A ValueTask<TResult> that completes when the lock is acquired. Dispose the returned releaser to release the lock.
Remarks
Use it only for innermost regions that never call back into this lock: a LockAsync(CancellationToken) or LockLeafAsync(CancellationToken) call made inside the hold deadlocks, as with AsyncLock.
Exceptions
- ArgumentOutOfRangeException
Thrown when
timeoutis negative and not equal to InfiniteTimeSpan.- TimeoutException
Thrown when the timeout elapses before the lock can be acquired.
- OperationCanceledException
Thrown when
cancellationTokenis cancelled before the lock can be acquired.- InvalidOperationException
Thrown when the call would nest deeper than the maximum depth set at construction.