فهرست منبع

Implement Wait with timeout.

Gert Driesen 8 سال پیش
والد
کامیت
7e72af810c
1فایلهای تغییر یافته به همراه72 افزوده شده و 0 حذف شده
  1. 72 0
      src/Renci.SshNet/Common/SemaphoreLight.cs

+ 72 - 0
src/Renci.SshNet/Common/SemaphoreLight.cs

@@ -76,5 +76,77 @@ namespace Renci.SshNet.Common
                 Monitor.Pulse(_lock);
             }
         }
+
+        /// <summary>
+        /// Blocks the current thread until it can enter the <see cref="SemaphoreLight"/>, using a 32-bit signed
+        /// integer that specifies the timeout.
+        /// </summary>
+        /// <param name="millisecondsTimeout">The number of milliseconds to wait, or Infinite(-1) to wait indefinitely.</param>
+        /// <returns>
+        /// <c>true</c> if the current thread successfully entered the <see cref="SemaphoreLight"/>; otherwise, <c>false</c>.
+        /// </returns>
+        public bool Wait(int millisecondsTimeout)
+        {
+            if (millisecondsTimeout < -1)
+                throw new ArgumentOutOfRangeException("millisecondsTimeout", "The timeout must represent a value between -1 and Int32.MaxValue, inclusive.");
+
+            return WaitWithTimeout(millisecondsTimeout);
+        }
+
+        /// <summary>
+        /// Blocks the current thread until it can enter the <see cref="SemaphoreLight"/>, using a <see cref="TimeSpan"/>
+        /// to specify the timeout.
+        /// </summary>
+        /// <param name="timeout">A <see cref="TimeSpan"/> that represents the number of milliseconds to wait, or a <see cref="TimeSpan"/> that represents -1 milliseconds to wait indefinitely.</param>
+        /// <returns>
+        /// <c>true</c> if the current thread successfully entered the <see cref="SemaphoreLight"/>; otherwise, <c>false</c>.
+        /// </returns>
+        public bool Wait(TimeSpan timeout)
+        {
+            var timeoutInMilliseconds = timeout.TotalMilliseconds;
+            if (timeoutInMilliseconds < -1d || timeoutInMilliseconds > int.MaxValue)
+                throw new ArgumentOutOfRangeException("timeout", "The timeout must represent a value between -1 and Int32.MaxValue, inclusive.");
+
+            return WaitWithTimeout((int) timeoutInMilliseconds);
+        }
+
+        private bool WaitWithTimeout(int timeoutInMilliseconds)
+        {
+            lock (_lock)
+            {
+                if (timeoutInMilliseconds == Session.Infinite)
+                {
+                    while (_currentCount < 1)
+                        Monitor.Wait(_lock);
+                }
+                else
+                {
+                    if (_currentCount < 1)
+                    {
+                        var remainingTimeInMilliseconds = timeoutInMilliseconds;
+                        var startTicks = Environment.TickCount;
+
+                        while (_currentCount < 1)
+                        {
+                            if (!Monitor.Wait(_lock, remainingTimeInMilliseconds))
+                            {
+                                return false;
+                            }
+
+                            var elapsed = Environment.TickCount - startTicks;
+                            remainingTimeInMilliseconds -= elapsed;
+                            if (remainingTimeInMilliseconds < 0)
+                                return false;
+                        }
+                    }
+                }
+
+                _currentCount--;
+
+                Monitor.Pulse(_lock);
+
+                return true;
+            }
+        }
     }
 }