using System; using System.Threading; namespace Renci.SshNet.Common { /// /// Light implementation of SemaphoreSlim. /// public class SemaphoreLight { private readonly object _lock = new object(); private int _currentCount; /// /// Initializes a new instance of the class, specifying /// the initial number of requests that can be granted concurrently. /// /// The initial number of requests for the semaphore that can be granted concurrently. /// is a negative number. public SemaphoreLight(int initialCount) { if (initialCount < 0 ) throw new ArgumentOutOfRangeException("initialCount", "The value cannot be negative."); _currentCount = initialCount; } /// /// Gets the current count of the . /// public int CurrentCount { get { return _currentCount; } } /// /// Exits the once. /// /// The previous count of the . public int Release() { return Release(1); } /// /// Exits the a specified number of times. /// /// The number of times to exit the semaphore. /// The previous count of the . public int Release(int releaseCount) { var oldCount = _currentCount; lock (_lock) { _currentCount += releaseCount; Monitor.Pulse(_lock); } return oldCount; } /// /// Blocks the current thread until it can enter the . /// public void Wait() { lock (_lock) { while (_currentCount < 1) { Monitor.Wait(_lock); } _currentCount--; Monitor.Pulse(_lock); } } /// /// Blocks the current thread until it can either enter the , /// or until the specified timeout has expired. /// /// /// 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."); lock (_lock) { if (timeoutInMilliseconds == -1) { while (_currentCount < 1) Monitor.Wait(_lock); } else { if (_currentCount < 1) { var remainingTimeInMilliseconds = (int) 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; } } } }