mirror of
https://github.com/sshnet/SSH.NET.git
synced 2026-09-10 09:15:47 +00:00
Replace SemaphoreLight with SemaphoreSlim (#1265)
This paves the way for asynchronous synchronisation via WaitAsync (and eliminates a timing test which sometimes fails in CI) Co-authored-by: Wojciech Nagórski <wojtpl2@gmail.com>
This commit is contained in:
@@ -285,7 +285,7 @@ namespace Renci.SshNet.Channels
|
||||
/// Gets the session semaphore to control number of session channels.
|
||||
/// </summary>
|
||||
/// <value>The session semaphore.</value>
|
||||
protected SemaphoreLight SessionSemaphore
|
||||
protected SemaphoreSlim SessionSemaphore
|
||||
{
|
||||
get { return _session.SessionSemaphore; }
|
||||
}
|
||||
|
||||
@@ -1,244 +0,0 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
|
||||
namespace Renci.SshNet.Common
|
||||
{
|
||||
/// <summary>
|
||||
/// Light implementation of SemaphoreSlim.
|
||||
/// </summary>
|
||||
public sealed class SemaphoreLight : IDisposable
|
||||
{
|
||||
private readonly object _lock = new object();
|
||||
private ManualResetEvent _waitHandle;
|
||||
|
||||
private int _currentCount;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="SemaphoreLight"/> class, specifying the initial number of requests that can
|
||||
/// be granted concurrently.
|
||||
/// </summary>
|
||||
/// <param name="initialCount">The initial number of requests for the semaphore that can be granted concurrently.</param>
|
||||
/// <exception cref="ArgumentOutOfRangeException"><paramref name="initialCount"/> is a negative number.</exception>
|
||||
public SemaphoreLight(int initialCount)
|
||||
{
|
||||
if (initialCount < 0)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(initialCount), "The value cannot be negative.");
|
||||
}
|
||||
|
||||
_currentCount = initialCount;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current count of the <see cref="SemaphoreLight"/>.
|
||||
/// </summary>
|
||||
public int CurrentCount
|
||||
{
|
||||
get { return _currentCount; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a <see cref="WaitHandle"/> that can be used to wait on the semaphore.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="WaitHandle"/> that can be used to wait on the semaphore.
|
||||
/// </value>
|
||||
/// <remarks>
|
||||
/// A successful wait on the <see cref="AvailableWaitHandle"/> does not imply a successful
|
||||
/// wait on the <see cref="SemaphoreLight"/> itself. It should be followed by a true wait
|
||||
/// on the semaphore.
|
||||
/// </remarks>
|
||||
public WaitHandle AvailableWaitHandle
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_waitHandle is null)
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
_waitHandle ??= new ManualResetEvent(_currentCount > 0);
|
||||
}
|
||||
}
|
||||
|
||||
return _waitHandle;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Exits the <see cref="SemaphoreLight"/> once.
|
||||
/// </summary>
|
||||
/// <returns>The previous count of the <see cref="SemaphoreLight"/>.</returns>
|
||||
public int Release()
|
||||
{
|
||||
return Release(1);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Exits the <see cref="SemaphoreLight"/> a specified number of times.
|
||||
/// </summary>
|
||||
/// <param name="releaseCount">The number of times to exit the semaphore.</param>
|
||||
/// <returns>
|
||||
/// The previous count of the <see cref="SemaphoreLight"/>.
|
||||
/// </returns>
|
||||
public int Release(int releaseCount)
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
var oldCount = _currentCount;
|
||||
|
||||
_currentCount += releaseCount;
|
||||
|
||||
// signal waithandle when the original semaphore count was zero
|
||||
if (_waitHandle != null && oldCount == 0)
|
||||
{
|
||||
_ = _waitHandle.Set();
|
||||
}
|
||||
|
||||
Monitor.PulseAll(_lock);
|
||||
|
||||
return oldCount;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Blocks the current thread until it can enter the <see cref="SemaphoreLight"/>.
|
||||
/// </summary>
|
||||
public void Wait()
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
while (_currentCount < 1)
|
||||
{
|
||||
_ = Monitor.Wait(_lock);
|
||||
}
|
||||
|
||||
_currentCount--;
|
||||
|
||||
// unsignal waithandle when the semaphore count reaches zero
|
||||
if (_waitHandle != null && _currentCount == 0)
|
||||
{
|
||||
_ = _waitHandle.Reset();
|
||||
}
|
||||
|
||||
Monitor.PulseAll(_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>
|
||||
/// <see langword="true"/> if the current thread successfully entered the <see cref="SemaphoreLight"/>; otherwise, <see langword="false"/>.
|
||||
/// </returns>
|
||||
public bool Wait(int millisecondsTimeout)
|
||||
{
|
||||
if (millisecondsTimeout < -1)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(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>
|
||||
/// <see langword="true"/> if the current thread successfully entered the <see cref="SemaphoreLight"/>; otherwise, <see langword="false"/>.
|
||||
/// </returns>
|
||||
public bool Wait(TimeSpan timeout)
|
||||
{
|
||||
var timeoutInMilliseconds = timeout.TotalMilliseconds;
|
||||
if (timeoutInMilliseconds is < -1d or > int.MaxValue)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(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)
|
||||
{
|
||||
if (timeoutInMilliseconds > 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
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--;
|
||||
|
||||
// unsignal waithandle when the semaphore count is zero
|
||||
if (_waitHandle != null && _currentCount == 0)
|
||||
{
|
||||
_ = _waitHandle.Reset();
|
||||
}
|
||||
|
||||
Monitor.PulseAll(_lock);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(disposing: true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Releases unmanaged and - optionally - managed resources.
|
||||
/// </summary>
|
||||
/// <param name="disposing"><see langword="true"/> to release both managed and unmanaged resources; <see langword="false"/> to release only unmanaged resources.</param>
|
||||
private void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
var waitHandle = _waitHandle;
|
||||
if (waitHandle is not null)
|
||||
{
|
||||
waitHandle.Dispose();
|
||||
_waitHandle = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -36,7 +36,7 @@ namespace Renci.SshNet
|
||||
/// <value>
|
||||
/// The session semaphore.
|
||||
/// </value>
|
||||
SemaphoreLight SessionSemaphore { get; }
|
||||
SemaphoreSlim SessionSemaphore { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a <see cref="WaitHandle"/> that can be used to wait for the message listener loop to complete.
|
||||
|
||||
@@ -87,7 +87,7 @@ namespace Renci.SshNet
|
||||
/// <remarks>
|
||||
/// Some server may restrict number to prevent authentication attacks.
|
||||
/// </remarks>
|
||||
private static readonly SemaphoreLight AuthenticationConnection = new SemaphoreLight(3);
|
||||
private static readonly SemaphoreSlim AuthenticationConnection = new SemaphoreSlim(3);
|
||||
|
||||
/// <summary>
|
||||
/// Holds the factory to use for creating new services.
|
||||
@@ -196,7 +196,7 @@ namespace Renci.SshNet
|
||||
|
||||
private Compressor _clientCompression;
|
||||
|
||||
private SemaphoreLight _sessionSemaphore;
|
||||
private SemaphoreSlim _sessionSemaphore;
|
||||
|
||||
private bool _isDisconnectMessageSent;
|
||||
|
||||
@@ -213,7 +213,7 @@ namespace Renci.SshNet
|
||||
/// <value>
|
||||
/// The session semaphore.
|
||||
/// </value>
|
||||
public SemaphoreLight SessionSemaphore
|
||||
public SemaphoreSlim SessionSemaphore
|
||||
{
|
||||
get
|
||||
{
|
||||
@@ -221,7 +221,7 @@ namespace Renci.SshNet
|
||||
{
|
||||
lock (_connectAndLazySemaphoreInitLock)
|
||||
{
|
||||
_sessionSemaphore ??= new SemaphoreLight(ConnectionInfo.MaxSessions);
|
||||
_sessionSemaphore ??= new SemaphoreSlim(ConnectionInfo.MaxSessions);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ namespace Renci.SshNet.Sftp
|
||||
private readonly byte[] _handle;
|
||||
private readonly ISftpSession _sftpSession;
|
||||
private readonly uint _chunkSize;
|
||||
private readonly SemaphoreLight _semaphore;
|
||||
private readonly SemaphoreSlim _semaphore;
|
||||
private readonly object _readLock;
|
||||
private readonly ManualResetEvent _disposingWaitHandle;
|
||||
private readonly ManualResetEvent _readAheadCompleted;
|
||||
@@ -62,7 +62,7 @@ namespace Renci.SshNet.Sftp
|
||||
_sftpSession = sftpSession;
|
||||
_chunkSize = chunkSize;
|
||||
_fileSize = fileSize;
|
||||
_semaphore = new SemaphoreLight(maxPendingReads);
|
||||
_semaphore = new SemaphoreSlim(maxPendingReads);
|
||||
_queue = new Dictionary<int, BufferedRead>(maxPendingReads);
|
||||
_readLock = new object();
|
||||
_readAheadCompleted = new ManualResetEvent(initialState: false);
|
||||
|
||||
@@ -23,7 +23,7 @@ namespace Renci.SshNet.Tests.Classes.Channels
|
||||
private uint _remotePacketSize;
|
||||
private uint _remoteChannelNumber;
|
||||
private TimeSpan _channelCloseTimeout;
|
||||
private SemaphoreLight _sessionSemaphore;
|
||||
private SemaphoreSlim _sessionSemaphore;
|
||||
private IList<ChannelEventArgs> _channelClosedRegister;
|
||||
private List<ExceptionEventArgs> _channelExceptionRegister;
|
||||
|
||||
@@ -38,7 +38,7 @@ namespace Renci.SshNet.Tests.Classes.Channels
|
||||
_remoteWindowSize = (uint)random.Next(0, int.MaxValue);
|
||||
_remotePacketSize = (uint)random.Next(100, 200);
|
||||
_channelCloseTimeout = TimeSpan.FromSeconds(random.Next(10, 20));
|
||||
_sessionSemaphore = new SemaphoreLight(1);
|
||||
_sessionSemaphore = new SemaphoreSlim(1);
|
||||
_channelClosedRegister = new List<ChannelEventArgs>();
|
||||
_channelExceptionRegister = new List<ExceptionEventArgs>();
|
||||
}
|
||||
|
||||
+2
-2
@@ -24,7 +24,7 @@ namespace Renci.SshNet.Tests.Classes.Channels
|
||||
private List<ExceptionEventArgs> _channelExceptionRegister;
|
||||
private ChannelSession _channel;
|
||||
private MockSequence _sequence;
|
||||
private SemaphoreLight _sessionSemaphore;
|
||||
private SemaphoreSlim _sessionSemaphore;
|
||||
private int _initialSessionSemaphoreCount;
|
||||
|
||||
protected override void SetupData()
|
||||
@@ -41,7 +41,7 @@ namespace Renci.SshNet.Tests.Classes.Channels
|
||||
_channelClosedRegister = new List<ChannelEventArgs>();
|
||||
_channelExceptionRegister = new List<ExceptionEventArgs>();
|
||||
_initialSessionSemaphoreCount = random.Next(10, 20);
|
||||
_sessionSemaphore = new SemaphoreLight(_initialSessionSemaphoreCount);
|
||||
_sessionSemaphore = new SemaphoreSlim(_initialSessionSemaphoreCount);
|
||||
}
|
||||
|
||||
protected override void SetupMocks()
|
||||
|
||||
+3
-3
@@ -22,7 +22,7 @@ namespace Renci.SshNet.Tests.Classes.Channels
|
||||
private List<ExceptionEventArgs> _channelExceptionRegister;
|
||||
private ChannelSession _channel;
|
||||
private MockSequence _sequence;
|
||||
private SemaphoreLight _sessionSemaphore;
|
||||
private SemaphoreSlim _sessionSemaphore;
|
||||
private int _initialSessionSemaphoreCount;
|
||||
|
||||
protected override void SetupData()
|
||||
@@ -38,7 +38,7 @@ namespace Renci.SshNet.Tests.Classes.Channels
|
||||
_channelClosedRegister = new List<ChannelEventArgs>();
|
||||
_channelExceptionRegister = new List<ExceptionEventArgs>();
|
||||
_initialSessionSemaphoreCount = random.Next(10, 20);
|
||||
_sessionSemaphore = new SemaphoreLight(_initialSessionSemaphoreCount);
|
||||
_sessionSemaphore = new SemaphoreSlim(_initialSessionSemaphoreCount);
|
||||
}
|
||||
|
||||
protected override void SetupMocks()
|
||||
@@ -126,4 +126,4 @@ namespace Renci.SshNet.Tests.Classes.Channels
|
||||
Assert.IsFalse(_channel.IsOpen);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+3
-3
@@ -23,7 +23,7 @@ namespace Renci.SshNet.Tests.Classes.Channels
|
||||
private IList<ChannelEventArgs> _channelClosedRegister;
|
||||
private List<ExceptionEventArgs> _channelExceptionRegister;
|
||||
private ChannelSession _channel;
|
||||
private SemaphoreLight _sessionSemaphore;
|
||||
private SemaphoreSlim _sessionSemaphore;
|
||||
private int _initialSessionSemaphoreCount;
|
||||
|
||||
protected override void SetupData()
|
||||
@@ -40,7 +40,7 @@ namespace Renci.SshNet.Tests.Classes.Channels
|
||||
_channelClosedRegister = new List<ChannelEventArgs>();
|
||||
_channelExceptionRegister = new List<ExceptionEventArgs>();
|
||||
_initialSessionSemaphoreCount = random.Next(10, 20);
|
||||
_sessionSemaphore = new SemaphoreLight(_initialSessionSemaphoreCount);
|
||||
_sessionSemaphore = new SemaphoreSlim(_initialSessionSemaphoreCount);
|
||||
}
|
||||
|
||||
protected override void SetupMocks()
|
||||
@@ -134,4 +134,4 @@ namespace Renci.SshNet.Tests.Classes.Channels
|
||||
Assert.IsFalse(_channel.IsOpen);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -22,7 +22,7 @@ namespace Renci.SshNet.Tests.Classes.Channels
|
||||
private List<ExceptionEventArgs> _channelExceptionRegister;
|
||||
private ChannelSession _channel;
|
||||
private MockSequence _sequence;
|
||||
private SemaphoreLight _sessionSemaphore;
|
||||
private SemaphoreSlim _sessionSemaphore;
|
||||
private int _initialSessionSemaphoreCount;
|
||||
|
||||
protected override void SetupData()
|
||||
@@ -38,7 +38,7 @@ namespace Renci.SshNet.Tests.Classes.Channels
|
||||
_channelClosedRegister = new List<ChannelEventArgs>();
|
||||
_channelExceptionRegister = new List<ExceptionEventArgs>();
|
||||
_initialSessionSemaphoreCount = random.Next(10, 20);
|
||||
_sessionSemaphore = new SemaphoreLight(_initialSessionSemaphoreCount);
|
||||
_sessionSemaphore = new SemaphoreSlim(_initialSessionSemaphoreCount);
|
||||
}
|
||||
|
||||
protected override void SetupMocks()
|
||||
|
||||
+2
-2
@@ -23,7 +23,7 @@ namespace Renci.SshNet.Tests.Classes.Channels
|
||||
private IList<ChannelEventArgs> _channelClosedRegister;
|
||||
private List<ExceptionEventArgs> _channelExceptionRegister;
|
||||
private ChannelSession _channel;
|
||||
private SemaphoreLight _sessionSemaphore;
|
||||
private SemaphoreSlim _sessionSemaphore;
|
||||
private int _initialSessionSemaphoreCount;
|
||||
|
||||
protected override void SetupData()
|
||||
@@ -40,7 +40,7 @@ namespace Renci.SshNet.Tests.Classes.Channels
|
||||
_channelClosedRegister = new List<ChannelEventArgs>();
|
||||
_channelExceptionRegister = new List<ExceptionEventArgs>();
|
||||
_initialSessionSemaphoreCount = random.Next(10, 20);
|
||||
_sessionSemaphore = new SemaphoreLight(_initialSessionSemaphoreCount);
|
||||
_sessionSemaphore = new SemaphoreSlim(_initialSessionSemaphoreCount);
|
||||
}
|
||||
|
||||
protected override void SetupMocks()
|
||||
|
||||
+2
-2
@@ -22,7 +22,7 @@ namespace Renci.SshNet.Tests.Classes.Channels
|
||||
private List<ExceptionEventArgs> _channelExceptionRegister;
|
||||
private ChannelSession _channel;
|
||||
private MockSequence _sequence;
|
||||
private SemaphoreLight _sessionSemaphore;
|
||||
private SemaphoreSlim _sessionSemaphore;
|
||||
private int _initialSessionSemaphoreCount;
|
||||
|
||||
protected override void SetupData()
|
||||
@@ -38,7 +38,7 @@ namespace Renci.SshNet.Tests.Classes.Channels
|
||||
_channelClosedRegister = new List<ChannelEventArgs>();
|
||||
_channelExceptionRegister = new List<ExceptionEventArgs>();
|
||||
_initialSessionSemaphoreCount = random.Next(10, 20);
|
||||
_sessionSemaphore = new SemaphoreLight(_initialSessionSemaphoreCount);
|
||||
_sessionSemaphore = new SemaphoreSlim(_initialSessionSemaphoreCount);
|
||||
}
|
||||
|
||||
protected override void SetupMocks()
|
||||
|
||||
+2
-2
@@ -22,7 +22,7 @@ namespace Renci.SshNet.Tests.Classes.Channels
|
||||
private IList<ChannelEventArgs> _channelClosedRegister;
|
||||
private List<ExceptionEventArgs> _channelExceptionRegister;
|
||||
private ChannelSession _channel;
|
||||
private SemaphoreLight _sessionSemaphore;
|
||||
private SemaphoreSlim _sessionSemaphore;
|
||||
private int _initialSessionSemaphoreCount;
|
||||
|
||||
protected override void SetupData()
|
||||
@@ -39,7 +39,7 @@ namespace Renci.SshNet.Tests.Classes.Channels
|
||||
_channelClosedRegister = new List<ChannelEventArgs>();
|
||||
_channelExceptionRegister = new List<ExceptionEventArgs>();
|
||||
_initialSessionSemaphoreCount = random.Next(10, 20);
|
||||
_sessionSemaphore = new SemaphoreLight(_initialSessionSemaphoreCount);
|
||||
_sessionSemaphore = new SemaphoreSlim(_initialSessionSemaphoreCount);
|
||||
}
|
||||
|
||||
protected override void SetupMocks()
|
||||
|
||||
+3
-3
@@ -20,7 +20,7 @@ namespace Renci.SshNet.Tests.Classes.Channels
|
||||
private uint _remotePacketSize;
|
||||
private uint _remoteChannelNumber;
|
||||
private TimeSpan _channelCloseTimeout;
|
||||
private SemaphoreLight _sessionSemaphore;
|
||||
private SemaphoreSlim _sessionSemaphore;
|
||||
private IList<ChannelEventArgs> _channelClosedRegister;
|
||||
private List<ExceptionEventArgs> _channelExceptionRegister;
|
||||
|
||||
@@ -35,7 +35,7 @@ namespace Renci.SshNet.Tests.Classes.Channels
|
||||
_remoteWindowSize = (uint) random.Next(0, int.MaxValue);
|
||||
_remotePacketSize = (uint) random.Next(100, 200);
|
||||
_channelCloseTimeout = TimeSpan.FromSeconds(random.Next(10, 20));
|
||||
_sessionSemaphore = new SemaphoreLight(1);
|
||||
_sessionSemaphore = new SemaphoreSlim(1);
|
||||
_channelClosedRegister = new List<ChannelEventArgs>();
|
||||
_channelExceptionRegister = new List<ExceptionEventArgs>();
|
||||
}
|
||||
@@ -142,4 +142,4 @@ namespace Renci.SshNet.Tests.Classes.Channels
|
||||
Assert.IsFalse(_channel.IsOpen);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -20,7 +20,7 @@ namespace Renci.SshNet.Tests.Classes.Channels
|
||||
private uint _remotePacketSize;
|
||||
private uint _remoteChannelNumber;
|
||||
private TimeSpan _channelCloseTimeout;
|
||||
private SemaphoreLight _sessionSemaphore;
|
||||
private SemaphoreSlim _sessionSemaphore;
|
||||
private IList<ChannelEventArgs> _channelClosedRegister;
|
||||
private List<ExceptionEventArgs> _channelExceptionRegister;
|
||||
|
||||
@@ -35,7 +35,7 @@ namespace Renci.SshNet.Tests.Classes.Channels
|
||||
_remoteWindowSize = (uint) random.Next(0, int.MaxValue);
|
||||
_remotePacketSize = (uint) random.Next(100, 200);
|
||||
_channelCloseTimeout = TimeSpan.FromSeconds(random.Next(10, 20));
|
||||
_sessionSemaphore = new SemaphoreLight(1);
|
||||
_sessionSemaphore = new SemaphoreSlim(1);
|
||||
_channelClosedRegister = new List<ChannelEventArgs>();
|
||||
_channelExceptionRegister = new List<ExceptionEventArgs>();
|
||||
}
|
||||
|
||||
+2
-2
@@ -22,7 +22,7 @@ namespace Renci.SshNet.Tests.Classes.Channels
|
||||
private List<ExceptionEventArgs> _channelExceptionRegister;
|
||||
private ChannelSession _channel;
|
||||
private MockSequence _sequence;
|
||||
private SemaphoreLight _sessionSemaphore;
|
||||
private SemaphoreSlim _sessionSemaphore;
|
||||
private int _initialSessionSemaphoreCount;
|
||||
|
||||
protected override void SetupData()
|
||||
@@ -38,7 +38,7 @@ namespace Renci.SshNet.Tests.Classes.Channels
|
||||
_channelClosedRegister = new List<ChannelEventArgs>();
|
||||
_channelExceptionRegister = new List<ExceptionEventArgs>();
|
||||
_initialSessionSemaphoreCount = random.Next(10, 20);
|
||||
_sessionSemaphore = new SemaphoreLight(_initialSessionSemaphoreCount);
|
||||
_sessionSemaphore = new SemaphoreSlim(_initialSessionSemaphoreCount);
|
||||
}
|
||||
|
||||
protected override void SetupMocks()
|
||||
|
||||
+2
-2
@@ -22,7 +22,7 @@ namespace Renci.SshNet.Tests.Classes.Channels
|
||||
private List<ExceptionEventArgs> _channelExceptionRegister;
|
||||
private ChannelSession _channel;
|
||||
private MockSequence _sequence;
|
||||
private SemaphoreLight _sessionSemaphore;
|
||||
private SemaphoreSlim _sessionSemaphore;
|
||||
private int _initialSessionSemaphoreCount;
|
||||
|
||||
protected override void SetupData()
|
||||
@@ -38,7 +38,7 @@ namespace Renci.SshNet.Tests.Classes.Channels
|
||||
_channelClosedRegister = new List<ChannelEventArgs>();
|
||||
_channelExceptionRegister = new List<ExceptionEventArgs>();
|
||||
_initialSessionSemaphoreCount = random.Next(10, 20);
|
||||
_sessionSemaphore = new SemaphoreLight(_initialSessionSemaphoreCount);
|
||||
_sessionSemaphore = new SemaphoreSlim(_initialSessionSemaphoreCount);
|
||||
}
|
||||
|
||||
protected override void SetupMocks()
|
||||
|
||||
+2
-2
@@ -22,7 +22,7 @@ namespace Renci.SshNet.Tests.Classes.Channels
|
||||
private List<ExceptionEventArgs> _channelExceptionRegister;
|
||||
private ChannelSession _channel;
|
||||
private MockSequence _sequence;
|
||||
private SemaphoreLight _sessionSemaphore;
|
||||
private SemaphoreSlim _sessionSemaphore;
|
||||
private int _initialSessionSemaphoreCount;
|
||||
|
||||
protected override void SetupData()
|
||||
@@ -38,7 +38,7 @@ namespace Renci.SshNet.Tests.Classes.Channels
|
||||
_channelClosedRegister = new List<ChannelEventArgs>();
|
||||
_channelExceptionRegister = new List<ExceptionEventArgs>();
|
||||
_initialSessionSemaphoreCount = random.Next(10, 20);
|
||||
_sessionSemaphore = new SemaphoreLight(_initialSessionSemaphoreCount);
|
||||
_sessionSemaphore = new SemaphoreSlim(_initialSessionSemaphoreCount);
|
||||
}
|
||||
|
||||
protected override void SetupMocks()
|
||||
|
||||
+2
-2
@@ -24,7 +24,7 @@ namespace Renci.SshNet.Tests.Classes.Channels
|
||||
private List<ExceptionEventArgs> _channelExceptionRegister;
|
||||
private ChannelSession _channel;
|
||||
private MockSequence _sequence;
|
||||
private SemaphoreLight _sessionSemaphore;
|
||||
private SemaphoreSlim _sessionSemaphore;
|
||||
private int _initialSessionSemaphoreCount;
|
||||
|
||||
protected override void SetupData()
|
||||
@@ -41,7 +41,7 @@ namespace Renci.SshNet.Tests.Classes.Channels
|
||||
_channelClosedRegister = new List<ChannelEventArgs>();
|
||||
_channelExceptionRegister = new List<ExceptionEventArgs>();
|
||||
_initialSessionSemaphoreCount = random.Next(10, 20);
|
||||
_sessionSemaphore = new SemaphoreLight(_initialSessionSemaphoreCount);
|
||||
_sessionSemaphore = new SemaphoreSlim(_initialSessionSemaphoreCount);
|
||||
}
|
||||
|
||||
protected override void SetupMocks()
|
||||
|
||||
+2
-2
@@ -18,7 +18,7 @@ namespace Renci.SshNet.Tests.Classes.Channels
|
||||
private uint _localPacketSize;
|
||||
private IList<ChannelEventArgs> _channelClosedRegister;
|
||||
private List<ExceptionEventArgs> _channelExceptionRegister;
|
||||
private SemaphoreLight _sessionSemaphore;
|
||||
private SemaphoreSlim _sessionSemaphore;
|
||||
private int _initialSessionSemaphoreCount;
|
||||
private Exception _waitOnConfirmationException;
|
||||
private SystemException _actualException;
|
||||
@@ -31,7 +31,7 @@ namespace Renci.SshNet.Tests.Classes.Channels
|
||||
_localWindowSize = (uint) random.Next(2000, 3000);
|
||||
_localPacketSize = (uint) random.Next(1000, 2000);
|
||||
_initialSessionSemaphoreCount = random.Next(10, 20);
|
||||
_sessionSemaphore = new SemaphoreLight(_initialSessionSemaphoreCount);
|
||||
_sessionSemaphore = new SemaphoreSlim(_initialSessionSemaphoreCount);
|
||||
_channelClosedRegister = new List<ChannelEventArgs>();
|
||||
_channelExceptionRegister = new List<ExceptionEventArgs>();
|
||||
_waitOnConfirmationException = new SystemException();
|
||||
|
||||
+2
-2
@@ -19,7 +19,7 @@ namespace Renci.SshNet.Tests.Classes.Channels
|
||||
private uint _localPacketSize;
|
||||
private IList<ChannelEventArgs> _channelClosedRegister;
|
||||
private List<ExceptionEventArgs> _channelExceptionRegister;
|
||||
private SemaphoreLight _sessionSemaphore;
|
||||
private SemaphoreSlim _sessionSemaphore;
|
||||
private int _initialSessionSemaphoreCount;
|
||||
private uint _failureReasonCode;
|
||||
private string _failureDescription;
|
||||
@@ -34,7 +34,7 @@ namespace Renci.SshNet.Tests.Classes.Channels
|
||||
_localWindowSize = (uint) random.Next(2000, 3000);
|
||||
_localPacketSize = (uint) random.Next(1000, 2000);
|
||||
_initialSessionSemaphoreCount = random.Next(10, 20);
|
||||
_sessionSemaphore = new SemaphoreLight(_initialSessionSemaphoreCount);
|
||||
_sessionSemaphore = new SemaphoreSlim(_initialSessionSemaphoreCount);
|
||||
_channelClosedRegister = new List<ChannelEventArgs>();
|
||||
_channelExceptionRegister = new List<ExceptionEventArgs>();
|
||||
_actualException = null;
|
||||
|
||||
+3
-3
@@ -22,7 +22,7 @@ namespace Renci.SshNet.Tests.Classes.Channels
|
||||
private uint _remotePacketSize;
|
||||
private IList<ChannelEventArgs> _channelClosedRegister;
|
||||
private List<ExceptionEventArgs> _channelExceptionRegister;
|
||||
private SemaphoreLight _sessionSemaphore;
|
||||
private SemaphoreSlim _sessionSemaphore;
|
||||
private int _initialSessionSemaphoreCount;
|
||||
private uint _failureReasonCode;
|
||||
private string _failureDescription;
|
||||
@@ -39,7 +39,7 @@ namespace Renci.SshNet.Tests.Classes.Channels
|
||||
_remoteWindowSize = (uint) random.Next(0, int.MaxValue);
|
||||
_remotePacketSize = (uint) random.Next(0, int.MaxValue);
|
||||
_initialSessionSemaphoreCount = random.Next(10, 20);
|
||||
_sessionSemaphore = new SemaphoreLight(_initialSessionSemaphoreCount);
|
||||
_sessionSemaphore = new SemaphoreSlim(_initialSessionSemaphoreCount);
|
||||
_channelClosedRegister = new List<ChannelEventArgs>();
|
||||
_channelExceptionRegister = new List<ExceptionEventArgs>();
|
||||
|
||||
@@ -147,4 +147,4 @@ namespace Renci.SshNet.Tests.Classes.Channels
|
||||
Assert.IsTrue(_channel.IsOpen);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,94 +0,0 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Threading;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Renci.SshNet.Common;
|
||||
using Renci.SshNet.Tests.Common;
|
||||
|
||||
namespace Renci.SshNet.Tests.Classes.Common
|
||||
{
|
||||
[TestClass]
|
||||
public class SemaphoreLightTest : TestBase
|
||||
{
|
||||
[TestMethod]
|
||||
public void SemaphoreLightConstructorTest()
|
||||
{
|
||||
var initialCount = new Random().Next(1, 10);
|
||||
var target = new SemaphoreLight(initialCount);
|
||||
Assert.AreEqual(initialCount, target.CurrentCount);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Release()
|
||||
{
|
||||
var initialCount = new Random().Next(1, 10);
|
||||
var target = new SemaphoreLight(initialCount);
|
||||
|
||||
Assert.AreEqual(initialCount, target.Release());
|
||||
Assert.AreEqual(initialCount + 1, target.CurrentCount);
|
||||
|
||||
Assert.AreEqual(initialCount + 1, target.Release());
|
||||
Assert.AreEqual(initialCount + 2, target.CurrentCount);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///A test for Release
|
||||
///</summary>
|
||||
[TestMethod]
|
||||
public void Release_ReleaseCount()
|
||||
{
|
||||
var initialCount = new Random().Next(1, 10);
|
||||
var target = new SemaphoreLight(initialCount);
|
||||
|
||||
var releaseCount1 = new Random().Next(1, 10);
|
||||
Assert.AreEqual(initialCount, target.Release(releaseCount1));
|
||||
Assert.AreEqual(initialCount + releaseCount1, target.CurrentCount);
|
||||
|
||||
var releaseCount2 = new Random().Next(1, 10);
|
||||
Assert.AreEqual(initialCount + releaseCount1, target.Release(releaseCount2));
|
||||
Assert.AreEqual(initialCount + releaseCount1 + releaseCount2, target.CurrentCount);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///A test for Wait
|
||||
///</summary>
|
||||
[TestMethod]
|
||||
public void WaitTest()
|
||||
{
|
||||
const int sleepTime = 200;
|
||||
const int initialCount = 2;
|
||||
var target = new SemaphoreLight(initialCount);
|
||||
|
||||
var watch = new Stopwatch();
|
||||
watch.Start();
|
||||
|
||||
target.Wait();
|
||||
target.Wait();
|
||||
|
||||
Assert.IsTrue(watch.ElapsedMilliseconds < 50);
|
||||
|
||||
var releaseThread = new Thread(() =>
|
||||
{
|
||||
Thread.Sleep(sleepTime);
|
||||
_ = target.Release();
|
||||
});
|
||||
releaseThread.Start();
|
||||
|
||||
target.Wait();
|
||||
|
||||
watch.Stop();
|
||||
|
||||
Assert.IsTrue(watch.ElapsedMilliseconds >= 200);
|
||||
Assert.IsTrue(watch.ElapsedMilliseconds < 250);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CurrentCountTest()
|
||||
{
|
||||
var initialCount = new Random().Next(1, 20);
|
||||
var target = new SemaphoreLight(initialCount);
|
||||
|
||||
Assert.AreEqual(initialCount, target.CurrentCount);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user