From 21c89ff541d210d4bef04e074c1be962d3104fbc Mon Sep 17 00:00:00 2001 From: Ben Adams Date: Wed, 24 Aug 2016 20:02:29 +0100 Subject: [PATCH] SemaphoreSlim, fail faster for timeout 0 --- .../src/System/Threading/SemaphoreSlim.cs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/mscorlib/src/System/Threading/SemaphoreSlim.cs b/src/mscorlib/src/System/Threading/SemaphoreSlim.cs index 0bc175b020a6..c2dcbb3451f6 100644 --- a/src/mscorlib/src/System/Threading/SemaphoreSlim.cs +++ b/src/mscorlib/src/System/Threading/SemaphoreSlim.cs @@ -76,6 +76,9 @@ public class SemaphoreSlim : IDisposable // A pre-completed task with Result==true private readonly static Task s_trueTask = new Task(false, true, (TaskCreationOptions)InternalTaskOptions.DoNotDispose, default(CancellationToken)); + // A pre-completed task with Result==false + private readonly static Task s_falseTask = + new Task(false, false, (TaskCreationOptions)InternalTaskOptions.DoNotDispose, default(CancellationToken)); // No maximum constant private const int NO_MAXIMUM = Int32.MaxValue; @@ -320,6 +323,13 @@ public bool Wait(int millisecondsTimeout, CancellationToken cancellationToken) cancellationToken.ThrowIfCancellationRequested(); + // Perf: Check the stack timeout parameter before checking the volatile count + if (millisecondsTimeout == 0 && m_currentCount == 0) + { + // Pessimistic fail fast, check volatile count outside lock (only when timeout is zero!) + return false; + } + uint startTime = 0; if (millisecondsTimeout != Timeout.Infinite && millisecondsTimeout > 0) { @@ -617,6 +627,11 @@ public Task WaitAsync(int millisecondsTimeout, CancellationToken cancellat --m_currentCount; if (m_waitHandle != null && m_currentCount == 0) m_waitHandle.Reset(); return s_trueTask; + } + else if (millisecondsTimeout == 0) + { + // No counts, if timeout is zero fail fast + return s_falseTask; } // If there aren't, create and return a task to the caller. // The task will be completed either when they've successfully acquired