#if MONO
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
using System.Security.Permissions;
using System.Threading;
namespace System.Collections.Concurrent
{
internal struct VolatileBool
{
public volatile bool m_value;
public VolatileBool(bool value)
{
this.m_value = value;
}
}
/// Defines methods to manipulate thread-safe collections intended for producer/consumer usage. This interface provides a unified representation for producer/consumer collections so that higher level abstractions such as can use the collection as the underlying storage mechanism.
/// Specifies the type of elements in the collection.
[__DynamicallyInvokable]
public interface IProducerConsumerCollection : IEnumerable, ICollection, IEnumerable
{
/// Copies the elements of the to an , starting at a specified index.
/// The one-dimensional that is the destination of the elements copied from the . The array must have zero-based indexing.
/// The zero-based index in at which copying begins.
///
/// is a null reference (Nothing in Visual Basic).
///
/// is less than zero.
///
/// is equal to or greater than the length of the -or- The number of elements in the collection is greater than the available space from to the end of the destination .
[__DynamicallyInvokable]
void CopyTo(T[] array, int index);
/// Attempts to add an object to the .
/// true if the object was added successfully; otherwise, false.
/// The object to add to the .
/// The was invalid for this collection.
[__DynamicallyInvokable]
bool TryAdd(T item);
/// Attempts to remove and return an object from the .
/// true if an object was removed and returned successfully; otherwise, false.
/// When this method returns, if the object was removed and returned successfully, contains the removed object. If no object was available to be removed, the value is unspecified.
[__DynamicallyInvokable]
bool TryTake(out T item);
/// Copies the elements contained in the to a new array.
/// A new array containing the elements copied from the .
[__DynamicallyInvokable]
T[] ToArray();
}
/// Represents a thread-safe first in-first out (FIFO) collection.
/// The type of the elements contained in the queue.
[__DynamicallyInvokable, DebuggerDisplay("Count = {Count}"), ComVisible(false)]
[HostProtection(SecurityAction.LinkDemand, Synchronization = true, ExternalThreading = true)]
[Serializable]
public class ConcurrentQueue : IProducerConsumerCollection, IEnumerable, ICollection, IEnumerable
{
private class Segment
{
internal volatile T[] m_array;
internal volatile VolatileBool[] m_state;
private volatile ConcurrentQueue.Segment m_next;
internal readonly long m_index;
private volatile int m_low;
private volatile int m_high;
private volatile ConcurrentQueue m_source;
internal ConcurrentQueue.Segment Next
{
get
{
return this.m_next;
}
}
internal bool IsEmpty
{
get
{
return this.Low > this.High;
}
}
internal int Low
{
get
{
return Math.Min(this.m_low, 32);
}
}
internal int High
{
get
{
return Math.Min(this.m_high, 31);
}
}
internal Segment(long index, ConcurrentQueue source)
{
this.m_array = new T[32];
this.m_state = new VolatileBool[32];
this.m_high = -1;
this.m_index = index;
this.m_source = source;
}
internal void UnsafeAdd(T value)
{
this.m_high++;
this.m_array[this.m_high] = value;
this.m_state[this.m_high].m_value = true;
}
internal ConcurrentQueue.Segment UnsafeGrow()
{
ConcurrentQueue.Segment segment = new ConcurrentQueue.Segment(this.m_index + 1L, this.m_source);
this.m_next = segment;
return segment;
}
internal void Grow()
{
ConcurrentQueue.Segment next = new ConcurrentQueue.Segment(this.m_index + 1L, this.m_source);
this.m_next = next;
this.m_source.m_tail = this.m_next;
}
internal bool TryAppend(T value)
{
if (this.m_high >= 31)
{
return false;
}
int num = 32;
try
{
}
finally
{
num = Interlocked.Increment(ref this.m_high);
if (num <= 31)
{
this.m_array[num] = value;
this.m_state[num].m_value = true;
}
if (num == 31)
{
this.Grow();
}
}
return num <= 31;
}
internal bool TryRemove(out T result)
{
SpinWait spinWait = default(SpinWait);
int i = this.Low;
int high = this.High;
while (i <= high)
{
if (Interlocked.CompareExchange(ref this.m_low, i + 1, i) == i)
{
SpinWait spinWait2 = default(SpinWait);
while (!this.m_state[i].m_value)
{
spinWait2.SpinOnce();
}
result = this.m_array[i];
if (this.m_source.m_numSnapshotTakers <= 0)
{
this.m_array[i] = default(T);
}
if (i + 1 >= 32)
{
spinWait2 = default(SpinWait);
while (this.m_next == null)
{
spinWait2.SpinOnce();
}
this.m_source.m_head = this.m_next;
}
return true;
}
spinWait.SpinOnce();
i = this.Low;
high = this.High;
}
result = default(T);
return false;
}
internal bool TryPeek(out T result)
{
result = default(T);
int low = this.Low;
if (low > this.High)
{
return false;
}
SpinWait spinWait = default(SpinWait);
while (!this.m_state[low].m_value)
{
spinWait.SpinOnce();
}
result = this.m_array[low];
return true;
}
internal void AddToList(List list, int start, int end)
{
for (int i = start; i <= end; i++)
{
SpinWait spinWait = default(SpinWait);
while (!this.m_state[i].m_value)
{
spinWait.SpinOnce();
}
list.Add(this.m_array[i]);
}
}
}
[NonSerialized]
private volatile ConcurrentQueue.Segment m_head;
[NonSerialized]
private volatile ConcurrentQueue.Segment m_tail;
private T[] m_serializationArray;
[NonSerialized]
internal volatile int m_numSnapshotTakers;
private const int SEGMENT_SIZE = 32;
/// Gets a value indicating whether access to the is synchronized with the SyncRoot.
/// true if access to the is synchronized with the SyncRoot; otherwise, false. For , this property always returns false.
[__DynamicallyInvokable]
bool ICollection.IsSynchronized
{
[__DynamicallyInvokable]
get
{
return false;
}
}
/// Gets an object that can be used to synchronize access to the . This property is not supported.
/// Returns null (Nothing in Visual Basic).
/// The SyncRoot property is not supported.
[__DynamicallyInvokable]
object ICollection.SyncRoot
{
[__DynamicallyInvokable]
get
{
throw new NotSupportedException("ConcurrentCollection_SyncRoot_NotSupported");
}
}
/// Gets a value that indicates whether the is empty.
/// true if the is empty; otherwise, false.
[__DynamicallyInvokable]
public bool IsEmpty
{
[__DynamicallyInvokable]
get
{
ConcurrentQueue.Segment head = this.m_head;
if (!head.IsEmpty)
{
return false;
}
if (head.Next == null)
{
return true;
}
SpinWait spinWait = default(SpinWait);
while (head.IsEmpty)
{
if (head.Next == null)
{
return true;
}
spinWait.SpinOnce();
head = this.m_head;
}
return false;
}
}
/// Gets the number of elements contained in the .
/// The number of elements contained in the .
[__DynamicallyInvokable]
public int Count
{
[__DynamicallyInvokable]
get
{
ConcurrentQueue.Segment segment;
ConcurrentQueue.Segment segment2;
int num;
int num2;
this.GetHeadTailPositions(out segment, out segment2, out num, out num2);
if (segment == segment2)
{
return num2 - num + 1;
}
int num3 = 32 - num;
num3 += 32 * (int)(segment2.m_index - segment.m_index - 1L);
return num3 + (num2 + 1);
}
}
/// Initializes a new instance of the class.
[__DynamicallyInvokable]
public ConcurrentQueue()
{
this.m_head = (this.m_tail = new ConcurrentQueue.Segment(0L, this));
}
private void InitializeFromCollection(IEnumerable collection)
{
ConcurrentQueue.Segment segment = new ConcurrentQueue.Segment(0L, this);
this.m_head = segment;
int num = 0;
foreach (T current in collection)
{
segment.UnsafeAdd(current);
num++;
if (num >= 32)
{
segment = segment.UnsafeGrow();
num = 0;
}
}
this.m_tail = segment;
}
/// Initializes a new instance of the class that contains elements copied from the specified collection
/// The collection whose elements are copied to the new .
/// The argument is null.
[__DynamicallyInvokable]
public ConcurrentQueue(IEnumerable collection)
{
if (collection == null)
{
throw new ArgumentNullException("collection");
}
this.InitializeFromCollection(collection);
}
[OnSerializing]
private void OnSerializing(StreamingContext context)
{
this.m_serializationArray = this.ToArray();
}
[OnDeserialized]
private void OnDeserialized(StreamingContext context)
{
this.InitializeFromCollection(this.m_serializationArray);
this.m_serializationArray = null;
}
/// Copies the elements of the to an , starting at a particular index.
/// The one-dimensional that is the destination of the elements copied from the . The must have zero-based indexing.
/// The zero-based index in at which copying begins.
///
/// is a null reference (Nothing in Visual Basic).
///
/// is less than zero.
///
/// is multidimensional. -or- does not have zero-based indexing. -or- is equal to or greater than the length of the -or- The number of elements in the source is greater than the available space from to the end of the destination . -or- The type of the source cannot be cast automatically to the type of the destination .
[__DynamicallyInvokable]
void ICollection.CopyTo(Array array, int index)
{
if (array == null)
{
throw new ArgumentNullException("array");
}
((ICollection)this.ToList()).CopyTo(array, index);
}
/// Returns an enumerator that iterates through a collection.
/// An that can be used to iterate through the collection.
[__DynamicallyInvokable]
IEnumerator IEnumerable.GetEnumerator()
{
return ((IEnumerable)this).GetEnumerator();
}
[__DynamicallyInvokable]
bool IProducerConsumerCollection.TryAdd(T item)
{
this.Enqueue(item);
return true;
}
[__DynamicallyInvokable]
bool IProducerConsumerCollection.TryTake(out T item)
{
return this.TryDequeue(out item);
}
/// Copies the elements stored in the to a new array.
/// A new array containing a snapshot of elements copied from the .
[__DynamicallyInvokable]
public T[] ToArray()
{
return this.ToList().ToArray();
}
private List ToList()
{
Interlocked.Increment(ref this.m_numSnapshotTakers);
List list = new List();
try
{
ConcurrentQueue.Segment segment;
ConcurrentQueue.Segment segment2;
int start;
int end;
this.GetHeadTailPositions(out segment, out segment2, out start, out end);
if (segment == segment2)
{
segment.AddToList(list, start, end);
}
else
{
segment.AddToList(list, start, 31);
for (ConcurrentQueue.Segment next = segment.Next; next != segment2; next = next.Next)
{
next.AddToList(list, 0, 31);
}
segment2.AddToList(list, 0, end);
}
}
finally
{
Interlocked.Decrement(ref this.m_numSnapshotTakers);
}
return list;
}
private void GetHeadTailPositions(out ConcurrentQueue.Segment head, out ConcurrentQueue.Segment tail, out int headLow, out int tailHigh)
{
head = this.m_head;
tail = this.m_tail;
headLow = head.Low;
tailHigh = tail.High;
SpinWait spinWait = default(SpinWait);
while (head != this.m_head || tail != this.m_tail || headLow != head.Low || tailHigh != tail.High || head.m_index > tail.m_index)
{
spinWait.SpinOnce();
head = this.m_head;
tail = this.m_tail;
headLow = head.Low;
tailHigh = tail.High;
}
}
/// Copies the elements to an existing one-dimensional , starting at the specified array index.
/// The one-dimensional that is the destination of the elements copied from the . The must have zero-based indexing.
/// The zero-based index in at which copying begins.
///
/// is a null reference (Nothing in Visual Basic).
///
/// is less than zero.
///
/// is equal to or greater than the length of the -or- The number of elements in the source is greater than the available space from to the end of the destination .
[__DynamicallyInvokable]
public void CopyTo(T[] array, int index)
{
if (array == null)
{
throw new ArgumentNullException("array");
}
this.ToList().CopyTo(array, index);
}
/// Returns an enumerator that iterates through the .
/// An enumerator for the contents of the .
[__DynamicallyInvokable]
public IEnumerator GetEnumerator()
{
Interlocked.Increment(ref this.m_numSnapshotTakers);
ConcurrentQueue.Segment head;
ConcurrentQueue.Segment tail;
int headLow;
int tailHigh;
this.GetHeadTailPositions(out head, out tail, out headLow, out tailHigh);
return this.GetEnumerator(head, tail, headLow, tailHigh);
}
private IEnumerator GetEnumerator(ConcurrentQueue.Segment head, ConcurrentQueue.Segment tail, int headLow, int tailHigh)
{
try
{
SpinWait spinWait = default(SpinWait);
if (head == tail)
{
for (int i = headLow; i <= tailHigh; i++)
{
spinWait.Reset();
while (!head.m_state[i].m_value)
{
spinWait.SpinOnce();
}
yield return head.m_array[i];
}
}
else
{
for (int j = headLow; j < 32; j++)
{
spinWait.Reset();
while (!head.m_state[j].m_value)
{
spinWait.SpinOnce();
}
yield return head.m_array[j];
}
for (ConcurrentQueue.Segment next = head.Next; next != tail; next = next.Next)
{
for (int k = 0; k < 32; k++)
{
spinWait.Reset();
while (!next.m_state[k].m_value)
{
spinWait.SpinOnce();
}
yield return next.m_array[k];
}
}
for (int l = 0; l <= tailHigh; l++)
{
spinWait.Reset();
while (!tail.m_state[l].m_value)
{
spinWait.SpinOnce();
}
yield return tail.m_array[l];
}
}
}
finally
{
Interlocked.Decrement(ref this.m_numSnapshotTakers);
}
yield break;
}
/// Adds an object to the end of the .
/// The object to add to the end of the . The value can be a null reference (Nothing in Visual Basic) for reference types.
[__DynamicallyInvokable]
public void Enqueue(T item)
{
SpinWait spinWait = default(SpinWait);
while (true)
{
ConcurrentQueue.Segment tail = this.m_tail;
if (tail.TryAppend(item))
{
break;
}
spinWait.SpinOnce();
}
}
/// Attempts to remove and return the object at the beginning of the .
/// true if an element was removed and returned from the beginning of the successfully; otherwise, false.
/// When this method returns, if the operation was successful, contains the object removed. If no object was available to be removed, the value is unspecified.
[__DynamicallyInvokable]
public bool TryDequeue(out T result)
{
while (!this.IsEmpty)
{
ConcurrentQueue.Segment head = this.m_head;
if (head.TryRemove(out result))
{
return true;
}
}
result = default(T);
return false;
}
/// Attempts to return an object from the beginning of the without removing it.
/// true if and object was returned successfully; otherwise, false.
/// When this method returns, contains an object from the beginning of the or an unspecified value if the operation failed.
[__DynamicallyInvokable]
public bool TryPeek(out T result)
{
while (!this.IsEmpty)
{
ConcurrentQueue.Segment head = this.m_head;
if (head.TryPeek(out result))
{
return true;
}
}
result = default(T);
return false;
}
}
}
#endif