#if !NET_4_6
using System;
using System.Collections.Generic;
using System.Threading;
using LinqInternal.Core;
namespace LinqInternal.Collections.ThreadSafe
{
///
/// Represents a thread-safe wait-free fixed size circular bucket.
///
/// The type of the item.
///
/// The items added an instance of this type will be overwritten after the entry point reaches the end of the bucket. This class was created for the purpose of storing in-memory logs for debugging threaded software.
///
[Serializable]
internal sealed class CircularBucket : IEnumerable
{
private readonly int _capacity;
private readonly FixedSizeBucket _entries;
private int _index;
///
/// Initializes a new instance of the class.
///
/// The capacity.
public CircularBucket(int capacity)
{
_capacity = NumericHelper.PopulationCount(capacity) == 1 ? capacity : NumericHelper.NextPowerOf2(capacity);
_index = -1;
_entries = new FixedSizeBucket(_capacity);
}
///
/// Gets the capacity.
///
public int Capacity
{
get { return _capacity; }
}
///
/// Gets the number of items that has been added.
///
public int Count
{
get { return _entries.Count; }
}
///
/// Adds the specified item. May overwrite an existing item.
///
/// The item.
/// Returns the position where the item was added.
public int Add(T item)
{
var index = Interlocked.Increment(ref _index) & (_capacity - 1);
bool isNew;
_entries.SetInternal(index, item, out isNew);
return index;
}
///
/// Returns an that allows to iterate through the collection.
///
///
/// An object that can be used to iterate through the collection.
///
public IEnumerator GetEnumerator()
{
return _entries.GetEnumerator();
}
///
/// Removes the item at the specified index.
///
/// The index.
///
/// true if the item was removed; otherwise, false.
///
/// index;index must be greater or equal to 0 and less than capacity
public bool RemoveAt(int index)
{
return _entries.RemoveAt(index);
}
///
/// Removes the item at the specified index.
///
/// The index.
/// The previous item in the specified index.
///
/// true if the item was removed; otherwise, false.
///
/// index;index must be greater or equal to 0 and less than capacity
public bool RemoveAt(int index, out T previous)
{
return _entries.RemoveAt(index, out previous);
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
///
/// Adds the specified item. Will not overwrite existing items.
///
/// The item.
/// Returns the position where the item was added, -1 otherwise.
public int TryAdd(T item)
{
var index = Interlocked.Increment(ref _index) & (_capacity - 1);
if (_entries.InsertInternal(index, item))
{
return index;
}
return -1;
}
///
/// Tries to retrieve the item at the specified index.
///
/// The index.
/// The value.
///
/// true if the item was retrieved; otherwise, false.
///
/// index;index must be greater or equal to 0 and less than capacity
public bool TryGet(int index, out T value)
{
return _entries.TryGet(index, out value);
}
}
}
#endif