@@ -10,7 +10,8 @@ namespace AsyncToSyncCodeRoundtripSynchroniserMonitor
1010{
1111 public class AsyncLockQueueDictionary
1212 {
13- private readonly object DictionaryAccessMutex = new object ( ) ;
13+ //private readonly object DictionaryAccessMutex = new object();
14+ private readonly SemaphoreSlim DictionaryAccessMutex = new SemaphoreSlim ( 1 , 1 ) ;
1415 private readonly Dictionary < string , AsyncLockWithCount > LockQueueDictionary = new Dictionary < string , AsyncLockWithCount > ( ) ;
1516
1617 public sealed class AsyncLockWithCount
@@ -25,7 +26,7 @@ public AsyncLockWithCount()
2526 }
2627 }
2728
28- public sealed class LockDictReleaser : IDisposable
29+ public sealed class LockDictReleaser : IDisposable //TODO: implement IAsyncDisposable in .NET 5.0
2930 {
3031 private readonly string Name ;
3132 private readonly AsyncLockWithCount LockEntry ;
@@ -50,7 +51,9 @@ private void ReleaseLock(string name, AsyncLockWithCount lockEntry, IDisposable
5051 {
5152 lockHandle . Dispose ( ) ;
5253
53- lock ( DictionaryAccessMutex )
54+ //lock (DictionaryAccessMutex)
55+ DictionaryAccessMutex . Wait ( ) ;
56+ try
5457 {
5558 lockEntry . WaiterCount -- ;
5659 Debug . Assert ( lockEntry . WaiterCount >= 0 ) ;
@@ -60,29 +63,39 @@ private void ReleaseLock(string name, AsyncLockWithCount lockEntry, IDisposable
6063 LockQueueDictionary . Remove ( name ) ;
6164 }
6265 }
66+ finally
67+ {
68+ DictionaryAccessMutex . Release ( ) ;
69+ }
6370 }
6471
6572 public async Task < LockDictReleaser > LockAsync ( string name , CancellationToken cancellationToken = default ( CancellationToken ) )
6673 {
6774 AsyncLockWithCount lockEntry ;
68- lock ( DictionaryAccessMutex )
75+ //lock (DictionaryAccessMutex)
76+ await DictionaryAccessMutex . WaitAsync ( cancellationToken ) ;
77+ try
6978 {
7079 if ( ! LockQueueDictionary . TryGetValue ( name , out lockEntry ) )
7180 {
72- lockEntry = new AsyncLockWithCount ( ) ;
81+ lockEntry = new AsyncLockWithCount ( ) ;
7382 LockQueueDictionary . Add ( name , lockEntry ) ;
7483 }
7584 else
7685 {
7786 lockEntry . WaiterCount ++ ; //NB! must be done inside the lock and BEFORE waiting for the lock
7887 }
7988 }
89+ finally
90+ {
91+ DictionaryAccessMutex . Release ( ) ;
92+ }
8093
8194 var lockHandle = await lockEntry . LockEntry . LockAsync ( cancellationToken ) ;
8295 return new LockDictReleaser ( name , lockEntry , lockHandle , this ) ;
8396 }
8497
85- public sealed class MultiLockDictReleaser : IDisposable
98+ public sealed class MultiLockDictReleaser : IDisposable //TODO: implement IAsyncDisposable in .NET 5.0
8699 {
87100 private readonly LockDictReleaser [ ] Releasers ;
88101
@@ -111,7 +124,7 @@ public void Dispose()
111124
112125 //NB! in order to avoid deadlocks, always take the locks in deterministic order
113126 names . Sort ( StringComparer . InvariantCultureIgnoreCase ) ;
114-
127+
115128 var releaser1 = await this . LockAsync ( names [ 0 ] , cancellationToken ) ;
116129 var releaser2 = name1 != name2 ? await this . LockAsync ( names [ 1 ] , cancellationToken ) : null ;
117130
0 commit comments