@@ -60,14 +60,6 @@ private sealed class AsyncLazyImpl<TData> : AsyncLazy<T>
6060 /// </summary>
6161 private Task < T > ? _cachedResult ;
6262
63- /// <summary>
64- /// Mutex used to protect reading and writing to all mutable objects and fields. Traces
65- /// indicate that there's negligible contention on this lock, hence we can save some memory
66- /// by using a single lock for all AsyncLazy instances. Only trivial and non-reentrant work
67- /// should be done while holding the lock.
68- /// </summary>
69- private static readonly NonReentrantLock s_gate = new ( useThisInstanceForSynchronization : true ) ;
70-
7163 /// <summary>
7264 /// The hash set of all currently outstanding asynchronous requests. Null if there are no requests,
7365 /// and will never be empty.
@@ -118,6 +110,13 @@ private AsyncLazyImpl(
118110 _data = data ;
119111 }
120112
113+ /// <summary>
114+ /// Mutex used to protect reading and writing to all mutable objects and fields. Only trivial and non-reentrant
115+ /// work should be done while holding the lock, as cancellation is not supported while waiting to acquire this
116+ /// lock.
117+ /// </summary>
118+ private object SyncObject => this ;
119+
121120 public static AsyncLazy < T > CreateImpl ( T value )
122121 => new AsyncLazyImpl < VoidResult > ( value ) ;
123122
@@ -136,7 +135,10 @@ public static AsyncLazy<T> CreateImpl(
136135 /// </summary>
137136 private WaitThatValidatesInvariants TakeLock ( CancellationToken cancellationToken )
138137 {
139- s_gate . Wait ( cancellationToken ) ;
138+ Contract . ThrowIfTrue ( Monitor . IsEntered ( SyncObject ) ) ;
139+
140+ cancellationToken . ThrowIfCancellationRequested ( ) ;
141+ Monitor . Enter ( SyncObject ) ;
140142 AssertInvariants_NoLock ( ) ;
141143 return new WaitThatValidatesInvariants ( this ) ;
142144 }
@@ -146,7 +148,8 @@ private readonly struct WaitThatValidatesInvariants(AsyncLazyImpl<TData> asyncLa
146148 public void Dispose ( )
147149 {
148150 asyncLazy . AssertInvariants_NoLock ( ) ;
149- s_gate . Release ( ) ;
151+ Contract . ThrowIfFalse ( Monitor . IsEntered ( asyncLazy . SyncObject ) ) ;
152+ Monitor . Exit ( asyncLazy . SyncObject ) ;
150153 }
151154 }
152155
0 commit comments