Skip to content

Commit a37d4cc

Browse files
committed
Enable fast path in Wait/Release for SemaphoreSlim
1 parent e6d984a commit a37d4cc

File tree

1 file changed

+21
-0
lines changed

1 file changed

+21
-0
lines changed

src/libraries/System.Private.CoreLib/src/System/Threading/SemaphoreSlim.cs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -336,6 +336,17 @@ private bool WaitCore(long millisecondsTimeout, CancellationToken cancellationTo
336336
return false;
337337
}
338338

339+
// Perf: If there is no wait handle, we can try entering the semaphore without using the lock.
340+
// Otherwise, we would actually need to take the lock to avoid race conditions when calling m_waitHandle.Reset()
341+
if (m_waitHandle is null)
342+
{
343+
int currentCount = m_currentCount;
344+
if (currentCount > 0 && Interlocked.CompareExchange(ref m_currentCount, currentCount - 1, currentCount) == currentCount)
345+
{
346+
return true;
347+
}
348+
}
349+
339350
long startTime = 0;
340351
if (millisecondsTimeout != Timeout.Infinite && millisecondsTimeout > 0)
341352
{
@@ -848,6 +859,16 @@ public int Release(int releaseCount)
848859
throw new ArgumentOutOfRangeException(
849860
nameof(releaseCount), releaseCount, SR.SemaphoreSlim_Release_CountWrong);
850861
}
862+
863+
if (m_waitCount == 0 && m_waitHandle is null && m_asyncHead is null)
864+
{
865+
int currentCount = m_currentCount;
866+
if (m_maxCount - currentCount >= releaseCount && Interlocked.CompareExchange(ref m_currentCount, currentCount + releaseCount, currentCount) == currentCount)
867+
{
868+
return currentCount;
869+
}
870+
}
871+
851872
int returnCount;
852873

853874
lock (m_lockObjAndDisposed)

0 commit comments

Comments
 (0)