-2009-02-16 Jérémie Laval <jeremie.laval@gmail.com>
-
- * System.Threading.Collections/:
- * System.Threading.Tasks: Added ParallelFx related directories from
- Google code svn r516.
- * corlib.dll.sources/corlib_test.dll.sources: Added ParallelFx files
-
2009-02-07 Zoltan Varga <vargaz@gmail.com>
* Makefile: Add Test/resources/Fergie.GED to EXTRA_DIST.
+++ /dev/null
-#if NET_4_0
-// BlockingCollection.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.
-//
-//
-
-using System;
-using System.Linq;
-using System.Threading;
-using System.Collections;
-using System.Collections.Generic;
-using System.Diagnostics;
-
-namespace System.Threading.Collections
-{
- public class BlockingCollection<T>: IEnumerable<T>, ICollection, IEnumerable, IDisposable
- {
- readonly IConcurrentCollection<T> underlyingColl;
- readonly int upperBound;
- readonly Func<bool> isFull;
-
- readonly SpinWait sw = new SpinWait();
-
- volatile bool isComplete;
- readonly SpinLock addLock = new SpinLock(false);
-
- #region ctors
- public BlockingCollection():
- this(new ConcurrentQueue<T>(), -1)
- {
- }
-
- public BlockingCollection(int upperBound):
- this(new ConcurrentQueue<T>(), upperBound)
- {
- }
-
- public BlockingCollection(IConcurrentCollection<T> underlyingColl):
- this(underlyingColl, -1)
- {
- }
-
- public BlockingCollection(IConcurrentCollection<T> underlyingColl, int upperBound)
- {
- this.underlyingColl = underlyingColl;
- this.upperBound = upperBound;
-
- if (upperBound == -1)
- isFull = FalseIsFull;
- else
- isFull = CountBasedIsFull;
- //isFull = (upperBound == -1) ? FalseIsFull : CountBasedIsFull;
- }
-
- ~BlockingCollection()
- {
- Dispose(false);
- }
-
- static bool FalseIsFull()
- {
- return false;
- }
-
- bool CountBasedIsFull()
- {
- return underlyingColl.Count >= upperBound;
- }
- #endregion
-
- #region Add & Remove (+ Try)
- public void Add(T item)
- {
- while (true) {
- while (isFull()) {
- if (isComplete)
- throw new InvalidOperationException("The BlockingCollection<T>"
- + " has been marked as complete with regards to additions.");
- Block();
- }
- // Extra check. The status might have changed after Block() or if isFull() is always false
- if (isComplete)
- throw new InvalidOperationException("The BlockingCollection<T> has"
- + " been marked as complete with regards to additions.");
-
- try {
- addLock.Enter();
- // Go back in main waiting loop
- if (isFull())
- continue;
- underlyingColl.Add(item);
- return;
- } finally {
- addLock.Exit(true);
- }
- }
- }
-
- public T Remove()
- {
- while (underlyingColl.Count == 0) {
- if (isComplete)
- throw new OperationCanceledException("The BlockingCollection<T> is empty and has been marked as complete with regards to additions.");
- Block();
- }
-
- T item;
- underlyingColl.Remove(out item);
-
- return item;
- }
-
- public bool TryAdd(T item)
- {
- if (isComplete || isFull()) {
- return false;
- }
- try {
- addLock.Enter();
- if (isFull()) {
- return false;
- }
- return underlyingColl.Add(item);
- } finally {
- addLock.Exit(true);
- }
- }
-
- public bool TryAdd(T item, TimeSpan ts)
- {
- return TryAdd(item, (int)ts.TotalMilliseconds);
- }
-
- public bool TryAdd(T item, int millisecondsTimeout)
- {
- Stopwatch sw = Stopwatch.StartNew();
- while (isFull()) {
- if (isComplete || sw.ElapsedMilliseconds > millisecondsTimeout) {
- sw.Stop();
- return false;
- }
- Block();
- }
- return underlyingColl.Add(item);
- }
-
- public bool TryRemove(out T item)
- {
- return underlyingColl.Remove(out item);
- }
-
- public bool TryRemove(out T item, TimeSpan ts)
- {
- return TryRemove(out item, (int)ts.TotalMilliseconds);
- }
-
- public bool TryRemove(out T item, int millisecondsTimeout)
- {
- Stopwatch sw = Stopwatch.StartNew();
- while (underlyingColl.Count == 0) {
- if (isComplete || sw.ElapsedMilliseconds > millisecondsTimeout) {
- item = default(T);
- return false;
- }
-
- Block();
- }
- return underlyingColl.Remove(out item);
- }
- #endregion
-
- #region static methods
- static void CheckArray(BlockingCollection<T>[] collections)
- {
- if (collections == null)
- throw new ArgumentNullException("collections");
- if (collections.Length == 0 || collections.Where(e => e == null).Any())
- throw new ArgumentException("The collections argument is a 0-length array or contains a null element.", "collections");
- }
-
- public static int AddAny(BlockingCollection<T>[] collections, T item)
- {
- CheckArray(collections);
- int index = 0;
- foreach (var coll in collections) {
- try {
- coll.Add(item);
- return index;
- } catch {}
- index++;
- }
- return -1;
- }
-
- public static int TryAddAny(BlockingCollection<T>[] collections, T item)
- {
- CheckArray(collections);
- int index = 0;
- foreach (var coll in collections) {
- if (coll.TryAdd(item))
- return index;
- index++;
- }
- return -1;
- }
-
- public static int TryAddAny(BlockingCollection<T>[] collections, T item, TimeSpan ts)
- {
- CheckArray(collections);
- int index = 0;
- foreach (var coll in collections) {
- if (coll.TryAdd(item, ts))
- return index;
- index++;
- }
- return -1;
- }
-
- public static int TryAddAny(BlockingCollection<T>[] collections, T item, int millisecondsTimeout)
- {
- CheckArray(collections);
- int index = 0;
- foreach (var coll in collections) {
- if (coll.TryAdd(item, millisecondsTimeout))
- return index;
- index++;
- }
- return -1;
- }
-
- public static int RemoveAny(BlockingCollection<T>[] collections, out T item)
- {
- item = default(T);
- CheckArray(collections);
- int index = 0;
- foreach (var coll in collections) {
- try {
- item = coll.Remove();
- return index;
- } catch {}
- index++;
- }
- return -1;
- }
-
- public static int TryRemoveAny(BlockingCollection<T>[] collections, out T item)
- {
- item = default(T);
-
- CheckArray(collections);
- int index = 0;
- foreach (var coll in collections) {
- if (coll.TryRemove(out item))
- return index;
- index++;
- }
- return -1;
- }
-
- public static int TryRemoveAny(BlockingCollection<T>[] collections, out T item, TimeSpan ts)
- {
- item = default(T);
-
- CheckArray(collections);
- int index = 0;
- foreach (var coll in collections) {
- if (coll.TryRemove(out item, ts))
- return index;
- index++;
- }
- return -1;
- }
-
- public static int TryRemoveAny(BlockingCollection<T>[] collections, out T item, int millisecondsTimeout)
- {
- item = default(T);
-
- CheckArray(collections);
- int index = 0;
- foreach (var coll in collections) {
- if (coll.TryRemove(out item, millisecondsTimeout))
- return index;
- index++;
- }
- return -1;
- }
- #endregion
-
- public void CompleteAdding()
- {
- isComplete = true;
- }
-
- void ICollection.CopyTo(Array array, int index)
- {
- underlyingColl.CopyTo(array, index);
- }
-
- public void CopyTo(T[] array, int index)
- {
- underlyingColl.CopyTo(array, index);
- }
-
- public IEnumerable<T> GetConsumingEnumerable()
- {
- T item;
- while (underlyingColl.Remove(out item)) {
- yield return item;
- }
- }
-
- IEnumerator IEnumerable.GetEnumerator ()
- {
- return ((IEnumerable)underlyingColl).GetEnumerator();
- }
-
- IEnumerator<T> IEnumerable<T>.GetEnumerator ()
- {
- return ((IEnumerable<T>)underlyingColl).GetEnumerator();
- }
-
- public IEnumerator<T> GetEnumerator ()
- {
- return ((IEnumerable<T>)underlyingColl).GetEnumerator();
- }
-
- public void Dispose()
- {
- Dispose(true);
- }
-
- protected virtual void Dispose(bool managedRes)
- {
-
- }
-
- public T[] ToArray()
- {
- return underlyingColl.ToArray();
- }
-
- // Method used to stall the thread for a limited period of time before retrying an operation
- void Block()
- {
- sw.SpinOnce();
- }
-
- public int BoundedCapacity {
- get {
- return upperBound;
- }
- }
-
- public int Count {
- get {
- return underlyingColl.Count;
- }
- }
-
- public bool IsAddingCompleted {
- get {
- return isComplete;
- }
- }
-
- public bool IsCompleted {
- get {
- return isComplete && underlyingColl.Count == 0;
- }
- }
-
- object ICollection.SyncRoot {
- get {
- return underlyingColl.SyncRoot;
- }
- }
-
- bool ICollection.IsSynchronized {
- get {
- return underlyingColl.IsSynchronized;
- }
- }
- }
-}
-#endif
+++ /dev/null
-2009-02-16 Jérémie Laval <jeremie.laval@gmail.com>
-
- * *.cs: Initial commit from Google code svn r516.
+++ /dev/null
-#if NET_4_0
-// ConcurrentSkipList.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.
-//
-//
-
-using System;
-using System.Threading;
-using System.Collections;
-using System.Collections.Generic;
-
-namespace System.Threading.Collections
-{
- public class ConcurrentDictionary<TKey, TValue> : IDictionary<TKey, TValue>
- {
- class Pair
- {
- public readonly TKey Key;
- public TValue Value;
-
- public Pair(TKey key, TValue value)
- {
- Key = key;
- Value = value;
- }
-
- public override bool Equals (object obj)
- {
- Pair rhs = obj as Pair;
- return rhs == null ? false : Key.Equals(rhs.Key) && Value.Equals(rhs.Value);
- }
-
- public override int GetHashCode ()
- {
- return Key.GetHashCode();
- }
- }
-
- class Basket: List<Pair>
- {
- }
-
- // Assumption: a List<T> is never empty
- ConcurrentSkipList<Basket> container
- = new ConcurrentSkipList<Basket>((value) => value[0].GetHashCode());
- int count;
- int stamp = int.MinValue;
-
- public ConcurrentDictionary()
- {
- }
-
- public void Add(TKey key, TValue value)
- {
- Basket basket;
- // Add a value to an existing basket
- if (TryGetBasket(key, out basket)) {
- // Find a maybe more sexy locking scheme later
- lock (basket) {
- foreach (var p in basket) {
- if (p.Key.Equals(key))
- throw new ArgumentException("An element with the same key already exists");
- }
- basket.Add(new Pair(key, value));
- }
- } else {
- // Add a new basket
- basket = new Basket();
- basket.Add(new Pair(key, value));
- container.Add(basket);
- }
- Interlocked.Increment(ref count);
- Interlocked.Increment(ref stamp);
- }
-
- void ICollection<KeyValuePair<TKey,TValue>>.Add(KeyValuePair<TKey, TValue> pair)
- {
- Add(pair.Key, pair.Value);
- }
-
- public TValue GetValue(TKey key)
- {
- TValue temp;
- if (!TryGetValue(key, out temp))
- // TODO: find a correct Exception
- throw new ArgumentOutOfRangeException("key");
- return temp;
- }
-
- public bool TryGetValue(TKey key, out TValue value)
- {
- Basket basket;
- value = default(TValue);
-
- if (!TryGetBasket(key, out basket))
- return false;
-
- lock (basket) {
- Pair pair = basket.Find((p) => p.Key.Equals(key));
- if (pair == null)
- return false;
- value = pair.Value;
- }
-
- return true;
- }
-
- public TValue this[TKey key] {
- get {
- return GetValue(key);
- }
- set {
- Basket basket;
- if (!TryGetBasket(key, out basket)) {
- Add(key, value);
- return;
- }
- lock (basket) {
- Pair pair = basket.Find((p) => p.Key.Equals(key));
- if (pair == null)
- throw new InvalidOperationException("pair is null, shouldn't be");
- pair.Value = value;
- Interlocked.Increment(ref stamp);
- }
- }
- }
-
- public bool Remove(TKey key)
- {
- Basket b;
- if (!TryGetBasket(key, out b))
- return false;
-
- lock (b) {
- // Should always be == 1 but who know
- return b.RemoveAll((p) => p.Key.Equals(key)) >= 1;
- }
- }
-
- bool ICollection<KeyValuePair<TKey,TValue>>.Remove(KeyValuePair<TKey,TValue> pair)
- {
- return Remove(pair.Key);
- }
-
- public bool ContainsKey(TKey key)
- {
- return container.ContainsFromHash(key.GetHashCode());
- }
-
- bool ICollection<KeyValuePair<TKey,TValue>>.Contains(KeyValuePair<TKey, TValue> pair)
- {
- return ContainsKey(pair.Key);
- }
-
- public void Clear()
- {
- // Pronk
- container = new ConcurrentSkipList<Basket>((value) => value[0].GetHashCode());
- }
-
- public int Count {
- get {
- return count;
- }
- }
-
- public bool IsReadOnly {
- get {
- return false;
- }
- }
-
- public ICollection<TKey> Keys {
- get {
- return null;
- }
- }
-
- public ICollection<TValue> Values {
- get {
- return null;
- }
- }
-
- public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
- {
- return GetEnumeratorInternal();
- }
-
- IEnumerator IEnumerable.GetEnumerator()
- {
- return (IEnumerator)GetEnumeratorInternal();
- }
-
- IEnumerator<KeyValuePair<TKey, TValue>> GetEnumeratorInternal()
- {
- foreach (Basket b in container) {
- lock (b) {
- foreach (Pair p in b)
- yield return new KeyValuePair<TKey, TValue>(p.Key, p.Value);
- }
- }
- }
-
- public void CopyTo(KeyValuePair<TKey,TValue>[] array, int startIndex)
- {
-
- }
-
- /*void UpdateKeysValuesColl()
- {
- foreach (Pair p in this) {
- // Read from time to time to see if we became useless
- if (currStamp != tempStamp)
- break;
- keys.Add(p.Key);
- values.Add(p.Value);
- }
- }*/
-
- bool TryGetBasket(TKey key, out Basket basket)
- {
- basket = null;
- if (!container.GetFromHash(key.GetHashCode(), out basket))
- return false;
-
- return true;
- }
- }
-}
-#endif
+++ /dev/null
-#if NET_4_0
-// 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.
-//
-//
-
-using System;
-using System.Collections;
-using System.Collections.Generic;
-using System.Runtime.Serialization;
-
-namespace System.Threading.Collections
-{
-
-
- public class ConcurrentQueue<T>: IConcurrentCollection<T>, IEnumerable<T>, ICollection
- , IEnumerable, ISerializable, IDeserializationCallback
- {
- class Node
- {
- public T Value;
- public Node Next;
- }
-
- Node head = new Node();
- Node tail;
- int count;
-
- /// <summary>
- /// </summary>
- public ConcurrentQueue()
- {
- tail = head;
- }
-
- public ConcurrentQueue(IEnumerable<T> enumerable): this()
- {
- foreach (T item in enumerable)
- Enqueue(item);
- }
-
- /// <summary>
- /// </summary>
- /// <param name="item"></param>
- 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 IConcurrentCollection<T>.Add(T item)
- {
- Enqueue(item);
- return true;
- }
-
- /// <summary>
- /// </summary>
- /// <returns></returns>
- public bool TryDequeue(out T value)
- {
- value = 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);
- }
- value = default(T);
- return false;
- } else {
- value = oldNext.Value;
- advanced = Interlocked.CompareExchange(ref head, oldNext, oldHead) == oldHead;
- }
- }
- }
-
- Interlocked.Decrement(ref count);
- return true;
- }
-
- /// <summary>
- /// </summary>
- /// <returns></returns>
- public bool TryPeek(out T value)
- {
- if (IsEmpty) {
- value = default(T);
- return false;
- }
-
- Node first = head.Next;
- value = first.Value;
- return true;
- }
-
- public void Clear()
- {
- count = 0;
- tail = head = new Node();
- }
-
- IEnumerator IEnumerable.GetEnumerator ()
- {
- return (IEnumerator)InternalGetEnumerator();
- }
-
- IEnumerator<T> IEnumerable<T>.GetEnumerator ()
- {
- return 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)
- {
- T[] dest = array as T[];
- if (dest == null)
- return;
- CopyTo(dest, index);
- }
-
- public void CopyTo(T[] dest, int index)
- {
- IEnumerator<T> e = InternalGetEnumerator();
- int i = index;
- while (e.MoveNext()) {
- dest[i++] = e.Current;
- }
- }
-
- public T[] ToArray ()
- {
- T[] dest = new T[count];
- CopyTo(dest, 0);
- return dest;
- }
-
- public void GetObjectData (SerializationInfo info, StreamingContext context)
- {
- throw new NotImplementedException ();
- }
-
- bool ICollection.IsSynchronized {
- get { return true; }
- }
-
- public void OnDeserialization (object sender)
- {
- throw new NotImplementedException ();
- }
-
- bool IConcurrentCollection<T>.Remove (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
+++ /dev/null
-#if NET_4_0
-// ConcurrentSkipList.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.
-//
-//
-
-using System;
-using System.Threading;
-using System.Collections;
-using System.Collections.Generic;
-
-namespace System.Threading.Collections
-{
-
- public class ConcurrentSkipList<T>: IConcurrentCollection<T>
- {
- // Used for randomSeed
- static readonly Random r = new Random();
- // Used in FindNodes and thus most others methods
- // avoid heavy local array creation at each method call and use
- // for thread locallity ThreadStatic attribute
- [ThreadStaticAttribute]
- static Node[] preds;
- [ThreadStaticAttribute]
- static Node[] succs;
-
- int count = 0;
-
- class Node
- {
- public readonly int Key;
- public T Value;
- public readonly int TopLayer;
- public readonly Node[] Nexts;
- public volatile bool Marked;
- public volatile bool FullyLinked;
- public readonly SpinLock SpinLock;
-
- public Node(int key, T value, int heightValue)
- {
- Key = key;
- Value = value;
- TopLayer = heightValue;
- Nexts = new Node[heightValue + 1];
- SpinLock = new SpinLock(false);
- Marked = FullyLinked = false;
- }
- }
-
- Node leftSentinel;
- Node rightSentinel;
-
- const int MaxHeight = 200;
- uint randomSeed;
-
- Func<T, int> GetKey;
-
- public ConcurrentSkipList(): this((value) => value.GetHashCode())
- {
- }
-
- public ConcurrentSkipList(IEqualityComparer<T> comparer)
- : this((value) => comparer.GetHashCode(value))
- {
- }
-
- public ConcurrentSkipList(Func<T, int> hasher)
- {
- GetKey = hasher;
- Init();
- }
-
- void Init()
- {
- if (succs == null)
- succs = new Node[MaxHeight];
- if (preds == null)
- preds = new Node[MaxHeight];
-
- leftSentinel = new Node(int.MinValue, default(T), MaxHeight);
- rightSentinel = new Node(int.MaxValue, default(T), MaxHeight);
-
- for (int i = 0; i < MaxHeight; i++) {
- leftSentinel.Nexts[i] = rightSentinel;
- }
- // The or ensures that randomSeed != 0
- randomSeed = ((uint)Math.Abs(r.Next())) | 0x0100;
- }
-
- public bool Add(T value)
- {
- if (value == null)
- throw new ArgumentNullException("value");
-
- CleanArrays();
- int topLayer = GetRandomLevel();
- Console.WriteLine(topLayer);
- int v = GetKey(value);
-
- while (true) {
- int found = FindNode(v, preds, succs);
- if (found != -1) {
- // A node with the same key already exists
- Node nodeFound = succs[found];
- if (!nodeFound.Marked) {
- SpinWait sw = new SpinWait();
- while (!nodeFound.FullyLinked) { sw.SpinOnce(); }
- return false;
- }
- continue;
- }
- int highestLocked = -1;
- try {
- bool valid = LockNodes(topLayer, ref highestLocked,
- (layer, pred, succ) => !pred.Marked && !succ.Marked && pred.Nexts[layer] == succ);
- if (!valid)
- continue;
-
- Node newNode = new Node(v, value, topLayer);
- for (int layer = 0; layer <= topLayer; layer++) {
- newNode.Nexts[layer] = succs[layer];
- preds[layer].Nexts[layer] = newNode;
- }
- newNode.FullyLinked = true;
- } finally {
- Unlock(preds, highestLocked);
- }
- Interlocked.Increment(ref count);
- return true;
- }
- }
-
- bool IConcurrentCollection<T>.Remove(out T value)
- {
- throw new NotSupportedException();
- }
-
- public T[] ToArray()
- {
- int countSnapshot = count;
- T[] temp = new T[countSnapshot];
-
- CopyTo(temp, 0);
-
- return temp;
- }
-
- public void CopyTo(T[] array, int startIndex)
- {
- IEnumerator<T> e = GetInternalEnumerator();
- for (int i = startIndex; i < array.Length; i++) {
- if (!e.MoveNext())
- return;
- array[i] = e.Current;
- }
- e.Dispose();
- }
-
- void ICollection.CopyTo(Array array, int startIndex)
- {
- T[] temp = array as T[];
- if (temp == null)
- return;
-
- CopyTo(temp, startIndex);
- }
-
- object ICollection.SyncRoot {
- get {
- return this;
- }
- }
-
- bool ICollection.IsSynchronized {
- get {
- return true;
- }
- }
-
- public bool Remove(T value)
- {
- if (value == null)
- throw new ArgumentNullException("value");
-
- CleanArrays();
- Node toDelete = null;
- bool isMarked = false;
- int topLayer = -1;
- int v = GetKey(value);
-
- while (true) {
- int found = FindNode(v, preds, succs);
-
- if (isMarked || (found != -1 && OkToDelete(succs[found], found))) {
- // If not marked then logically delete the node
- if (!isMarked) {
- toDelete = succs[found];
- topLayer = toDelete.TopLayer;
- toDelete.SpinLock.Enter();
- // Now that we have the lock, check if the node hasn't already been marked
- if (toDelete.Marked) {
- toDelete.SpinLock.Exit(true);
- return false;
- }
- toDelete.Marked = true;
- isMarked = true;
- }
- int highestLocked = -1;
- try {
- bool valid = LockNodes(topLayer, ref highestLocked,
- (layer, pred, succ) => !pred.Marked && pred.Nexts[layer] == succ);
- if (!valid)
- continue;
-
- for (int layer = topLayer; layer >= 0; layer--) {
- preds[layer].Nexts[layer] = toDelete.Nexts[layer];
- }
- toDelete.SpinLock.Exit(true);
- } finally {
- Unlock(preds, highestLocked);
- }
- Interlocked.Decrement(ref count);
- return true;
- } else {
- return false;
- }
- }
- }
-
- public bool Contains(T value)
- {
- if (value == null)
- throw new ArgumentNullException("value");
-
- CleanArrays();
- int found = FindNode(GetKey(value), preds, succs);
- return found != -1 && succs[found].FullyLinked && !succs[found].Marked;
- }
-
- internal bool ContainsFromHash(int hash)
- {
- CleanArrays();
- int found = FindNode(hash, preds, succs);
- return found != -1 && succs[found].FullyLinked && !succs[found].Marked;
- }
-
- internal bool GetFromHash(int hash, out T value)
- {
- value = default(T);
- CleanArrays();
- // We are blindly supposing that the hash is correct
- // i.e. I trust myself :-)
- int found = FindNode(hash, preds, succs);
- if (found == -1)
- return false;
-
- try {
- succs[found].SpinLock.Enter();
- Node node = succs[found];
- if (node.FullyLinked && !node.Marked) {
- value = node.Value;
- return true;
- }
- } finally {
- succs[found].SpinLock.Exit(true);
- }
-
- return false;
- }
-
- public int Count {
- get {
- return count;
- }
- }
-
- IEnumerator<T> IEnumerable<T>.GetEnumerator()
- {
- return GetInternalEnumerator();
- }
-
- IEnumerator IEnumerable.GetEnumerator()
- {
- return GetInternalEnumerator();
- }
-
- IEnumerator<T> GetInternalEnumerator()
- {
- Node curr = leftSentinel;
- while ((curr = curr.Nexts[0]) != rightSentinel) {
- // If there is an Add operation ongoing we wait a little
- // Possible optimization : use a helping scheme
- SpinWait sw = new SpinWait();
- while (!curr.FullyLinked) {
- sw.SpinOnce();
- }
- yield return curr.Value;
- }
- }
-
- void Unlock(Node[] preds, int highestLocked)
- {
- for (int i = 0; i <= highestLocked; i++) {
- preds[i].SpinLock.Exit(true);
- }
- }
-
- bool LockNodes(int topLayer, ref int highestLocked, Func<int, Node, Node, bool> validityTest)
- {
- Node pred, succ, prevPred = null;
- bool valid = true;
-
- for (int layer = 0; valid && (layer <= topLayer); layer++) {
- pred = preds[layer];
- succ = succs[layer];
- if (pred != prevPred) {
- // Possible optimization : limit topLayer to the first refused lock
- pred.SpinLock.Enter();
- highestLocked = layer;
- prevPred = pred;
- }
- valid = validityTest(layer, pred, succ);
- }
-
- return valid;
- }
-
- int FindNode(int v, Node[] preds, Node[] succs)
- {
- // With preds and succs we record the path we use for searching v
- if (preds.Length != MaxHeight || succs.Length != MaxHeight)
- throw new Exception("precs or succs don't have the good length");
-
- int found = -1;
- Node pred = leftSentinel;
-
- // We start at the higher layer
- for (int layer = MaxHeight - 1; layer >= 0; layer--) {
- Node curr = pred.Nexts[layer];
- // In the current layer we find the best position, then the operation will continue on the
- // layer just beneath
- while (v > curr.Key) {
- pred = curr;
- curr = curr.Nexts[layer];
- }
- if (found == -1 && v == curr.Key)
- found = layer;
- preds[layer] = pred;
- succs[layer] = curr;
- }
-
- return found;
- }
-
- bool OkToDelete(Node candidate, int found)
- {
- return candidate.FullyLinked && candidate.TopLayer == found && !candidate.Marked;
- }
-
- // Taken from Doug Lea's code released in the public domain
- int GetRandomLevel()
- {
- uint x = randomSeed;
- x ^= x << 13;
- x ^= x >> 17;
- x ^= x << 5;
- randomSeed = x;
- if ((x & 0x80000001) != 0) // test highest and lowest bits
- return 0;
- int level = 1;
- while (((x >>= 1) & 1) != 0) ++level;
- return level;
- }
-
- void CleanArrays()
- {
- // Hopefully these are more optimized than a bare for loop
- // (I suppose it uses memset internally)
- Array.Clear(preds, 0, preds.Length);
- Array.Clear(succs, 0, succs.Length);
- }
- }
-}
-#endif
+++ /dev/null
-#if NET_4_0
-// ConcurrentStack.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.
-//
-//
-
-using System;
-using System.Collections;
-using System.Collections.Generic;
-using System.Runtime.Serialization;
-
-namespace System.Threading.Collections
-{
-
-
- public class ConcurrentStack<T>: IConcurrentCollection<T>, IEnumerable<T>
- , ICollection, IEnumerable, ISerializable, IDeserializationCallback
- {
- class Node
- {
- public T Value = default(T);
- public Node Next = null;
- }
-
- Node head = null;
-
- int count;
-
- public ConcurrentStack()
- {
- }
-
- public ConcurrentStack(IEnumerable<T> enumerable)
- {
- foreach (T item in enumerable)
- Push(item);
- }
-
- bool IConcurrentCollection<T>.Add(T elem)
- {
- Push(elem);
- return true;
- }
-
- /// <summary>
- /// </summary>
- /// <param name="element"></param>
- public void Push(T element)
- {
- Node temp = new Node();
- temp.Value = element;
-
- do {
- temp.Next = head;
- } while (Interlocked.CompareExchange<Node>(ref head, temp, temp.Next) != temp.Next);
-
- Interlocked.Increment(ref count);
- }
-
- /// <summary>
- /// </summary>
- /// <returns></returns>
- public bool TryPop(out T value)
- {
- Node temp;
- do {
- temp = head;
- // The stak is empty
- if (temp == null) {
- value = default(T);
- return false;
- }
- } while (Interlocked.CompareExchange<Node>(ref head, temp.Next, temp) != temp);
-
- Interlocked.Decrement(ref count);
-
- value = temp.Value;
- return true;
- }
-
- /// <summary>
- /// </summary>
- /// <returns></returns>
- public bool TryPeek(out T value)
- {
- Node myHead = head;
- if (myHead == null) {
- value = default(T);
- return false;
- }
- value = myHead.Value;
- return true;
- }
-
- public void Clear()
- {
- // This is not satisfactory
- count = 0;
- head = null;
- }
-
- IEnumerator IEnumerable.GetEnumerator ()
- {
- return (IEnumerator)InternalGetEnumerator();
- }
-
- IEnumerator<T> IEnumerable<T>.GetEnumerator ()
- {
- return 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)
- {
- T[] dest = array as T[];
- if (dest == null)
- return;
- CopyTo(dest, index);
- }
-
- public void CopyTo(T[] dest, int index)
- {
- IEnumerator<T> e = InternalGetEnumerator();
- int i = index;
- while (e.MoveNext()) {
- dest[i++] = e.Current;
- }
- }
-
- public void GetObjectData (SerializationInfo info, StreamingContext context)
- {
- throw new NotImplementedException ();
- }
-
- bool ICollection.IsSynchronized {
- get { return true; }
- }
-
- public void OnDeserialization (object sender)
- {
- throw new NotImplementedException ();
- }
-
- bool IConcurrentCollection<T>.Remove (out T item)
- {
- return TryPop(out item);
- }
-
- object syncRoot = new object();
- object ICollection.SyncRoot {
- get { return syncRoot; }
- }
-
- public T[] ToArray ()
- {
- T[] dest = new T[count];
- CopyTo(dest, 0);
- return dest;
- }
-
- public int Count {
- get {
- return count;
- }
- }
-
- public bool IsEmpty {
- get {
- return count == 0;
- }
- }
- }
-}
-#endif
+++ /dev/null
-#if NET_4_0
-// 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.
-//
-//
-
-using System;
-using System.Collections;
-using System.Collections.Generic;
-
-namespace System.Threading.Collections
-{
- public interface IConcurrentCollection<T>: IEnumerable<T>, ICollection, IEnumerable
- {
- bool Add(T item);
- bool Remove(out T item);
- T[] ToArray();
- }
-}
-#endif
+++ /dev/null
-2009-02-16 Jérémie Laval <jeremie.laval@gmail.com>
-
- * *.cs: Initial commit from Google code svn r516.
+++ /dev/null
-#if NET_4_0
-// Future.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.
-//
-//
-
-using System;
-
-namespace System.Threading.Tasks
-{
- public static class Future
- {
- public static Future<T> StartNew<T>()
- {
- return StartNew<T>(null, TaskManager.Current, TaskCreationOptions.None);
- }
-
- public static Future<T> StartNew<T>(Func<T> function)
- {
- return StartNew<T>(function, TaskManager.Current, TaskCreationOptions.None);
- }
-
- public static Future<T> StartNew<T>(Func<T> function, TaskCreationOptions options)
- {
- return StartNew<T>(function, TaskManager.Current, options);
- }
-
- public static Future<T> StartNew<T>(Func<T> function, TaskManager tm)
- {
- return StartNew<T>(function, tm, TaskCreationOptions.None);
- }
-
- public static Future<T> StartNew<T>(Func<T> function, TaskManager tm, TaskCreationOptions options)
- {
- Future<T> future = new Future<T>(tm, function, options, true);
-
- return future;
- }
- }
-
- public sealed class Future<T>: Task
- {
- T value;
- int alreadySet;
- Action func;
-
- public T Value {
- get {
- if (func != null)
- Wait();
- return value;
- }
- set {
- int result = Interlocked.Exchange(ref alreadySet, 1);
- if (result == 1)
- throw new Exception("Value has already been set for this Future or you can't manually set it");
- this.value = value;
- }
- }
-
- internal Future(TaskManager tm, Func<T> f, TaskCreationOptions options):
- this(tm, f, options, false)
- {
- }
-
- internal Future(TaskManager tm, Func<T> f, TaskCreationOptions options, bool scheduleNow):
- base(tm, null, null, options)
- {
- if (f != null) {
- // Block manual set
- alreadySet = 1;
- func = delegate {
- value = f();
- };
- } else {
- func = EmptyFunc;
- }
-
- if (scheduleNow)
- Schedule();
- }
-
- static void EmptyFunc()
- {
- }
-
- protected override void InnerInvoke ()
- {
- func();
- // Same reason as in Task.InnerInvoke
- func = null;
- }
-
- public static Future<T> StartNew()
- {
- return StartNew(null, TaskManager.Current, TaskCreationOptions.None);
- }
-
- public static Future<T> StartNew(Func<T> function)
- {
- return StartNew(function, TaskManager.Current, TaskCreationOptions.None);
- }
-
- public static Future<T> StartNew(Func<T> function, TaskCreationOptions options)
- {
- return StartNew(function, TaskManager.Current, options);
- }
-
- public static Future<T> StartNew(Func<T> function, TaskManager tm)
- {
- return StartNew(function, tm, TaskCreationOptions.None);
- }
-
- public static Future<T> StartNew(Func<T> function, TaskManager tm, TaskCreationOptions options)
- {
- Future<T> future = new Future<T>(tm, function, options, true);
-
- return future;
- }
-
- public Task ContinueWith(Action<Future<T>> a)
- {
- return ContinueWith(a, TaskContinuationKind.OnAny, TaskCreationOptions.None);
- }
-
- public Task ContinueWith(Action<Future<T>> a, TaskContinuationKind kind)
- {
- return ContinueWith(a, kind, TaskCreationOptions.None);
- }
-
- public Task ContinueWith(Action<Future<T>> a, TaskContinuationKind kind, TaskCreationOptions option)
- {
- return ContinueWith(a, kind, option, false);
- }
-
- public Task ContinueWith(Action<Future<T>> a, TaskContinuationKind kind, TaskCreationOptions option, bool exSync)
- {
- Task continuation = new Task(TaskManager.Current, delegate { a(this); }, null, option);
- ContinueWithCore(continuation, kind, exSync);
-
- return continuation;
- }
-
- public Future<U> ContinueWith<U>(Func<Future<T>, U> a)
- {
- return ContinueWith(a, TaskContinuationKind.OnAny, TaskCreationOptions.None);
- }
-
- public Future<U> ContinueWith<U>(Func<Future<T>, U> a, TaskContinuationKind kind)
- {
- return ContinueWith(a, kind, TaskCreationOptions.None);
- }
-
- public Future<U> ContinueWith<U>(Func<Future<T>, U> a, TaskContinuationKind kind, TaskCreationOptions option)
- {
- return ContinueWith<U>(a, kind, option, false);
- }
-
- public Future<U> ContinueWith<U>(Func<Future<T>, U> a, TaskContinuationKind kind, TaskCreationOptions option, bool exSync)
- {
- Future<U> continuation = new Future<U>(TaskManager.Current, delegate { return a(this); }, option, false);
- ContinueWithCore(continuation, kind, exSync);
-
- return continuation;
- }
- }
-}
-#endif
+++ /dev/null
-#if NET_4_0
-// ConcurrentVector.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.
-//
-//
-
-using System;
-using System.Threading;
-
-namespace System.Threading.Tasks
-{
- internal enum PopResult {
- Succeed,
- Empty,
- Abort
- }
-
- internal class DynamicDeque<T> where T : class
- {
- const int ArraySize = 10;
- const int BaseArraySize = 2000;
-
- internal class Node
- {
- public T[] Data;
- public Node Previous;
- public Node Next;
-
- public Node(): this(false)
- {
- }
-
- public Node(bool isBase)
- {
- Data = isBase ? new T[BaseArraySize] : new T[ArraySize];
- }
- }
-
- class BottomInfo
- {
- public Node Bottom;
- public int BottomIndex;
- }
-
- class TopInfo
- {
- public Node Top;
- public int TopIndex;
- public int TopTag;
- }
-
- BottomInfo bottom;
- TopInfo top;
-
- //int isBaseNodeFreed;
- Node baseNode;
-
- public DynamicDeque()
- {
- baseNode = new Node(true);
- Node tempB = new Node();
- baseNode.Next = tempB;
- tempB.Previous = baseNode;
- bottom = EncodeBottom(baseNode, BaseArraySize - 1);
- top = EncodeTop(baseNode, BaseArraySize - 1, int.MinValue);
- }
-
- public void PushBottom(T item)
- {
- Node currNode;
- int currIndex;
- DecodeBottom(bottom, out currNode, out currIndex);
- //Console.WriteLine("Pushing Bottom at " + currIndex + " from " + Thread.CurrentThread.ManagedThreadId);
- currNode.Data[currIndex] = item;
-
- Node newNode;
- int newIndex;
- if (currIndex > 0) {
- newNode = currNode;
- newIndex = currIndex - 1;
- } else {
- // Normally the node should come out of a Shared pool but I prefered to put a big base node
- // so that call to new Node() would be minimized (and we can take advantage of .NET garbage collection)
- //int result = Interlocked.Exchange(ref isBaseNodeFreed, 0);
- //newNode = result == 0 ? new Node() : baseNode;
- newNode = new Node();
- newNode.Next = currNode;
- currNode.Previous = newNode;
- newIndex = newNode.Data.Length - 1;
- }
- bottom = EncodeBottom(newNode, newIndex);
- }
-
- public PopResult PopTop(out T result)
- {
- TopInfo currTop = top;
- BottomInfo currBottom = bottom;
-
- Node currTopNode, newTopNode;
- int currTopIndex, newTopIndex;
- int currTopTag, newTopTag;
-
- DecodeTop(currTop, out currTopNode, out currTopIndex, out currTopTag);
-
- if (EmptinessTest(currTop, currBottom)) {
- result = null;
- if (currTop == top)
- return PopResult.Empty;
- else
- return PopResult.Abort;
- }
-
- if (currTopIndex != 0) {
- newTopNode = currTopNode;
- newTopIndex = currTopIndex - 1;
- newTopTag = currTopTag;
- } else {
- newTopTag = currTopTag + 1;
- newTopNode = currTopNode.Previous;
- newTopIndex = newTopNode.Data.Length - 1;
- //if (currTopNode == baseNode) isBaseNodeFreed = 1;
- //newTopIndex = ArraySize - 1;
- }
-
- TopInfo newTop = EncodeTop(newTopNode, newTopIndex, newTopTag);
- T retVal = currTopNode.Data[currTopIndex];
- if (Interlocked.CompareExchange(ref top, newTop, currTop) == currTop) {
- result = retVal;
- return PopResult.Succeed;
- }
- result = null;
- return PopResult.Abort;
- }
-
- public PopResult PopBottom(out T result)
- {
- Node oldBotNode, newBotNode;
- int oldBotIndex, newBotIndex;
- DecodeBottom(bottom, out oldBotNode, out oldBotIndex);
- //Console.WriteLine("Poping Bottom at " + oldBotIndex + " from " + Thread.CurrentThread.ManagedThreadId);
-
- if (oldBotIndex != oldBotNode.Data.Length - 1) {
- //if (oldBotIndex != ArraySize - 1) {
- newBotNode = oldBotNode;
- newBotIndex = oldBotIndex + 1;
- } else {
- newBotNode = oldBotNode.Next;
- newBotIndex = 0;
- }
- // It's ok to touch Bottom like this since only the thread owning DynamicDeque will touch bottom
- bottom = EncodeBottom(newBotNode, newBotIndex);
-
- TopInfo currTop = top;
- Node currTopNode;
- int currTopIndex;
- int currTopTag;
- DecodeTop(currTop, out currTopNode, out currTopIndex, out currTopTag);
- T retVal = newBotNode.Data[newBotIndex];
- // We are attempting to make Bottom cross over Top. Bad. Revert the last EncodeBottom
- if (object.ReferenceEquals(oldBotNode, currTopNode) && oldBotIndex == currTopIndex) {
- bottom = EncodeBottom(oldBotNode, oldBotIndex);
- result = null;
- return PopResult.Empty;
- // Same as before but in the case of the updated bottom info
- } else if (object.ReferenceEquals(newBotNode, currTopNode) && newBotIndex == currTopIndex) {
- // We update top's tag to prevent a concurrent PopTop crossing over
- TopInfo newTop = EncodeTop(currTopNode, currTopIndex, currTopTag + 1);
- // If the CAS fails then it's already to late and we revert back the Bottom position like before to prevent
- // the cross-over
- if (Interlocked.CompareExchange(ref top, newTop, currTop) == currTop) {
- result = retVal;
- return PopResult.Succeed;
- } else {
- bottom = EncodeBottom(oldBotNode, oldBotIndex);
- result = null;
- return PopResult.Empty;
- }
- } else {
- result = retVal;
- return PopResult.Succeed;
- }
- }
-
- void DecodeBottom(BottomInfo info, out Node node, out int index)
- {
- node = info.Bottom;
- index = info.BottomIndex;
- }
-
- BottomInfo EncodeBottom(Node node, int index)
- {
- BottomInfo temp = new BottomInfo();
- temp.Bottom = node;
- temp.BottomIndex = index;
- return temp;
- }
-
- void DecodeTop(TopInfo info, out Node node, out int index, out int tag)
- {
- node = info.Top;
- index = info.TopIndex;
- tag = info.TopTag;
- }
-
- TopInfo EncodeTop(Node node, int index, int tag)
- {
- TopInfo temp = new TopInfo();
- temp.Top = node;
- temp.TopIndex = index;
- temp.TopTag = tag;
- return temp;
- }
-
- // Take care both of emptiness and cross-over
- bool EmptinessTest(TopInfo topInfo, BottomInfo bottomInfo)
- {
- Node bot, top;
- int bInd, tInd, tTag;
- DecodeBottom(bottomInfo, out bot, out bInd);
- DecodeTop(topInfo, out top, out tInd, out tTag);
-
- // Empty case is we are on the same node
- if (top == bot && (tInd == bInd || tInd + 1 == bInd))
- return true;
- // Over-crossing state
- else if (bot == top.Next && bInd == 0 && tInd == top.Data.Length - 1)
- return true;
- return false;
- }
- }
-}
-#endif
+++ /dev/null
-#if NET_4_0
-// IScheduler.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.
-//
-//
-
-using System;
-using System.Threading;
-using System.Collections.Generic;
-
-namespace System.Threading.Tasks
-{
- internal interface IScheduler: IDisposable
- {
- void AddWork(Task t);
- //void Participate();
- void ParticipateUntil(Task task);
- bool ParticipateUntil(Task task, Func<bool> predicate);
- void ParticipateUntil(Func<bool> predicate);
- void PulseAll();
- /*void InhibitPulse();
- void UnInhibitPulse();*/
- }
-}
-#endif
+++ /dev/null
-#if NET_4_0
-// Scheduler.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.
-//
-//
-
-using System;
-using System.Linq;
-//using System.Collections.Generic;
-using System.Threading.Collections;
-
-namespace System.Threading.Tasks
-{
- internal class Scheduler: IScheduler
- {
- ConcurrentStack<Task> workQueue;
- //ConcurrentStack<Task>[] workBuffers;
- ThreadWorker[] workers;
- //ThreadWorker participant;
- bool isPulsable = true;
-
- public Scheduler(int maxWorker, int maxStackSize, ThreadPriority priority)
- {
- //workQueue = new OptimizedStack<Task>(maxWorker);
- workQueue = new ConcurrentStack<Task>();
- workers = new ThreadWorker[maxWorker];
-
- for (int i = 0; i < maxWorker; i++) {
- workers[i] = new ThreadWorker(this, workers, workQueue, maxStackSize, priority);
- }
- }
-
- public void AddWork(Task t)
- {
- // Add to the shared work pool
- workQueue.Push(t);
- // Wake up some worker if they were asleep
- PulseAll();
- }
-
- public void ParticipateUntil(Task task)
- {
- if (AreTasksFinished(task))
- return;
-
- ParticipateUntil(delegate {
- return AreTasksFinished(task);
- });
- }
-
- public bool ParticipateUntil(Task task, Func<bool> predicate)
- {
- if (AreTasksFinished(task))
- return false;
-
- bool isFromPredicate = false;
-
- ParticipateUntil(delegate {
- if (predicate()) {
- isFromPredicate = true;
- return true;
- }
- return AreTasksFinished(task);
- });
-
- return isFromPredicate;
- }
-
- // Called with Task.WaitAll(someTasks) or Task.WaitAny(someTasks) so that we can remove ourselves
- // also when our wait condition is ok
- public void ParticipateUntil(Func<bool> predicate)
- {
- ThreadWorker.WorkerMethod(predicate, workQueue, workers);
- }
-
- public void PulseAll()
- {
- if (isPulsable) {
- foreach (ThreadWorker worker in workers) {
- if (worker != null)
- worker.Pulse();
- }
- }
- }
-
- public void InhibitPulse()
- {
- isPulsable = false;
- }
-
- public void UnInhibitPulse()
- {
- isPulsable = true;
- }
-
- public void Dispose()
- {
- foreach (ThreadWorker w in workers) {
- w.Dispose();
- }
- }
-
- bool AreTasksFinished(Task parent)
- {
- if (!parent.IsCompleted)
- return false;
-
- return parent.ChildTasks;
- }
- }
-}
-#endif
+++ /dev/null
-#if NET_4_0
-// ThreadWorker.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.
-//
-//
-
-using System;
-using System.Threading;
-using System.Threading.Collections;
-
-namespace System.Threading.Tasks
-{
- internal class ThreadWorker: IDisposable
- {
- static Random r = new Random();
-
- Thread workerThread;
-
- readonly ThreadWorker[] others;
- internal readonly DynamicDeque<Task> dDeque;
- readonly ConcurrentStack<Task> sharedWorkQueue;
- //readonly OptimizedStack<Task> sharedWorkQueue;
- readonly Action<Task> childWorkAdder;
-
- // Flag to tell if workerThread is running
- int started = 0;
-
- readonly bool isLocal;
- readonly int workerLength;
- readonly int stealingStart;
- const int maxRetry = 5;
-
- #region Sleep related fields
- readonly SpinWait wait = new SpinWait();
- const int sleepThreshold = 100000;
- #endregion
-
- Action threadInitializer;
-
- public ThreadWorker(IScheduler sched, ThreadWorker[] others, ConcurrentStack<Task> sharedWorkQueue,
- int maxStackSize, ThreadPriority priority):
- this(sched, others, sharedWorkQueue, true, maxStackSize, priority)
- {
-
- }
-
- public ThreadWorker(IScheduler sched, ThreadWorker[] others, ConcurrentStack<Task> sharedWorkQueue,
- bool createThread, int maxStackSize, ThreadPriority priority)
- {
- this.others = others;
- this.dDeque = new DynamicDeque<Task>();
- this.sharedWorkQueue = sharedWorkQueue;
- this.workerLength = others.Length;
- this.isLocal = !createThread;
-
- this.childWorkAdder = delegate (Task t) {
- dDeque.PushBottom(t);
- sched.PulseAll();
- };
-
- // Find the stealing start index randomly (then the traversal
- // will be done in Round-Robin fashion)
- do {
- this.stealingStart = r.Next(0, workerLength);
- } while (others[stealingStart] == this);
-
- InitializeUnderlyingThread(maxStackSize, priority);
- }
-
- void InitializeUnderlyingThread(int maxStackSize, ThreadPriority priority)
- {
- threadInitializer = delegate {
- // Special case of the participant ThreadWorker
- if (isLocal) {
- this.workerThread = Thread.CurrentThread;
- return;
- }
-
- this.workerThread = (maxStackSize == 0) ? new Thread(WorkerMethodWrapper) :
- new Thread(WorkerMethodWrapper, maxStackSize);
-
- this.workerThread.IsBackground = true;
- this.workerThread.Priority = priority;
- };
- threadInitializer();
- }
-
- public void Dispose()
- {
- Stop();
- if (!isLocal && workerThread.ThreadState != ThreadState.Stopped)
- workerThread.Abort();
- }
-
- public void Pulse()
- {
- // If the thread was stopped then set it in use and restart it
- int result = Interlocked.Exchange(ref started, 1);
- if (result != 0)
- return;
- if (!isLocal) {
- if (this.workerThread.ThreadState != ThreadState.Unstarted) {
- threadInitializer();
- }
- workerThread.Start();
- }
- }
-
- public void Stop()
- {
- // Set the flag to stop so that the while in the thread will stop
- // doing its infinite loop.
- started = 0;
- }
-
- // This is the actual method called in the Thread
- void WorkerMethodWrapper()
- {
- int sleepTime = 0;
-
- // Main loop
- while (started == 1) {
- bool result = WorkerMethod();
-
- // Wait a little and if the Thread has been more sleeping than working shut it down
- wait.SpinOnce();
- if (result)
- sleepTime = 0;
- if (sleepTime++ > sleepThreshold)
- break;
- }
-
- started = 0;
- }
-
- // Main method, used to do all the logic of retrieving, processing and stealing work.
- bool WorkerMethod()
- {
- bool result = false;
- bool hasStolenFromOther;
- do {
- hasStolenFromOther = false;
-
- Task value;
-
- // We fill up our work deque concurrently with other ThreadWorker
- while (!sharedWorkQueue.IsEmpty) {
- while (sharedWorkQueue.TryPop(out value)) {
- dDeque.PushBottom(value);
- }
-
- // Now we process our work
- while (dDeque.PopBottom(out value) == PopResult.Succeed) {
- if (value != null) {
- value.Execute(childWorkAdder);
- result = true;
- }
- }
- }
-
- // When we have finished, steal from other worker
- ThreadWorker other;
-
- // Repeat the operation a little so that we can let other things process.
- for (int j = 0; j < maxRetry; j++) {
- // Start stealing with the ThreadWorker at our right to minimize contention
- for (int it = stealingStart; it < stealingStart + workerLength; it++) {
- int i = it % workerLength;
- if ((other = others[i]) == null || other == this)
- continue;
-
- // Maybe make this steal more than one item at a time, see TODO.
- if (other.dDeque.PopTop(out value) == PopResult.Succeed) {
- hasStolenFromOther = true;
- if (value != null) {
- value.Execute(childWorkAdder);
- result = true;
- }
- }
- }
- }
- } while (!sharedWorkQueue.IsEmpty || hasStolenFromOther);
-
- return result;
- }
-
- // Almost same as above but with an added predicate and treating one item at a time.
- // It's used by Scheduler Participate(...) method for special waiting case like
- // Task.WaitAll(someTasks) or Task.WaitAny(someTasks)
- public static void WorkerMethod(Func<bool> predicate, ConcurrentStack<Task> sharedWorkQueue, ThreadWorker[] others)
- {
- while (!predicate()) {
- Task value;
-
- // Dequeue only one item as we have restriction
- if (sharedWorkQueue.TryPop(out value)) {
- if (value != null) {
- value.Execute(null);
- }
- }
-
- // First check to see if we comply to predicate
- if (predicate()) {
- return;
- }
-
- // Try to complete other work by stealing since our desired tasks may be in other worker
- ThreadWorker other;
- for (int i = 0; i < others.Length; i++) {
- if ((other = others[i]) == null)
- continue;
-
- if (other.dDeque.PopTop(out value) == PopResult.Succeed) {
- if (value != null) {
- value.Execute(null);
- }
- }
-
- if (predicate()) {
- return;
- }
- }
- }
- }
-
- public bool Finished {
- get {
- return started == 0;
- }
- }
-
- public bool IsLocal {
- get {
- return isLocal;
- }
- }
-
- public int Id {
- get {
- return workerThread.ManagedThreadId;
- }
- }
-
- public bool Equals(ThreadWorker other)
- {
- return (other == null) ? false : object.ReferenceEquals(this.dDeque, other.dDeque);
- }
-
- public override bool Equals (object obj)
- {
- ThreadWorker temp = obj as ThreadWorker;
- return temp == null ? false : Equals(temp);
- }
-
- public override int GetHashCode ()
- {
- return workerThread.ManagedThreadId.GetHashCode();
- }
- }
-}
-#endif
+++ /dev/null
-#if NET_4_0
-// Task.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.
-//
-//
-
-using System;
-using System.Threading;
-using System.Threading.Collections;
-
-namespace System.Threading.Tasks
-{
- public class Task: TaskBase, IDisposable, IAsyncResult
- {
- // With this attribute each thread has its own value so that it's correct for our Schedule code
- // and for Parent and Creator properties. Though it may not be the value that Current should yield.
- [System.ThreadStatic]
- static Task current;
- [System.ThreadStatic]
- static Action<Task> childWorkAdder;
- static int id = 0;
-
- CountdownEvent childTasks = new CountdownEvent(1);
- Task parent = current;
- Task creator = current;
-
- int taskId;
- Exception exception;
- AtomicBoolean isCanceled;
- bool respectParentCancellation;
- bool isCompleted;
- TaskCreationOptions taskCreationOptions;
-
- // Ugly coding style because of initial API
- protected readonly TaskManager m_taskManager;
- protected readonly object m_stateObject;
-
- Action<object> action;
- EventHandler completed;
-
- internal Task(TaskManager tm, Action<object> action, object state, TaskCreationOptions taskCreationOptions)
- {
- this.taskCreationOptions = taskCreationOptions;
- this.m_taskManager = TaskManager.Current = tm;
- this.action = action == null ? EmptyFunc : action;
- this.m_stateObject = state;
- this.taskId = Interlocked.Increment(ref id);
-
- // Process taskCreationOptions
- if (CheckTaskOptions(taskCreationOptions, TaskCreationOptions.Detached))
- parent = null;
- else if (parent != null)
- parent.AddChild();
-
- respectParentCancellation = CheckTaskOptions(taskCreationOptions, TaskCreationOptions.RespectCreatorCancellation);
-
- if (CheckTaskOptions(taskCreationOptions, TaskCreationOptions.SelfReplicating))
- ContinueWith(_ => action(state), TaskContinuationKind.OnAny, taskCreationOptions);
- }
-
- bool CheckTaskOptions(TaskCreationOptions opt, TaskCreationOptions member)
- {
- return (opt & member) == member;
- }
-
- // TODO: Not useful in our implementation of Task
- // but may break other's API
- /*~Task() {
- Dispose(false);
- }*/
-
- static void EmptyFunc(object o)
- {
- }
-
- #region Create and ContinueWith
- public static Task StartNew(Action<object> action)
- {
- return StartNew(action, null, TaskManager.Default, TaskCreationOptions.None);
- }
-
- public static Task StartNew(Action<object> action, object state)
- {
- return StartNew(action, state, TaskManager.Current, TaskCreationOptions.None);
- }
-
- public static Task StartNew(Action<object> action, TaskManager tm)
- {
- return StartNew(action, null, tm, TaskCreationOptions.None);
- }
-
- public static Task StartNew(Action<object> action, TaskCreationOptions options)
- {
- return StartNew(action, null, TaskManager.Current, options);
- }
-
-
- public static Task StartNew(Action<object> action, TaskManager tm, TaskCreationOptions options)
- {
- return StartNew(action, null, tm, options);
- }
-
- public static Task StartNew(Action<object> action, object state, TaskManager tm, TaskCreationOptions options)
- {
- Task result = new Task(tm, action, state, options);
- result.Schedule();
- return result;
- }
-
- public Task ContinueWith(Action<Task> a)
- {
- return ContinueWith(a, TaskContinuationKind.OnAny, TaskCreationOptions.None);
- }
-
- public Task ContinueWith(Action<Task> a, TaskContinuationKind kind)
- {
- return ContinueWith(a, kind, TaskCreationOptions.None);
- }
-
- public Task ContinueWith(Action<Task> a, TaskContinuationKind kind, TaskCreationOptions option)
- {
- return ContinueWith(a, kind, option, false);
- }
-
- public Task ContinueWith(Action<Task> a, TaskContinuationKind kind, TaskCreationOptions option, bool executeSync)
- {
- Task continuation = new Task(TaskManager.Current, delegate { a(this); }, null, option);
- ContinueWithCore(continuation, kind, false);
- return continuation;
- }
-
- protected void ContinueWithCore(Task continuation, TaskContinuationKind kind, bool executeSync)
- {
- if (IsCompleted) {
- CheckAndSchedule(executeSync, continuation);
- return;
- }
-
- completed += delegate {
- switch (kind) {
- case TaskContinuationKind.OnAny:
- CheckAndSchedule(executeSync, continuation);
- break;
- case TaskContinuationKind.OnAborted:
- if (isCanceled.Value)
- CheckAndSchedule(executeSync, continuation);
- break;
- case TaskContinuationKind.OnFailed:
- if (exception != null)
- CheckAndSchedule(executeSync, continuation);
- break;
- case TaskContinuationKind.OnCompletedSuccessfully:
- if (exception == null && !isCanceled.Value)
- CheckAndSchedule(executeSync, continuation);
- break;
- }
- };
- }
-
- void CheckAndSchedule(bool executeSync, Task continuation)
- {
- if (executeSync)
- continuation.ThreadStart();
- else
- continuation.Schedule();
- }
- #endregion
-
- #region Internal and protected thingies
- internal protected void Schedule()
- {
- // If worker is null it means it is a local one, revert to the old behavior
- if (current == null || childWorkAdder == null) {
- m_taskManager.AddWork(this);
- } else {
- /* Like the semantic of the ABP paper describe it, we add ourselves to the bottom
- * of our Parent Task's ThreadWorker deque. It's ok to do that since we are in
- * the correct Thread during the creation
- */
- childWorkAdder(this);
- }
- }
-
- void ThreadStart()
- {
- if (!isCanceled.Value
- && (!respectParentCancellation || (respectParentCancellation && parent != null && !parent.IsCanceled))) {
- current = this;
- try {
- InnerInvoke();
- } catch (Exception e) {
- exception = e;
- } finally {
- current = null;
- }
- } else {
- this.exception = new TaskCanceledException(this);
- }
-
- isCompleted = true;
-
- // Call the event in the correct style
- EventHandler tempCompleted = completed;
- if (tempCompleted != null) tempCompleted(this, EventArgs.Empty);
-
- Finish();
- }
-
- internal void Execute(Action<Task> childAdder)
- {
- childWorkAdder = childAdder;
- ThreadStart();
- }
-
- internal void AddChild()
- {
- childTasks.Increment();
- }
-
- internal void ChildCompleted()
- {
- childTasks.Decrement();
- }
-
- protected virtual void InnerInvoke()
- {
- action(m_stateObject);
- // Set action to null so that the GC can collect the delegate and thus
- // any big object references that the user might have captured in an anonymous method
- action = null;
- }
-
- protected void Finish()
- {
- // If there wasn't any child created in the task we set the CountdownEvent
- childTasks.Decrement();
- // Tell parent that we are finished
- if (!CheckTaskOptions(taskCreationOptions, TaskCreationOptions.Detached) && parent != null)
- parent.ChildCompleted();
- Dispose();
- }
-
- internal bool ChildTasks {
- get {
- return childTasks.IsSet;
- }
- }
- #endregion
-
- #region Cancel and Wait related methods
- public void Cancel()
- {
- // Mark the Task as canceled so that the worker function will return immediately
- isCanceled.Value = true;
- }
-
- public void CancelAndWait()
- {
- Cancel();
- Wait();
- }
-
- public bool CancelAndWait(TimeSpan ts)
- {
- Cancel();
- return Wait(ts);
- }
-
- public bool CancelAndWait(int millisecondsTimeout)
- {
- Cancel();
- return Wait(millisecondsTimeout);
- }
-
- public void Wait()
- {
- m_taskManager.WaitForTask(this);
- }
-
- public bool Wait(TimeSpan ts)
- {
- return Wait((int)ts.TotalMilliseconds);
- }
-
- public bool Wait(int millisecondsTimeout)
- {
- System.Diagnostics.Stopwatch sw = System.Diagnostics.Stopwatch.StartNew();
- bool result = m_taskManager.WaitForTaskWithPredicate(this, delegate { return sw.ElapsedMilliseconds >= millisecondsTimeout; });
- sw.Stop();
- return !result;
- }
-
- public static void WaitAll(params Task[] tasks)
- {
- if (tasks == null)
- throw new ArgumentNullException("tasks");
- if (tasks.Length == 0)
- throw new ArgumentException("tasks is empty", "tasks");
-
- foreach (var t in tasks)
- t.Wait();
- }
-
- public static bool WaitAll(Task[] tasks, TimeSpan ts)
- {
- if (tasks == null)
- throw new ArgumentNullException("tasks");
- if (tasks.Length == 0)
- throw new ArgumentException("tasks is empty", "tasks");
-
- bool result = true;
- foreach (var t in tasks)
- result &= t.Wait(ts);
- return result;
- }
-
- public static bool WaitAll(Task[] tasks, int millisecondsTimeout)
- {
- if (tasks == null)
- throw new ArgumentNullException("tasks");
- if (tasks.Length == 0)
- throw new ArgumentException("tasks is empty", "tasks");
-
- bool result = true;
- foreach (var t in tasks)
- result &= t.Wait(millisecondsTimeout);
- return result;
- }
-
- // predicate for WaitAny would be numFinished == 1 and for WaitAll numFinished == count
- public static int WaitAny(params Task[] tasks)
- {
- if (tasks == null)
- throw new ArgumentNullException("tasks");
- if (tasks.Length == 0)
- throw new ArgumentException("tasks is empty", "tasks");
-
- int numFinished = 0;
- int indexFirstFinished = -1;
- int index = 0;
-
- foreach (Task t in tasks) {
- if (t.IsCompleted) {
- return index;
- }
- t.completed += delegate (object sender, EventArgs e) {
- int result = Interlocked.Increment(ref numFinished);
- // Check if we are the first to have finished
- if (result == 1) {
- Task target = (Task)sender;
- indexFirstFinished = Array.FindIndex(tasks, (elem) => elem == target);
- }
- };
- index++;
- }
-
- // All tasks are supposed to use the same TaskManager
- tasks[0].m_taskManager.WaitForTasksUntil(delegate {
- return numFinished >= 1;
- });
-
- return indexFirstFinished;
- }
-
- public static int WaitAny(Task[] tasks, TimeSpan ts)
- {
- return WaitAny(tasks, (int)ts.TotalMilliseconds);
- }
-
- public static int WaitAny(Task[] tasks, int millisecondsTimeout)
- {
- if (millisecondsTimeout < -1)
- throw new ArgumentOutOfRangeException("millisecondsTimeout");
- if (tasks == null)
- throw new ArgumentNullException("tasks");
-
- if (millisecondsTimeout == -1)
- return WaitAny(tasks);
-
- int numFinished = 0;
- int indexFirstFinished = -1;
-
- foreach (Task t in tasks) {
- t.completed += delegate (object sender, EventArgs e) {
- int result = Interlocked.Increment(ref numFinished);
- if (result == 1) {
- Task target = (Task)sender;
- indexFirstFinished = Array.FindIndex(tasks, (elem) => elem == target);
- }
- };
- }
-
- System.Diagnostics.Stopwatch sw = System.Diagnostics.Stopwatch.StartNew();
- tasks[0].m_taskManager.WaitForTasksUntil(delegate {
- if (sw.ElapsedMilliseconds > millisecondsTimeout)
- return true;
- return numFinished >= 1;
- });
- sw.Stop();
-
- return indexFirstFinished;
- }
- #endregion
-
- #region Dispose
- public void Dispose()
- {
- Dispose(true);
- }
-
- protected virtual void Dispose(bool disposeManagedRes)
- {
- // Set action to null so that the GC can collect the delegate and thus
- // any big object references that the user might have captured in a anonymous method
- if (disposeManagedRes) {
- action = null;
- completed = null;
- }
- }
- #endregion
-
- #region Properties
- public static Task Current {
- get {
- return current;
- }
- }
-
- public Exception Exception {
- get {
- return exception;
- }
- }
-
- public bool IsCanceled {
- get {
- return isCanceled.Value && isCompleted;
- }
- }
-
- public bool IsCancellationRequested {
- get {
- return isCanceled.Value;
- }
- }
-
- public bool IsCompleted {
- get {
- return isCompleted;
- }
- }
-
- public Task Parent {
- get {
- return parent;
- }
- }
-
- public Task Creator {
- get {
- return creator;
- }
- }
-
- public TaskCreationOptions TaskCreationOptions {
- get {
- return taskCreationOptions;
- }
- }
-
- object IAsyncResult.AsyncState {
- get {
- return m_stateObject;
- }
- }
-
- bool IAsyncResult.CompletedSynchronously {
- get {
- return true;
- }
- }
-
- WaitHandle IAsyncResult.AsyncWaitHandle {
- get {
- return null;
- }
- }
-
- public int Id {
- get {
- return taskId;
- }
- }
-
- public override string ToString ()
- {
- return Id.ToString();
- }
- #endregion
- }
-}
-#endif
+++ /dev/null
-#if NET_4_0
-// TaskBase.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.
-//
-//
-
-using System;
-
-namespace System.Threading.Tasks
-{
- public class TaskBase
- {
-
- public TaskBase()
- {
- }
- }
-}
-#endif
+++ /dev/null
-#if NET_4_0
-// TaskCanceledException.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.
-//
-//
-
-using System;
-
-namespace System.Threading.Tasks
-{
- [Serializable]
- public class TaskCanceledException: Exception
- {
- Task task;
-
- public TaskCanceledException(): base()
- {
- }
-
- public TaskCanceledException(string message): base(message)
- {
- }
-
- public TaskCanceledException(string message, Exception inner): base(message, inner)
- {
- }
-
- public TaskCanceledException(Task task): base ("The Task was canceled")
- {
- this.task = task;
- }
-
- public Task Task {
- get {
- return task;
- }
- }
- }
-}
-#endif
+++ /dev/null
-#if NET_4_0
-// TaskContinuationKind.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.
-//
-//
-
-using System;
-
-namespace System.Threading.Tasks
-{
- [System.FlagsAttribute, System.SerializableAttribute]
- public enum TaskContinuationKind
- {
- OnCompletedSuccessfully,
- OnFailed,
- OnAborted,
- OnAny
- }
-}
-#endif
+++ /dev/null
-#if NET_4_0
-// TaskCreationOptions.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.
-//
-//
-
-using System;
-
-namespace System.Threading.Tasks
-{
- [FlagsAttribute, System.SerializableAttribute]
- public enum TaskCreationOptions
- {
- None,
- SuppressExecutionContextFlow,
- RespectCreatorCancellation,
- SelfReplicating,
- Detached,
- }
-}
-#endif
+++ /dev/null
-#if NET_4_0
-// TaskManager.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.
-//
-//
-
-using System;
-using System.Collections.Generic;
-
-namespace System.Threading.Tasks
-{
- public class TaskManager: IDisposable
- {
- static TaskManager tdefault = new TaskManager();
- static TaskManager tcurrent = tdefault;
-
- TaskManagerPolicy policy;
-
- IScheduler sched;
-
- public TaskManager(): this(new TaskManagerPolicy())
- {
- }
-
- public TaskManager(TaskManagerPolicy policy):
- this(policy, new Scheduler(policy.IdealProcessors * policy.IdealThreadsPerProcessor,
- policy.MaxStackSize, policy.ThreadPriority))
- {
- }
-
- internal TaskManager(TaskManagerPolicy policy, IScheduler sched)
- {
- this.policy = policy;
- this.sched = sched;
- }
-
- ~TaskManager()
- {
- Dispose(false);
- }
-
- public void Dispose()
- {
- Dispose(true);
- }
-
- protected virtual void Dispose(bool managedRes)
- {
- if (managedRes)
- sched.Dispose();
- }
-
- internal void AddWork(Task t)
- {
- sched.AddWork(t);
- }
-
- internal void WaitForTask(Task task)
- {
- sched.ParticipateUntil(task);
- }
-
- internal bool WaitForTaskWithPredicate(Task task, Func<bool> predicate)
- {
- return sched.ParticipateUntil(task, predicate);
- }
-
- internal void WaitForTasksUntil(Func<bool> predicate)
- {
- sched.ParticipateUntil(predicate);
- }
-
- public TaskManagerPolicy Policy {
- get {
- return policy;
- }
- }
-
- public static TaskManager Default {
- get {
- return tdefault;
- }
- }
-
- public static TaskManager Current {
- get {
- return tcurrent;
- }
- set {
- if (value != null)
- tcurrent = value;
- }
- }
-
- // May be used if we want to feed a big bunch of Tasks without waking up Workers
- /*internal bool IsInhibited {
- set {
- if (value)
- sched.InhibitPulse();
- else {
- sched.UnInhibitPulse();
- sched.PulseAll();
- }
- }
- }*/
- }
-}
-#endif
+++ /dev/null
-#if NET_4_0
-// TaskManagerPolicy.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.
-//
-//
-
-using System;
-
-namespace System.Threading.Tasks
-{
-
-
- public class TaskManagerPolicy
- {
- static readonly int defaultIdealThreadsPerProcessor = 1;
- static readonly int defaultIdealProcessors = Environment.ProcessorCount;
- static readonly int defaultMinProcessors = 1;
- static readonly int defaultStackSize = 0;
- static readonly ThreadPriority defaultPriority = ThreadPriority.Normal;
-
- int idealProcessors;
- int idealThreadsPerProcessor;
- int minProcessors;
- int maxStackSize;
- ThreadPriority priority;
-
- public ThreadPriority ThreadPriority {
- get {
- return priority;
- }
- }
-
- public int MinProcessors {
- get {
- return minProcessors;
- }
- }
-
- public int MaxStackSize {
- get {
- return maxStackSize;
- }
-
- }
-
- public int IdealThreadsPerProcessor {
- get {
- return idealThreadsPerProcessor;
- }
-
- }
-
- public int IdealProcessors {
- get {
- return idealProcessors;
- }
-
- }
-
- public TaskManagerPolicy():
- this(defaultMinProcessors, defaultIdealProcessors, defaultIdealThreadsPerProcessor, defaultStackSize, defaultPriority)
- {
- }
-
- public TaskManagerPolicy(int minProcessors, int idealProcessors):
- this(minProcessors, idealProcessors, defaultIdealThreadsPerProcessor, defaultStackSize, defaultPriority)
- {
-
- }
-
- public TaskManagerPolicy(int minProcessors, int idealProcessors, int idealThreadsPerProcessor):
- this(minProcessors, idealProcessors, idealThreadsPerProcessor, defaultStackSize, defaultPriority)
- {
-
- }
-
- public TaskManagerPolicy(int maxStackSize):
- this(defaultMinProcessors, defaultIdealProcessors, defaultIdealThreadsPerProcessor, maxStackSize, defaultPriority)
- {
-
- }
-
- public TaskManagerPolicy(int minProcessors, int idealProcessors, ThreadPriority priority):
- this(minProcessors, idealProcessors, defaultIdealThreadsPerProcessor, defaultStackSize, priority)
- {
-
- }
-
- public TaskManagerPolicy(int minProcessors, int idealProcessors,
- int idealThreadsPerProcessor, int maxStackSize, ThreadPriority priority)
- {
- this.minProcessors = minProcessors;
- this.idealProcessors = idealProcessors;
- this.idealThreadsPerProcessor = idealThreadsPerProcessor;
- this.maxStackSize = maxStackSize;
- this.priority = priority;
- }
- }
-}
-#endif
+++ /dev/null
-#if NET_4_0
-// AggregateException.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.
-//
-//
-
-using System;
-using System.Collections.ObjectModel;
-using System.Collections.Generic;
-using System.Runtime.Serialization;
-using System.Linq;
-
-namespace System.Threading
-{
- [System.SerializableAttribute]
- public class AggregateException: Exception
- {
- List<Exception> innerExceptions;
-
- public AggregateException(): base()
- {
- }
-
- public AggregateException(string message): base(message, null)
- {
- }
-
- public AggregateException(string message, Exception e): base(message, e)
- {
- }
-
- public AggregateException(SerializationInfo info, StreamingContext ctx): base(info, ctx)
- {
- }
-
- public AggregateException(params Exception[] innerExceptions): this(string.Empty, innerExceptions)
- {
- }
-
- public AggregateException(string message, params Exception[] innerExceptions):
- this(message, (IEnumerable<Exception>)innerExceptions)
- {
- }
-
- public AggregateException(IEnumerable<Exception> innerExceptions): this(string.Empty, innerExceptions)
- {
- }
-
- public AggregateException(string message, IEnumerable<Exception> inner):
- base(GetFormattedMessage(message, inner))
- {
- this.innerExceptions = new List<Exception>(inner);
- }
-
- public AggregateException Flatten()
- {
- List<Exception> inner = new List<Exception>();
-
- foreach (AggregateException e in innerExceptions.Select((e) => e as AggregateException).Where ((e) => e != null))
- inner.AddRange(e.Flatten().InnerExceptions);
- foreach (Exception e in innerExceptions.Where((e) => !(e is AggregateException)))
- inner.Add(e);
-
- return new AggregateException(inner);
- }
-
- public void Handle(Func<Exception, bool> handler)
- {
- List<Exception> failed = new List<Exception>();
- foreach (var e in innerExceptions) {
- try {
- if(!handler(e))
- failed.Add(e);
- } catch {
- throw new AggregateException(failed);
- }
- }
- if (failed.Count > 0)
- throw new AggregateException(failed);
- }
-
- public ReadOnlyCollection<Exception> InnerExceptions {
- get {
- return innerExceptions.AsReadOnly();
- }
- }
-
- public override string ToString()
- {
- return this.Message;
- }
-
- const string baseMessage = "Exception(s) occurred while inside the Parallel loop. {0}.";
- static string GetFormattedMessage(string customMessage, IEnumerable<Exception> inner)
- {
- System.Text.StringBuilder finalMessage = new System.Text.StringBuilder(string.Format(baseMessage, customMessage));
- foreach (Exception e in inner) {
- finalMessage.Append(Environment.NewLine);
- finalMessage.Append("[ ");
- finalMessage.Append(e.ToString());
- finalMessage.Append(" ]");
- finalMessage.Append(Environment.NewLine);
- }
- return finalMessage.ToString();
- }
- }
-}
-#endif
+++ /dev/null
-#if NET_4_0
-// AtomicBoolean.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.
-//
-//
-
-using System;
-
-namespace System.Threading
-{
- internal struct AtomicBoolean
- {
- int flag;
- const int UnSet = 0;
- const int Set = 1;
-
- public bool CompareAndExchange(bool expected, bool newVal)
- {
- int newTemp = newVal ? Set : UnSet;
- int expectedTemp = expected ? Set : UnSet;
-
- return Interlocked.CompareExchange(ref flag, newTemp, expectedTemp) == expectedTemp;
- }
-
- public static AtomicBoolean FromValue(bool value)
- {
- AtomicBoolean temp = new AtomicBoolean();
- temp.Value = value;
-
- return temp;
- }
-
- public bool Exchange(bool newVal)
- {
- int newTemp = newVal ? Set : UnSet;
- return Interlocked.Exchange(ref flag, newTemp) == Set;
- }
-
- public bool Value {
- get {
- return flag == Set;
- }
- set {
- Thread.VolatileWrite(ref flag, value ? Set : UnSet);
- }
- }
-
- public bool Equals(AtomicBoolean rhs)
- {
- return this.flag == rhs.flag;
- }
-
- public override bool Equals(object rhs)
- {
- return rhs is AtomicBoolean ? Equals((AtomicBoolean)rhs) : false;
- }
-
- public override int GetHashCode()
- {
- return flag.GetHashCode();
- }
-
- public static explicit operator bool(AtomicBoolean rhs)
- {
- return rhs.Value;
- }
-
- public static implicit operator AtomicBoolean(bool rhs)
- {
- return AtomicBoolean.FromValue(rhs);
- }
- }
-}
-#endif
-2009-02-16 Jérémie Laval <jeremie.laval@gmail.com>
-
- * AggregateException.cs
- * AtomicBoolean.cs
- * CountdownEvent.cs
- * ISupportsCancellation.cs
- * LazyInit.cs
- * LazyInitMode.cs
- * ManuelResetEventSlim.cs
- * Parallel.cs
- * ParallelLogger.cs
- * ParallelState.cs
- * SemaphoreSlim.cs
- * SpinLock.cs
- * SpinWait.cs
- * WriteOnce.cs: Added ParallelFx files
-
2009-01-30 Andreia Gaita <avidigal@novell.com>
* SynchronizationContext.cs: Remove moonlight hacks, dispatcher should
+++ /dev/null
-#if NET_4_0
-// CountdownEvent.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.
-//
-//
-
-using System;
-using System.Diagnostics;
-
-namespace System.Threading
-{
- public class CountdownEvent: ISupportsCancellation, IDisposable
- {
- int count;
- readonly int initial;
- bool isCanceled;
-
- public CountdownEvent(int count)
- {
- if (count < 0)
- throw new ArgumentOutOfRangeException("count is negative");
- this.initial = this.count = count;
- }
-
- /*~CountdownEvent()
- {
- Dispose(false);
- }*/
-
- public void Decrement()
- {
- Decrement(1);
- }
-
- public void Decrement(int num)
- {
- if (num < 0)
- throw new ArgumentOutOfRangeException("num");
- if (IsSet || num > count)
- throw new InvalidOperationException();
- Interlocked.Add(ref count, -num);
- }
-
- public void Increment()
- {
- Increment(1);
- }
-
- public void Increment(int num)
- {
- if (num < 0)
- throw new ArgumentOutOfRangeException("num");
- if (IsSet || num > int.MaxValue - count)
- throw new InvalidOperationException();
- Interlocked.Add(ref count, num);
- }
-
- public bool TryIncrement()
- {
- return TryIncrement(1);
- }
-
- public bool TryIncrement(int num)
- {
- if (IsSet)
- return false;
- if (num < 0)
- throw new ArgumentOutOfRangeException("num");
- if (num > int.MaxValue - count)
- throw new InvalidOperationException();
-
- if (IsSet)
- return false;
-
- Interlocked.Add(ref count, num);
- return true;
- }
-
- public void Wait()
- {
- SpinWait wait = new SpinWait();
- while (!IsSet) {
- wait.SpinOnce();
- }
- }
-
- public bool Wait(int timeoutMilli)
- {
- if (timeoutMilli == -1) {
- Wait();
- return true;
- }
-
- SpinWait wait = new SpinWait();
- Stopwatch sw = Stopwatch.StartNew();
-
- while (!IsSet) {
- if (sw.ElapsedMilliseconds > (long)timeoutMilli) {
- sw.Stop();
- return false;
- }
- wait.SpinOnce();
- }
- return true;
- }
-
- public bool Wait(TimeSpan span)
- {
- return Wait((int)span.TotalMilliseconds);
- }
-
- public void Reset()
- {
- Reset(initial);
- }
-
- public void Reset(int value)
- {
- Thread.VolatileWrite(ref count, value);
- }
-
- public int CurrentCount {
- get {
- return count;
- }
- }
-
- public int InitialCount {
- get {
- return initial;
- }
- }
-
- public bool IsSet {
- get {
- return count <= 0;
- }
- }
-
- public WaitHandle WaitHandle {
- get {
- return null;
- }
- }
-
- #region IDisposable implementation
-
- public void Dispose ()
- {
- //Dispose(true);
- }
-
- /*protected virtual void Dispose(bool managedRes)
- {
-
- }*/
- #endregion
-
-
- #region ISupportsCancellation implementation
-
- public void Cancel()
- {
- Thread.VolatileWrite(ref count, 0);
- isCanceled = true;
- }
-
- public bool IsCanceled {
- get {
- return isCanceled;
- }
- }
-
- #endregion
-
- }
-}
-#endif
+++ /dev/null
-#if NET_4_0
-// ISupportsCancellation.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.
-//
-//
-
-using System;
-
-namespace System.Threading
-{
-
- public interface ISupportsCancellation
- {
- void Cancel();
- bool IsCanceled { get; }
- }
-}
-#endif
+++ /dev/null
-#if NET_4_0
-// LazyInit.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.
-//
-//
-
-using System;
-using System.Threading;
-using System.Collections.Generic;
-using System.Runtime.Serialization;
-
-namespace System.Threading
-{
- //FIXME: This should be a struct. In a perfect world made this a intern class and construct the corresponding struct as a wrapper
- [SerializableAttribute]
- public class LazyInit<T>: IEquatable<LazyInit<T>>, ISerializable
- {
- LazyInitMode mode;
- Func<T> valueSelector;
- Func<bool> isInitialized;
- Func<T> specializedValue;
- T value;
-
- readonly SpinLock spinLock;
- LocalDataStoreSlot localStore;
-
- static bool StartIsInitialized()
- {
- return false;
- }
-
- static bool FinalIsInitialized()
- {
- return true;
- }
-
- T DefaultFinalValue()
- {
- return value;
- }
-
- class DataSlotWrapper
- {
- public bool Init;
- public Func<T> Getter;
- }
-
- public LazyInit(Func<T> valueSelector): this(valueSelector, LazyInitMode.AllowMultipleExecution)
- {
- }
-
- public LazyInit(Func<T> valueSelector, LazyInitMode mode)
- {
- // Common initialization
- this.valueSelector = valueSelector;
- this.mode = mode;
- specializedValue = null;
- value = default(T);
- spinLock = new SpinLock(false);
- localStore = null;
- isInitialized = StartIsInitialized;
-
- // Depending on mode, do specific initialization
- switch (mode) {
- case LazyInitMode.AllowMultipleExecution:
- InitAllowMultipleExecution();
- break;
- case LazyInitMode.EnsureSingleExecution:
- InitEnsureSingleExecution();
- break;
- case LazyInitMode.ThreadLocal:
- InitThreadLocal();
- break;
- }
- }
-
- void InitAllowMultipleExecution()
- {
- specializedValue = GetValueMultipleExecution;
- }
-
- void InitEnsureSingleExecution()
- {
- specializedValue = GetValueSingleExecution;
- }
-
- void InitThreadLocal()
- {
- localStore = Thread.AllocateDataSlot();
-
- specializedValue = GetValueThreadLocal;
-
- isInitialized = IsInitializedThreadLocal;
- }
-
- T GetValueMultipleExecution()
- {
- value = valueSelector();
- isInitialized = FinalIsInitialized;
- specializedValue = DefaultFinalValue;
- return value;
- }
-
- T GetValueSingleExecution()
- {
- try {
- spinLock.Enter();
- if (!isInitialized()) {
- isInitialized = FinalIsInitialized;
- value = valueSelector();
- specializedValue = DefaultFinalValue;
- }
- } finally { spinLock.Exit(); }
-
- return value;
- }
-
- T GetValueThreadLocal()
- {
- DataSlotWrapper myWrapper = Thread.GetData(localStore) as DataSlotWrapper;
- // In case it's the first time the Thread access its data
- if (myWrapper == null) {
- myWrapper = DataSlotCreator();
- Thread.SetData(localStore, myWrapper);
- }
-
- return myWrapper.Getter();
- }
-
- bool IsInitializedThreadLocal()
- {
- DataSlotWrapper myWrapper = (DataSlotWrapper)Thread.GetData(localStore);
- if (myWrapper == null) {
- myWrapper = DataSlotCreator();
- Thread.SetData(localStore, myWrapper);
- }
-
- return myWrapper.Init;
- }
-
- DataSlotWrapper DataSlotCreator()
- {
- DataSlotWrapper wrapper = new DataSlotWrapper();
- Func<T> valSelector = valueSelector;
-
- wrapper.Getter = delegate {
- T val = valSelector();
- wrapper.Init = true;
- wrapper.Getter = delegate { return val; };
- return val;
- };
-
- return wrapper;
- }
-
- void ISerializable.GetObjectData (SerializationInfo info, StreamingContext context)
- {
- throw new NotImplementedException ();
- }
-
- public bool Equals (LazyInit<T> other)
- {
- // TODO: Find its it's correct or not via unit tests
- return mode == other.mode && valueSelector == other.valueSelector;
- }
-
- public override bool Equals (object other)
- {
- if (!(other is LazyInit<T>))
- return false;
-
- LazyInit<T> temp = (LazyInit<T>)other;
- return Equals(temp);
- }
-
- public override int GetHashCode()
- {
- return Value.GetHashCode();
- }
-
- public override string ToString()
- {
- return Value.ToString();
- }
-
- public T Value {
- get {
- Func<T> temp = specializedValue;
- return temp();
- }
- }
-
- public LazyInitMode Mode {
- get {
- return mode;
- }
- }
-
- public bool IsInitialized {
- get {
- Func<bool> temp = isInitialized;
- return temp();
- }
- }
- }
-}
-#endif
+++ /dev/null
-#if NET_4_0
-// LazyInitMode.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.
-//
-//
-
-using System;
-
-namespace System.Threading
-{
- public enum LazyInitMode
- {
- AllowMultipleExecution,
- EnsureSingleExecution,
- ThreadLocal
- }
-}
-#endif
+++ /dev/null
-#if NET_4_0
-// ManuelResetEventSlim.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.
-//
-//
-
-using System;
-using System.Diagnostics;
-
-namespace System.Threading
-{
- public class ManualResetEventSlim: IDisposable
- {
- const int defaultSpinCount = 20;
- const int isSet = 1;
- const int isNotSet = 0;
- readonly int spinCount;
- readonly SpinWait sw = new SpinWait();
-
- int state;
-
- //bool isDisposed;
-
- public ManualResetEventSlim(): this(false, 20)
- {
- }
-
- public ManualResetEventSlim(bool initState): this(initState, 20)
- {
- }
-
- public ManualResetEventSlim(bool initState, int spinCount)
- {
- this.state = initState ? isSet : isNotSet;
- this.spinCount = spinCount;
- }
-
- /*~ManualResetEventSlim()
- {
- Dispose(false);
- }*/
-
- public bool IsSet {
- get {
- return state == isSet;
- }
- }
-
- public int SpinCount {
- get {
- return spinCount;
- }
- }
-
- public void Reset()
- {
- Thread.VolatileWrite(ref state, isNotSet);
- }
-
- public void Set()
- {
- // Make sure that even is state was cached by a CPU the new value is correctly propagated
- Thread.VolatileWrite(ref state, isSet);
- }
-
- public void Wait()
- {
- // First spin
- for (int i = 0; i < spinCount && state == isNotSet; i++)
- sw.SpinOnce();
-
- // Then, fallback to classic Sleep's yielding
- while (state == isNotSet)
- Thread.Sleep(0);
- }
-
- public bool Wait(int millisecondsTimeout)
- {
- if (millisecondsTimeout < -1)
- throw new ArgumentOutOfRangeException("millisecondsTimeout",
- "millisecondsTimeout is a negative number other than -1");
-
- if (millisecondsTimeout == -1) {
- Wait();
- return true;
- }
-
- Stopwatch s = Stopwatch.StartNew();
-
- // First spin
- for (int i = 0; i < spinCount && state == isNotSet; i++) {
- if (s.ElapsedMilliseconds >= millisecondsTimeout)
- return false;
-
- sw.SpinOnce();
- }
-
- // Then, fallback to classic Sleep's yielding
- while (state == isNotSet) {
- if (s.ElapsedMilliseconds >= millisecondsTimeout)
- return false;
-
- Thread.Sleep(0);
- }
-
- return true;
- }
-
- public bool Wait(TimeSpan ts)
- {
- return Wait((int)ts.TotalMilliseconds);
- }
-
- public WaitHandle WaitHandle {
- get {
- // FIXME
- return null;
- }
- }
-
- #region IDisposable implementation
-
- public void Dispose ()
- {
- //Dispose(true);
- }
-
- /*protected virtual void Dispose(bool managedRes)
- {
-
- }*/
- #endregion
-
- }
-}
-#endif
+++ /dev/null
-#if NET_4_0
-// Parallel.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.
-//
-//
-
-using System;
-using System.Linq;
-using System.Collections.Generic;
-using System.Threading.Tasks;
-
-namespace System.Threading
-{
- public static class Parallel
- {
- public static int GetBestWorkerNumber()
- {
- return GetBestWorkerNumber(TaskManager.Current.Policy);
- }
-
- public static int GetBestWorkerNumber(TaskManagerPolicy policy)
- {
- return policy.IdealProcessors * policy.IdealThreadsPerProcessor;
- }
-
- static void HandleExceptions(IEnumerable<Task> tasks)
- {
- IEnumerable<Exception> exs = tasks.Where(t => t.Exception != null)
- .Where(t => !(t.Exception is TaskCanceledException))
- .Select(t => t.Exception);
-
- if (exs.Any()) {
- throw new AggregateException(exs);
- }
- }
-
- static void InitTasks(Task[] tasks, Action<object> action, int count)
- {
- InitTasks(tasks, count, () => Task.StartNew(action, TaskCreationOptions.Detached));
- }
-
- static void InitTasks(Task[] tasks, int count, Func<Task> taskCreator)
- {
- for (int i = 0; i < count; i++) {
- tasks[i] = taskCreator();
- }
- }
-
- static void InitCleanerCallback<TLocal>(Task[] tasks, ParallelState<TLocal> state, Action<TLocal> cleanFunc)
- {
- Action<Task> cleanCallback = delegate (Task t) {
- cleanFunc(state.ThreadLocalState);
- };
- foreach (Task t in tasks)
- t.ContinueWith(cleanCallback, TaskContinuationKind.OnAny, TaskCreationOptions.None, true);
- }
-
- #region For
-
- public static void For(int from, int to, Action<int> action)
- {
- For(from, to, 1, action);
- }
-
- public static void For(int from, int to, int step, Action<int> action)
- {
- For(from, to, step, (i, state) => action(i));
- }
-
- public static void For(int from, int to, Action<int, ParallelState> action)
- {
- For(from, to, 1, action);
- }
-
- public static void For(int from, int to, int step, Action<int, ParallelState> action)
- {
- if (action == null)
- throw new ArgumentNullException("action");
- if (step < 0)
- throw new ArgumentOutOfRangeException("step", "step must be positive");
-
- int num = GetBestWorkerNumber();
-
- Task[] tasks = new Task[num];
- ParallelState state = new ParallelState(tasks);
-
- int currentIndex = from;
-
- Action<object> workerMethod = delegate {
- int index;
- while ((index = Interlocked.Add(ref currentIndex, step) - step) < to && !state.IsStopped) {
- action (index, state);
- }
- };
-
- InitTasks(tasks, workerMethod, num);
- Task.WaitAll(tasks);
- HandleExceptions(tasks);
- }
-
- public static void For<TLocal>(int fromInclusive, int toExclusive, Func<TLocal> threadLocalSelector,
- Action<int, ParallelState<TLocal>> body)
- {
- For<TLocal>(fromInclusive, toExclusive, 1, threadLocalSelector, body);
- }
-
- public static void For<TLocal>(int fromInclusive, int toExclusive, int step, Func<TLocal> threadLocalSelector,
- Action<int, ParallelState<TLocal>> body)
- {
- For<TLocal>(fromInclusive, toExclusive, step, threadLocalSelector, body, null);
- }
-
- public static void For<TLocal>(int fromInclusive, int toExclusive, Func<TLocal> threadLocalSelector,
- Action<int, ParallelState<TLocal>> body, Action<TLocal> threadLocalCleanup)
- {
- For<TLocal>(fromInclusive, toExclusive, 1, threadLocalSelector, body, threadLocalCleanup);
- }
-
- public static void For<TLocal>(int fromInclusive, int toExclusive, int step, Func<TLocal> threadLocalSelector,
- Action<int, ParallelState<TLocal>> body, Action<TLocal> threadLocalCleanup)
- {
- if (body == null)
- throw new ArgumentNullException("body");
- if (step < 0)
- throw new ArgumentOutOfRangeException("step", "step must be positive");
- if (threadLocalSelector == null)
- throw new ArgumentNullException("threadLocalSelector");
-
- For<TLocal>(fromInclusive, toExclusive, step, threadLocalSelector,
- body, threadLocalCleanup, (a, count, act) => InitTasks(a, act, count));
- }
-
- public static void For<TLocal>(int fromInclusive, int toExclusive, int step, Func<TLocal> threadLocalSelector,
- Action<int, ParallelState<TLocal>> body, Action<TLocal> threadLocalCleanup,
- TaskManager manager, TaskCreationOptions options)
- {
- if (body == null)
- throw new ArgumentNullException("body");
- if (step < 0)
- throw new ArgumentOutOfRangeException("step", "step must be positive");
- if (threadLocalSelector == null)
- throw new ArgumentNullException("threadLocalSelector");
- if (manager == null)
- throw new ArgumentNullException("manager");
-
- For<TLocal>(fromInclusive, toExclusive, step, threadLocalSelector,
- body, threadLocalCleanup, (a, count, act) => InitTasks(a, count, () => Task.StartNew(act, manager, options)));
- }
-
- public static void For<TLocal>(int fromInclusive, int toExclusive, int step, Func<TLocal> threadLocalSelector,
- Action<int, ParallelState<TLocal>> body, Action<TLocal> threadLocalCleanup, Action<Task[], int, Action<object>> tasksCreator)
- {
- int num = GetBestWorkerNumber();
-
- Task[] tasks = new Task[num];
- ParallelState<TLocal> state = new ParallelState<TLocal>(tasks, threadLocalSelector);
-
- int currentIndex = fromInclusive;
-
- Action<object> workerMethod = delegate {
- int index;
- while ((index = Interlocked.Add(ref currentIndex, step) - step) < toExclusive && !state.IsStopped) {
- body (index, state);
- }
- };
-
- tasksCreator(tasks, num, workerMethod);
- if (threadLocalCleanup != null)
- InitCleanerCallback(tasks, state, threadLocalCleanup);
-
- Task.WaitAll(tasks);
- HandleExceptions(tasks);
- }
-
- #endregion
-
- #region Foreach
-
- public static void ForEach<TSource>(IEnumerable<TSource> enumerable, Action<TSource> action)
- {
- ForEach(enumerable, (e, index, state) => action(e));
- }
-
- public static void ForEach<TSource>(IEnumerable<TSource> enumerable, Action<TSource, ParallelState> action)
- {
- ForEach(enumerable, (e, index, state) => action(e, state));
- }
-
- public static void ForEach<TSource>(IEnumerable<TSource> enumerable, Action<TSource, int> action)
- {
- ForEach(enumerable, (e, index, state) => action(e, index));
- }
-
- public static void ForEach<TSource>(IEnumerable<TSource> enumerable, Action<TSource, int, ParallelState> action)
- {
- // Unfortunately the enumerable manipulation isn't guaranteed to be thread-safe so we use
- // a light weight lock for the 3 or so operations to retrieve an element which should be fast for
- // most collection.
- SpinLock sl = new SpinLock(false);
-
- int num = GetBestWorkerNumber();
-
- Task[] tasks = new Task[num];
- ParallelState state = new ParallelState(tasks);
-
- IEnumerator<TSource> enumerator = enumerable.GetEnumerator();
- int currentIndex = 0;
- bool isFinished = false;
-
- Action<object> workerMethod = delegate {
- int index = -1;
- TSource element = default(TSource);
-
- while (!isFinished && !state.IsStopped) {
- try {
- sl.Enter();
- // From here it's thread-safe
- index = currentIndex++;
- isFinished = !enumerator.MoveNext();
- if (isFinished) return;
- element = enumerator.Current;
- // End of thread-safety
- } finally {
- sl.Exit();
- }
-
- action(element, index, state);
- }
- };
-
- InitTasks(tasks, workerMethod, num);
-
- Task.WaitAll(tasks);
- HandleExceptions(tasks);
- }
-
- public static void ForEach<TSource, TLocal>(IEnumerable<TSource> enumerable, Func<TLocal> threadLocalSelector,
- Action<TSource, int, ParallelState<TLocal>> body)
- {
- ForEach<TSource, TLocal>(enumerable, threadLocalSelector, body, null);
- }
-
- public static void ForEach<TSource, TLocal>(IEnumerable<TSource> source, Func<TLocal> threadLocalSelector,
- Action<TSource, int, ParallelState<TLocal>> body, Action<TLocal> threadLocalCleanup)
- {
- ForEach<TSource, TLocal>(source, threadLocalSelector, body, threadLocalCleanup, (a, count, act) => InitTasks(a, act, count));
- }
-
- public static void ForEach<TSource, TLocal>(IEnumerable<TSource> source, Func<TLocal> threadLocalSelector,
- Action<TSource, int, ParallelState<TLocal>> body, Action<TLocal> threadLocalCleanup,
- TaskManager manager, TaskCreationOptions options)
- {
- ForEach<TSource, TLocal>(source, threadLocalSelector, body, threadLocalCleanup, (a, count, act) => InitTasks(a, count, () => Task.StartNew(act, manager, options)));
- }
-
- public static void ForEach<TSource, TLocal>(IEnumerable<TSource> source, Func<TLocal> threadLocalSelector,
- Action<TSource, int, ParallelState<TLocal>> body, Action<TLocal> threadLocalCleanup, Action<Task[], int, Action<object>> tasksCreator)
- {
- // Unfortunately the enumerable manipulation isn't guaranteed to be thread-safe so we use
- // a light weight lock for the 3 or so operations to retrieve an element which should be fast for
- // most collection.
- SpinLock sl = new SpinLock(false);
-
- int num = GetBestWorkerNumber();
-
- Task[] tasks = new Task[num];
- ParallelState<TLocal> state = new ParallelState<TLocal>(tasks, threadLocalSelector);
-
- IEnumerator<TSource> enumerator = source.GetEnumerator();
- int currentIndex = 0;
- bool isFinished = false;
-
- Action<object> workerMethod = delegate {
- int index = -1;
- TSource element = default(TSource);
-
- while (!isFinished && !state.IsStopped) {
- try {
- sl.Enter();
- // From here it's thread-safe
- index = currentIndex++;
- isFinished = !enumerator.MoveNext();
- if (isFinished) return;
- element = enumerator.Current;
- // End of thread-safety
- } finally {
- sl.Exit();
- }
-
- body(element, index, state);
- }
- };
-
- tasksCreator(tasks, num, workerMethod);
- if (threadLocalCleanup != null)
- InitCleanerCallback(tasks, state, threadLocalCleanup);
- Task.WaitAll(tasks);
- HandleExceptions(tasks);
- }
-
- #endregion
-
- #region While
- public static void While(Func<bool> predicate, Action body)
- {
- While(predicate, (state) => body());
- }
-
- public static void While(Func<bool> predicate, Action<ParallelState> body)
- {
- int num = GetBestWorkerNumber();
-
- Task[] tasks = new Task[num];
- ParallelState state = new ParallelState(tasks);
-
- Action<object> action = delegate {
- while (!state.IsStopped && predicate())
- body(state);
- };
-
- InitTasks(tasks, action, num);
- Task.WaitAll(tasks);
- HandleExceptions(tasks);
- }
-
- #endregion
-
- #region Invoke
- public static void Invoke(params Action[] actions)
- {
- Invoke(actions, (Action a) => Task.StartNew((o) => a()));
- }
-
- public static void Invoke(Action[] actions, TaskManager tm, TaskCreationOptions tco)
- {
- Invoke(actions, (Action a) => Task.StartNew((o) => a(), tm, tco));
- }
-
- static void Invoke(Action[] actions, Func<Action, Task> taskCreator)
- {
- if (actions.Length == 0)
- throw new ArgumentException("actions is empty");
-
- // Execute it directly
- if (actions.Length == 1)
- actions[0]();
-
- Task[] ts = Array.ConvertAll(actions, delegate (Action a) {
- return taskCreator(a);
- });
- Task.WaitAll(ts);
- HandleExceptions(ts);
- }
- #endregion
-
- #region SpawnBestNumber, used by PLinq
- internal static Task[] SpawnBestNumber(Action action, Action callback)
- {
- return SpawnBestNumber(action, -1, callback);
- }
-
- internal static Task[] SpawnBestNumber(Action action, int dop, Action callback)
- {
- return SpawnBestNumber(action, dop, false, callback);
- }
-
- internal static Task[] SpawnBestNumber(Action action, int dop, bool wait, Action callback)
- {
- // Get the optimum amount of worker to create
- int num = dop == -1 ? (wait ? GetBestWorkerNumber() + 1 : GetBestWorkerNumber()) : dop;
-
- // Initialize worker
- Task[] tasks = new Task[num];
- for (int i = 0; i < num; i++) {
- tasks[i] = Task.StartNew(_ => action());
- }
-
- // Register wait callback if any
- if (callback != null) {
- for (int j = 0; j < num; j++) {
- tasks[j].ContinueWith(delegate {
- for (int i = 0; i < num; i++) {
- if (i == j) continue;
- // Dont call callback if we aren't
- // the last task
- if (!tasks[i].IsCompleted)
- return;
- }
- callback();
- });
- }
- }
-
- // If explicitely told, wait for all workers to complete
- // and thus let main thread participate in the processing
- if (wait)
- Task.WaitAll(tasks);
-
- return tasks;
- }
- #endregion
- }
-}
-#endif
+++ /dev/null
-#if NET_4_0
-// ParallelLogger.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.
-//
-//
-
-using System;
-using System.Threading;
-
-namespace System.Threading
-{
-
- internal static class ParallelLogger
- {
- public static void WriteLine(string str)
- {
- Console.WriteLine(Thread.CurrentThread.ManagedThreadId.ToString() + " : " + str);
- }
- }
-}
-#endif
+++ /dev/null
-#if NET_4_0
-// ParallelState.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.
-//
-//
-
-using System;
-using System.Threading.Tasks;
-
-namespace System.Threading
-{
- public class ParallelState
- {
- int isStopped = 0;
- Task[] tasks;
-
- internal ParallelState(Task[] tasks)
- {
- this.tasks = tasks;
- }
-
- public bool IsStopped {
- get {
- return isStopped == 1;
- }
- }
-
- public void Stop()
- {
- int result = Interlocked.Exchange(ref isStopped, 1);
- if (result == 0) {
- foreach (var t in tasks) {
- if (t == null)
- continue;
- t.Cancel();
- }
- }
- }
- }
-
- public class ParallelState<TLocal>: ParallelState
- {
- LazyInit<TLocal> val;
-
- internal ParallelState(Task[] tasks, Func<TLocal> localDataCreator): base(tasks)
- {
- val = new LazyInit<TLocal>(localDataCreator, LazyInitMode.ThreadLocal);
- }
-
- public TLocal ThreadLocalState {
- get {
- return val.Value;
- }
- set {
- // FIXME
- }
- }
- }
-}
-#endif
+++ /dev/null
-#if NET_4_0
-// SemaphoreSlim.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.
-//
-//
-
-using System;
-using System.Diagnostics;
-
-namespace System.Threading
-{
- public class SemaphoreSlim: IDisposable, ISupportsCancellation
- {
- readonly int max;
-
- int currCount;
-
- bool isCanceled;
- bool isDisposed;
-
- SpinWait wait = new SpinWait();
-
- public SemaphoreSlim(int initial): this (initial, int.MaxValue)
- {
- }
-
- public SemaphoreSlim(int initial, int max)
- {
- if (initial < 0 || initial > max || max < 0)
- throw new ArgumentOutOfRangeException("The initial argument is negative, initial is greater than max, or max is not positive.");
-
- this.max = max;
- this.currCount = initial;
- }
-
- ~SemaphoreSlim()
- {
- Dispose(false);
- }
-
- public void Dispose()
- {
- Dispose(true);
- }
-
- protected virtual void Dispose(bool managedRes)
- {
- isDisposed = true;
- }
-
- void CheckState()
- {
- if (isCanceled)
- throw new OperationCanceledException("The SemaphoreSlim is canceled.");
- if (isDisposed)
- throw new ObjectDisposedException("The SemaphoreSlim has been disposed.");
- }
-
- public int CurrentCount {
- get {
- return currCount;
- }
- }
-
- public bool IsCanceled {
- get {
- return isCanceled;
- }
- }
-
- public void Cancel()
- {
- isCanceled = true;
- }
-
- public int Release()
- {
- return Release(1);
- }
-
- public int Release(int releaseCount)
- {
- CheckState();
- if (releaseCount < 0)
- throw new ArgumentOutOfRangeException("releaseCount", " The releaseCount must be positive.");
-
- // As we have to take care of the max limit we resort to CAS
- int oldValue, newValue;
- do {
- oldValue = currCount;
- newValue = (currCount + releaseCount);
- newValue = newValue > max ? max : newValue;
- } while (Interlocked.CompareExchange(ref currCount, newValue, oldValue) != oldValue);
-
- return oldValue;
- }
-
- public void Wait()
- {
- CheckState();
- do {
- int result = Interlocked.Decrement(ref currCount);
- if (result >= 0)
- break;
-
- // We revert back the operation
- Interlocked.Increment(ref currCount);
- while (Thread.VolatileRead(ref currCount) <= 0) {
- wait.SpinOnce();
- }
- } while(true);
- }
-
- public bool Wait(TimeSpan ts)
- {
- CheckState();
- return Wait((int)ts.TotalMilliseconds);
- }
-
- public bool Wait(int millisecondsTimeout)
- {
- CheckState();
- if (millisecondsTimeout < -1)
- throw new ArgumentOutOfRangeException("millisecondsTimeout",
- "millisecondsTimeout is a negative number other than -1");
- if (millisecondsTimeout == -1) {
- Wait();
- return true;
- }
-
- do {
- int result = Interlocked.Decrement(ref currCount);
- if (result >= 0)
- break;
-
- // We revert back the operation
- result = Interlocked.Increment(ref currCount);
- Stopwatch sw = Stopwatch.StartNew();
- while (Thread.VolatileRead(ref currCount) <= 0) {
- if (sw.ElapsedMilliseconds > millisecondsTimeout) {
- sw.Stop();
- return false;
- }
- wait.SpinOnce();
- }
- } while(true);
-
- return true;
- }
-
- public WaitHandle AvailableWaitHandle {
- get {
- return null;
- }
- }
- }
-}
-#endif
+++ /dev/null
-#if NET_4_0
-// SpinLock.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.
-//
-//
-
-using System;
-using System.Diagnostics;
-using System.Runtime.ConstrainedExecution;
-
-namespace System.Threading
-{
- public struct SpinLock
- {
- const int isFree = 0;
- const int isOwned = 1;
- int lockState;
- SpinWait sw;
- int threadWhoTookLock;
- bool isThreadOwnerTrackingEnabled;
-
- public bool IsThreadOwnerTrackingEnabled {
- get {
- return isThreadOwnerTrackingEnabled;
- }
- }
-
- public bool IsHeldByCurrentThread {
- get {
- if (isThreadOwnerTrackingEnabled)
- return lockState == isOwned && Thread.CurrentThread.ManagedThreadId == threadWhoTookLock;
- else
- return lockState == isOwned;
- }
- }
-
- public SpinLock(bool trackId)
- {
- this.isThreadOwnerTrackingEnabled = trackId;
- this.threadWhoTookLock = 0;
- this.lockState = isFree;
- this.sw = new SpinWait();
- }
-
- void CheckAndSetThreadId()
- {
- // FIXME: LockRecursionException is not implement atm, swap line when it is
- if (threadWhoTookLock == Thread.CurrentThread.ManagedThreadId)
- //throw new LockRecursionException("The current thread has already acquired this lock.");
- throw new Exception("The current thread has already acquired this lock.");
- threadWhoTookLock = Thread.CurrentThread.ManagedThreadId;
- }
-
- public void ReliableEnter(ref bool lockTaken)
- {
- try {
- Enter();
- lockTaken = lockState == isOwned && Thread.CurrentThread.ManagedThreadId == threadWhoTookLock;
- } catch {
- lockTaken = false;
- }
- }
-
- // FIXME
- //[ReliabilityContractAttribute]
- public void Enter()
- {
- int result = Interlocked.Exchange(ref lockState, isOwned);
-
- //Thread.BeginCriticalRegion();
- while (result == isOwned) {
- // If resource available, set it to in-use and return
- result = Interlocked.Exchange(ref lockState, isOwned);
- if (result == isFree)
- break;
-
- // Efficiently spin, until the resource looks like it might
- // be free. NOTE: Just reading here (as compared to repeatedly
- // calling Exchange) improves performance because writing
- // forces all CPUs to update this value
- while (Thread.VolatileRead(ref lockState) == isOwned) {
- sw.SpinOnce();
- }
- }
-
- CheckAndSetThreadId();
- }
-
- public bool TryEnter()
- {
- //Thread.BeginCriticalRegion();
-
- // If resource available, set it to in-use and return
- if (Interlocked.Exchange(ref lockState, isOwned) == isFree) {
- CheckAndSetThreadId();
- return true;
- }
- return false;
- }
-
- public bool TryEnter(TimeSpan timeout)
- {
- return TryEnter((int)timeout.TotalMilliseconds);
- }
-
- public bool TryEnter(int milliSeconds)
- {
- //Thread.BeginCriticalRegion();
-
- Stopwatch sw = Stopwatch.StartNew();
- bool result = false;
-
- while (sw.ElapsedMilliseconds < milliSeconds) {
- if (Interlocked.Exchange(ref lockState, isOwned) == isFree) {
- threadWhoTookLock = Thread.CurrentThread.ManagedThreadId;
- result = true;
- }
- }
- sw.Stop();
- return result;
- }
-
- public void TryReliableEnter(ref bool lockTaken)
- {
- try {
- lockTaken = TryEnter();
- } catch {
- lockTaken = false;
- }
- }
-
- public void TryReliableEnter(TimeSpan timeout, ref bool lockTaken)
- {
- TryReliableEnter((int)timeout.TotalMilliseconds, ref lockTaken);
- }
-
- public void TryReliableEnter(int milliSeconds, ref bool lockTaken)
- {
- //Thread.BeginCriticalRegion();
-
- Stopwatch sw = Stopwatch.StartNew();
-
- while (sw.ElapsedMilliseconds < milliSeconds) {
- TryReliableEnter(ref lockTaken);
- }
- sw.Stop();
- }
-
- //FIXME
- //[ReliabilityContractAttribute]
- public void Exit()
- {
- Exit(false);
- }
-
- public void Exit(bool flushReleaseWrites)
- {
- threadWhoTookLock = int.MinValue;
-
- // Mark the resource as available
- if (!flushReleaseWrites) {
- lockState = isFree;
- } else {
- Thread.VolatileWrite(ref lockState, isFree);
- }
- //Thread.EndCriticalRegion();
- }
- }
-}
-#endif
+++ /dev/null
-#if NET_4_0
-// SpinWait.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.
-//
-//
-
-using System;
-
-namespace System.Threading
-{
-
- public struct SpinWait
- {
- // The number of step until SpinOnce yield on multicore machine
- const int step = 10;
- static readonly bool isSingleCpu = (Environment.ProcessorCount == 1);
-
- int ntime;
-
- public void SpinOnce()
- {
- // On a single-CPU system, spinning does no good
- if (isSingleCpu) {
- Yield();
- } else {
- if (Interlocked.Increment(ref ntime) % step == 0) {
- Yield();
- } else {
- // Multi-CPU system might be hyper-threaded, let other thread run
- Thread.SpinWait(10);
- }
- }
- }
-
- void Yield()
- {
- // Replace sched_yield by Thread.Sleep(0) which does almost the same thing
- // (going back in kernel mode and yielding) but avoid the branching and unmanaged bridge
- Thread.Sleep(0);
- }
-
- public void Reset()
- {
- ntime = 0;
- }
-
- public bool NextSpinWillYield {
- get {
- return isSingleCpu ? true : ntime % step == 0;
- }
- }
-
- public int Count {
- get {
- return ntime;
- }
- }
- }
-}
-#endif
+++ /dev/null
-#if NET_4_0
-// WriteOnce.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.
-//
-//
-
-using System;
-
-namespace System.Threading
-{
- [SerializableAttribute]
- public struct WriteOnce<T>: IEquatable<WriteOnce<T>>
- {
- T value;
- AtomicBoolean setFlag;
- bool hasValue;
-
- public WriteOnce(T value)
- {
- this.value = value;
- this.setFlag = true;
- this.hasValue = true;
- }
-
- public bool HasValue {
- get {
- return hasValue;
- }
- }
-
- public T Value {
- get {
- if (!HasValue) {
- if (setFlag.Value) {
- SpinWait wait = new SpinWait();
- while (!HasValue) wait.SpinOnce();
- } else {
- throw new InvalidOperationException("An attempt was made to retrieve the value, but no value had been set.");
- }
- }
- return value;
- }
- set {
- bool result = setFlag.Exchange(true);
- if (result)
- throw new InvalidOperationException("An attempt was made to set the value when the value was already set.");
- this.value = value;
- hasValue = true;
- }
- }
-
- public bool TryGetValue(out T val)
- {
- bool result = HasValue;
- val = result ? value : default(T);
- return result;
- }
-
- public bool TrySetValue(T val)
- {
- bool result = setFlag.Exchange(true);
- if (result)
- return false;
- value = val;
- hasValue = true;
- return true;
- }
-
- public bool Equals(WriteOnce<T> other)
- {
- return value == null ? other.value == null : value.Equals(other.value);
- }
-
- public override bool Equals(object other)
- {
- return (other is WriteOnce<T>) ? Equals((WriteOnce<T>)other) : false;
- }
-
- public override int GetHashCode()
- {
- return (HasValue) ? value.GetHashCode() : base.GetHashCode();
- }
-
- public override string ToString()
- {
- return (HasValue) ? value.ToString() : base.ToString();
- }
- }
-}
-#endif
-2009-02-16 Jérémie Laval <jeremie.laval@gmail.com>
-
- * System.Threading/AggregateExceptionTests.cs
- * System.Threading/CountdownEventTests.cs
- * System.Threading/LazyInitTests.cs
- * System.Threading/ManuelResetEventSlimTests.cs
- * System.Threading/ParallelTests.cs
- * System.Threading/SemaphoreSlimTests.cs
- * System.Threading/WriteOnceTests.cs
- * System.Threading/RayTracerHelper.cs
- * System.Threading.Tasks/FutureTests.cs
- * System.Threading.Tasks/TaskTests.cs
- * System.Threading.Collections/BlockingCollectionTests.cs
- * System.Threading.Collections/ConcurrentDictionaryTests.cs
- * System.Threading.Collections/ConcurrentQueueTests.cs
- * System.Threading.Collections/ConcurrentSkipListTests.cs
- * System.Threading.Collections/ConcurrentStackTests.cs
- * System.Threading.Collections/ParallelConcurrentQueueTests.cs
- * System.Threading.Collections/ParallelConcurrentStackTests.cs
- : Added ParallelFx test suite
-
2007-05-31 Atsushi Enomoto <atsushi@ximian.com>
* Makefile : missing EXTRA_DISTFILES.
<Compile Include="System.Threading\ThreadTest.cs" />\r
<Compile Include="System.Threading\TimerTest.cs" />\r
<Compile Include="System.Threading\WaitHandleCas.cs" />\r
- <Compile Include="System.Threading\AggregateExceptionTests.cs" />\r
- <Compile Include="System.Threading\CountdownEventTests.cs" />\r
- <Compile Include="System.Threading\LazyInitTests.cs" />\r
- <Compile Include="System.Threading\ManuelResetEventSlimTests.cs" />\r
- <Compile Include="System.Threading\ParallelTests.cs" />\r
- <Compile Include="System.Threading\SemaphoreSlimTests.cs" />\r
- <Compile Include="System.Threading\WriteOnceTests.cs" />\r
- <Compile Include="System.Threading\RayTracerHelper.cs" />\r
- <Compile Include="System.Threading.Tasks\FutureTests.cs" />\r
- <Compile Include="System.Threading.Tasks\TaskTests.cs" />\r
- <Compile Include="System.Threading.Collections\BlockingCollectionTests.cs" />\r
- <Compile Include="System.Threading.Collections\ConcurrentDictionaryTests.cs" />\r
- <Compile Include="System.Threading.Collections\ConcurrentQueueTests.cs" />\r
- <Compile Include="System.Threading.Collections\ConcurrentSkipListTests.cs" />\r
- <Compile Include="System.Threading.Collections\ConcurrentStackTests.cs" />\r
- <Compile Include="System.Threading.Collections\ParallelConcurrentQueueTests.cs" />\r
- <Compile Include="System.Threading.Collections\ParallelConcurrentStackTests.cs" />\r
<Compile Include="System\ActivatorTest.cs">\r
<SubType>Code</SubType>\r
</Compile>\r
<UserProperties REFS-JarPath-j2se-helpers="..\..\..\..\..\..\..\Program Files\Mainsoft\Visual MainWin for J2EE V2\jgac\vmw4j2ee_110\J2SE.Helpers.jar" REFS-JarPath-mscorlib="..\..\..\..\..\..\..\Program Files\Mainsoft\Visual MainWin for J2EE 2\jgac\vmw4j2ee_110\mscorlib.jar" REFS-JarPath-system="..\..\..\..\..\..\..\Program Files\Mainsoft\Visual MainWin for J2EE 2\jgac\vmw4j2ee_110\System.jar" REFS-JarPath-system-data="..\..\..\..\..\..\..\Program Files\Mainsoft\Visual MainWin for J2EE 2\jgac\vmw4j2ee_110\System.Data.jar" REFS-JarPath-system-xml="..\..\..\..\..\..\..\Program Files\Mainsoft\Visual MainWin for J2EE 2\jgac\vmw4j2ee_110\System.Xml.jar" REFS-JarPath-rt="..\..\..\..\..\..\..\Program Files\Mainsoft\Visual MainWin for J2EE 2\jre5\lib\rt.jar" REFS-JarPath-nunit-framework="..\..\..\nunit20\framework\bin\Debug_Java20\nunit.framework.jar" REFS-JarPath-system-runtime-remoting="..\..\..\..\..\..\Program Files\Mainsoft\Visual MainWin for J2EE 2\jgac\vmw4j2ee_110\System.Runtime.Remoting.jar;..\..\..\..\..\..\Program Files\Mainsoft\Visual MainWin for J2EE 2\jgac\vmw4j2ee_110\System.Runtime.Serialization.Formatters.Soap.jar" />\r
</VisualStudio>\r
</ProjectExtensions>\r
-</Project>\r
+</Project>
\ No newline at end of file
+++ /dev/null
-#if NET_4_0
-// BlockingCollectionTests.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.
-//
-//
-
-using System;
-using System.Threading;
-using System.Threading.Collections;
-using System.Collections.Generic;
-
-using NUnit.Framework;
-
-namespace ParallelFxTests
-{
- [TestFixture()]
- public class BlockingCollectionTests
- {
- BlockingCollection<int> defaultCollection;
- BlockingCollection<int> boundedCollection;
-
- [SetUpAttribute]
- public void Setup()
- {
- defaultCollection = new BlockingCollection<int>();
- boundedCollection = new BlockingCollection<int>(10);
- }
-
- [TestAttribute]
- public void DefaultAddTestCase()
- {
- defaultCollection.Add(1);
- defaultCollection.Add(2);
- Assert.AreEqual(2, defaultCollection.Count, "#1");
-
- }
-
- [TestAttribute]
- public void BoundedAddTestCase()
- {
- boundedCollection.Add(1);
- boundedCollection.Add(2);
- Assert.AreEqual(2, boundedCollection.Count, "#1");
- }
-
- [TestAttribute]
- public void BoundedIsFullTestCase()
- {
- boundedCollection.Add(1);
- boundedCollection.Add(2);
- boundedCollection.Add(3);
- boundedCollection.Add(4);
- boundedCollection.Add(5);
- boundedCollection.Add(6);
- boundedCollection.Add(7);
- boundedCollection.Add(8);
- boundedCollection.Add(9);
- boundedCollection.Add(10);
- Assert.AreEqual(boundedCollection.BoundedCapacity, boundedCollection.Count, "#1");
- }
-
- [TestAttribute]
- public void RemoveTestCase()
- {
- defaultCollection.Add(1);
- defaultCollection.Add(2);
- boundedCollection.Add(1);
- boundedCollection.Add(2);
-
- int value = defaultCollection.Remove();
- Assert.AreEqual(1, value, "#1");
- value = boundedCollection.Remove();
- Assert.AreEqual(1, value, "#2");
- }
-
- [TestAttribute, ExpectedExceptionAttribute(typeof(InvalidOperationException))]
- public void DefaultAddCompletedTestCase()
- {
- defaultCollection.Add(1);
- defaultCollection.Add(2);
- defaultCollection.CompleteAdding();
- Assert.IsTrue(defaultCollection.IsAddingCompleted, "#1");
-
- defaultCollection.Add(3);
- }
-
- [TestAttribute, ExpectedExceptionAttribute(typeof(InvalidOperationException))]
- public void BoundedAddCompletedTestCase()
- {
- boundedCollection.Add(1);
- boundedCollection.Add(2);
- boundedCollection.Add(3);
- boundedCollection.Add(4);
- boundedCollection.Add(5);
- boundedCollection.Add(6);
- boundedCollection.Add(7);
- boundedCollection.Add(8);
- boundedCollection.Add(9);
- boundedCollection.Add(10);
- boundedCollection.CompleteAdding();
- Assert.IsTrue(boundedCollection.IsAddingCompleted, "#1");
-
- boundedCollection.Add(3);
- }
-
- [TestAttribute]
- public void IsCompletedTestCase()
- {
- defaultCollection.Add(1);
- defaultCollection.Add(2);
-
- defaultCollection.CompleteAdding();
- Assert.IsFalse(defaultCollection.IsCompleted, "#3");
-
- defaultCollection.Remove();
- defaultCollection.Remove();
-
- Assert.IsTrue(defaultCollection.IsAddingCompleted, "#1");
- Assert.AreEqual(0, defaultCollection.Count, "#2");
- Assert.IsTrue(defaultCollection.IsCompleted, "#4");
- }
-
- [TestAttribute]
- public void ConsumingEnumerableTestCase()
- {
- defaultCollection.Add(1);
- defaultCollection.Add(2);
- defaultCollection.Add(3);
- defaultCollection.Add(4);
- defaultCollection.Add(5);
- defaultCollection.Add(6);
-
- IEnumerable<int> enumerable = defaultCollection.GetConsumingEnumerable();
- Assert.IsNotNull(enumerable, "#1");
- int i = 1;
- foreach (int j in enumerable) {
- int temp = i++;
- Assert.AreEqual(temp, j, "#" + temp);
- }
- Assert.AreEqual(0, defaultCollection.Count, "#" + i);
- }
- }
-}
-#endif
+++ /dev/null
-#if NET_4_0
-
-using System;
-using System.Threading.Collections;
-
-using NUnit;
-using NUnit.Framework;
-
-namespace ParallelFxTests
-{
- [TestFixture]
- public class ConcurrentDictionaryTests
- {
- ConcurrentDictionary<string, int> map;
-
- [SetUp]
- public void Setup()
- {
- map = new ConcurrentDictionary<string, int>();
- AddStuff();
- }
-
- void AddStuff()
- {
- map.Add("foo", 1);
- map.Add("bar", 2);
- map.Add("foobar", 3);
- }
-
- [Test]
- public void AddWithoutDuplicateTest()
- {
- map.Add("baz", 2);
-
- Assert.AreEqual(2, map.GetValue("baz"));
- Assert.AreEqual(2, map["baz"]);
- Assert.AreEqual(4, map.Count);
- }
-
- [Test, ExpectedException(typeof(ArgumentException))]
- public void AddWithDuplicate()
- {
- map.Add("foo", 6);
- }
-
- [Test]
- public void GetValueTest()
- {
- Assert.AreEqual(1, map.GetValue("foo"), "#1");
- Assert.AreEqual(2, map["bar"], "#2");
- Assert.AreEqual(3, map.Count, "#3");
- }
-
- [Test, ExpectedException(typeof(ArgumentOutOfRangeException))]
- public void GetValueUnknownTest()
- {
- int val;
- Assert.IsFalse(map.TryGetValue("barfoo", out val));
- map.GetValue("barfoo");
- }
-
- [Test]
- public void ModificationTest()
- {
- map["foo"] = 9;
- int val;
-
- Assert.AreEqual(9, map["foo"], "#1");
- Assert.AreEqual(9, map.GetValue("foo"), "#2");
- Assert.IsTrue(map.TryGetValue("foo", out val), "#3");
- Assert.AreEqual(9, val, "#4");
- }
- }
-}
-#endif
+++ /dev/null
-#if NET_4_0
-// ConcurrentQueueTest.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.
-//
-//
-
-using System;
-using System.Threading.Collections;
-
-using NUnit.Framework;
-
-namespace ParallelFxTests
-{
-
-
- [TestFixture()]
- public class ConcurrentQueueTests
- {
- ConcurrentQueue<int> queue;
-
- [SetUpAttribute]
- public void Setup()
- {
- queue = new ConcurrentQueue<int>();
- for (int i = 0; i < 10; i++) {
- queue.Enqueue(i);
- }
- }
-
- [Test]
- public void CountTestCase()
- {
- Assert.AreEqual(10, queue.Count, "#1");
- int value;
- queue.TryPeek(out value);
- queue.TryDequeue(out value);
- queue.TryDequeue(out value);
- Assert.AreEqual(8, queue.Count, "#2");
- queue.Clear();
- Assert.AreEqual(0, queue.Count, "#3");
- Assert.IsTrue(queue.IsEmpty, "#4");
- }
-
- //[Ignore]
- [Test()]
- public void EnumerateTestCase()
- {
- string s = string.Empty;
- foreach (int i in queue) {
- s += i;
- }
- Assert.AreEqual("0123456789", s, "#1 : " + s);
- }
-
- [Test()]
- public void TryPeekTestCase()
- {
- int value;
- queue.TryPeek(out value);
- Assert.AreEqual(0, value, "#1 : " + value);
- queue.TryDequeue(out value);
- Assert.AreEqual(0, value, "#2 : " + value);
- queue.TryDequeue(out value);
- Assert.AreEqual(1, value, "#3 : " + value);
- queue.TryPeek(out value);
- Assert.AreEqual(2, value, "#4 : " + value);
- queue.TryPeek(out value);
- Assert.AreEqual(2, value, "#5 : " + value);
- }
-
- [Test()]
- public void TryDequeueTestCase()
- {
- int value;
- queue.TryPeek(out value);
- Assert.AreEqual(0, value, "#1");
- Assert.IsTrue(queue.TryDequeue(out value), "#2");
- Assert.IsTrue(queue.TryDequeue(out value), "#3");
- Assert.AreEqual(1, value, "#4");
- }
-
- [Test()]
- public void TryDequeueEmptyTestCase()
- {
- int value;
- queue.Clear();
- queue.Enqueue(1);
- Assert.IsTrue(queue.TryDequeue(out value), "#1");
- Assert.IsFalse(queue.TryDequeue(out value), "#2");
- Assert.IsTrue(queue.IsEmpty, "#3");
- }
-
- [Test]
- public void ToArrayTest()
- {
- int[] array = queue.ToArray();
- string s = string.Empty;
- foreach (int i in array) {
- s += i;
- }
- Assert.AreEqual("0123456789", s, "#1 : " + s);
- queue.CopyTo(array, 0);
- s = string.Empty;
- foreach (int i in array) {
- s += i;
- }
- Assert.AreEqual("0123456789", s, "#2 : " + s);
- }
- }
-}
-#endif
+++ /dev/null
-#if NET_4_0
-// ConcurrentSkipListTests.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.
-//
-//
-
-using System;
-using System.Threading;
-using System.Threading.Collections;
-
-using NUnit;
-using NUnit.Framework;
-
-namespace ParallelFxTests
-{
- [TestFixtureAttribute]
- public class ConcurrentSkipListTests
- {
- ConcurrentSkipList<int> skiplist;
-
- [SetUpAttribute]
- public void Setup()
- {
- skiplist = new ConcurrentSkipList<int>();
- }
-
- void AddStuff()
- {
- skiplist.Add(1);
- skiplist.Add(2);
- skiplist.Add(3);
- skiplist.Add(4);
- }
-
- [TestAttribute]
- public void AddTestCase()
- {
- Assert.IsTrue(skiplist.Add(1), "#1");
- Assert.AreEqual(1, skiplist.Count, "#2");
- }
-
- [TestAttribute]
- public void RemoveTestCase()
- {
- Assert.IsFalse(skiplist.Remove(2), "#1");
- Assert.IsFalse(skiplist.Remove(3), "#2");
-
- AddStuff();
- int count = skiplist.Count;
- Assert.IsTrue(skiplist.Remove(1), "#3");
- Assert.IsFalse(skiplist.Remove(1), "#4");
- Assert.IsTrue(skiplist.Remove(4), "#5");
- Assert.AreEqual(count - 2, skiplist.Count, "#6");
- }
-
- [Test]
- public void ContainsTestCase()
- {
- AddStuff();
- Assert.IsTrue(skiplist.Contains(1), "#1");
- Assert.IsTrue(skiplist.Contains(2), "#2");
- Assert.IsTrue(skiplist.Contains(3), "#3");
- Assert.IsTrue(skiplist.Contains(4), "#4");
- }
-
- [TestAttribute]
- public void EnumerateTestCase()
- {
- AddStuff();
-
- string s = string.Empty;
- foreach (int i in skiplist)
- s += i.ToString();
-
- Assert.AreEqual("1234", s);
- }
-
- [TestAttribute]
- public void ToArrayTestCase()
- {
- int[] expected = new int[] { 1, 2, 3, 4 };
- AddStuff();
- int[] array = skiplist.ToArray();
- CollectionAssert.AreEqual(expected, array, "#1");
-
- Array.Clear(array, 0, array.Length);
- skiplist.CopyTo(array, 0);
- CollectionAssert.AreEqual(expected, array, "#2");
- }
-
- }
-}
-#endif
+++ /dev/null
-#if NET_4_0
-// ConcurrentStackRe.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.
-//
-//
-
-using System;
-using System.Threading.Collections;
-using NUnit.Framework;
-
-namespace ParallelFxTests
-{
- [TestFixture()]
- public class ConcurrentStackTests
- {
- ConcurrentStack<int> stack;
-
- [SetUpAttribute]
- public void Setup()
- {
- stack = new ConcurrentStack<int>();
- for (int i = 0; i < 10; i++) {
- stack.Push(i);
- }
- }
-
- [Test]
- public void CountTestCase()
- {
- Assert.IsTrue(stack.Count == 10, "#1");
- int value;
- stack.TryPeek(out value);
- stack.TryPop(out value);
- stack.TryPop(out value);
- Assert.IsTrue(stack.Count == 8, "#2");
- stack.Clear();
- Assert.IsTrue(stack.Count == 0, "#3");
- Assert.IsTrue(stack.IsEmpty, "#4");
- }
-
- //[Ignore]
- [Test()]
- public void EnumerateTestCase()
- {
- string s = string.Empty;
- foreach (int i in stack) {
- s += i;
- }
- Assert.IsTrue(s == "9876543210", "#1 : " + s);
- }
-
- [Test()]
- public void TryPeekTestCase()
- {
- int value;
- stack.TryPeek(out value);
- Assert.IsTrue(value == 9, "#1 : " + value);
- stack.TryPop(out value);
- Assert.IsTrue(value == 9, "#2 : " + value);
- stack.TryPop(out value);
- Assert.IsTrue(value == 8, "#3 : " + value);
- stack.TryPeek(out value);
- Assert.IsTrue(value == 7, "#4 : " + value);
- stack.TryPeek(out value);
- Assert.IsTrue(value == 7, "#5 : " + value);
- }
-
- [Test()]
- public void TryPopTestCase()
- {
- int value;
- stack.TryPeek(out value);
- Assert.IsTrue(value == 9, "#1");
- stack.TryPop(out value);
- stack.TryPop(out value);
- Assert.IsTrue(value == 8, "#2 : " + value);
- }
-
- [Test()]
- public void TryPopEmptyTestCase()
- {
- int value;
- stack.Clear();
- stack.Push(1);
- Assert.IsTrue(stack.TryPop(out value), "#1");
- Assert.IsFalse(stack.TryPop(out value), "#2");
- Assert.IsTrue(stack.IsEmpty, "#3");
- }
-
- [Test]
- public void ToArrayTest()
- {
- int[] array = stack.ToArray();
- string s = string.Empty;
- foreach (int i in array) {
- s += i;
- }
- Assert.IsTrue(s == "9876543210", "#1 : " + s);
- stack.CopyTo(array, 0);
- s = string.Empty;
- foreach (int i in array) {
- s += i;
- }
- Assert.IsTrue(s == "9876543210", "#1 : " + s);
- }
- }
-}
-#endif
+++ /dev/null
-#if NET_4_0
-// ParallelConcurrentQueueTests.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.
-//
-//
-
-using System;
-using System.Threading;
-using System.Threading.Collections;
-
-using NUnit.Framework;
-
-namespace ParallelFxTests
-{
- [TestFixture()]
- public class ParallelConcurrentQueueTests
- {
- ConcurrentQueue<int> queue;
-
- [SetUpAttribute]
- public void Setup()
- {
- queue = new ConcurrentQueue<int>();
- }
-
- [Test]
- public void CountTestCase()
- {
- const int numThread = 5;
- ParallelTestHelper.ParallelAdder(queue, numThread);
- Assert.AreEqual(10 * numThread, queue.Count, "#1");
- int value;
- queue.TryPeek(out value);
- ParallelTestHelper.ParallelRemover(queue, numThread, 3);
- Assert.AreEqual(10 * numThread - 3, queue.Count, "#2");
- queue.Clear();
- Assert.AreEqual(0, queue.Count, "#3");
- Assert.IsTrue(queue.IsEmpty, "#4");
- }
- }
-}
-#endif
+++ /dev/null
-#if NET_4_0
-// ParallelConcurrentStackTests.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.
-//
-//
-
-using System;
-using System.Threading;
-using System.Threading.Collections;
-
-using NUnit.Framework;
-
-namespace ParallelFxTests
-{
-
- [TestFixture()]
- public class ParallelConcurrentStackTests
- {
- ConcurrentStack<int> stack;
-
- [SetUpAttribute]
- public void Setup()
- {
- stack = new ConcurrentStack<int>();
- }
-
- [Test]
- public void CountTestCase()
- {
- const int numThread = 5;
- ParallelTestHelper.ParallelAdder(stack, numThread);
- Assert.AreEqual(10 * numThread, stack.Count, "#1");
- int value;
- stack.TryPeek(out value);
- ParallelTestHelper.ParallelRemover(stack, numThread, 3);
- Assert.AreEqual(10 * numThread - 3, stack.Count, "#2");
- stack.Clear();
- Assert.AreEqual(0, stack.Count, "#3");
- Assert.IsTrue(stack.IsEmpty, "#4");
- }
- }
-}
-#endif
+++ /dev/null
-#if NET_4_0
-// FutureTests.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.
-//
-//
-
-using System;
-using System.Threading;
-using System.Threading.Tasks;
-
-using NUnit.Framework;
-
-namespace ParallelFxTests
-{
- [TestFixture]
- public class FutureTests
- {
- Future<int> InitTestFuture()
- {
- return Future.StartNew(() => 5);
- }
-
- [Test]
- public void SimpleFutureTestCase()
- {
- Future<int> f = InitTestFuture();
-
- Assert.IsNotNull(f, "#1");
- Assert.AreEqual(5, f.Value, "#2");
- }
-
- [Test]
- public void EmptyFutureTestCase()
- {
- Future<int> f = Future.StartNew<int>();
- f.Value = 3;
-
- Assert.AreEqual(3, f.Value, "#1");
- }
-
- [Test, ExpectedExceptionAttribute()]
- public void ManualSetWhenFunctionProvidedTestCase()
- {
- Future<int> f = InitTestFuture();
- f.Value = 2;
- }
-
- [Test, ExpectedExceptionAttribute()]
- public void ManualSetTwoTimesTestCase()
- {
- Future<int> f = Future.StartNew<int>();
- f.Value = 2;
- f.Value = 3;
- }
-
- [Test]
- public void FutureContinueWithTestCase()
- {
- bool result = false;
-
- Future<int> f = InitTestFuture();
- Future<int> cont = f.ContinueWith((future) => { result = true; return future.Value * 2; });
- f.Wait();
- cont.Wait();
-
- Assert.IsNotNull(cont, "#1");
- Assert.IsTrue(result, "#2");
- Assert.AreEqual(10, cont.Value);
- }
- }
-}
-#endif
+++ /dev/null
-#if NET_4_0
-// TaskTest.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.
-//
-//
-
-using System;
-using System.Threading;
-using System.Threading.Tasks;
-
-using NUnit.Framework;
-
-namespace ParallelFxTests
-{
- [TestFixture()]
- public class TaskTest
- {
- Task[] tasks;
- //IScheduler mockScheduler;
- //DynamicMock mock;
- static readonly int max = 3 * Environment.ProcessorCount;
- const int testRun = 10;
-
- [SetUp]
- public void Setup()
- {
- /*mock = new DynamicMock(typeof(IScheduler));
- mockScheduler = (IScheduler)mock.MockInstance;*/
- tasks = new Task[max];
- //TaskManager.Current = new TaskManager(new TaskManagerPolicy(), mockScheduler);
-
- }
-
- void InitWithDelegate(Action<object> action)
- {
- for (int i = 0; i < max; i++) {
- tasks[i] = Task.StartNew(action);
- }
- }
-
- void InitWithDelegate(Action<object> action, int startIndex)
- {
- for (int i = startIndex; i < max; i++) {
- tasks[i] = Task.StartNew(action);
- }
- }
-
- [TestAttribute]
- public void WaitAnyTest()
- {
- int achieved = 0;
- tasks[0] = Task.StartNew(delegate {
- Interlocked.Increment(ref achieved);
- });
- InitWithDelegate(delegate {
- Thread.Sleep(1000);
- Interlocked.Increment(ref achieved);
- }, 1);
- int index = Task.WaitAny(tasks);
- Assert.AreNotEqual(0, achieved, "#1");
- Assert.Less(index, max, "#3");
- Assert.GreaterOrEqual(index, 0, "#2");
- }
-
- [TestAttribute]
- public void WaitAllTest()
- {
- int achieved = 0;
- InitWithDelegate(delegate { Interlocked.Increment(ref achieved); });
- Task.WaitAll(tasks);
- Assert.AreEqual(max, achieved, "#1");
- }
-
- [Test]
- public void CancelTestCase()
- {
- bool result = false;
-
- Task t = new Task(TaskManager.Current, delegate {
- result = true;
- }, null, TaskCreationOptions.None);
- t.Cancel();
- t.Schedule();
-
- Assert.IsInstanceOfType(typeof(TaskCanceledException), t.Exception, "#1");
- TaskCanceledException ex = (TaskCanceledException)t.Exception;
- Assert.AreEqual(t, ex.Task, "#2");
- Assert.IsFalse(result, "#3");
- }
-
- [Test]
- public void ContinueWithOnAnyTestCase()
- {
- bool result = false;
-
- Task t = Task.StartNew(delegate { });
- Task cont = t.ContinueWith(delegate { result = true; }, TaskContinuationKind.OnAny);
- t.Wait();
- cont.Wait();
-
- Assert.IsNull(cont.Exception, "#1");
- Assert.IsNotNull(cont, "#2");
- Assert.IsTrue(result, "#3");
- }
-
- [Test]
- public void ContinueWithOnCompletedSuccessfullyTestCase()
- {
- bool result = false;
-
- Task t = Task.StartNew(delegate { });
- Task cont = t.ContinueWith(delegate { result = true; }, TaskContinuationKind.OnCompletedSuccessfully);
- t.Wait();
- cont.Wait();
-
- Assert.IsNull(cont.Exception, "#1");
- Assert.IsNotNull(cont, "#2");
- Assert.IsTrue(result, "#3");
- }
-
- [Test]
- public void ContinueWithOnAbortedTestCase()
- {
- bool result = false;
-
- Task t = new Task(TaskManager.Current, delegate { }, null, TaskCreationOptions.None);
- t.Cancel();
- t.Schedule();
-
- Task cont = t.ContinueWith(delegate { result = true; }, TaskContinuationKind.OnAborted);
- t.Wait();
- cont.Wait();
-
- Assert.IsNull(cont.Exception, "#1");
- Assert.IsNotNull(cont, "#2");
- Assert.IsTrue(result, "#3");
- }
-
- [Test]
- public void ContinueWithOnFailedTestCase()
- {
- bool result = false;
-
- Task t = Task.StartNew(delegate {throw new Exception("foo"); });
- Task cont = t.ContinueWith(delegate { result = true; }, TaskContinuationKind.OnFailed);
- t.Wait();
- cont.Wait();
-
- Assert.IsNotNull(t.Exception, "#1");
- Assert.IsNotNull(cont, "#2");
- Assert.IsTrue(result, "#3");
- }
-
- [TestAttribute]
- public void MultipleTaskTestCase()
- {
- bool r1 = false, r2 = false, r3 = false;
-
- Task t1 = Task.StartNew(delegate {
- r1 = true;
- });
- Task t2 = Task.StartNew(delegate {
- r2 = true;
- });
- Task t3 = Task.StartNew(delegate {
- r3 = true;
- });
-
- t1.Wait();
- t2.Wait();
- t3.Wait();
-
- Assert.IsTrue(r1, "#1");
- Assert.IsTrue(r2, "#2");
- Assert.IsTrue(r3, "#3");
- }
-
- [Test]
- public void WaitChildTestCase()
- {
- bool r1 = false, r2 = false, r3 = false;
-
- Task.StartNew(delegate { Console.WriteLine("foo"); });
-
- //Console.WriteLine("bar");
-
- Task t = Task.StartNew(delegate {
- //Console.WriteLine("foobar");
- Task.StartNew(delegate {
- Thread.Sleep(50);
- r1 = true;
- Console.WriteLine("finishing 1");
- });
- Task.StartNew(delegate {
- Thread.Sleep(1000);
- r2 = true;
- Console.WriteLine("finishing 2");
- });
- Task.StartNew(delegate {
- Thread.Sleep(150);
- r3 = true;
- Console.WriteLine("finishing 3");
- });
- });
-
- t.Wait();
- Assert.IsTrue(r3, "#1");
- Assert.IsTrue(r2, "#2");
- Assert.IsTrue(r1, "#1");
- }
- }
-}
-#endif
+++ /dev/null
-#if NET_4_0
-// AggregateExceptionTests.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.
-//
-//
-
-using System;
-using System.Linq;
-using System.Threading;
-
-using NUnit;
-using NUnit.Core;
-using NUnit.Framework;
-
-namespace ParallelFxTests
-{
-
- [TestFixture()]
- public class AggregateExceptionTests
- {
- AggregateException e;
-
- [SetUpAttribute]
- public void Setup()
- {
- e = new AggregateException(new Exception("foo"), new AggregateException(new Exception("bar"), new Exception("foobar")));
- }
-
- [TestAttribute]
- public void FlattenTestCase()
- {
- AggregateException ex = e.Flatten();
-
- Assert.AreEqual(3, ex.InnerExceptions.Count, "#1");
- Assert.AreEqual(3, ex.InnerExceptions.Where((exception) => !(exception is AggregateException)).Count(), "#2");
- }
- }
-}
-#endif
+++ /dev/null
-#if NET_4_0
-// CountdownEventTests.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.
-//
-//
-
-using System;
-using System.Threading;
-
-using NUnit.Framework;
-
-namespace ParallelFxTests
-{
- [TestFixtureAttribute]
- public class CountdownEventTests
- {
- CountdownEvent evt;
-
- [SetUpAttribute]
- public void Setup()
- {
- evt = new CountdownEvent(5);
- }
-
- [Test]
- public void InitialTestCase()
- {
- Assert.AreEqual(5, evt.InitialCount, "#1");
- evt.Increment();
- evt.Decrement(3);
- Assert.AreEqual(5, evt.InitialCount, "#2");
- }
-
- [Test]
- public void CurrentCountTestCase()
- {
- Assert.AreEqual(5, evt.CurrentCount, "#1");
-
- evt.Increment();
- Assert.AreEqual(6, evt.CurrentCount, "#2");
-
- evt.TryIncrement(2);
- Assert.AreEqual(8, evt.CurrentCount, "#3");
-
- evt.Decrement(4);
- Assert.AreEqual(4, evt.CurrentCount, "#4");
-
- evt.Reset();
- Assert.AreEqual(5, evt.CurrentCount, "#5");
- }
-
- [Test]
- public void IsSetTestCase()
- {
- Assert.IsFalse(evt.IsSet, "#1");
-
- evt.Decrement(5);
- Assert.IsTrue(evt.IsSet, "#2");
-
- evt.Reset();
- Assert.IsFalse(evt.IsSet, "#3");
- }
-
- [Test]
- public void TryIncrementTestCase()
- {
- Assert.IsTrue(evt.TryIncrement(2), "#1");
- evt.Decrement(7);
- Assert.IsFalse(evt.TryIncrement(), "#2");
- }
-
- [Test]
- public void WaitTestCase()
- {
- int count = 0;
- bool s = false;
-
- ParallelTestHelper.ParallelStressTest(evt, delegate (CountdownEvent e) {
- if (Interlocked.Increment(ref count) % 2 == 0) {
- Thread.Sleep(100);
- while(!e.IsSet)
- e.Decrement();
- } else {
- e.Wait();
- s = true;
- }
- });
-
- Assert.IsTrue(s, "#1");
- Assert.IsTrue(evt.IsSet, "#2");
- }
-
- [Test]
- public void IncrementDecrementStressTestCase()
- {
- int count = 0;
- ParallelTestHelper.ParallelStressTest(evt, delegate (CountdownEvent e) {
- int num = Interlocked.Increment(ref count);
- if (num % 2 == 0)
- e.Increment();
- else
- e.Decrement();
- }, 7);
-
- Assert.AreEqual(4, evt.CurrentCount, "#1");
- Assert.IsFalse(evt.IsSet, "#2");
- }
- }
-}
-#endif
+++ /dev/null
-#if NET_4_0
-// LazyInitTests.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.
-//
-//
-
-using System;
-using System.Threading;
-
-using NUnit;
-using NUnit.Core;
-using NUnit.Framework;
-
-namespace ParallelFxTests
-{
- [TestFixtureAttribute]
- public class LazyInitTests
- {
- LazyInit<int> val;
- int nTime = 0;
-
- int InitializationFunc()
- {
- nTime++;
- return 1;
- }
-
- [SetUp]
- public void Setup()
- {
- nTime = 0;
- }
-
- [TestAttribute]
- public void AllowMultipleExecutionTestCase()
- {
- val = new LazyInit<int>(InitializationFunc, LazyInitMode.AllowMultipleExecution);
- AssertLazyInit(ref val);
- }
-
- [TestAttribute]
- public void EnsureSingleExecutionTestCase()
- {
- val = new LazyInit<int>(InitializationFunc, LazyInitMode.EnsureSingleExecution);
- AssertLazyInit(ref val);
- }
-
- [TestAttribute]
- public void ThreadLocalTestCase()
- {
- val = new LazyInit<int>(InitializationFunc, LazyInitMode.ThreadLocal);
- AssertLazyInit(ref val);
- }
-
- void AssertLazyInit(ref LazyInit<int> value)
- {
- Assert.IsFalse(value.IsInitialized, "#1");
- Assert.AreEqual(1, value.Value, "#2");
- //Assert.IsTrue(value.IsInitialized, "#3");
- Assert.AreEqual(value, value, "#4");
- Assert.AreEqual(1.ToString(), value.ToString(), "#5");
- Assert.AreEqual(1.GetHashCode(), value.GetHashCode(), "#6");
- Assert.AreEqual(1, nTime, "#7");
- }
- }
-}
-#endif
+++ /dev/null
-#if NET_4_0
-// ManualResetEventSlimTests.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.
-//
-//
-
-using System;
-using System.Threading;
-
-using NUnit.Framework;
-
-namespace ParallelFxTests
-{
-
- [TestFixture]
- public class ManualResetEventSlimTests
- {
- ManualResetEventSlim mre;
-
- [SetUp]
- public void Setup()
- {
- mre = new ManualResetEventSlim();
- }
-
- [Test]
- public void IsSetTestCase()
- {
- Assert.IsFalse(mre.IsSet, "#1");
- mre.Set();
- Assert.IsTrue(mre.IsSet, "#2");
- mre.Reset();
- Assert.IsFalse(mre.IsSet, "#3");
- }
-
- [Test]
- public void WaitTest()
- {
- int count = 0;
- bool s = false;
-
- ParallelTestHelper.ParallelStressTest(mre, delegate (ManualResetEventSlim m) {
- if (Interlocked.Increment(ref count) % 2 == 0) {
- Thread.Sleep(50);
- for (int i = 0; i < 10; i++) {
- if (i % 2 == 0)
- m.Reset();
- else
- m.Set();
- }
- } else {
- m.Wait();
- s = true;
- }
- });
-
- Assert.IsTrue(s, "#1");
- Assert.IsTrue(mre.IsSet, "#2");
- }
- }
-}
-#endif
+++ /dev/null
-#if NET_4_0
-// ParallelTests.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.
-//
-//
-
-using System;
-using System.Linq;
-using System.Reflection;
-using System.Threading;
-using System.IO;
-using System.Xml.Serialization;
-using System.Collections.Generic;
-
-using ParallelFxTests.RayTracer;
-
-using NUnit;
-using NUnit.Core;
-using NUnit.Framework;
-
-namespace ParallelFxTests
-{
-
- [TestFixture()]
- public class ParallelTests
- {
- int[] pixels;
- RayTracerApp rayTracer;
-
- public void Setup()
- {
- Stream stream = Assembly.GetAssembly(typeof(ParallelTests)).GetManifestResourceStream("raytracer-output.xml");
- Console.WriteLine(stream == null);
- XmlSerializer serializer = new XmlSerializer(typeof(int[]));
- pixels = (int[])serializer.Deserialize(stream);
- rayTracer = new RayTracerApp();
- }
-
- [Test]
- public void ParallelForTestCase()
- {
- Setup();
- // Test the the output of the Parallel RayTracer is the same than the synchronous ones
- CollectionAssert.AreEquivalent(pixels, rayTracer.Pixels, "#1, same pixels");
- CollectionAssert.AreEqual(pixels, rayTracer.Pixels, "#2, pixels in order");
- }
-
- [Test, ExpectedException(typeof(AggregateException))]
- public void ParallelForExceptionTestCase()
- {
- Parallel.For(1, 10, delegate (int i) { throw new Exception("foo"); });
- }
-
- [Test]
- public void ParallelForEachTestCase()
- {
- IEnumerable<int> e = Enumerable.Repeat(1, 10);
- int count = 0;
-
- Parallel.ForEach(e, (element) => Interlocked.Increment(ref count));
-
- Assert.AreEqual(10, count);
- }
-
- [Test, ExpectedException(typeof(AggregateException))]
- public void ParallelForEachExceptionTestCse()
- {
- IEnumerable<int> e = Enumerable.Repeat(1, 10);
- Parallel.ForEach(e, delegate (int element) { throw new Exception("foo"); });
- }
-
- [Test]
- public void ParallelWhileTestCase()
- {
- int i = 0;
- int count = 0;
-
- Parallel.While(() => Interlocked.Increment(ref i) <= 10, () => Interlocked.Increment(ref count));
-
- Assert.Greater(i, 10, "#1");
- Assert.AreEqual(10, count, "#2");
- }
- }
-}
-#endif
+++ /dev/null
-#if NET_4_0
-// RayTracerHelper.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.
-//
-//
-
-using System;\r
-using System.Linq;\r
-using System.Threading;\r
-using System.Collections.Generic;\r
-using System.Runtime.InteropServices;
-
-namespace ParallelFxTests.RayTracer
-{\r
- public class RayTracer {\r
-\r
- private int screenWidth;\r
- private int screenHeight;\r
- private const int MaxDepth = 5;\r
-\r
- //public Action<int, int, System.Drawing.Color> setPixel;\r
-\r
- public RayTracer(int screenWidth, int screenHeight)
- {\r
- this.screenWidth = screenWidth;\r
- this.screenHeight = screenHeight;\r
- //this.setPixel = setPixel;\r
- }\r
-\r
- private IEnumerable<ISect> Intersections(Ray ray, Scene scene)\r
- {\r
- return scene.Things\r
- .Select(obj => obj.Intersect(ray))\r
- .Where(inter => inter != null)\r
- .OrderBy(inter => inter.Dist);\r
- }\r
-\r
- private double TestRay(Ray ray, Scene scene)
- {\r
- var isects = Intersections(ray, scene);\r
- ISect isect = isects.FirstOrDefault();\r
- if (isect == null)\r
- return 0;\r
- return isect.Dist;\r
- }\r
-\r
- private Color TraceRay(Ray ray, Scene scene, int depth)
- {\r
- var isects = Intersections(ray, scene);\r
- ISect isect = isects.FirstOrDefault();\r
- if (isect == null)\r
- return Color.Background;\r
- return Shade(isect, scene, depth);\r
- }\r
-\r
- private Color GetNaturalColor(SceneObject thing, Vector pos, Vector norm, Vector rd, Scene scene)
- {\r
- Color ret = Color.Make(0, 0, 0);\r
- foreach (Light light in scene.Lights) {\r
- Vector ldis = Vector.Minus(light.Pos, pos);\r
- Vector livec = Vector.Norm(ldis);\r
- double neatIsect = TestRay(new Ray() { Start = pos, Dir = livec }, scene);\r
- bool isInShadow = !((neatIsect > Vector.Mag(ldis)) || (neatIsect == 0));\r
- if (!isInShadow) {\r
- double illum = Vector.Dot(livec, norm);\r
- Color lcolor = illum > 0 ? Color.Times(illum, light.Color) : Color.Make(0, 0, 0);\r
- double specular = Vector.Dot(livec, Vector.Norm(rd));\r
- Color scolor = specular > 0 ? Color.Times(Math.Pow(specular, thing.Surface.Roughness), light.Color) : Color.Make(0, 0, 0);\r
- ret = Color.Plus(ret, Color.Plus(Color.Times(thing.Surface.Diffuse(pos), lcolor),\r
- Color.Times(thing.Surface.Specular(pos), scolor)));\r
- }\r
- }\r
- return ret;\r
- }\r
-\r
- private Color GetReflectionColor(SceneObject thing, Vector pos, Vector norm, Vector rd, Scene scene, int depth)
- {\r
- return Color.Times(thing.Surface.Reflect(pos), TraceRay(new Ray() { Start = pos, Dir = rd }, scene, depth + 1));\r
- }\r
-\r
- private Color Shade(ISect isect, Scene scene, int depth)
- {\r
- var d = isect.Ray.Dir;\r
- var pos = Vector.Plus(Vector.Times(isect.Dist, isect.Ray.Dir), isect.Ray.Start);\r
- var normal = isect.Thing.Normal(pos);\r
- var reflectDir = Vector.Minus(d, Vector.Times(2 * Vector.Dot(normal, d), normal));\r
- Color ret = Color.DefaultColor;\r
- ret = Color.Plus(ret, GetNaturalColor(isect.Thing, pos, normal, reflectDir, scene));\r
- if (depth >= MaxDepth) {\r
- return Color.Plus(ret, Color.Make(.5, .5, .5));\r
- }\r
- ret = Color.Plus(ret, GetReflectionColor(isect.Thing, Vector.Plus(pos, Vector.Times(.001, reflectDir)), normal, reflectDir, scene, depth));\r
- return ret;\r
- }\r
-\r
- private double RecenterX(double x)
- {\r
- return (x - (screenWidth / 2.0)) / (2.0 * screenWidth);\r
- }\r
- private double RecenterY(double y)
- {\r
- return -(y - (screenHeight / 2.0)) / (2.0 * screenHeight);\r
- }\r
-\r
- private Vector GetPoint(double x, double y, Camera camera)
- {\r
- return Vector.Norm(Vector.Plus(camera.Forward, Vector.Plus(Vector.Times(RecenterX(x), camera.Right),\r
- Vector.Times(RecenterY(y), camera.Up))));\r
- }\r
-\r
- internal void RenderParallel(Scene scene, Int32[] rgb)\r
- {\r
- Parallel.For(0, screenHeight, y =>\r
- {\r
- int stride = y * screenWidth;\r
- //Camera camera = scene.Camera;\r
- for (int x = 0; x < screenWidth; x++)\r
- {\r
- Color color = TraceRay(new Ray() { Start = scene.Camera.Pos, Dir = GetPoint(x, y, scene.Camera) }, scene, 0);\r
- rgb[x + stride] = color.ToInt32();\r
- }\r
- });\r
- }\r
-\r
- internal readonly Scene DefaultScene = new Scene() {\r
- Things = new SceneObject[] { \r
- new Plane() {\r
- Norm = Vector.Make(0,1,0),\r
- Offset = 0,\r
- Surface = Surfaces.CheckerBoard\r
- },\r
- new Sphere() {\r
- Center = Vector.Make(0,1,0),\r
- Radius = 1,\r
- Surface = Surfaces.Shiny\r
- },\r
- new Sphere() {\r
- Center = Vector.Make(-1,.5,1.5),\r
- Radius = .5,\r
- Surface = Surfaces.Shiny\r
- }},\r
- Lights = new Light[] { \r
- new Light() {\r
- Pos = Vector.Make(-2,2.5,0),\r
- Color = Color.Make(.49,.07,.07)\r
- },\r
- new Light() {\r
- Pos = Vector.Make(1.5,2.5,1.5),\r
- Color = Color.Make(.07,.07,.49)\r
- },\r
- new Light() {\r
- Pos = Vector.Make(1.5,2.5,-1.5),\r
- Color = Color.Make(.07,.49,.071)\r
- },\r
- new Light() {\r
- Pos = Vector.Make(0,3.5,0),\r
- Color = Color.Make(.21,.21,.35)\r
- }},\r
- Camera = Camera.Create(Vector.Make(3,2,4), Vector.Make(-1,.5,0))\r
- };\r
- }\r
- static class Surfaces
- {\r
- // Only works with X-Z plane.\r
- public static readonly Surface CheckerBoard = \r
- new Surface() {\r
- Diffuse = pos => ((Math.Floor(pos.Z) + Math.Floor(pos.X)) % 2 != 0)\r
- ? Color.Make(1,1,1)\r
- : Color.Make(0,0,0),\r
- Specular = pos => Color.Make(1,1,1),\r
- Reflect = pos => ((Math.Floor(pos.Z) + Math.Floor(pos.X)) % 2 != 0)\r
- ? .1\r
- : .7,\r
- Roughness = 150\r
- };\r
- \r
-\r
- public static readonly Surface Shiny = \r
- new Surface() {\r
- Diffuse = pos => Color.Make(1,1,1),\r
- Specular = pos => Color.Make(.5,.5,.5),\r
- Reflect = pos => .6,\r
- Roughness = 50\r
- };\r
- }\r
-\r
- class Vector {\r
- public double X;\r
- public double Y;\r
- public double Z;\r
-\r
- public Vector(double x, double y, double z) { X = x; Y = y; Z = z; }\r
- public Vector(string str) {\r
- string[] nums = str.Split(',');\r
- if (nums.Length != 3) throw new ArgumentException();\r
- X = double.Parse(nums[0]);\r
- Y = double.Parse(nums[1]);\r
- Z = double.Parse(nums[2]);\r
- }\r
- public static Vector Make(double x, double y, double z) { return new Vector(x, y, z); }\r
- public static Vector Times(double n, Vector v) {\r
- return new Vector(v.X * n, v.Y * n, v.Z * n);\r
- }\r
- public static Vector Minus(Vector v1, Vector v2) {\r
- return new Vector(v1.X - v2.X, v1.Y - v2.Y, v1.Z - v2.Z);\r
- }\r
- public static Vector Plus(Vector v1, Vector v2) {\r
- return new Vector(v1.X + v2.X, v1.Y + v2.Y, v1.Z + v2.Z);\r
- }\r
- public static double Dot(Vector v1, Vector v2) {\r
- return (v1.X * v2.X) + (v1.Y * v2.Y) + (v1.Z * v2.Z);\r
- }\r
- public static double Mag(Vector v) { return Math.Sqrt(Dot(v, v)); }\r
- public static Vector Norm(Vector v) {\r
- double mag = Mag(v);\r
- double div = mag == 0 ? double.PositiveInfinity : 1 / mag;\r
- return Times(div, v);\r
- }\r
- public static Vector Cross(Vector v1, Vector v2) {\r
- return new Vector(((v1.Y * v2.Z) - (v1.Z * v2.Y)),\r
- ((v1.Z * v2.X) - (v1.X * v2.Z)),\r
- ((v1.X * v2.Y) - (v1.Y * v2.X)));\r
- }\r
- public static bool Equals(Vector v1, Vector v2) {\r
- return (v1.X == v2.X) && (v1.Y == v2.Y) && (v1.Z == v2.Z);\r
- }\r
- }\r
-\r
- public class Color {\r
- public double R;\r
- public double G;\r
- public double B;\r
-\r
- public Color(double r, double g, double b) { R = r; G = g; B = b; }\r
- public Color(string str) {\r
- string[] nums = str.Split(',');\r
- if (nums.Length != 3) throw new ArgumentException();\r
- R = double.Parse(nums[0]);\r
- G = double.Parse(nums[1]);\r
- B = double.Parse(nums[2]);\r
- }\r
-\r
- public static Color Make(double r, double g, double b) { return new Color(r, g, b); }\r
- \r
- public static Color Times(double n, Color v) {\r
- return new Color(n * v.R, n * v.G, n * v.B);\r
- }\r
- public static Color Times(Color v1, Color v2) { \r
- return new Color(v1.R * v2.R, v1.G * v2.G,v1.B * v2.B);\r
- }\r
- \r
- public static Color Plus(Color v1, Color v2) { \r
- return new Color(v1.R + v2.R, v1.G + v2.G,v1.B + v2.B);\r
- }\r
- public static Color Minus(Color v1, Color v2) { \r
- return new Color(v1.R - v2.R, v1.G - v2.G,v1.B - v2.B);\r
- }\r
-\r
- public static readonly Color Background = Make(0, 0, 0);\r
- public static readonly Color DefaultColor = Make(0, 0, 0);\r
-\r
- public double Legalize(double d) {\r
- return d > 1 ? 1 : d;\r
- }\r
- \r
- public Int32 ToInt32() {\r
- return (ToInt32(B) | ToInt32(G) << 8 | ToInt32(R) << 16 | 255 << 24);\r
- }\r
- \r
- public static Int32 ToInt32(double c)\r
- {\r
- Int32 r = (Int32)(255 * c);\r
- return (r > 255 ? 255 : r);\r
- }\r
-\r
- }\r
-\r
- class Ray {\r
- public Vector Start;\r
- public Vector Dir;\r
- }\r
-\r
- class ISect {\r
- public SceneObject Thing;\r
- public Ray Ray;\r
- public double Dist;\r
- }\r
-\r
- class Surface {\r
- public Func<Vector, Color> Diffuse;\r
- public Func<Vector, Color> Specular;\r
- public Func<Vector, double> Reflect;\r
- public double Roughness;\r
- }\r
-\r
- class Camera {\r
- public Vector Pos;\r
- public Vector Forward;\r
- public Vector Up;\r
- public Vector Right;\r
-\r
- public static Camera Create(Vector pos, Vector lookAt) {\r
- Vector forward = Vector.Norm(Vector.Minus(lookAt, pos));\r
- Vector down = new Vector(0, -1, 0);\r
- Vector right = Vector.Times(1.5, Vector.Norm(Vector.Cross(forward, down)));\r
- Vector up = Vector.Times(1.5, Vector.Norm(Vector.Cross(forward, right)));\r
-\r
- return new Camera() { Pos = pos, Forward = forward, Up = up, Right = right };\r
- }\r
- }\r
-\r
- class Light {\r
- public Vector Pos;\r
- public Color Color;\r
- }\r
-\r
- abstract class SceneObject {\r
- public Surface Surface;\r
- public abstract ISect Intersect(Ray ray);\r
- public abstract Vector Normal(Vector pos);\r
- }\r
-\r
- class Sphere : SceneObject {\r
- public Vector Center;\r
- public double Radius;\r
-\r
- public override ISect Intersect(Ray ray) {\r
- Vector eo = Vector.Minus(Center, ray.Start);\r
- double v = Vector.Dot(eo, ray.Dir);\r
- double dist;\r
- if (v < 0) {\r
- dist = 0;\r
- }\r
- else {\r
- double disc = Math.Pow(Radius,2) - (Vector.Dot(eo, eo) - Math.Pow(v,2));\r
- dist = disc < 0 ? 0 : v - Math.Sqrt(disc);\r
- }\r
- if (dist == 0) return null;\r
- return new ISect() {\r
- Thing = this,\r
- Ray = ray,\r
- Dist = dist};\r
- }\r
-\r
- public override Vector Normal(Vector pos) {\r
- return Vector.Norm(Vector.Minus(pos, Center));\r
- }\r
- }\r
-\r
- class Plane : SceneObject {\r
- public Vector Norm;\r
- public double Offset;\r
-\r
- public override ISect Intersect(Ray ray) {\r
- double denom = Vector.Dot(Norm, ray.Dir);\r
- if (denom > 0) return null;\r
- return new ISect() {\r
- Thing = this,\r
- Ray = ray,\r
- Dist = (Vector.Dot(Norm, ray.Start) + Offset) / (-denom)};\r
- }\r
-\r
- public override Vector Normal(Vector pos) {\r
- return Norm;\r
- }\r
- }\r
-\r
- class Scene {\r
- public SceneObject[] Things;\r
- public Light[] Lights;\r
- public Camera Camera;\r
-\r
- public IEnumerable<ISect> Intersect(Ray r) {\r
- return from thing in Things\r
- select thing.Intersect(r);\r
- }\r
- }\r
-\r
- public delegate void Action<T,U,V>(T t, U u, V v);\r
-\r
- internal class RayTracerApp\r
- {\r
- //Bitmap bitmap;\r
- //PictureBox pictureBox;\r
- int[] pixelsData; \r
- //Rectangle rect;\r
- const int width = 600;\r
- const int height = 600;\r
-\r
- public RayTracerApp()\r
- {\r
- //bitmap = new Bitmap(width,height, PixelFormat.Format32bppRgb);\r
- pixelsData = new int[width * height];\r
- //rect = new Rectangle(0, 0, width, height);\r
- \r
- RayTracer rayTracer = new RayTracer(width, height);\r
- rayTracer.RenderParallel(rayTracer.DefaultScene, pixelsData);
- //RayTracerLoad();\r
- }
-
- public int[] Pixels {
- get {
- return pixelsData;
- }
- }\r
-\r
- /*private void RayTracerLoad()\r
- {\r
- var bmpData = bitmap.LockBits(rect, ImageLockMode.WriteOnly, bitmap.PixelFormat);\r
- Marshal.Copy(pixelsData, 0, bmpData.Scan0, pixelsData.Length);\r
- bitmap.UnlockBits(bmpData);\r
- }*/
- }
-}
-#endif
+++ /dev/null
-#if NET_4_0
-// SemaphoreSlimTests.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.
-//
-//
-
-using System;
-using System.Linq;
-using System.Threading;
-
-using NUnit.Framework;
-
-namespace ParallelFxTests
-{
- [TestFixture]
- public class SemaphoreSlimTests
- {
- SemaphoreSlim sem;
- SemaphoreSlim semMax;
-
- [SetUp]
- public void Setup()
- {
- sem = new SemaphoreSlim(5);
- semMax = new SemaphoreSlim(5, 5);
- }
-
- [Test]
- public void CurrentCountMaxTestCase()
- {
- semMax.Wait();
- semMax.Release(3);
- Assert.AreEqual(5, semMax.CurrentCount);
- }
-
- [Test]
- public void CurrentCountTestCase()
- {
- sem.Wait();
- sem.Wait();
- sem.Release();
- Assert.AreEqual(4, sem.CurrentCount);
- }
-
- [Test]
- public void WaitStressTest()
- {
- int count = -1;
- bool[] array = new bool[7];
- ParallelTestHelper.ParallelStressTest(sem, delegate (SemaphoreSlim s) {
- int index = Interlocked.Increment(ref count);
- s.Wait();
- Thread.Sleep(40);
- s.Release();
- array[index] = true;
- }, 7);
-
- bool result = array.Aggregate((acc, e) => acc && e);
-
- Assert.IsTrue(result, "#1");
- Assert.AreEqual(5, sem.CurrentCount, "#2");
- }
- }
-}
-#endif
+++ /dev/null
-#if NET_4_0
-// WriteOnceTests.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.
-//
-//
-
-using System;
-using System.Threading;
-
-using NUnit;
-using NUnit.Framework;
-
-namespace ParallelFxTests
-{
-
- [TestFixture]
- public class WriteOnceTests
- {
- WriteOnce<int> wo;
-
- [SetUpAttribute]
- public void Setup()
- {
- wo = new WriteOnce<int>();
- }
-
- [Test, ExpectedExceptionAttribute(typeof(InvalidOperationException))]
- public void OnlyOneWriteTestCase()
- {
- wo.Value = 1;
- wo.Value = 1;
- }
-
- [Test]
- public void HasValueTestCase()
- {
- Assert.IsFalse(wo.HasValue);
- wo.Value = 1;
- Assert.IsTrue(wo.HasValue);
- }
-
- [Test]
- public void EqualityTestCase()
- {
- Assert.AreEqual(wo, wo, "#1");
- wo.Value = 1;
- Assert.AreEqual(wo, wo, "#2");
-
- WriteOnce<object> wObj = new WriteOnce<object>();
- Assert.AreEqual(wObj, wObj, "#3");
- wObj.Value = new object();
- Assert.AreEqual(wObj, wObj, "#4");
- }
- }
-}
-#endif
System.Threading/WaitHandle.cs
System.Threading/WaitHandleCannotBeOpenedException.cs
System.Threading/WaitOrTimerCallback.cs
-System.Threading/AggregateException.cs
-System.Threading/AtomicBoolean.cs
-System.Threading/CountdownEvent.cs
-System.Threading/ISupportsCancellation.cs
-System.Threading/LazyInit.cs
-System.Threading/LazyInitMode.cs
-System.Threading/ManuelResetEventSlim.cs
-System.Threading/Parallel.cs
-System.Threading/ParallelLogger.cs
-System.Threading/ParallelState.cs
-System.Threading/SemaphoreSlim.cs
-System.Threading/SpinLock.cs
-System.Threading/SpinWait.cs
-System.Threading/WriteOnce.cs
-System.Threading.Collections/BlockingCollection.cs
-System.Threading.Collections/ConcurrentDictionary.cs
-System.Threading.Collections/ConcurrentQueue.cs
-System.Threading.Collections/ConcurrentSkipList.cs
-System.Threading.Collections/ConcurrentStack.cs
-System.Threading.Collections/IConcurrentCollection.cs
-System.Threading.Tasks/Future.cs
-System.Threading.Tasks/Task.cs
-System.Threading.Tasks/TaskBase.cs
-System.Threading.Tasks/TaskCanceledException.cs
-System.Threading.Tasks/TaskContinuationKind.cs
-System.Threading.Tasks/TaskCreationOptions.cs
-System.Threading.Tasks/TaskManager.cs
-System.Threading.Tasks/TaskManagerPolicy.cs
-System.Threading.Tasks/Internal/DynamicDeque.cs
-System.Threading.Tasks/Internal/IScheduler.cs
-System.Threading.Tasks/Internal/Scheduler.cs
-System.Threading.Tasks/Internal/ThreadWorker.cs
System.Collections.Generic/Dictionary.cs
System.Collections.Generic/ICollection.cs
System.Collections.Generic/IEnumerable.cs
System.Threading/MutexCas.cs
System.Threading/ThreadCas.cs
System.Threading/WaitHandleCas.cs
-System.Threading/AggregateExceptionTests.cs
-System.Threading/CountdownEventTests.cs
-System.Threading/LazyInitTests.cs
-System.Threading/ManualResetEventSlimTests.cs
-System.Threading/ParallelTests.cs
-System.Threading/SemaphoreSlimTests.cs
-System.Threading/WriteOnceTests.cs
-System.Threading/RayTracerHelper.cs
-System.Threading.Tasks/FutureTests.cs
-System.Threading.Tasks/TaskTest.cs
-System.Threading.Collections/BlockingCollectionTests.cs
-System.Threading.Collections/ConcurrentDictionaryTests.cs
-System.Threading.Collections/ConcurrentQueueTests.cs
-System.Threading.Collections/ConcurrentSkipListTests.cs
-System.Threading.Collections/ConcurrentStackTests.cs
-System.Threading.Collections/ParallelConcurrentQueueTests.cs
-System.Threading.Collections/ParallelConcurrentStackTests.cs