22// https://github.com/usercode/AsyncKeyLock
33// MIT License
44
5+ using System . Runtime . InteropServices ;
6+
57namespace AsyncKeyLock ;
68
79/// <summary>
@@ -15,44 +17,46 @@ public AsyncLock(int maxPoolSize = 64)
1517 _pool = new Pool < AsyncLock > ( maxPoolSize ) ;
1618 }
1719
18- private readonly Dictionary < TKey , AsyncLock > _locks = new ( ) ;
20+ private readonly Dictionary < TKey , AsyncLock > _activeLocks = new ( ) ;
1921 private readonly Pool < AsyncLock > _pool ;
22+ private readonly Lock _lock = new Lock ( ) ;
2023
2124 /// <summary>
2225 /// GetAsyncLock
2326 /// </summary>
2427 private AsyncLock GetAsyncLock ( TKey key )
2528 {
26- if ( _locks . TryGetValue ( key , out AsyncLock ? asyncLock ) == false )
29+ ref AsyncLock ? dictionaryValue = ref CollectionsMarshal . GetValueRefOrAddDefault ( _activeLocks , key , out bool exists ) ;
30+
31+ if ( exists )
2732 {
28- //create new AsyncLock
29- _pool . GetOrCreate ( out asyncLock ,
30- ( ) =>
31- {
32- AsyncLock a = new AsyncLock ( _locks ) ;
33- a . Released += x =>
34- {
35- _locks . Remove ( key ) ;
33+ return dictionaryValue ! ;
34+ }
3635
37- //add idle AsynLock to pool
38- _pool . Add ( x ) ;
39- } ;
36+ _pool . GetOrCreate ( out dictionaryValue ,
37+ ( ) =>
38+ {
39+ AsyncLock a = new AsyncLock ( _lock ) ;
40+ a . Released += x =>
41+ {
42+ _activeLocks . Remove ( key ) ;
4043
41- return a ;
42- } ) ;
44+ //add idle AsynLock to pool
45+ _pool . Add ( x ) ;
46+ } ;
4347
44- _locks . Add ( key , asyncLock ) ;
45- }
48+ return a ;
49+ } ) ;
4650
47- return asyncLock ;
51+ return dictionaryValue ;
4852 }
4953
5054 /// <summary>
5155 /// ReaderLockAsync
5256 /// </summary>
5357 public Task < ReaderReleaser > ReaderLockAsync ( TKey key , CancellationToken cancellation = default )
5458 {
55- lock ( _locks )
59+ lock ( _lock )
5660 {
5761 return GetAsyncLock ( key ) . ReaderLockAsync ( cancellation ) ;
5862 }
@@ -63,7 +67,7 @@ public Task<ReaderReleaser> ReaderLockAsync(TKey key, CancellationToken cancella
6367 /// </summary>
6468 public Task < WriterReleaser > WriterLockAsync ( TKey key , CancellationToken cancellation = default )
6569 {
66- lock ( _locks )
70+ lock ( _lock )
6771 {
6872 return GetAsyncLock ( key ) . WriterLockAsync ( cancellation ) ;
6973 }
0 commit comments