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.
122 lines
3.1 KiB
122 lines
3.1 KiB
5 years ago
|
#if FAT
|
||
|
|
||
|
using System;
|
||
|
using System.Threading;
|
||
|
using LinqInternal.Threading.Needles;
|
||
|
|
||
|
namespace LinqInternal.Threading
|
||
|
{
|
||
|
internal sealed class LockSlot<T> : IComparable<LockSlot<T>>, INeedle<T>, IEquatable<LockSlot<T>>
|
||
|
{
|
||
|
internal readonly int _id;
|
||
|
private readonly LockContext<T> _context;
|
||
|
private int _free;
|
||
|
private VersionProvider.VersionToken _versionToken;
|
||
|
|
||
|
internal LockSlot(LockContext<T> context, int id, VersionProvider.VersionToken versionToken)
|
||
|
{
|
||
|
if (context == null)
|
||
|
{
|
||
|
throw new ArgumentNullException("context");
|
||
|
}
|
||
|
_context = context;
|
||
|
_versionToken = versionToken;
|
||
|
_id = id;
|
||
|
}
|
||
|
|
||
|
bool IReadOnlyNeedle<T>.IsAlive
|
||
|
{
|
||
|
get { return !ReferenceEquals(Value, null); }
|
||
|
}
|
||
|
|
||
|
public T Value { get; set; }
|
||
|
|
||
|
internal bool IsOpen
|
||
|
{
|
||
|
get { return Volatile.Read(ref _free) == 0; }
|
||
|
}
|
||
|
|
||
|
public static bool operator !=(LockSlot<T> left, LockSlot<T> right)
|
||
|
{
|
||
|
if (ReferenceEquals(left, null))
|
||
|
{
|
||
|
return !ReferenceEquals(right, null);
|
||
|
}
|
||
|
return !left.Equals(right);
|
||
|
}
|
||
|
|
||
|
public static bool operator <(LockSlot<T> left, LockSlot<T> right)
|
||
|
{
|
||
|
if (ReferenceEquals(left, null))
|
||
|
{
|
||
|
return true;
|
||
|
}
|
||
|
return left.CompareTo(right) < 0;
|
||
|
}
|
||
|
|
||
|
public static bool operator ==(LockSlot<T> left, LockSlot<T> right)
|
||
|
{
|
||
|
if (ReferenceEquals(left, null))
|
||
|
{
|
||
|
return ReferenceEquals(right, null);
|
||
|
}
|
||
|
return left.Equals(right);
|
||
|
}
|
||
|
|
||
|
public static bool operator >(LockSlot<T> left, LockSlot<T> right)
|
||
|
{
|
||
|
if (ReferenceEquals(left, null))
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
return left.CompareTo(right) > 0;
|
||
|
}
|
||
|
|
||
|
public void Close()
|
||
|
{
|
||
|
if (Interlocked.CompareExchange(ref _free, 1, 0) == 0)
|
||
|
{
|
||
|
Value = default(T);
|
||
|
_context.Close(this);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public int CompareTo(LockSlot<T> other)
|
||
|
{
|
||
|
if (ReferenceEquals(other, null))
|
||
|
{
|
||
|
return 1;
|
||
|
}
|
||
|
return _versionToken.CompareTo(other._versionToken);
|
||
|
}
|
||
|
|
||
|
public override bool Equals(object obj)
|
||
|
{
|
||
|
return obj is LockSlot<T> && Equals((LockSlot<T>)obj);
|
||
|
}
|
||
|
|
||
|
public bool Equals(LockSlot<T> other)
|
||
|
{
|
||
|
if (other == null)
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
return _versionToken.Equals(other._versionToken);
|
||
|
}
|
||
|
|
||
|
public override int GetHashCode()
|
||
|
{
|
||
|
return _context.GetHashCode();
|
||
|
}
|
||
|
|
||
|
internal void Open(VersionProvider.VersionToken versionToken)
|
||
|
{
|
||
|
if (Interlocked.CompareExchange(ref _free, 0, 1) == 1)
|
||
|
{
|
||
|
_versionToken = versionToken;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#endif
|