网上演练
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.

161 lines
4.1 KiB

#if FAT
using System;
using System.Threading;
using LinqInternal.Collections;
using LinqInternal.Collections.Specialized;
using LinqInternal.Threading.Needles;
namespace LinqInternal.Threading
{
internal sealed class NeedleLock<T> : IReadOnlyNeedle<T>
{
private readonly LockContext<T> _context;
private readonly int _hashCode;
private FlagArray _capture;
private int _owner;
private T _target;
internal NeedleLock(LockContext<T> context)
{
if (context == null)
{
throw new ArgumentNullException("context");
}
_context = context;
_hashCode = base.GetHashCode();
_capture = new FlagArray(_context.Capacity);
_owner = -1;
}
internal NeedleLock(LockContext<T> context, T target)
{
if (context == null)
{
throw new ArgumentNullException("context");
}
_context = context;
if (ReferenceEquals(target, null))
{
_hashCode = base.GetHashCode();
}
else
{
_target = target;
_hashCode = target.GetHashCode();
}
_capture = new FlagArray(_context.Capacity);
_owner = -1;
}
bool IReadOnlyNeedle<T>.IsAlive
{
get { return !ReferenceEquals(_target, null); }
}
public T Value
{
get
{
LockSlot<T> slot;
if (_context.Read(_capture, ref _owner, out slot))
{
_target = slot.Value;
}
return _target;
}
}
public static explicit operator T(NeedleLock<T> needle)
{
if (needle == null)
{
throw new ArgumentNullException("needle");
}
return needle.Value;
}
public static bool operator !=(NeedleLock<T> left, NeedleLock<T> right)
{
return NotEqualsExtracted(left, right);
}
public static bool operator ==(NeedleLock<T> left, NeedleLock<T> right)
{
return EqualsExtracted(left, right);
}
public override bool Equals(object obj)
{
var needle = obj as NeedleLock<T>;
if (needle == null)
{
return _target.Equals(obj);
}
return EqualsExtracted(this, needle);
}
public bool Equals(NeedleLock<T> other)
{
return EqualsExtracted(this, other);
}
public override int GetHashCode()
{
return _hashCode;
}
public override string ToString()
{
var target = Value;
if ((this as IReadOnlyNeedle<T>).IsAlive)
{
return target.ToString();
}
return "<Dead Needle>";
}
internal void Capture(LockSlot<T> slot)
{
_capture[slot._id] = true;
}
internal void Release()
{
if (Volatile.Read(ref _capture).Flags.IsEmpty())
{
_target = default(T);
}
}
internal void Uncapture(LockSlot<T> slot)
{
Interlocked.CompareExchange(ref _owner, -1, slot._id);
_capture[slot._id] = false;
}
private static bool EqualsExtracted(NeedleLock<T> left, NeedleLock<T> right)
{
if (left == null)
{
return right == null;
}
return left._target.Equals(right._target);
}
private static bool NotEqualsExtracted(NeedleLock<T> left, NeedleLock<T> right)
{
if (left == null)
{
if (right == null)
{
return false;
}
return true;
}
return !left._target.Equals(right._target);
}
}
}
#endif