Skip to content

Commit 8e56c49

Browse files
committed
Use Monitor instead of NonReentrantLock for AsyncLazy
1 parent d9c433e commit 8e56c49

File tree

1 file changed

+13
-10
lines changed
  • src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Utilities

1 file changed

+13
-10
lines changed

src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Utilities/AsyncLazy`1.cs

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)