# < Summary

Information

Class: | Renci.SshNet.Common.SemaphoreLight
Assembly: | Renci.SshNet
File(s): | \home\appveyor\projects\ssh-net\src\Renci.SshNet\Common\SemaphoreLight.cs

Line coverage
67%

Covered lines: | 78
Uncovered lines: | 38
Coverable lines: | 116
Total lines: | 244
Line coverage: | 67.2%

Branch coverage
50%

Covered branches: | 23
Total branches: | 46
Branch coverage: | 50%

Method coverage

Feature is only available for sponsors

Upgrade to PRO version

# Metrics

Method | Branch coverage | Cyclomatic complexity | Line coverage
--- | --- | --- | ---
.ctor(...) | 50% | 2 | 75%
get_CurrentCount() | 100% | 1 | 100%
get_AvailableWaitHandle() | 100% | 4 | 100%
Release() | 100% | 1 | 100%
Release(...) | 100% | 4 | 100%
Wait() | 66.66% | 6 | 80%
Wait(...) | 50% | 2 | 66.66%
Wait(...) | 0% | 6 | 0%
WaitWithTimeout(...) | 27.77% | 18 | 38.46%
Dispose() | 100% | 1 | 100%
Dispose(...) | 100% | 4 | 100%

# File(s)

## \home\appveyor\projects\ssh-net\src\Renci.SshNet\Common\SemaphoreLight.cs

| # | Line |  | Line coverage
--- | --- | --- | --- | ---
|  | `1` |  | `using System;`
|  | `2` |  | `using System.Threading;`
|  | `3` |  | ``
|  | `4` |  | `namespace Renci.SshNet.Common`
|  | `5` |  | `{`
|  | `6` |  | `/// <summary>`
|  | `7` |  | `/// Light implementation of SemaphoreSlim.`
|  | `8` |  | `/// </summary>`
|  | `9` |  | `public sealed class SemaphoreLight : IDisposable`
|  | `10` |  | `{`
| 1618 | `11` |  | `private readonly object _lock = new object();`
|  | `12` |  | `private ManualResetEvent _waitHandle;`
|  | `13` |  | ``
|  | `14` |  | `private int _currentCount;`
|  | `15` |  | ``
|  | `16` |  | `/// <summary>`
|  | `17` |  | `/// Initializes a new instance of the <see cref="SemaphoreLight"/> class, specifying the initial number of reque`
|  | `18` |  | `/// be granted concurrently.`
|  | `19` |  | `/// </summary>`
|  | `20` |  | `/// <param name="initialCount">The initial number of requests for the semaphore that can be granted concurrently`
|  | `21` |  | `/// <exception cref="ArgumentOutOfRangeException"><paramref name="initialCount"/> is a negative number.</excepti`
| 1618 | `22` |  | `public SemaphoreLight(int initialCount)`
| 1618 | `23` |  | `{`
| 1618 | `24` |  | `if (initialCount < 0)`
| 0 | `25` |  | `{`
| 0 | `26` |  | `throw new ArgumentOutOfRangeException(nameof(initialCount), "The value cannot be negative.");`
|  | `27` |  | `}`
|  | `28` |  | ``
| 1618 | `29` |  | `_currentCount = initialCount;`
| 1618 | `30` |  | `}`
|  | `31` |  | ``
|  | `32` |  | `/// <summary>`
|  | `33` |  | `/// Gets the current count of the <see cref="SemaphoreLight"/>.`
|  | `34` |  | `/// </summary>`
|  | `35` |  | `public int CurrentCount`
|  | `36` |  | `{`
| 180 | `37` |  | `get { return _currentCount; }`
|  | `38` |  | `}`
|  | `39` |  | ``
|  | `40` |  | `/// <summary>`
|  | `41` |  | `/// Gets a <see cref="WaitHandle"/> that can be used to wait on the semaphore.`
|  | `42` |  | `/// </summary>`
|  | `43` |  | `/// <value>`
|  | `44` |  | `/// A <see cref="WaitHandle"/> that can be used to wait on the semaphore.`
|  | `45` |  | `/// </value>`
|  | `46` |  | `/// <remarks>`
|  | `47` |  | `/// A successful wait on the <see cref="AvailableWaitHandle"/> does not imply a successful`
|  | `48` |  | `/// wait on the <see cref="SemaphoreLight"/> itself. It should be followed by a true wait`
|  | `49` |  | `/// on the semaphore.`
|  | `50` |  | `/// </remarks>`
|  | `51` |  | `public WaitHandle AvailableWaitHandle`
|  | `52` |  | `{`
|  | `53` |  | `get`
| 220 | `54` |  | `{`
| 220 | `55` |  | `if (_waitHandle is null)`
| 220 | `56` |  | `{`
| 220 | `57` |  | `lock (_lock)`
| 220 | `58` |  | `{`
| 220 | `59` |  | `_waitHandle ??= new ManualResetEvent(_currentCount > 0);`
| 220 | `60` |  | `}`
| 220 | `61` |  | `}`
|  | `62` |  | ``
| 220 | `63` |  | `return _waitHandle;`
| 220 | `64` |  | `}`
|  | `65` |  | `}`
|  | `66` |  | ``
|  | `67` |  | `/// <summary>`
|  | `68` |  | `/// Exits the <see cref="SemaphoreLight"/> once.`
|  | `69` |  | `/// </summary>`
|  | `70` |  | `/// <returns>The previous count of the <see cref="SemaphoreLight"/>.</returns>`
|  | `71` |  | `public int Release()`
| 7972 | `72` |  | `{`
| 7972 | `73` |  | `return Release(1);`
| 7972 | `74` |  | `}`
|  | `75` |  | ``
|  | `76` |  | `/// <summary>`
|  | `77` |  | `/// Exits the <see cref="SemaphoreLight"/> a specified number of times.`
|  | `78` |  | `/// </summary>`
|  | `79` |  | `/// <param name="releaseCount">The number of times to exit the semaphore.</param>`
|  | `80` |  | `/// <returns>`
|  | `81` |  | `/// The previous count of the <see cref="SemaphoreLight"/>.`
|  | `82` |  | `/// </returns>`
|  | `83` |  | `public int Release(int releaseCount)`
| 7978 | `84` |  | `{`
| 7978 | `85` |  | `lock (_lock)`
| 7978 | `86` |  | `{`
| 7978 | `87` |  | `var oldCount = _currentCount;`
|  | `88` |  | ``
| 7978 | `89` |  | `_currentCount += releaseCount;`
|  | `90` |  | ``
|  | `91` |  | `// signal waithandle when the original semaphore count was zero`
| 7978 | `92` |  | `if (_waitHandle != null && oldCount == 0)`
| 2189 | `93` |  | `{`
| 2189 | `94` |  | `_ = _waitHandle.Set();`
| 2189 | `95` |  | `}`
|  | `96` |  | ``
| 7978 | `97` |  | `Monitor.PulseAll(_lock);`
|  | `98` |  | ``
| 7978 | `99` |  | `return oldCount;`
|  | `100` |  | `}`
| 7978 | `101` |  | `}`
|  | `102` |  | ``
|  | `103` |  | `/// <summary>`
|  | `104` |  | `/// Blocks the current thread until it can enter the <see cref="SemaphoreLight"/>.`
|  | `105` |  | `/// </summary>`
|  | `106` |  | `public void Wait()`
| 3887 | `107` |  | `{`
| 3887 | `108` |  | `lock (_lock)`
| 3887 | `109` |  | `{`
| 6642 | `110` |  | `while (_currentCount < 1)`
| 2755 | `111` |  | `{`
| 2755 | `112` |  | `_ = Monitor.Wait(_lock);`
| 2755 | `113` |  | `}`
|  | `114` |  | ``
| 3887 | `115` |  | `_currentCount--;`
|  | `116` |  | ``
|  | `117` |  | `// unsignal waithandle when the semaphore count reaches zero`
| 3887 | `118` |  | `if (_waitHandle != null && _currentCount == 0)`
| 0 | `119` |  | `{`
| 0 | `120` |  | `_ = _waitHandle.Reset();`
| 0 | `121` |  | `}`
|  | `122` |  | ``
| 3887 | `123` |  | `Monitor.PulseAll(_lock);`
| 3887 | `124` |  | `}`
| 3887 | `125` |  | `}`
|  | `126` |  | ``
|  | `127` |  | `/// <summary>`
|  | `128` |  | `/// Blocks the current thread until it can enter the <see cref="SemaphoreLight"/>, using a 32-bit signed`
|  | `129` |  | `/// integer that specifies the timeout.`
|  | `130` |  | `/// </summary>`
|  | `131` |  | `/// <param name="millisecondsTimeout">The number of milliseconds to wait, or Infinite(-1) to wait indefinitely.<`
|  | `132` |  | `/// <returns>`
|  | `133` |  | `/// <see langword="true"/> if the current thread successfully entered the <see cref="SemaphoreLight"/>; otherwis`
|  | `134` |  | `/// </returns>`
|  | `135` |  | `public bool Wait(int millisecondsTimeout)`
| 4202 | `136` |  | `{`
| 4202 | `137` |  | `if (millisecondsTimeout < -1)`
| 0 | `138` |  | `{`
| 0 | `139` |  | `throw new ArgumentOutOfRangeException(nameof(millisecondsTimeout), "The timeout must represent a value b`
|  | `140` |  | `}`
|  | `141` |  | ``
| 4202 | `142` |  | `return WaitWithTimeout(millisecondsTimeout);`
| 4202 | `143` |  | `}`
|  | `144` |  | ``
|  | `145` |  | `/// <summary>`
|  | `146` |  | `/// Blocks the current thread until it can enter the <see cref="SemaphoreLight"/>, using a <see cref="TimeSpan"/`
|  | `147` |  | `/// to specify the timeout.`
|  | `148` |  | `/// </summary>`
|  | `149` |  | `/// <param name="timeout">A <see cref="TimeSpan"/> that represents the number of milliseconds to wait, or a <see`
|  | `150` |  | `/// <returns>`
|  | `151` |  | `/// <see langword="true"/> if the current thread successfully entered the <see cref="SemaphoreLight"/>; otherwis`
|  | `152` |  | `/// </returns>`
|  | `153` |  | `public bool Wait(TimeSpan timeout)`
| 0 | `154` |  | `{`
| 0 | `155` |  | `var timeoutInMilliseconds = timeout.TotalMilliseconds;`
| 0 | `156` |  | `if (timeoutInMilliseconds is < -1d or > int.MaxValue)`
| 0 | `157` |  | `{`
| 0 | `158` |  | `throw new ArgumentOutOfRangeException(nameof(timeout), "The timeout must represent a value between -1 an`
|  | `159` |  | `}`
|  | `160` |  | ``
| 0 | `161` |  | `return WaitWithTimeout((int) timeoutInMilliseconds);`
| 0 | `162` |  | `}`
|  | `163` |  | ``
|  | `164` |  | `private bool WaitWithTimeout(int timeoutInMilliseconds)`
| 4202 | `165` |  | `{`
| 4202 | `166` |  | `lock (_lock)`
| 4202 | `167` |  | `{`
| 4202 | `168` |  | `if (timeoutInMilliseconds == Session.Infinite)`
| 0 | `169` |  | `{`
| 0 | `170` |  | `while (_currentCount < 1)`
| 0 | `171` |  | `{`
| 0 | `172` |  | `_ = Monitor.Wait(_lock);`
| 0 | `173` |  | `}`
| 0 | `174` |  | `}`
|  | `175` |  | `else`
| 4202 | `176` |  | `{`
| 4202 | `177` |  | `if (_currentCount < 1)`
| 0 | `178` |  | `{`
| 0 | `179` |  | `if (timeoutInMilliseconds > 0)`
| 0 | `180` |  | `{`
| 0 | `181` |  | `return false;`
|  | `182` |  | `}`
|  | `183` |  | ``
| 0 | `184` |  | `var remainingTimeInMilliseconds = timeoutInMilliseconds;`
| 0 | `185` |  | `var startTicks = Environment.TickCount;`
|  | `186` |  | ``
| 0 | `187` |  | `while (_currentCount < 1)`
| 0 | `188` |  | `{`
| 0 | `189` |  | `if (!Monitor.Wait(_lock, remainingTimeInMilliseconds))`
| 0 | `190` |  | `{`
| 0 | `191` |  | `return false;`
|  | `192` |  | `}`
|  | `193` |  | ``
| 0 | `194` |  | `var elapsed = Environment.TickCount - startTicks;`
| 0 | `195` |  | `remainingTimeInMilliseconds -= elapsed;`
| 0 | `196` |  | `if (remainingTimeInMilliseconds < 0)`
| 0 | `197` |  | `{`
| 0 | `198` |  | `return false;`
|  | `199` |  | `}`
| 0 | `200` |  | `}`
| 0 | `201` |  | `}`
| 4202 | `202` |  | `}`
|  | `203` |  | ``
| 4202 | `204` |  | `_currentCount--;`
|  | `205` |  | ``
|  | `206` |  | `// unsignal waithandle when the semaphore count is zero`
| 4202 | `207` |  | `if (_waitHandle != null && _currentCount == 0)`
| 2269 | `208` |  | `{`
| 2269 | `209` |  | `_ = _waitHandle.Reset();`
| 2269 | `210` |  | `}`
|  | `211` |  | ``
| 4202 | `212` |  | `Monitor.PulseAll(_lock);`
|  | `213` |  | ``
| 4202 | `214` |  | `return true;`
|  | `215` |  | `}`
| 4202 | `216` |  | `}`
|  | `217` |  | ``
|  | `218` |  | `/// <summary>`
|  | `219` |  | `/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.`
|  | `220` |  | `/// </summary>`
|  | `221` |  | `public void Dispose()`
| 115 | `222` |  | `{`
| 115 | `223` |  | `Dispose(disposing: true);`
| 115 | `224` |  | `GC.SuppressFinalize(this);`
| 115 | `225` |  | `}`
|  | `226` |  | ``
|  | `227` |  | `/// <summary>`
|  | `228` |  | `/// Releases unmanaged and - optionally - managed resources.`
|  | `229` |  | `/// </summary>`
|  | `230` |  | `/// <param name="disposing"><see langword="true"/> to release both managed and unmanaged resources; <see langwor`
|  | `231` |  | `private void Dispose(bool disposing)`
| 115 | `232` |  | `{`
| 115 | `233` |  | `if (disposing)`
| 115 | `234` |  | `{`
| 115 | `235` |  | `var waitHandle = _waitHandle;`
| 115 | `236` |  | `if (waitHandle is not null)`
| 115 | `237` |  | `{`
| 115 | `238` |  | `waitHandle.Dispose();`
| 115 | `239` |  | `_waitHandle = null;`
| 115 | `240` |  | `}`
| 115 | `241` |  | `}`
| 115 | `242` |  | `}`
|  | `243` |  | `}`
|  | `244` |  | `}`

# Methods/Properties

.ctor(System.Int32)
get_CurrentCount()
get_AvailableWaitHandle()
Release()
Release(System.Int32)
Wait()
Wait(System.Int32)
Wait(System.TimeSpan)
WaitWithTimeout(System.Int32)
Dispose()
Dispose(System.Boolean)