SemaphoreSlim, fail faster for timeout 0
authorBen Adams <thundercat@illyriad.co.uk>
Wed, 24 Aug 2016 19:02:29 +0000 (20:02 +0100)
committerBen Adams <thundercat@illyriad.co.uk>
Thu, 25 Aug 2016 08:29:22 +0000 (09:29 +0100)
src/mscorlib/src/System/Threading/SemaphoreSlim.cs

index 0bc175b..c2dcbb3 100644 (file)
@@ -76,6 +76,9 @@ namespace System.Threading
         // A pre-completed task with Result==true
         private readonly static Task<bool> s_trueTask =
             new Task<bool>(false, true, (TaskCreationOptions)InternalTaskOptions.DoNotDispose, default(CancellationToken));
+        // A pre-completed task with Result==false
+        private readonly static Task<bool> s_falseTask =
+            new Task<bool>(false, false, (TaskCreationOptions)InternalTaskOptions.DoNotDispose, default(CancellationToken));
 
         // No maximum constant
         private const int NO_MAXIMUM = Int32.MaxValue;
@@ -320,6 +323,13 @@ namespace System.Threading
 
             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)
             {
@@ -618,6 +628,11 @@ namespace System.Threading
                     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
                     // the semaphore or when the timeout expired or cancellation was requested.