// ConcurrentStack.cs
//
+// Authors:
+// Marek Safar <marek.safar@gmail.com>
+//
// Copyright (c) 2008 Jérémie "Garuma" Laval
+// Copyright (C) 2014 Xamarin Inc (http://www.xamarin.com)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
//
//
-#if NET_4_0 || MOBILE
+#if NET_4_0
using System;
using System.Threading;
class Node
{
public T Value = default (T);
- public Node Next = null;
+ public Node Next;
}
- Node head = null;
+ Node head;
int count;
-
- class NodeObjectPool : ObjectPool<Node> {
- protected override Node Creator ()
- {
- return new Node ();
- }
- }
- static readonly NodeObjectPool pool = new NodeObjectPool ();
-
- static Node ZeroOut (Node node)
- {
- node.Value = default(T);
- node.Next = null;
- return node;
- }
public ConcurrentStack ()
{
public ConcurrentStack (IEnumerable<T> collection)
{
+ if (collection == null)
+ throw new ArgumentNullException ("collection");
+
foreach (T item in collection)
Push (item);
}
public void Push (T item)
{
- Node temp = pool.Take ();
+ Node temp = new Node ();
temp.Value = item;
do {
temp.Next = head;
public void PushRange (T[] items)
{
+ if (items == null)
+ throw new ArgumentNullException ("items");
+
PushRange (items, 0, items.Length);
}
public void PushRange (T[] items, int startIndex, int count)
{
+ RangeArgumentsCheck (items, startIndex, count);
+
Node insert = null;
Node first = null;
for (int i = startIndex; i < count; i++) {
- Node temp = pool.Take ();
+ Node temp = new Node ();
temp.Value = items[i];
temp.Next = insert;
insert = temp;
Interlocked.Decrement (ref count);
result = temp.Value;
- pool.Release (ZeroOut (temp));
return true;
}
public int TryPopRange (T[] items, int startIndex, int count)
{
- if (items == null)
- throw new ArgumentNullException ("items");
- if (startIndex < 0 || startIndex >= items.Length)
- throw new ArgumentOutOfRangeException ("startIndex");
- if (count < 0)
- throw new ArgumentOutOfRangeException ("count");
- if (startIndex + count > items.Length)
- throw new ArgumentException ("startIndex + count is greater than the length of items.");
+ RangeArgumentsCheck (items, startIndex, count);
Node temp;
Node end;
do {
temp = head;
if (temp == null)
- return -1;
+ return 0;
end = temp;
for (int j = 0; j < count; j++) {
end = end.Next;
items[i] = temp.Value;
end = temp;
temp = temp.Next;
- pool.Release (ZeroOut (end));
}
- this.count -= (i - startIndex);
+ Interlocked.Add (ref this.count, -(i - startIndex));
return i - startIndex;
}
void ICollection.CopyTo (Array array, int index)
{
- T[] dest = array as T[];
- if (dest == null)
- return;
- CopyTo (dest, index);
+ ICollection ic = new List<T> (this);
+ ic.CopyTo (array, index);
}
public void CopyTo (T[] array, int index)
{
+ if (array == null)
+ throw new ArgumentNullException ("array");
+ if (index < 0)
+ throw new ArgumentOutOfRangeException ("index");
+ if (index > array.Length)
+ throw new ArgumentException ("index is equals or greather than array length", "index");
+
IEnumerator<T> e = InternalGetEnumerator ();
int i = index;
while (e.MoveNext ()) {
+ if (i == array.Length - index)
+ throw new ArgumentException ("The number of elememts in the collection exceeds the capacity of array", "array");
array[i++] = e.Current;
}
}
bool ICollection.IsSynchronized {
- get { return true; }
+ get { return false; }
}
bool IProducerConsumerCollection<T>.TryTake (out T item)
return TryPop (out item);
}
- object syncRoot = new object ();
object ICollection.SyncRoot {
- get { return syncRoot; }
+ get {
+ throw new NotSupportedException ();
+ }
}
public T[] ToArray ()
{
- T[] dest = new T [count];
- CopyTo (dest, 0);
- return dest;
+ return new List<T> (this).ToArray ();
}
public int Count {
return count == 0;
}
}
+
+ static void RangeArgumentsCheck (T[] items, int startIndex, int count)
+ {
+ if (items == null)
+ throw new ArgumentNullException ("items");
+ if (startIndex < 0 || startIndex >= items.Length)
+ throw new ArgumentOutOfRangeException ("startIndex");
+ if (count < 0)
+ throw new ArgumentOutOfRangeException ("count");
+ if (startIndex + count > items.Length)
+ throw new ArgumentException ("startIndex + count is greater than the length of items.");
+ }
}
}
#endif