Imported Upstream version 3.6.0

Former-commit-id: da6be194a6b1221998fc28233f2503bd61dd9d14
This commit is contained in:
Jo Shields
2014-08-13 10:39:27 +01:00
commit a575963da9
50588 changed files with 8155799 additions and 0 deletions

View File

@@ -0,0 +1,84 @@
2010-04-15 Jérémie Laval <jeremie.laval@gmail.com>
* ConcurrentDictionary.cs:
* ConcurrentSkipList.cs:
* OrderablePartitioner.cs:
* Partitioner.cs: Add BOOTSTRAP_NET_4_0 define
2010-03-24 Jérémie Laval <jeremie.laval@gmail.com>
* ConcurrentDictionary.cs: Remove while looping
2010-03-24 Jérémie Laval <jeremie.laval@gmail.com>
* ConcurrentDictionary.cs: Enable tracking on SpinLock
* ConcurrentSkipList.cs: Use Spinlock instead of Monitor and
refactor to use a saner lock acquiring scheme.
2010-03-24 Jérémie Laval <jeremie.laval@gmail.com>
* ConcurrentDictionary.cs: Fix lock releasing
2010-03-24 Jérémie Laval <jeremie.laval@gmail.com>
* ConcurrentDictionary.cs: Use SpinLock instead of Monitor
for basket locking
2010-02-02 Jérémie Laval <jeremie.laval@gmail.com>
* ConcurrentDictionary.cs:
* ConcurrentQueue.cs:
* ConcurrentStack.cs:
* Partitioner.cs: Port to .NET 4 beta 2 API
* ConcurrentSkipList.cs: Use Monitor for locking
2009-08-19 Jérémie Laval <jeremie.laval@gmail.com>
* Partitioner.cs: Fix infinite recursion when calling Create
with a IList.
* Partitionners/ListPartitioner.cs: Fix bad splitting for the
last partition.
2009-08-11 Jérémie Laval <jeremie.laval@gmail.com>
* ConcurrentQueue.cs:
* IProducerConsumerCollection.cs: Add BOOTSTRAP_NET_4_0.
2009-08-11 Jérémie Laval <jeremie.laval@gmail.com>
* BlockingCollection.cs: Moved type.
2009-08-04 Jérémie Laval <jeremie.laval@gmail.com>
* ConcurrentDictionary: Fix compilation issue
with IDictionary methods.
2009-07-31 Jérémie Laval <jeremie.laval@gmail.com>
* ConcurrentBag.cs:
* ConcurrentQueue.cs:
* ConcurrentStack.cs:
* ConcurrentSkipList.cs:
* ConcurrentDictionary.cs:
* IProducerConsumerCollection.cs: Make the namespace comply to 4.0b1
2009-07-31 Jérémie Laval <jeremie.laval@gmail.com>
* ConcurrentDictionary.cs:
* ConcurrentQueue.cs:
* ConcurrentStack.cs: Make the classes comply with B1 API
2009-07-27 Jérémie Laval <jeremie.laval@gmail.com>
* BlockingCollection.cs:
* ConcurrentBag.cs:
* ConcurrentDictionary.cs:
* ConcurrentQueue.cs:
* ConcurrentSkipList.cs:
* ConcurrentStack.cs:
* IProducerConsumerCollection.cs:
* OrderablePartitioner.cs:
* Partitioner.cs: Added ParallelFx files for System.Collections.Concurrent namespace

View File

@@ -0,0 +1,461 @@
// ConcurrentDictionary.cs
//
// Copyright (c) 2009 Jérémie "Garuma" Laval
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
//
#if NET_4_0
using System;
using System.Threading;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.Serialization;
using System.Diagnostics;
namespace System.Collections.Concurrent
{
[DebuggerDisplay ("Count={Count}")]
[DebuggerTypeProxy (typeof (CollectionDebuggerView<,>))]
[Serializable]
public class ConcurrentDictionary<TKey, TValue> : IDictionary<TKey, TValue>,
ICollection<KeyValuePair<TKey, TValue>>, IEnumerable<KeyValuePair<TKey, TValue>>,
IDictionary, ICollection, IEnumerable
{
IEqualityComparer<TKey> comparer;
SplitOrderedList<TKey, KeyValuePair<TKey, TValue>> internalDictionary;
public ConcurrentDictionary () : this (EqualityComparer<TKey>.Default)
{
}
public ConcurrentDictionary (IEnumerable<KeyValuePair<TKey, TValue>> collection)
: this (collection, EqualityComparer<TKey>.Default)
{
}
public ConcurrentDictionary (IEqualityComparer<TKey> comparer)
{
this.comparer = comparer;
this.internalDictionary = new SplitOrderedList<TKey, KeyValuePair<TKey, TValue>> (comparer);
}
public ConcurrentDictionary (IEnumerable<KeyValuePair<TKey, TValue>> collection, IEqualityComparer<TKey> comparer)
: this (comparer)
{
foreach (KeyValuePair<TKey, TValue> pair in collection)
Add (pair.Key, pair.Value);
}
// Parameters unused
public ConcurrentDictionary (int concurrencyLevel, int capacity)
: this (EqualityComparer<TKey>.Default)
{
}
public ConcurrentDictionary (int concurrencyLevel,
IEnumerable<KeyValuePair<TKey, TValue>> collection,
IEqualityComparer<TKey> comparer)
: this (collection, comparer)
{
}
// Parameters unused
public ConcurrentDictionary (int concurrencyLevel, int capacity, IEqualityComparer<TKey> comparer)
: this (comparer)
{
}
void CheckKey (TKey key)
{
if (key == null)
throw new ArgumentNullException ("key");
}
void Add (TKey key, TValue value)
{
while (!TryAdd (key, value));
}
void IDictionary<TKey, TValue>.Add (TKey key, TValue value)
{
Add (key, value);
}
public bool TryAdd (TKey key, TValue value)
{
CheckKey (key);
return internalDictionary.Insert (Hash (key), key, Make (key, value));
}
void ICollection<KeyValuePair<TKey,TValue>>.Add (KeyValuePair<TKey, TValue> pair)
{
Add (pair.Key, pair.Value);
}
public TValue AddOrUpdate (TKey key, Func<TKey, TValue> addValueFactory, Func<TKey, TValue, TValue> updateValueFactory)
{
CheckKey (key);
if (addValueFactory == null)
throw new ArgumentNullException ("addValueFactory");
if (updateValueFactory == null)
throw new ArgumentNullException ("updateValueFactory");
return internalDictionary.InsertOrUpdate (Hash (key),
key,
() => Make (key, addValueFactory (key)),
(e) => Make (key, updateValueFactory (key, e.Value))).Value;
}
public TValue AddOrUpdate (TKey key, TValue addValue, Func<TKey, TValue, TValue> updateValueFactory)
{
return AddOrUpdate (key, (_) => addValue, updateValueFactory);
}
TValue AddOrUpdate (TKey key, TValue addValue, TValue updateValue)
{
CheckKey (key);
return internalDictionary.InsertOrUpdate (Hash (key),
key,
Make (key, addValue),
Make (key, updateValue)).Value;
}
TValue GetValue (TKey key)
{
TValue temp;
if (!TryGetValue (key, out temp))
throw new KeyNotFoundException (key.ToString ());
return temp;
}
public bool TryGetValue (TKey key, out TValue value)
{
CheckKey (key);
KeyValuePair<TKey, TValue> pair;
bool result = internalDictionary.Find (Hash (key), key, out pair);
value = pair.Value;
return result;
}
public bool TryUpdate (TKey key, TValue newValue, TValue comparisonValue)
{
CheckKey (key);
return internalDictionary.CompareExchange (Hash (key), key, Make (key, newValue), (e) => e.Value.Equals (comparisonValue));
}
public TValue this[TKey key] {
get {
return GetValue (key);
}
set {
AddOrUpdate (key, value, value);
}
}
public TValue GetOrAdd (TKey key, Func<TKey, TValue> valueFactory)
{
CheckKey (key);
return internalDictionary.InsertOrGet (Hash (key), key, Make (key, default(TValue)), () => Make (key, valueFactory (key))).Value;
}
public TValue GetOrAdd (TKey key, TValue value)
{
CheckKey (key);
return internalDictionary.InsertOrGet (Hash (key), key, Make (key, value), null).Value;
}
public bool TryRemove (TKey key, out TValue value)
{
CheckKey (key);
KeyValuePair<TKey, TValue> data;
bool result = internalDictionary.Delete (Hash (key), key, out data);
value = data.Value;
return result;
}
bool Remove (TKey key)
{
TValue dummy;
return TryRemove (key, out dummy);
}
bool IDictionary<TKey, TValue>.Remove (TKey key)
{
return Remove (key);
}
bool ICollection<KeyValuePair<TKey,TValue>>.Remove (KeyValuePair<TKey,TValue> pair)
{
return Remove (pair.Key);
}
public bool ContainsKey (TKey key)
{
CheckKey (key);
KeyValuePair<TKey, TValue> dummy;
return internalDictionary.Find (Hash (key), key, out dummy);
}
bool IDictionary.Contains (object key)
{
if (!(key is TKey))
return false;
return ContainsKey ((TKey)key);
}
void IDictionary.Remove (object key)
{
if (!(key is TKey))
return;
Remove ((TKey)key);
}
object IDictionary.this [object key]
{
get {
TValue obj;
if (key is TKey && TryGetValue ((TKey) key, out obj))
return obj;
return null;
}
set {
if (!(key is TKey) || !(value is TValue))
throw new ArgumentException ("key or value aren't of correct type");
this[(TKey)key] = (TValue)value;
}
}
void IDictionary.Add (object key, object value)
{
if (!(key is TKey) || !(value is TValue))
throw new ArgumentException ("key or value aren't of correct type");
Add ((TKey)key, (TValue)value);
}
bool ICollection<KeyValuePair<TKey,TValue>>.Contains (KeyValuePair<TKey, TValue> pair)
{
return ContainsKey (pair.Key);
}
public KeyValuePair<TKey,TValue>[] ToArray ()
{
// This is most certainly not optimum but there is
// not a lot of possibilities
return new List<KeyValuePair<TKey,TValue>> (this).ToArray ();
}
public void Clear()
{
// Pronk
internalDictionary = new SplitOrderedList<TKey, KeyValuePair<TKey, TValue>> (comparer);
}
public int Count {
get {
return internalDictionary.Count;
}
}
public bool IsEmpty {
get {
return Count == 0;
}
}
bool ICollection<KeyValuePair<TKey, TValue>>.IsReadOnly {
get {
return false;
}
}
bool IDictionary.IsReadOnly {
get {
return false;
}
}
public ICollection<TKey> Keys {
get {
return GetPart<TKey> ((kvp) => kvp.Key);
}
}
public ICollection<TValue> Values {
get {
return GetPart<TValue> ((kvp) => kvp.Value);
}
}
ICollection IDictionary.Keys {
get {
return (ICollection)Keys;
}
}
ICollection IDictionary.Values {
get {
return (ICollection)Values;
}
}
ICollection<T> GetPart<T> (Func<KeyValuePair<TKey, TValue>, T> extractor)
{
List<T> temp = new List<T> ();
foreach (KeyValuePair<TKey, TValue> kvp in this)
temp.Add (extractor (kvp));
return temp.AsReadOnly ();
}
void ICollection.CopyTo (Array array, int startIndex)
{
KeyValuePair<TKey, TValue>[] arr = array as KeyValuePair<TKey, TValue>[];
if (arr == null)
return;
CopyTo (arr, startIndex, Count);
}
void CopyTo (KeyValuePair<TKey, TValue>[] array, int startIndex)
{
CopyTo (array, startIndex, Count);
}
void ICollection<KeyValuePair<TKey, TValue>>.CopyTo (KeyValuePair<TKey, TValue>[] array, int startIndex)
{
CopyTo (array, startIndex);
}
void CopyTo (KeyValuePair<TKey, TValue>[] array, int startIndex, int num)
{
foreach (var kvp in this) {
array [startIndex++] = kvp;
if (--num <= 0)
return;
}
}
public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator ()
{
return GetEnumeratorInternal ();
}
IEnumerator IEnumerable.GetEnumerator ()
{
return (IEnumerator)GetEnumeratorInternal ();
}
IEnumerator<KeyValuePair<TKey, TValue>> GetEnumeratorInternal ()
{
return internalDictionary.GetEnumerator ();
}
IDictionaryEnumerator IDictionary.GetEnumerator ()
{
return new ConcurrentDictionaryEnumerator (GetEnumeratorInternal ());
}
class ConcurrentDictionaryEnumerator : IDictionaryEnumerator
{
IEnumerator<KeyValuePair<TKey, TValue>> internalEnum;
public ConcurrentDictionaryEnumerator (IEnumerator<KeyValuePair<TKey, TValue>> internalEnum)
{
this.internalEnum = internalEnum;
}
public bool MoveNext ()
{
return internalEnum.MoveNext ();
}
public void Reset ()
{
internalEnum.Reset ();
}
public object Current {
get {
return Entry;
}
}
public DictionaryEntry Entry {
get {
KeyValuePair<TKey, TValue> current = internalEnum.Current;
return new DictionaryEntry (current.Key, current.Value);
}
}
public object Key {
get {
return internalEnum.Current.Key;
}
}
public object Value {
get {
return internalEnum.Current.Value;
}
}
}
object ICollection.SyncRoot {
get {
return this;
}
}
bool IDictionary.IsFixedSize {
get {
return false;
}
}
bool ICollection.IsSynchronized {
get { return true; }
}
static KeyValuePair<U, V> Make<U, V> (U key, V value)
{
return new KeyValuePair<U, V> (key, value);
}
uint Hash (TKey key)
{
return (uint)comparer.GetHashCode (key);
}
}
}
#endif

View File

@@ -0,0 +1,340 @@
// ConcurrentOrderedList.cs
//
// Copyright (c) 2010 Jérémie "Garuma" Laval
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
//
#if NET_4_0
using System;
using System.Threading;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.Serialization;
#if INSIDE_MONO_PARALLEL
using System.Collections.Concurrent;
namespace Mono.Collections.Concurrent
#else
namespace System.Collections.Concurrent
#endif
{
#if INSIDE_MONO_PARALLEL
public
#endif
class ConcurrentOrderedList<T>: ICollection<T>, IEnumerable<T>
{
class Node
{
public T Data;
public int Key;
public Node Next;
public bool Marked;
public Node ()
{
}
public Node (Node wrapped)
{
Marked = true;
Next = wrapped;
}
}
Node head;
Node tail;
IEqualityComparer<T> comparer;
int count;
public ConcurrentOrderedList () : this (EqualityComparer<T>.Default)
{
}
public ConcurrentOrderedList (IEqualityComparer<T> comparer)
{
if (comparer == null)
throw new ArgumentNullException ("comparer");
this.comparer = comparer;
head = new Node ();
tail = new Node ();
head.Next = tail;
}
public bool TryAdd (T data)
{
Node node = new Node ();
node.Data = data;
node.Key = comparer.GetHashCode (data);
if (ListInsert (node)) {
Interlocked.Increment (ref count);
return true;
}
return false;
}
public bool TryRemove (T data)
{
T dummy;
return TryRemoveHash (comparer.GetHashCode (data), out dummy);
}
public bool TryRemoveHash (int key, out T data)
{
if (ListDelete (key, out data)) {
Interlocked.Decrement (ref count);
return true;
}
return false;
}
public bool TryPop (out T data)
{
return ListPop (out data);
}
public bool Contains (T data)
{
return ContainsHash (comparer.GetHashCode (data));
}
public bool ContainsHash (int key)
{
Node node;
if (!ListFind (key, out node))
return false;
return true;
}
public bool TryGetFromHash (int key, out T data)
{
data = default (T);
Node node;
if (!ListFind (key, out node))
return false;
data = node.Data;
return true;
}
public void Clear ()
{
head.Next = tail;
}
public void CopyTo (T[] array, int startIndex)
{
if (array == null)
throw new ArgumentNullException ("array");
if (startIndex < 0)
throw new ArgumentOutOfRangeException ("startIndex");
if (count > array.Length - startIndex)
throw new ArgumentException ("array", "The number of elements is greater than the available space from startIndex to the end of the destination array.");
foreach (T item in this) {
if (startIndex >= array.Length)
break;
array[startIndex++] = item;
}
}
public IEqualityComparer<T> Comparer {
get {
return comparer;
}
}
public int Count {
get {
return count;
}
}
Node ListSearch (int key, ref Node left)
{
Node leftNodeNext = null, rightNode = null;
do {
Node t = head;
Node tNext = t.Next;
do {
if (!tNext.Marked) {
left = t;
leftNodeNext = tNext;
}
t = tNext.Marked ? tNext.Next : tNext;
if (t == tail)
break;
tNext = t.Next;
} while (tNext.Marked || t.Key < key);
rightNode = t;
if (leftNodeNext == rightNode) {
if (rightNode != tail && rightNode.Next.Marked)
continue;
else
return rightNode;
}
if (Interlocked.CompareExchange (ref left.Next, rightNode, leftNodeNext) == leftNodeNext) {
if (rightNode != tail && rightNode.Next.Marked)
continue;
else
return rightNode;
}
} while (true);
}
bool ListDelete (int key, out T data)
{
Node rightNode = null, rightNodeNext = null, leftNode = null;
data = default (T);
do {
rightNode = ListSearch (key, ref leftNode);
if (rightNode == tail || rightNode.Key != key)
return false;
data = rightNode.Data;
rightNodeNext = rightNode.Next;
if (!rightNodeNext.Marked)
if (Interlocked.CompareExchange (ref rightNode.Next, new Node (rightNodeNext), rightNodeNext) == rightNodeNext)
break;
} while (true);
if (Interlocked.CompareExchange (ref leftNode.Next, rightNodeNext, rightNode) != rightNodeNext)
ListSearch (rightNode.Key, ref leftNode);
return true;
}
bool ListPop (out T data)
{
Node rightNode = null, rightNodeNext = null, leftNode = head;
data = default (T);
do {
rightNode = head.Next;
if (rightNode == tail)
return false;
data = rightNode.Data;
rightNodeNext = rightNode.Next;
if (!rightNodeNext.Marked)
if (Interlocked.CompareExchange (ref rightNode.Next, new Node (rightNodeNext), rightNodeNext) == rightNodeNext)
break;
} while (true);
if (Interlocked.CompareExchange (ref leftNode.Next, rightNodeNext, rightNode) != rightNodeNext)
ListSearch (rightNode.Key, ref leftNode);
return true;
}
bool ListInsert (Node newNode)
{
int key = newNode.Key;
Node rightNode = null, leftNode = null;
do {
rightNode = ListSearch (key, ref leftNode);
if (rightNode != tail && rightNode.Key == key)
return false;
newNode.Next = rightNode;
if (Interlocked.CompareExchange (ref leftNode.Next, newNode, rightNode) == rightNode)
return true;
} while (true);
}
bool ListFind (int key, out Node data)
{
Node rightNode = null, leftNode = null;
data = null;
data = rightNode = ListSearch (key, ref leftNode);
return rightNode != tail && rightNode.Key == key;
}
IEnumerator<T> IEnumerable<T>.GetEnumerator ()
{
return GetEnumeratorInternal ();
}
IEnumerator IEnumerable.GetEnumerator ()
{
return GetEnumeratorInternal ();
}
IEnumerator<T> GetEnumeratorInternal ()
{
Node node = head.Next;
while (node != tail) {
while (node.Marked) {
node = node.Next;
if (node == tail)
yield break;
}
yield return node.Data;
node = node.Next;
}
}
bool ICollection<T>.IsReadOnly {
get {
return false;
}
}
void ICollection<T>.Add (T item)
{
TryAdd (item);
}
bool ICollection<T>.Remove (T item)
{
return TryRemove (item);
}
}
}
#endif

View File

@@ -0,0 +1,232 @@
// ConcurrentQueue.cs
//
// Copyright (c) 2008 Jérémie "Garuma" Laval
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
//
#if NET_4_0
using System;
using System.Threading;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.Serialization;
namespace System.Collections.Concurrent
{
[System.Diagnostics.DebuggerDisplay ("Count={Count}")]
[System.Diagnostics.DebuggerTypeProxy (typeof (CollectionDebuggerView<>))]
public class ConcurrentQueue<T> : IProducerConsumerCollection<T>, IEnumerable<T>, ICollection,
IEnumerable
{
class Node
{
public T Value;
public Node Next;
}
Node head = new Node ();
Node tail;
int count;
public ConcurrentQueue ()
{
tail = head;
}
public ConcurrentQueue (IEnumerable<T> collection): this()
{
foreach (T item in collection)
Enqueue (item);
}
public void Enqueue (T item)
{
Node node = new Node ();
node.Value = item;
Node oldTail = null;
Node oldNext = null;
bool update = false;
while (!update) {
oldTail = tail;
oldNext = oldTail.Next;
// Did tail was already updated ?
if (tail == oldTail) {
if (oldNext == null) {
// The place is for us
update = Interlocked.CompareExchange (ref tail.Next, node, null) == null;
} else {
// another Thread already used the place so give him a hand by putting tail where it should be
Interlocked.CompareExchange (ref tail, oldNext, oldTail);
}
}
}
// At this point we added correctly our node, now we have to update tail. If it fails then it will be done by another thread
Interlocked.CompareExchange (ref tail, node, oldTail);
Interlocked.Increment (ref count);
}
bool IProducerConsumerCollection<T>.TryAdd (T item)
{
Enqueue (item);
return true;
}
public bool TryDequeue (out T result)
{
result = default (T);
bool advanced = false;
while (!advanced) {
Node oldHead = head;
Node oldTail = tail;
Node oldNext = oldHead.Next;
if (oldHead == head) {
// Empty case ?
if (oldHead == oldTail) {
// This should be false then
if (oldNext != null) {
// If not then the linked list is mal formed, update tail
Interlocked.CompareExchange (ref tail, oldNext, oldTail);
continue;
}
result = default (T);
return false;
} else {
result = oldNext.Value;
advanced = Interlocked.CompareExchange (ref head, oldNext, oldHead) == oldHead;
}
}
}
Interlocked.Decrement (ref count);
return true;
}
public bool TryPeek (out T result)
{
Node first = head.Next;
if (first == null) {
result = default (T);
return false;
}
result = first.Value;
return true;
}
internal void Clear ()
{
count = 0;
tail = head = new Node ();
}
IEnumerator IEnumerable.GetEnumerator ()
{
return (IEnumerator)InternalGetEnumerator ();
}
public IEnumerator<T> GetEnumerator ()
{
return InternalGetEnumerator ();
}
IEnumerator<T> InternalGetEnumerator ()
{
Node my_head = head;
while ((my_head = my_head.Next) != null) {
yield return my_head.Value;
}
}
void ICollection.CopyTo (Array array, int index)
{
if (array == null)
throw new ArgumentNullException ("array");
if (array.Rank > 1)
throw new ArgumentException ("The array can't be multidimensional");
if (array.GetLowerBound (0) != 0)
throw new ArgumentException ("The array needs to be 0-based");
T[] dest = array as T[];
if (dest == null)
throw new ArgumentException ("The array cannot be cast to the collection element type", "array");
CopyTo (dest, 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;
}
}
public T[] ToArray ()
{
return new List<T> (this).ToArray ();
}
bool ICollection.IsSynchronized {
get { return true; }
}
bool IProducerConsumerCollection<T>.TryTake (out T item)
{
return TryDequeue (out item);
}
object syncRoot = new object();
object ICollection.SyncRoot {
get { return syncRoot; }
}
public int Count {
get {
return count;
}
}
public bool IsEmpty {
get {
return count == 0;
}
}
}
}
#endif

View File

@@ -0,0 +1,283 @@
// 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
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
//
#if NET_4_0
using System;
using System.Threading;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.Serialization;
namespace System.Collections.Concurrent
{
[System.Diagnostics.DebuggerDisplay ("Count = {Count}")]
[System.Diagnostics.DebuggerTypeProxy (typeof (CollectionDebuggerView<>))]
public class ConcurrentStack<T> : IProducerConsumerCollection<T>, IEnumerable<T>,
ICollection, IEnumerable
{
class Node
{
public T Value = default (T);
public Node Next;
}
Node head;
int count;
public ConcurrentStack ()
{
}
public ConcurrentStack (IEnumerable<T> collection)
{
if (collection == null)
throw new ArgumentNullException ("collection");
foreach (T item in collection)
Push (item);
}
bool IProducerConsumerCollection<T>.TryAdd (T elem)
{
Push (elem);
return true;
}
public void Push (T item)
{
Node temp = new Node ();
temp.Value = item;
do {
temp.Next = head;
} while (Interlocked.CompareExchange (ref head, temp, temp.Next) != temp.Next);
Interlocked.Increment (ref count);
}
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 = new Node ();
temp.Value = items[i];
temp.Next = insert;
insert = temp;
if (first == null)
first = temp;
}
do {
first.Next = head;
} while (Interlocked.CompareExchange (ref head, insert, first.Next) != first.Next);
Interlocked.Add (ref this.count, count);
}
public bool TryPop (out T result)
{
Node temp;
do {
temp = head;
// The stak is empty
if (temp == null) {
result = default (T);
return false;
}
} while (Interlocked.CompareExchange (ref head, temp.Next, temp) != temp);
Interlocked.Decrement (ref count);
result = temp.Value;
return true;
}
public int TryPopRange (T[] items)
{
if (items == null)
throw new ArgumentNullException ("items");
return TryPopRange (items, 0, items.Length);
}
public int TryPopRange (T[] items, int startIndex, int count)
{
RangeArgumentsCheck (items, startIndex, count);
Node temp;
Node end;
do {
temp = head;
if (temp == null)
return 0;
end = temp;
for (int j = 0; j < count; j++) {
end = end.Next;
if (end == null)
break;
}
} while (Interlocked.CompareExchange (ref head, end, temp) != temp);
int i;
for (i = startIndex; i < startIndex + count && temp != null; i++) {
items[i] = temp.Value;
end = temp;
temp = temp.Next;
}
Interlocked.Add (ref this.count, -(i - startIndex));
return i - startIndex;
}
public bool TryPeek (out T result)
{
Node myHead = head;
if (myHead == null) {
result = default (T);
return false;
}
result = myHead.Value;
return true;
}
public void Clear ()
{
// This is not satisfactory
count = 0;
head = null;
}
IEnumerator IEnumerable.GetEnumerator ()
{
return (IEnumerator)InternalGetEnumerator ();
}
public IEnumerator<T> GetEnumerator ()
{
return InternalGetEnumerator ();
}
IEnumerator<T> InternalGetEnumerator ()
{
Node my_head = head;
if (my_head == null) {
yield break;
} else {
do {
yield return my_head.Value;
} while ((my_head = my_head.Next) != null);
}
}
void ICollection.CopyTo (Array array, int 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 false; }
}
bool IProducerConsumerCollection<T>.TryTake (out T item)
{
return TryPop (out item);
}
object ICollection.SyncRoot {
get {
throw new NotSupportedException ();
}
}
public T[] ToArray ()
{
return new List<T> (this).ToArray ();
}
public int Count {
get {
return count;
}
}
public bool IsEmpty {
get {
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

View File

@@ -0,0 +1,40 @@
//
// EnumerablePartitionOptions.cs
//
// Authors:
// Martin Baulig (martin.baulig@xamarin.com)
//
// Copyright 2012 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 in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
#if NET_4_5
using System;
namespace System.Collections.Concurrent {
[Flags]
[Serializable]
public enum EnumerablePartitionerOptions {
None,
NoBuffering
}
}
#endif

View File

@@ -0,0 +1,40 @@
// IConcurrentCollection.cs
//
// Copyright (c) 2008 Jérémie "Garuma" Laval
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
//
#if NET_4_0
using System;
using System.Collections;
using System.Collections.Generic;
namespace System.Collections.Concurrent
{
public interface IProducerConsumerCollection<T> : IEnumerable<T>, ICollection, IEnumerable
{
bool TryAdd (T item);
bool TryTake (out T item);
T[] ToArray ();
void CopyTo (T[] array, int index);
}
}
#endif

View File

@@ -0,0 +1,144 @@
//
// OrderablePartitioner.cs
//
// Author:
// Jérémie "Garuma" Laval <jeremie.laval@gmail.com>
//
// Copyright (c) 2009 Jérémie "Garuma" Laval
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#if NET_4_0
using System;
using System.Collections.Generic;
namespace System.Collections.Concurrent
{
public abstract class OrderablePartitioner<TSource> : Partitioner<TSource>
{
bool keysOrderedInEachPartition;
bool keysOrderedAcrossPartitions;
bool keysNormalized;
protected OrderablePartitioner (bool keysOrderedInEachPartition,
bool keysOrderedAcrossPartitions,
bool keysNormalized) : base ()
{
this.keysOrderedInEachPartition = keysOrderedInEachPartition;
this.keysOrderedAcrossPartitions = keysOrderedAcrossPartitions;
this.keysNormalized = keysNormalized;
}
public override IEnumerable<TSource> GetDynamicPartitions ()
{
foreach (KeyValuePair<long, TSource> item in GetOrderableDynamicPartitions ())
yield return item.Value;
}
public override IList<IEnumerator<TSource>> GetPartitions (int partitionCount)
{
IEnumerator<TSource>[] temp = new IEnumerator<TSource>[partitionCount];
IList<IEnumerator<KeyValuePair<long, TSource>>> enumerators
= GetOrderablePartitions (partitionCount);
for (int i = 0; i < enumerators.Count; i++)
temp[i] = new ProxyEnumerator (enumerators[i]);
return temp;
}
IEnumerator<TSource> GetProxyEnumerator (IEnumerator<KeyValuePair<long, TSource>> enumerator)
{
while (enumerator.MoveNext ())
yield return enumerator.Current.Value;
}
public abstract IList<IEnumerator<KeyValuePair<long, TSource>>> GetOrderablePartitions(int partitionCount);
public virtual IEnumerable<KeyValuePair<long, TSource>> GetOrderableDynamicPartitions()
{
if (!SupportsDynamicPartitions)
throw new NotSupportedException ();
return null;
}
public bool KeysOrderedInEachPartition {
get {
return keysOrderedInEachPartition;
}
}
public bool KeysOrderedAcrossPartitions {
get {
return keysOrderedAcrossPartitions;
}
}
public bool KeysNormalized {
get {
return keysNormalized;
}
}
class ProxyEnumerator : IEnumerator<TSource>, IDisposable
{
IEnumerator<KeyValuePair<long, TSource>> internalEnumerator;
internal ProxyEnumerator (IEnumerator<KeyValuePair<long, TSource>> enumerator)
{
internalEnumerator = enumerator;
}
public void Dispose ()
{
internalEnumerator.Dispose ();
}
public bool MoveNext ()
{
if (!internalEnumerator.MoveNext ())
return false;
Current = internalEnumerator.Current.Value;
return true;
}
public void Reset ()
{
internalEnumerator.Reset ();
}
object IEnumerator.Current {
get {
return Current;
}
}
public TSource Current {
get;
private set;
}
}
}
}
#endif

View File

@@ -0,0 +1,136 @@
//
// Partitioner.cs
//
// Author:
// Jérémie "Garuma" Laval <jeremie.laval@gmail.com>
//
// Copyright (c) 2009 Jérémie "Garuma" Laval
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#if NET_4_0
using System;
using System.Collections.Generic;
namespace System.Collections.Concurrent
{
using Partitioners;
public static class Partitioner
{
public static OrderablePartitioner<TSource> Create<TSource> (IEnumerable<TSource> source)
{
IList<TSource> tempIList = source as IList<TSource>;
if (tempIList != null)
return Create (tempIList, true);
return new EnumerablePartitioner<TSource> (source);
}
public static OrderablePartitioner<TSource> Create<TSource> (TSource[] array, bool loadBalance)
{
return Create ((IList<TSource>)array, loadBalance);
}
public static OrderablePartitioner<TSource> Create<TSource> (IList<TSource> list, bool loadBalance)
{
return new ListPartitioner<TSource> (list);
}
public static OrderablePartitioner<Tuple<int, int>> Create (int fromInclusive,
int toExclusive)
{
// This formula that is somewhat non-straighforward was guessed based on MS output
int rangeSize = (toExclusive - fromInclusive) / (Environment.ProcessorCount * 3);
if (rangeSize < 1)
rangeSize = 1;
return Create (fromInclusive, toExclusive, rangeSize);
}
public static OrderablePartitioner<Tuple<int, int>> Create (int fromInclusive,
int toExclusive,
int rangeSize)
{
if (fromInclusive >= toExclusive)
throw new ArgumentOutOfRangeException ("toExclusive");
if (rangeSize <= 0)
throw new ArgumentOutOfRangeException ("rangeSize");
return new UserRangePartitioner (fromInclusive, toExclusive, rangeSize);
}
public static OrderablePartitioner<Tuple<long, long>> Create (long fromInclusive,
long toExclusive)
{
long rangeSize = (toExclusive - fromInclusive) / (Environment.ProcessorCount * 3);
if (rangeSize < 1)
rangeSize = 1;
return Create (fromInclusive, toExclusive, rangeSize);
}
public static OrderablePartitioner<Tuple<long, long>> Create (long fromInclusive,
long toExclusive,
long rangeSize)
{
if (rangeSize <= 0)
throw new ArgumentOutOfRangeException ("rangeSize");
if (fromInclusive >= toExclusive)
throw new ArgumentOutOfRangeException ("toExclusive");
return new UserLongRangePartitioner (fromInclusive, toExclusive, rangeSize);
}
#if NET_4_5
[MonoTODO]
public static OrderablePartitioner<TSource> Create<TSource> (IEnumerable<TSource> source,
EnumerablePartitionerOptions partitionerOptions)
{
throw new NotImplementedException ();
}
#endif
}
public abstract class Partitioner<TSource>
{
protected Partitioner ()
{
}
public virtual IEnumerable<TSource> GetDynamicPartitions ()
{
if (!SupportsDynamicPartitions)
throw new NotSupportedException ();
return null;
}
public abstract IList<IEnumerator<TSource>> GetPartitions (int partitionCount);
public virtual bool SupportsDynamicPartitions {
get {
return false;
}
}
}
}
#endif

File diff suppressed because it is too large Load Diff