网上演练
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

221 lines
5.5 KiB

// Needed for NET40
#if !NET_4_6
using System;
namespace LinqInternal.Threading.Needles
{
[Serializable]
[System.Diagnostics.DebuggerNonUserCode]
internal class Needle<T> : IEquatable<Needle<T>>, IRecyclableNeedle<T>, IPromise<T>
{
private readonly int _hashCode;
private INeedle<T> _target; // Can be null - set in SetTargetValue and SetTargetError
public Needle()
{
_target = null;
_hashCode = base.GetHashCode();
}
public Needle(T target)
{
if (ReferenceEquals(target, null))
{
_target = null;
_hashCode = base.GetHashCode();
}
else
{
_target = new StructNeedle<T>(target);
_hashCode = target.GetHashCode();
}
}
public Exception Exception
{
get
{
var target = _target;
if (target is ExceptionStructNeedle<T>)
{
return ((ExceptionStructNeedle<T>)target).Exception;
}
return null;
}
}
bool IPromise.IsCanceled
{
get { return false; }
}
bool IPromise.IsCompleted
{
get { return IsAlive; }
}
public bool IsAlive
{
get
{
var target = _target;
return target != null && target.IsAlive;
}
}
public bool IsFaulted
{
get { return _target is ExceptionStructNeedle<T>; }
}
public virtual T Value
{
get { return _target.Value; }
set { SetTargetValue(value); }
}
public static explicit operator T(Needle<T> needle)
{
if (needle == null)
{
throw new ArgumentNullException("needle");
}
return needle.Value;
}
public static implicit operator Needle<T>(T field)
{
return new Needle<T>(field);
}
public static bool operator !=(Needle<T> left, Needle<T> right)
{
return NotEqualsExtracted(left, right);
}
public static bool operator ==(Needle<T> left, Needle<T> right)
{
return EqualsExtracted(left, right);
}
public override bool Equals(object obj)
{
var needle = obj as Needle<T>;
if (needle != null)
{
return EqualsExtracted(this, needle);
}
var target = _target;
if (_target == null)
{
return obj == null;
}
if (obj == null)
{
return false;
}
return target.Equals(obj);
}
public bool Equals(Needle<T> other)
{
var target = _target;
if (target == null)
{
return other._target == null;
}
return EqualsExtracted(this, other);
}
public virtual void Free()
{
_target = null;
}
public override int GetHashCode()
{
return _hashCode;
}
public override string ToString()
{
var target = Value;
if (IsAlive)
{
return target.ToString();
}
return "<Dead Needle>";
}
protected void SetTargetError(Exception error)
{
_target = new ExceptionStructNeedle<T>(error);
}
protected void SetTargetValue(T value)
{
if (_target is StructNeedle<T>)
{
// This may throw NotSupportedException if SetTargetError has just executed
try
{
_target.Value = value;
return;
}
catch (NotSupportedException)
{
// preventing return
}
}
_target = new StructNeedle<T>(value);
}
private static bool EqualsExtracted(Needle<T> left, Needle<T> right)
{
if (ReferenceEquals(left, null))
{
return ReferenceEquals(right, null);
}
if (ReferenceEquals(right, null))
{
return false;
}
var leftTarget = left._target;
var rightTarget = right._target;
if (leftTarget == null)
{
return rightTarget == null;
}
if (rightTarget == null)
{
return false;
}
return leftTarget.Equals(rightTarget);
}
private static bool NotEqualsExtracted(Needle<T> left, Needle<T> right)
{
if (ReferenceEquals(left, null))
{
return !ReferenceEquals(right, null);
}
if (ReferenceEquals(right, null))
{
return true;
}
var leftTarget = left._target;
var rightTarget = right._target;
if (leftTarget == null)
{
return rightTarget != null;
}
if (rightTarget == null)
{
return true;
}
return !leftTarget.Equals(rightTarget);
}
}
}
#endif