using System;
using System.Threading;
namespace Renci.SshNet
{
internal class ForwardedPortStatus
{
private readonly int _value;
private readonly string _name;
public static readonly ForwardedPortStatus Stopped = new ForwardedPortStatus(1, "Stopped");
public static readonly ForwardedPortStatus Stopping = new ForwardedPortStatus(2, "Stopping");
public static readonly ForwardedPortStatus Started = new ForwardedPortStatus(3, "Started");
public static readonly ForwardedPortStatus Starting = new ForwardedPortStatus(4, "Starting");
private ForwardedPortStatus(int value, string name)
{
_value = value;
_name = name;
}
public override bool Equals(object other)
{
if (ReferenceEquals(other, null))
return false;
if (ReferenceEquals(this, other))
return true;
var forwardedPortStatus = other as ForwardedPortStatus;
if (forwardedPortStatus == null)
return false;
return forwardedPortStatus._value == _value;
}
public static bool operator ==(ForwardedPortStatus left, ForwardedPortStatus right)
{
// check if lhs is null
if (ReferenceEquals(left, null))
{
// check if both lhs and rhs are null
return (ReferenceEquals(right, null));
}
return left.Equals(right);
}
public static bool operator !=(ForwardedPortStatus left, ForwardedPortStatus right)
{
return !(left==right);
}
public override int GetHashCode()
{
return _value;
}
public override string ToString()
{
return _name;
}
///
/// Returns a value indicating whether has been changed to .
///
/// The status to transition from.
///
/// true if has been changed to ; otherwise, false.
///
/// Cannot transition to .
///
/// While a transition from to is not possible, this method will
/// return false for any such attempts. This is related to concurrency.
///
public static bool ToStopping(ref ForwardedPortStatus status)
{
// attempt to transition from Started to Stopping
var previousStatus = Interlocked.CompareExchange(ref status, Stopping, Started);
if (previousStatus == Stopping || previousStatus == Stopped)
{
// status is already Stopping or Stopped, so no transition to Stopping is necessary
return false;
}
// we've successfully transitioned from Started to Stopping
if (status == Stopping)
return true;
// attempt to transition from Starting to Stopping
previousStatus = Interlocked.CompareExchange(ref status, Stopping, Starting);
if (previousStatus == Stopping || previousStatus == Stopped)
{
// status is already Stopping or Stopped, so no transition to Stopping is necessary
return false;
}
// we've successfully transitioned from Starting to Stopping
if (status == Stopping)
return true;
// there's no valid transition from status to Stopping
throw new InvalidOperationException(string.Format("Forwarded port cannot transition from '{0}' to '{1}'.",
previousStatus,
Stopping));
}
///
/// Returns a value indicating whether has been changed to .
///
/// The status to transition from.
///
/// true if has been changed to ; otherwise, false.
///
/// Cannot transition to .
///
/// While a transition from to is not possible, this method will
/// return false for any such attempts. This is related to concurrency.
///
public static bool ToStarting(ref ForwardedPortStatus status)
{
// attemp to transition from Stopped to Starting
var previousStatus = Interlocked.CompareExchange(ref status, Starting, Stopped);
if (previousStatus == Starting || previousStatus == Started)
{
// port is already Starting or Started, so no transition to Starting is necessary
return false;
}
// we've successfully transitioned from Stopped to Starting
if (status == Starting)
return true;
// there's no valid transition from status to Starting
throw new InvalidOperationException(string.Format("Forwarded port cannot transition from '{0}' to '{1}'.",
previousStatus,
Starting));
}
}
}