#if !NET_4_6 using System; using System.Collections; using System.Collections.Generic; using System.Threading; namespace LinqInternal.Collections.ThreadSafe { /// /// Represent a thread-safe wait-free bucket. /// /// The type of the item. [Serializable] internal sealed class Bucket : IBucket { private readonly BucketCore _bucketCore; private int _count; public Bucket() { _bucketCore = new BucketCore(7); } public Bucket(IEnumerable source) { if (source == null) { throw new ArgumentNullException("source"); } _bucketCore = new BucketCore(7); var index = 0; foreach (var item in source) { var copy = item; _bucketCore.DoMayIncrement ( index, (ref object target) => Interlocked.Exchange(ref target, (object)copy ?? BucketHelper.Null) == null ); index++; _count++; } } public int Count { get { return _count; } } public void CopyTo(T[] array, int arrayIndex) { Extensions.CopyTo(this, array, arrayIndex); } public IEnumerable EnumerateRange(int indexFrom, int indexTo) { foreach (var value in _bucketCore.EnumerateRange(indexFrom, indexTo)) { yield return value == BucketHelper.Null ? default(T) : (T)value; } } public bool Exchange(int index, T item, out T previous) { var found = BucketHelper.Null; previous = default(T); var result = _bucketCore.DoMayIncrement ( index, (ref object target) => { found = Interlocked.Exchange(ref target, (object)item ?? BucketHelper.Null); return found == null; } ); if (result) { Interlocked.Increment(ref _count); return true; } if (found != BucketHelper.Null) { previous = (T)found; } return false; } public IEnumerator GetEnumerator() { foreach (var value in _bucketCore) { yield return value == BucketHelper.Null ? default(T) : (T)value; } } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } public bool Insert(int index, T item) { var result = _bucketCore.DoMayIncrement ( index, (ref object target) => { var found = Interlocked.CompareExchange(ref target, (object)item ?? BucketHelper.Null, null); return found == null; } ); if (result) { Interlocked.Increment(ref _count); } return result; } public bool Insert(int index, T item, out T previous) { var found = BucketHelper.Null; previous = default(T); var result = _bucketCore.DoMayIncrement ( index, (ref object target) => { found = Interlocked.CompareExchange(ref target, (object)item ?? BucketHelper.Null, null); return found == null; } ); if (result) { Interlocked.Increment(ref _count); return true; } if (found != BucketHelper.Null) { previous = (T)found; } return false; } public bool RemoveAt(int index) { var result = _bucketCore.DoMayDecrement ( index, (ref object target) => Interlocked.Exchange(ref target, null) != null ); if (result) { Interlocked.Decrement(ref _count); } return result; } public bool RemoveAt(int index, out T previous) { var found = BucketHelper.Null; previous = default(T); var result = _bucketCore.DoMayDecrement ( index, (ref object target) => { found = Interlocked.Exchange(ref target, null); return found != null; } ); if (!result) { return false; } Interlocked.Decrement(ref _count); if (found != BucketHelper.Null) { previous = (T)found; } return true; } public bool RemoveAt(int index, Predicate check) { if (check == null) { throw new ArgumentNullException("check"); } return _bucketCore.DoMayDecrement ( index, (ref object target) => { var found = Interlocked.CompareExchange(ref target, null, null); if (found != null) { var comparisonItem = found == BucketHelper.Null ? default(T) : (T)found; if (check(comparisonItem)) { var compare = Interlocked.CompareExchange(ref target, null, found); if (found == compare) { Interlocked.Decrement(ref _count); return true; } } } return false; } ); } public void Set(int index, T item, out bool isNew) { isNew = _bucketCore.DoMayIncrement ( index, (ref object target) => Interlocked.Exchange(ref target, (object)item ?? BucketHelper.Null) == null ); if (isNew) { Interlocked.Increment(ref _count); } } public bool TryGet(int index, out T value) { var found = BucketHelper.Null; value = default(T); var done = _bucketCore.Do ( index, (ref object target) => { found = Interlocked.CompareExchange(ref target, null, null); return true; } ); if (!done || found == null) { return false; } if (found != BucketHelper.Null) { value = (T)found; } return true; } public bool Update(int index, Func itemUpdateFactory, Predicate check, out bool isEmpty) { if (itemUpdateFactory == null) { throw new ArgumentNullException("itemUpdateFactory"); } if (check == null) { throw new ArgumentNullException("check"); } var found = BucketHelper.Null; var compare = BucketHelper.Null; var result = false; var done = _bucketCore.Do ( index, (ref object target) => { found = Interlocked.CompareExchange(ref target, null, null); if (found != null) { var comparisonItem = found == BucketHelper.Null ? default(T) : (T)found; if (check(comparisonItem)) { var item = itemUpdateFactory(comparisonItem); compare = Interlocked.CompareExchange(ref target, (object)item ?? BucketHelper.Null, found); result = found == compare; } } return true; } ); if (!done) { isEmpty = true; return false; } isEmpty = found == null || compare == null; return result; } public IEnumerable Where(Predicate check) { if (check == null) { throw new ArgumentNullException("check"); } foreach (var value in _bucketCore) { var castedValue = value == BucketHelper.Null ? default(T) : (T)value; if (check(castedValue)) { yield return castedValue; } } } } } #endif