@@ -68,8 +68,14 @@ internal InnerLock(AsyncLock parent, long oldId, int oldThreadId)
6868
6969 internal async Task < IDisposable > ObtainLockAsync ( CancellationToken ct = default )
7070 {
71- while ( ! await TryEnterAsync ( ct ) )
71+ while ( true )
7272 {
73+ await _parent . _reentrancy . WaitAsync ( ct ) ;
74+ if ( InnerTryEnter ( synchronous : false ) )
75+ {
76+ break ;
77+ }
78+ _parent . _reentrancy . Release ( ) ;
7379 // We need to wait for someone to leave the lock before trying again.
7480 await _parent . _retry . WaitAsync ( ct ) ;
7581 }
@@ -86,7 +92,8 @@ internal async Task<IDisposable> ObtainLockAsync(CancellationToken ct = default)
8692 // In case of zero-timeout, don't even wait for protective lock contention
8793 if ( timeout == TimeSpan . Zero )
8894 {
89- if ( await TryEnterAsync ( timeout ) )
95+ _parent . _reentrancy . Wait ( timeout ) ;
96+ if ( InnerTryEnter ( synchronous : false ) )
9097 {
9198 // Reset the owning thread id after all await calls have finished, otherwise we
9299 // could be resumed on a different thread and set an incorrect value.
@@ -95,6 +102,7 @@ internal async Task<IDisposable> ObtainLockAsync(CancellationToken ct = default)
95102 _parent . _reentrancy . Release ( ) ;
96103 return this ;
97104 }
105+ _parent . _reentrancy . Release ( ) ;
98106 return null ;
99107 }
100108
@@ -105,7 +113,8 @@ internal async Task<IDisposable> ObtainLockAsync(CancellationToken ct = default)
105113 // We need to wait for someone to leave the lock before trying again.
106114 while ( remainder > TimeSpan . Zero )
107115 {
108- if ( await TryEnterAsync ( remainder ) )
116+ await _parent . _reentrancy . WaitAsync ( remainder ) ;
117+ if ( InnerTryEnter ( synchronous : false ) )
109118 {
110119 // Reset the owning thread id after all await calls have finished, otherwise we
111120 // could be resumed on a different thread and set an incorrect value.
@@ -114,6 +123,7 @@ internal async Task<IDisposable> ObtainLockAsync(CancellationToken ct = default)
114123 _parent . _reentrancy . Release ( ) ;
115124 return this ;
116125 }
126+ _parent . _reentrancy . Release ( ) ;
117127
118128 now = DateTimeOffset . UtcNow ;
119129 remainder -= now - last ;
@@ -135,9 +145,15 @@ internal async Task<IDisposable> ObtainLockAsync(CancellationToken ct = default)
135145 {
136146 try
137147 {
138- while ( ! await TryEnterAsync ( cancel ) )
148+ while ( true )
139149 {
150+ await _parent . _reentrancy . WaitAsync ( cancel ) ;
151+ if ( InnerTryEnter ( synchronous : false ) )
152+ {
153+ break ;
154+ }
140155 // We need to wait for someone to leave the lock before trying again.
156+ _parent . _reentrancy . Release ( ) ;
141157 await _parent . _retry . WaitAsync ( cancel ) ;
142158 }
143159 }
@@ -156,8 +172,15 @@ internal async Task<IDisposable> ObtainLockAsync(CancellationToken ct = default)
156172
157173 internal IDisposable ObtainLock ( CancellationToken cancellationToken )
158174 {
159- while ( ! TryEnter ( ) )
175+ while ( true )
160176 {
177+ _parent . _reentrancy . Wait ( cancellationToken ) ;
178+ if ( InnerTryEnter ( synchronous : true ) )
179+ {
180+ _parent . _reentrancy . Release ( ) ;
181+ break ;
182+ }
183+ _parent . _reentrancy . Release ( ) ;
161184 // We need to wait for someone to leave the lock before trying again.
162185 _parent . _retry . Wait ( cancellationToken ) ;
163186 }
@@ -169,10 +192,13 @@ internal IDisposable ObtainLock(CancellationToken cancellationToken)
169192 // In case of zero-timeout, don't even wait for protective lock contention
170193 if ( timeout == TimeSpan . Zero )
171194 {
172- if ( TryEnter ( timeout ) )
195+ _parent . _reentrancy . Wait ( timeout ) ;
196+ if ( InnerTryEnter ( synchronous : true ) )
173197 {
198+ _parent . _reentrancy . Release ( ) ;
174199 return this ;
175200 }
201+ _parent . _reentrancy . Release ( ) ;
176202 return null ;
177203 }
178204
@@ -183,10 +209,13 @@ internal IDisposable ObtainLock(CancellationToken cancellationToken)
183209 // We need to wait for someone to leave the lock before trying again.
184210 while ( remainder > TimeSpan . Zero )
185211 {
186- if ( TryEnter ( remainder ) )
212+ _parent . _reentrancy . Wait ( remainder ) ;
213+ if ( InnerTryEnter ( synchronous : true ) )
187214 {
215+ _parent . _reentrancy . Release ( ) ;
188216 return this ;
189217 }
218+ _parent . _reentrancy . Release ( ) ;
190219
191220 now = DateTimeOffset . UtcNow ;
192221 remainder -= now - last ;
@@ -204,88 +233,43 @@ internal IDisposable ObtainLock(CancellationToken cancellationToken)
204233 return null ;
205234 }
206235
207- private async Task < bool > TryEnterAsync ( CancellationToken cancel = default )
208- {
209- await _parent . _reentrancy . WaitAsync ( cancel ) ;
210- return InnerTryEnter ( ) ;
211- }
212-
213- private async Task < bool > TryEnterAsync ( TimeSpan timeout )
214- {
215- if ( ! await _parent . _reentrancy . WaitAsync ( timeout ) )
216- {
217- return false ;
218- }
219-
220- return InnerTryEnter ( ) ;
221- }
222-
223- private bool TryEnter ( )
224- {
225- _parent . _reentrancy . Wait ( ) ;
226- return InnerTryEnter ( true /* synchronous */ ) ;
227- }
228-
229- private bool TryEnter ( TimeSpan timeout )
230- {
231- if ( ! _parent . _reentrancy . Wait ( timeout ) )
232- {
233- return false ;
234- }
235- return InnerTryEnter ( true /* synchronous */ ) ;
236- }
237-
238236 private bool InnerTryEnter ( bool synchronous = false )
239237 {
240238 bool result = false ;
241- try
239+ if ( synchronous )
242240 {
243- if ( synchronous )
241+ if ( _parent . _owningThreadId == UnlockedId )
244242 {
245- if ( _parent . _owningThreadId == UnlockedId )
246- {
247- _parent . _owningThreadId = ThreadId ;
248- }
249- else if ( _parent . _owningThreadId != ThreadId )
250- {
251- return false ;
252- }
253- _parent . _owningId = AsyncLock . AsyncId ;
243+ _parent . _owningThreadId = ThreadId ;
254244 }
255- else
245+ else if ( _parent . _owningThreadId != ThreadId )
256246 {
257- if ( _parent . _owningId == UnlockedId )
258- {
259- _parent . _owningId = AsyncLock . AsyncId ;
260- }
261- else if ( _parent . _owningId != _oldId )
262- {
263- // Another thread currently owns the lock
264- return false ;
265- }
266- else
267- {
268- // Nested re-entrance
269- _parent . _owningId = AsyncId ;
270- }
247+ return false ;
271248 }
272-
273- // We can go in
274- _parent . _reentrances += 1 ;
275- result = true ;
276- return result ;
249+ _parent . _owningId = AsyncLock . AsyncId ;
277250 }
278- finally
251+ else
279252 {
280- // We can't release this in case the lock was obtained because we still need to
281- // set the owning thread id, but we may have been called asynchronously in which
282- // case we could be currently running on a different thread than the one the
283- // locking will ultimately conclude on.
284- if ( ! result || synchronous )
253+ if ( _parent . _owningId == UnlockedId )
285254 {
286- _parent . _reentrancy . Release ( ) ;
255+ _parent . _owningId = AsyncLock . AsyncId ;
256+ }
257+ else if ( _parent . _owningId != _oldId )
258+ {
259+ // Another thread currently owns the lock
260+ return false ;
261+ }
262+ else
263+ {
264+ // Nested re-entrance
265+ _parent . _owningId = AsyncId ;
287266 }
288267 }
268+
269+ // We can go in
270+ _parent . _reentrances += 1 ;
271+ result = true ;
272+ return result ;
289273 }
290274
291275 public void Dispose ( )
0 commit comments