diff --git a/CHANGELOG.md b/CHANGELOG.md
index f7a801acc..6d1561ffa 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,10 @@
Release Notes
====
+# 06-07-2024
+DotNext.Metaprogramming 5.5.0
+* Fixed [240](https://github.com/dotnet/dotNext/issues/240)
+
# 05-30-2024
DotNext.Metaprogramming 5.4.1
* Smallish performance improvements for all synchronization primitives
diff --git a/README.md b/README.md
index 9497152f7..8b81b6a2f 100644
--- a/README.md
+++ b/README.md
@@ -44,16 +44,10 @@ All these things are implemented in 100% managed code on top of existing .NET AP
* [NuGet Packages](https://www.nuget.org/profiles/rvsakno)
# What's new
-Release Date: 05-30-2024
+Release Date: 06-07-2024
-DotNext.Metaprogramming 5.4.1
-* Smallish performance improvements for all synchronization primitives
-
-DotNext.Net.Cluster 5.6.0
-* Added support of custom data to be passed to `PersistentState.ApplyAsync` method through WAL processing pipeline
-
-DotNext.AspNetCore.Cluster 5.6.0
-* Updated dependencies
+DotNext.Metaprogramming 5.5.0
+* Fixed [240](https://github.com/dotnet/dotNext/issues/240)
Changelog for previous versions located [here](./CHANGELOG.md).
diff --git a/src/DotNext.Threading/DotNext.Threading.csproj b/src/DotNext.Threading/DotNext.Threading.csproj
index 49c3dfe02..3f0b4703d 100644
--- a/src/DotNext.Threading/DotNext.Threading.csproj
+++ b/src/DotNext.Threading/DotNext.Threading.csproj
@@ -7,7 +7,7 @@
true
true
nullablePublicOnly
- 5.4.1
+ 5.5.0
.NET Foundation and Contributors
.NEXT Family of Libraries
diff --git a/src/DotNext.Threading/Threading/AsyncLock.cs b/src/DotNext.Threading/Threading/AsyncLock.cs
index 5ba4285fe..93949ac76 100644
--- a/src/DotNext.Threading/Threading/AsyncLock.cs
+++ b/src/DotNext.Threading/Threading/AsyncLock.cs
@@ -256,7 +256,9 @@ public readonly async ValueTask AcquireAsync(TimeSpan timeout, Cancellat
task = As(lockedObject).UpgradeToWriteLockAsync(timeout, token);
break;
case Type.Semaphore:
- task = CheckOnTimeoutAsync(As(lockedObject).WaitAsync(timeout, token));
+ task = timeout == InfiniteTimeSpan
+ ? new(As(lockedObject).WaitAsync(token))
+ : CheckOnTimeoutAsync(As(lockedObject).WaitAsync(timeout, token));
break;
case Type.Strong:
task = As(lockedObject).AcquireAsync(true, timeout, token);
diff --git a/src/DotNext.Threading/Threading/AsyncLockAcquisition.cs b/src/DotNext.Threading/Threading/AsyncLockAcquisition.cs
index 73d16a873..3857bea9f 100644
--- a/src/DotNext.Threading/Threading/AsyncLockAcquisition.cs
+++ b/src/DotNext.Threading/Threading/AsyncLockAcquisition.cs
@@ -69,8 +69,9 @@ private static AsyncLock GetExclusiveLock(this T obj)
/// The interval to wait for the lock.
/// The acquired lock holder.
/// The lock cannot be acquired during the specified amount of time.
- public static ValueTask AcquireLockAsync(this T obj, TimeSpan timeout)
- where T : class => obj.GetExclusiveLock().AcquireAsync(timeout);
+ [Obsolete("Use AcquireLockAsync(T, TimeSpan, CancellationToken) overload instead.", error: true)]
+ public static ValueTask AcquireLockAsync(T obj, TimeSpan timeout)
+ where T : class => AcquireLockAsync(obj, timeout, CancellationToken.None);
///
/// Acquires exclusive lock associated with the given object.
@@ -79,9 +80,23 @@ private static AsyncLock GetExclusiveLock(this T obj)
/// The object to be locked.
/// The token that can be used to abort acquisition operation.
/// The acquired lock holder.
- public static ValueTask AcquireLockAsync(this T obj, CancellationToken token)
+ /// The operation has been canceled.
+ public static ValueTask AcquireLockAsync(this T obj, CancellationToken token = default)
where T : class => obj.GetExclusiveLock().AcquireAsync(token);
+ ///
+ /// Acquires exclusive lock associated with the given object.
+ ///
+ /// The type of the object to be locked.
+ /// The object to be locked.
+ /// The interval to wait for the lock.
+ /// The token that can be used to abort acquisition operation.
+ /// The acquired lock holder.
+ /// The operation has been canceled.
+ /// The lock cannot be acquired during the specified amount of time.
+ public static ValueTask AcquireLockAsync(this T obj, TimeSpan timeout, CancellationToken token = default)
+ where T : class => obj.GetExclusiveLock().AcquireAsync(timeout, token);
+
///
/// Acquires reader lock associated with the given object.
///
@@ -90,8 +105,9 @@ private static AsyncLock GetExclusiveLock(this T obj)
/// The interval to wait for the lock.
/// The acquired lock holder.
/// The lock cannot be acquired during the specified amount of time.
- public static ValueTask AcquireReadLockAsync(this T obj, TimeSpan timeout)
- where T : class => AsyncLock.ReadLock(obj.GetReaderWriterLock()).AcquireAsync(timeout);
+ [Obsolete("Use AcquireReadLockAsync(T, TimeSpan, CancellationToken) overload instead.", error: true)]
+ public static ValueTask AcquireReadLockAsync(T obj, TimeSpan timeout)
+ where T : class => AcquireReadLockAsync(obj, timeout, CancellationToken.None);
///
/// Acquires reader lock associated with the given object.
@@ -100,9 +116,23 @@ private static AsyncLock GetExclusiveLock(this T obj)
/// The object to be locked.
/// The token that can be used to abort acquisition operation.
/// The acquired lock holder.
- public static ValueTask AcquireReadLockAsync(this T obj, CancellationToken token)
+ /// The operation has been canceled.
+ public static ValueTask AcquireReadLockAsync(this T obj, CancellationToken token = default)
where T : class => AsyncLock.ReadLock(obj.GetReaderWriterLock()).AcquireAsync(token);
+ ///
+ /// Acquires reader lock associated with the given object.
+ ///
+ /// The type of the object to be locked.
+ /// The object to be locked.
+ /// The interval to wait for the lock.
+ /// The token that can be used to abort acquisition operation.
+ /// The acquired lock holder.
+ /// The lock cannot be acquired during the specified amount of time.
+ /// The operation has been canceled.
+ public static ValueTask AcquireReadLockAsync(this T obj, TimeSpan timeout, CancellationToken token = default)
+ where T : class => AsyncLock.ReadLock(obj.GetReaderWriterLock()).AcquireAsync(timeout, token);
+
///
/// Acquires writer lock associated with the given object.
///
@@ -111,8 +141,9 @@ private static AsyncLock GetExclusiveLock(this T obj)
/// The interval to wait for the lock.
/// The acquired lock holder.
/// The lock cannot be acquired during the specified amount of time.
- public static ValueTask AcquireWriteLockAsync(this T obj, TimeSpan timeout)
- where T : class => AsyncLock.WriteLock(obj.GetReaderWriterLock()).AcquireAsync(timeout);
+ [Obsolete("Use AcquireWriteLockAsync(T, TimeSpan, CancellationToken) overload instead.", error: true)]
+ public static ValueTask AcquireWriteLockAsync(T obj, TimeSpan timeout)
+ where T : class => AcquireWriteLockAsync(obj, timeout, CancellationToken.None);
///
/// Acquires reader lock associated with the given object.
@@ -121,6 +152,19 @@ private static AsyncLock GetExclusiveLock(this T obj)
/// The object to be locked.
/// The token that can be used to abort acquisition operation.
/// The acquired lock holder.
- public static ValueTask AcquireWriteLockAsync(this T obj, CancellationToken token)
+ /// The operation has been canceled.
+ public static ValueTask AcquireWriteLockAsync(this T obj, CancellationToken token = default)
where T : class => AsyncLock.WriteLock(obj.GetReaderWriterLock()).AcquireAsync(token);
+
+ ///
+ /// Acquires reader lock associated with the given object.
+ ///
+ /// The type of the object to be locked.
+ /// The object to be locked.
+ /// The interval to wait for the lock.
+ /// The token that can be used to abort acquisition operation.
+ /// The acquired lock holder.
+ /// The operation has been canceled.
+ public static ValueTask AcquireWriteLockAsync(this T obj, TimeSpan timeout, CancellationToken token = default)
+ where T : class => AsyncLock.WriteLock(obj.GetReaderWriterLock()).AcquireAsync(timeout, token);
}
\ No newline at end of file