#if FAT using System; using System.Collections.Generic; namespace LinqInternal.Threading.Needles { [System.Diagnostics.DebuggerNonUserCode] internal sealed class ReadOnlyDisposableNeedle : IReadOnlyNeedle { private readonly int _hashCode; private bool _isAlive; private int _status; private T _target; public ReadOnlyDisposableNeedle() { _isAlive = false; _hashCode = EqualityComparer.Default.GetHashCode(default(T)); } public ReadOnlyDisposableNeedle(T target) { _isAlive = true; _target = target; _hashCode = EqualityComparer.Default.GetHashCode(target); } public bool IsAlive { get { return _isAlive; } } public bool IsDisposed { get { return _status == -1; } } public T Value { get { return _target; } } public static explicit operator T(ReadOnlyDisposableNeedle needle) { if (needle == null) { throw new ArgumentNullException("needle"); } return needle.Value; } public static implicit operator ReadOnlyDisposableNeedle(T field) { return new ReadOnlyDisposableNeedle(field); } public static bool operator !=(ReadOnlyDisposableNeedle left, ReadOnlyDisposableNeedle right) { if (left == null && right == null) { return false; } if (left == null || right == null) { return true; } return !EqualityComparer.Default.Equals(left._target, right._target); } public static bool operator ==(ReadOnlyDisposableNeedle left, ReadOnlyDisposableNeedle right) { if (left == null && right == null) { return true; } if (left == null || right == null) { return false; } return EqualityComparer.Default.Equals(left._target, right._target); } [System.Diagnostics.DebuggerNonUserCode] public void Dispose() { if (TakeDisposalExecution()) { Kill(); } } [System.Diagnostics.DebuggerNonUserCode] public void DisposedConditional(Action whenDisposed, Action whenNotDisposed) { if (_status == -1) { if (whenDisposed == null) { whenDisposed.Invoke(); } } else { if (whenNotDisposed != null) { if (ThreadingHelper.SpinWaitRelativeSet(ref _status, 1, -1)) { try { whenNotDisposed.Invoke(); } finally { System.Threading.Interlocked.Decrement(ref _status); } } else { if (whenDisposed == null) { whenDisposed.Invoke(); } } } } } [System.Diagnostics.DebuggerNonUserCode] public TReturn DisposedConditional(Func whenDisposed, Func whenNotDisposed) { if (_status == -1) { if (whenDisposed == null) { return default(TReturn); } else { return whenDisposed.Invoke(); } } else { if (whenNotDisposed == null) { return default(TReturn); } else { if (ThreadingHelper.SpinWaitRelativeSet(ref _status, 1, -1)) { try { return whenNotDisposed.Invoke(); } finally { System.Threading.Interlocked.Decrement(ref _status); } } else { if (whenDisposed == null) { return default(TReturn); } else { return whenDisposed.Invoke(); } } } } } public override bool Equals(object obj) { var needle = obj as ReadOnlyDisposableNeedle; if (needle != null) { return EqualityComparer.Default.Equals(_target, needle._target); } // Keep the "is" operator if (obj is T) { return EqualityComparer.Default.Equals(_target, (T)obj); } return false; } public bool Equals(ReadOnlyDisposableNeedle other) { return !ReferenceEquals(_target, null) && EqualityComparer.Default.Equals(_target, other.Value); } public override int GetHashCode() { return _hashCode; } public override string ToString() { var target = Value; if (_isAlive) { return target.ToString(); } return ""; } private void Kill() { _isAlive = false; _target = default(T); } private bool TakeDisposalExecution() { if (_status == -1) { return false; } else { return ThreadingHelper.SpinWaitSetUnless(ref _status, -1, 0, -1); } } } } #endif