Browse Source

2010-02-02 Jérémie Laval <[email protected]>

In class/corlib/:
   * corlib.dll.sources: Add System.Threading.Tasks/SimpleConcurrentBag.cs
   and System.Threading.Tasks/UnobservedTaskExceptionEventArgs.cs

In class/corlib/System.Collections.Concurrent/:
   * ConcurrentDictionary.cs:
   * ConcurrentQueue.cs:
   * ConcurrentStack.cs:
   * Partitioner.cs: Port to .NET 4 beta 2 API
   * ConcurrentSkipList.cs: Use Monitor for locking

In class/corlib/System.Threading.Tasks/:
   * Future.cs:
   * Parallel.cs:
   * ParallelLoopState.cs:
   * Task.cs:
   * TaskCompletionSource.cs:
   * TaskContinuationOptions.cs:
   * TaskCreationOptions.cs:
   * TaskFactory.cs:
   * TaskScheduler.cs:
   * UnobservedTaskExceptionEventArgs.cs: Port to .NET 4 beta 2 API
   * SimpleConcurrentBag.cs: Add a simpler implementation of ConcurrentBag
   for use with parallel loops as ConcurrentBag was moved to System

In class/corlib/System.Threading/:
   * CancellationToken.cs:
   * CancellationTokenSource.cs:
   * ManualResetEventSlim.cs:
   * SemaphoreSlim.cs:
   * SpinLock.cs:
   * SpinWait.cs:
   * ThreadLocal.cs: Port to .NET 4 beta 2 API

In class/corlib/System/:
   * AggregateException.cs:
   * OperationCanceledException.cs: Port to .NET 4 beta 2 API

In class/corlib/Test/System.Collections.Concurrent/:
   * CollectionStressTestHelper.cs:
   * ConcurrentBagTests.cs:
   * ConcurrentDictionaryTests.cs:
   * ConcurrentQueueTests.cs:
   * ConcurrentSkipListTests.cs:
   * ConcurrentStackTests.cs:
   * ParallelConcurrentQueueTests.cs:
   * ParallelConcurrentStackTests.cs: Update namespaces and tested methods

In class/corlib/Test/System.Threading.Tasks/:
   * FutureTests.cs:
   * ParallelTestHelper.cs:
   * ParallelTests.cs:
   * SnziTests.cs:
   * TaskCompletionSourceTests.cs:
   * TaskTest.cs: Update namespace and tested methods

In class/corlib/Test/System.Threading/:
   * CancellationTokenTests.cs:
   * LazyInitTests.cs:
   * ThreadLazyTests.cs: Update namespace and tested methods

svn path=/trunk/mcs/; revision=150716
Jérémie Laval 16 years ago
parent
commit
e531fc2677
54 changed files with 1279 additions and 725 deletions
  1. 5 0
      mcs/class/corlib/ChangeLog
  2. 9 0
      mcs/class/corlib/System.Collections.Concurrent/ChangeLog
  3. 61 7
      mcs/class/corlib/System.Collections.Concurrent/ConcurrentDictionary.cs
  4. 2 37
      mcs/class/corlib/System.Collections.Concurrent/ConcurrentQueue.cs
  5. 9 18
      mcs/class/corlib/System.Collections.Concurrent/ConcurrentSkipList.cs
  6. 1 30
      mcs/class/corlib/System.Collections.Concurrent/ConcurrentStack.cs
  7. 32 2
      mcs/class/corlib/System.Collections.Concurrent/Partitioner.cs
  8. 0 0
      mcs/class/corlib/System.Collections.Concurrent/Partitioners/EnumerablePartitioner.cs
  9. 0 0
      mcs/class/corlib/System.Collections.Concurrent/Partitioners/ListPartitioner.cs
  10. 15 0
      mcs/class/corlib/System.Threading.Tasks/ChangeLog
  11. 47 19
      mcs/class/corlib/System.Threading.Tasks/Future.cs
  12. 17 10
      mcs/class/corlib/System.Threading.Tasks/Internal/ThreadWorker.cs
  13. 71 97
      mcs/class/corlib/System.Threading.Tasks/Parallel.cs
  14. 2 11
      mcs/class/corlib/System.Threading.Tasks/ParallelLoopState.cs
  15. 90 0
      mcs/class/corlib/System.Threading.Tasks/SimpleConcurrentBag.cs
  16. 85 126
      mcs/class/corlib/System.Threading.Tasks/Task.cs
  17. 16 4
      mcs/class/corlib/System.Threading.Tasks/TaskCompletionSource.cs
  18. 1 2
      mcs/class/corlib/System.Threading.Tasks/TaskContinuationOptions.cs
  19. 1 2
      mcs/class/corlib/System.Threading.Tasks/TaskCreationOptions.cs
  20. 350 85
      mcs/class/corlib/System.Threading.Tasks/TaskFactory.cs
  21. 17 2
      mcs/class/corlib/System.Threading.Tasks/TaskScheduler.cs
  22. 60 0
      mcs/class/corlib/System.Threading.Tasks/UnobservedTaskExceptionEventArgs.cs
  23. 32 21
      mcs/class/corlib/System.Threading/CancellationToken.cs
  24. 18 7
      mcs/class/corlib/System.Threading/CancellationTokenSource.cs
  25. 10 0
      mcs/class/corlib/System.Threading/ChangeLog
  26. 62 54
      mcs/class/corlib/System.Threading/ManualResetEventSlim.cs
  27. 75 54
      mcs/class/corlib/System.Threading/SemaphoreSlim.cs
  28. 28 24
      mcs/class/corlib/System.Threading/SpinLock.cs
  29. 14 14
      mcs/class/corlib/System.Threading/SpinWait.cs
  30. 11 1
      mcs/class/corlib/System.Threading/ThreadLocal.cs
  31. 1 1
      mcs/class/corlib/System/AggregateException.cs
  32. 5 0
      mcs/class/corlib/System/ChangeLog
  33. 38 1
      mcs/class/corlib/System/OperationCanceledException.cs
  34. 11 0
      mcs/class/corlib/Test/System.Collections.Concurrent/ChangeLog
  35. 1 1
      mcs/class/corlib/Test/System.Collections.Concurrent/CollectionStressTestHelper.cs
  36. 1 1
      mcs/class/corlib/Test/System.Collections.Concurrent/ConcurrentBagTests.cs
  37. 2 1
      mcs/class/corlib/Test/System.Collections.Concurrent/ConcurrentDictionaryTests.cs
  38. 1 1
      mcs/class/corlib/Test/System.Collections.Concurrent/ConcurrentQueueTests.cs
  39. 1 1
      mcs/class/corlib/Test/System.Collections.Concurrent/ConcurrentSkipListTests.cs
  40. 1 1
      mcs/class/corlib/Test/System.Collections.Concurrent/ConcurrentStackTests.cs
  41. 1 1
      mcs/class/corlib/Test/System.Collections.Concurrent/ParallelConcurrentQueueTests.cs
  42. 1 1
      mcs/class/corlib/Test/System.Collections.Concurrent/ParallelConcurrentStackTests.cs
  43. 9 0
      mcs/class/corlib/Test/System.Threading.Tasks/ChangeLog
  44. 1 26
      mcs/class/corlib/Test/System.Threading.Tasks/FutureTests.cs
  45. 0 1
      mcs/class/corlib/Test/System.Threading.Tasks/ParallelTestHelper.cs
  46. 3 17
      mcs/class/corlib/Test/System.Threading.Tasks/ParallelTests.cs
  47. 1 1
      mcs/class/corlib/Test/System.Threading.Tasks/SnziTests.cs
  48. 7 3
      mcs/class/corlib/Test/System.Threading.Tasks/TaskCompletionSourceTests.cs
  49. 40 35
      mcs/class/corlib/Test/System.Threading.Tasks/TaskTest.cs
  50. 1 1
      mcs/class/corlib/Test/System.Threading/CancellationTokenTests.cs
  51. 6 0
      mcs/class/corlib/Test/System.Threading/ChangeLog
  52. 1 1
      mcs/class/corlib/Test/System.Threading/LazyInitTests.cs
  53. 1 1
      mcs/class/corlib/Test/System.Threading/ThreadLazyTests.cs
  54. 4 2
      mcs/class/corlib/corlib.dll.sources

+ 5 - 0
mcs/class/corlib/ChangeLog

@@ -1,3 +1,8 @@
+2010-02-02  Jérémie Laval  <[email protected]>
+
+	* corlib.dll.sources: Add System.Threading.Tasks/SimpleConcurrentBag.cs
+	and System.Threading.Tasks/UnobservedTaskExceptionEventArgs.cs
+
 2010-01-26  Marek Habersack  <[email protected]>
 
 	* net_2_1_raw_corlib.dll.sources: added System.IO/SearchOption.cs

+ 9 - 0
mcs/class/corlib/System.Collections.Concurrent/ChangeLog

@@ -1,3 +1,12 @@
+2010-02-02  Jérémie Laval  <[email protected]>
+
+	* ConcurrentDictionary.cs:
+	* ConcurrentQueue.cs:
+	* ConcurrentStack.cs:
+	* Partitioner.cs: Port to .NET 4 beta 2 API
+
+	* ConcurrentSkipList.cs: Use Monitor for locking
+
 2009-08-19  Jérémie Laval  <[email protected]>
 
 	* Partitioner.cs: Fix infinite recursion when calling Create

+ 61 - 7
mcs/class/corlib/System.Collections.Concurrent/ConcurrentDictionary.cs

@@ -66,7 +66,6 @@ namespace System.Collections.Concurrent
 		ConcurrentSkipList<Basket> container
 			= new ConcurrentSkipList<Basket> ((value) => value[0].GetHashCode ());
 		int count;
-		int stamp = int.MinValue;
 		IEqualityComparer<TKey> comparer;
 		
 		public ConcurrentDictionary () : this (EqualityComparer<TKey>.Default)
@@ -125,10 +124,7 @@ namespace System.Collections.Concurrent
 		}
 		
 		public bool TryAdd (TKey key, TValue value)
-		{
-			Interlocked.Increment (ref count);
-			Interlocked.Increment (ref stamp);
-			
+		{			
 			Basket basket;
 			// Add a value to an existing basket
 			if (TryGetBasket (key, out basket)) {
@@ -144,9 +140,17 @@ namespace System.Collections.Concurrent
 				// Add a new basket
 				basket = new Basket ();
 				basket.Add (new Pair (key, value));
-				return container.TryAdd (basket);
+				
+				if (container.TryAdd (basket)) {
+					Interlocked.Increment (ref count);
+					return true;
+				} else {
+					return false;
+				}
 			}
 			
+			Interlocked.Increment (ref count);
+			
 			return true;
 		}
 		
@@ -155,6 +159,30 @@ namespace System.Collections.Concurrent
 			Add (pair.Key, pair.Value);
 		}
 		
+		public TValue AddOrUpdate (TKey key, Func<TKey, TValue> addValueFactory, Func<TKey, TValue, TValue> updateValueFactory)
+		{
+			Basket basket;
+			TValue temp;
+			
+			if (!TryGetBasket (key, out basket)) {
+				Add (key, (temp = addValueFactory (key)));
+			} else {
+				lock (basket) {
+					Pair pair = basket.Find ((p) => comparer.Equals (p.Key, key));
+					if (pair == null)
+						throw new InvalidOperationException ("pair is null, shouldn't be");
+					pair.Value = (temp = updateValueFactory (key, pair.Value));
+				}
+			}
+			
+			return temp;
+		}
+		
+		public TValue AddOrUpdate (TKey key, TValue addValue, Func<TKey, TValue, TValue> updateValueFactory)
+		{
+			return AddOrUpdate (key, (_) => addValue, updateValueFactory);
+		}
+		
 		TValue GetValue (TKey key)
 		{
 			TValue temp;
@@ -215,11 +243,37 @@ namespace System.Collections.Concurrent
 					if (pair == null)
 						throw new InvalidOperationException ("pair is null, shouldn't be");
 					pair.Value = value;
-					Interlocked.Increment (ref stamp);
 				}
 			}
 		}
 		
+		public TValue GetOrAdd (TKey key, Func<TKey, TValue> valueFactory)
+		{
+			Basket basket;
+			TValue temp = default (TValue);
+			
+			if (TryGetBasket (key, out basket)) {
+				Pair pair = null;
+				lock (basket) {
+					pair = basket.Find ((p) => comparer.Equals (p.Key, key));
+					if (pair != null)
+						temp = pair.Value;
+				}
+				
+				if (pair == null)
+					Add (key, (temp = valueFactory (key)));
+			} else {
+				Add (key, (temp = valueFactory (key)));
+			}
+			
+			return temp;
+		}
+		
+		public TValue GetOrAdd (TKey key, TValue value)
+		{
+			return GetOrAdd (key, (_) => value);
+		}
+		
 		public bool TryRemove(TKey key, out TValue value)
 		{
 			value = default (TValue);

+ 2 - 37
mcs/class/corlib/System.Collections.Concurrent/ConcurrentQueue.cs

@@ -33,7 +33,7 @@ namespace System.Collections.Concurrent
 {
 	
 	public class ConcurrentQueue<T> : IProducerConsumerCollection<T>, IEnumerable<T>, ICollection,
-	                                  IEnumerable, ISerializable, IDeserializationCallback
+	                                  IEnumerable
 	{
 		class Node
 		{
@@ -56,12 +56,6 @@ namespace System.Collections.Concurrent
 				Enqueue (item);
 		}
 		
-		[MonoTODO]
-		protected ConcurrentQueue (SerializationInfo info, StreamingContext context)
-		{
-			throw new NotImplementedException ();
-		}
-		
 		public void Enqueue (T item)
 		{
 			Interlocked.Increment (ref count);
@@ -97,10 +91,7 @@ namespace System.Collections.Concurrent
 			Enqueue (item);
 			return true;
 		}
-		
-		/// <summary>
-		/// </summary>
-		/// <returns></returns>
+
 		public bool TryDequeue (out T value)
 		{
 			value = default (T);
@@ -131,9 +122,6 @@ namespace System.Collections.Concurrent
 			return true;
 		}
 		
-		/// <summary>
-		/// </summary>
-		/// <returns></returns>
 		public bool TryPeek (out T value)
 		{
 			if (IsEmpty) {
@@ -199,33 +187,10 @@ namespace System.Collections.Concurrent
 			return dest;
 		}
 		
-		[MonoTODO]
-		protected virtual void GetObjectData (SerializationInfo info, StreamingContext context)
-		{
-			throw new NotImplementedException ();
-		}
-		
-		[MonoTODO]
-		void ISerializable.GetObjectData (SerializationInfo info, StreamingContext context)
-		{
-			GetObjectData (info, context);
-		}
-		
 		bool ICollection.IsSynchronized {
 			get { return true; }
 		}
 
-		[MonoTODO]
-		protected virtual void OnDeserialization (object sender)
-		{
-			throw new NotImplementedException ();
-		}
-		
-		void IDeserializationCallback.OnDeserialization (object sender)
-		{
-			OnDeserialization (sender);
-		}
-
 		bool IProducerConsumerCollection<T>.TryTake (out T item)
 		{
 			return TryDequeue (out item);

+ 9 - 18
mcs/class/corlib/System.Collections.Concurrent/ConcurrentSkipList.cs

@@ -54,7 +54,7 @@ namespace System.Collections.Concurrent
 			public readonly Node[]   Nexts;
 			public volatile bool     Marked;
 			public volatile bool     FullyLinked;
-			public readonly SpinLock SpinLock;
+			public readonly object   Lock;
 
 			public Node (int key, T value, int heightValue)
 			{
@@ -62,7 +62,7 @@ namespace System.Collections.Concurrent
 				Value = value;
 				TopLayer = heightValue;
 				Nexts = new Node [heightValue + 1];
-				SpinLock = new SpinLock (false);
+				Lock = new object ();
 				Marked = FullyLinked = false;
 			}
 		}
@@ -218,13 +218,10 @@ namespace System.Collections.Concurrent
 					if (!isMarked) {
 						toDelete = succs [found];
 						topLayer = toDelete.TopLayer;
-						bool taken = false;
-						do {
-							toDelete.SpinLock.Enter (ref taken);
-						} while (!taken);
+						Monitor.Enter (toDelete.Lock);
 						// Now that we have the lock, check if the node hasn't already been marked
 						if (toDelete.Marked) {
-							toDelete.SpinLock.Exit (true);
+							Monitor.Exit (toDelete.Lock);
 							return false;
 						}
 						toDelete.Marked = true;
@@ -240,7 +237,7 @@ namespace System.Collections.Concurrent
 						for (int layer = topLayer; layer >= 0; layer--) {
 							preds [layer].Nexts [layer] = toDelete.Nexts [layer];
 						}
-						toDelete.SpinLock.Exit (true);
+						Monitor.Exit (toDelete.Lock);
 					} finally {
 						Unlock (preds, highestLocked);
 					}
@@ -278,17 +275,14 @@ namespace System.Collections.Concurrent
 				return false;
 			
 			try {
-				bool taken = false;
-				do {
-					succs [found].SpinLock.Enter (ref taken);
-				} while (!taken);
+				Monitor.Enter (succs [found].Lock);
 				Node node = succs [found];
 				if (node.FullyLinked && !node.Marked) {
 					value = node.Value;
 					return true;
 				}
 			} finally {
-				succs [found].SpinLock.Exit (true);
+				Monitor.Exit (succs [found].Lock);
 			}
 			
 			return false;
@@ -327,7 +321,7 @@ namespace System.Collections.Concurrent
 		void Unlock(Node[] preds, int highestLocked)
 		{
 			for (int i = 0; i <= highestLocked; i++) {
-				preds [i].SpinLock.Exit (true);
+				Monitor.Exit (preds [i].Lock);
 			}
 		}
 
@@ -341,10 +335,7 @@ namespace System.Collections.Concurrent
 				succ = succs [layer];
 				if (pred != prevPred) {
 					// Possible optimization : limit topLayer to the first refused lock
-					bool taken = false;
-					do {
-						pred.SpinLock.Enter (ref taken);
-					} while (!taken);
+					Monitor.Enter (pred.Lock);
 					highestLocked = layer;
 					prevPred = pred;
 				}

+ 1 - 30
mcs/class/corlib/System.Collections.Concurrent/ConcurrentStack.cs

@@ -34,7 +34,7 @@ namespace System.Collections.Concurrent
 	
 	
 	public class ConcurrentStack<T> : IProducerConsumerCollection<T>, IEnumerable<T>,
-	                                  ICollection, IEnumerable, ISerializable, IDeserializationCallback
+	                                  ICollection, IEnumerable
 	{
 		class Node
 		{
@@ -56,12 +56,6 @@ namespace System.Collections.Concurrent
 				Push (item);
 		}
 		
-		[MonoTODO]
-		protected ConcurrentStack (SerializationInfo info, StreamingContext context)
-		{
-			throw new NotImplementedException ();
-		}
-		
 		bool IProducerConsumerCollection<T>.TryAdd (T elem)
 		{
 			Push (elem);
@@ -217,33 +211,10 @@ namespace System.Collections.Concurrent
 			}
 		}
 		
-		[MonoTODO]
-		protected virtual void GetObjectData (SerializationInfo info, StreamingContext context)
-		{
-			throw new NotImplementedException ();
-		}
-		
-		[MonoTODO]
-		void ISerializable.GetObjectData (SerializationInfo info, StreamingContext context)
-		{
-			GetObjectData (info, context);
-		}
-		
 		bool ICollection.IsSynchronized {
 			get { return true; }
 		}
-
-		[MonoTODO]
-		protected virtual void OnDeserialization (object sender)
-		{
-			throw new NotImplementedException ();
-		}
 		
-		void IDeserializationCallback.OnDeserialization (object sender)
-		{
-			OnDeserialization (sender);
-		}
-
 		bool IProducerConsumerCollection<T>.TryTake (out T item)
 		{
 			return TryPop (out item);

+ 32 - 2
mcs/class/corlib/System.Collections.Concurrent/Partitioner.cs

@@ -41,15 +41,45 @@ namespace System.Collections.Concurrent
 			return new EnumerablePartitioner<TSource> (source);
 		}
 		
-	  public static OrderablePartitioner<TSource> Create<TSource> (TSource[] source, bool loadBalance)
+		public static OrderablePartitioner<TSource> Create<TSource> (TSource[] source, bool loadBalance)
 		{
 			return Create ((IList<TSource>)source, loadBalance);
 		}
 		
-	  public static OrderablePartitioner<TSource> Create<TSource> (IList<TSource> source, bool loadBalance)
+		public static OrderablePartitioner<TSource> Create<TSource> (IList<TSource> source, bool loadBalance)
 		{
 			return new ListPartitioner<TSource> (source);
 		}
+		
+		[MonoTODO("What range size is supposed to be in context and what the result returned looks like")]
+		public static OrderablePartitioner<Tuple<int, int>> Create (int fromInclusive,
+		                                                             int toExclusive)
+		{
+			return Create (fromInclusive, toExclusive, 1);
+		}
+		
+		[MonoTODO("What range size is supposed to be in context and what the result returned looks like")]
+		public static OrderablePartitioner<Tuple<int, int>> Create (int fromInclusive,
+		                                                             int toExclusive,
+		                                                             int rangeSize)
+		{
+			throw new NotImplementedException ();
+		}
+		
+		[MonoTODO("What range size is supposed to be in context and what the result returned looks like")]
+		public static OrderablePartitioner<Tuple<long, long>> Create (long fromInclusive,
+		                                                               long toExclusive)
+		{
+			return Create (fromInclusive, toExclusive, 1);
+		}
+		
+		[MonoTODO("What range size is supposed to be in context and what the result returned looks like")]
+		public static OrderablePartitioner<Tuple<long, long>> Create (long fromInclusive,
+		                                                               long toExclusive,
+		                                                               long rangeSize)
+		{
+			throw new NotImplementedException ();
+		}
 	}
 	
 	public abstract class Partitioner<TSource>

+ 0 - 0
mcs/class/corlib/System.Collections.Concurrent/Partitionners/EnumerablePartitioner.cs → mcs/class/corlib/System.Collections.Concurrent/Partitioners/EnumerablePartitioner.cs


+ 0 - 0
mcs/class/corlib/System.Collections.Concurrent/Partitionners/ListPartitioner.cs → mcs/class/corlib/System.Collections.Concurrent/Partitioners/ListPartitioner.cs


+ 15 - 0
mcs/class/corlib/System.Threading.Tasks/ChangeLog

@@ -1,3 +1,18 @@
+2010-02-02  Jérémie Laval  <[email protected]>
+
+	* Future.cs:
+	* Parallel.cs:
+	* ParallelLoopState.cs:
+	* Task.cs:
+	* TaskCompletionSource.cs:
+	* TaskContinuationOptions.cs:
+	* TaskCreationOptions.cs:
+	* TaskFactory.cs:
+	* TaskScheduler.cs:
+	* UnobservedTaskExceptionEventArgs.cs: Port to .NET 4 beta 2 API
+	* SimpleConcurrentBag.cs: Add a simpler implementation of ConcurrentBag
+	for use with parallel loops as ConcurrentBag was moved to System
+
 2009-08-19  Jérémie Laval  <[email protected]>
 
 	* Task.cs: Refactor Wait methods.

+ 47 - 19
mcs/class/corlib/System.Threading.Tasks/Future.cs

@@ -47,15 +47,6 @@ namespace System.Threading.Tasks
 			}
 		}
 		
-		public new Exception Exception {
-			get {
-				return base.Exception;
-			}
-			internal set {
-				base.Exception = value;
-			}
-		}
-		
 		public static new TaskFactory<TResult> Factory {
 			get {
 				return factory;
@@ -67,7 +58,20 @@ namespace System.Threading.Tasks
 			
 		}
 		
-		public Task (Func<TResult> function, TaskCreationOptions options) : this ((o) => function (), null, options)
+		public Task (Func<TResult> function, CancellationToken token)
+			: this ((o) => function (), null, token, TaskCreationOptions.None)
+		{
+			
+		}
+		
+		public Task (Func<TResult> function, TaskCreationOptions options)
+			: this ((o) => function (), null, CancellationToken.None, options)
+		{
+			
+		}
+		
+		public Task (Func<TResult> function, CancellationToken token, TaskCreationOptions options)
+			: this ((o) => function (), null, token, options)
 		{
 			
 		}
@@ -77,8 +81,20 @@ namespace System.Threading.Tasks
 			
 		}
 		
+		public Task (Func<object, TResult> function, object state, CancellationToken token)
+			: this (function, state, token, TaskCreationOptions.None)
+		{
+			
+		}
+		
 		public Task (Func<object, TResult> function, object state, TaskCreationOptions options)
-			: base (null, state, options)
+			: this (function, state, CancellationToken.None, options)
+		{
+			
+		}
+		
+		public Task (Func<object, TResult> function, object state, CancellationToken token, TaskCreationOptions options)
+			: base (null, state, token, options)
 		{
 			this.function = function;
 			this.state = state;
@@ -100,17 +116,23 @@ namespace System.Threading.Tasks
 		
 		public Task ContinueWith (Action<Task<TResult>> a, TaskContinuationOptions options)
 		{
-			return ContinueWith (a, options, TaskScheduler.Current);
+			return ContinueWith (a, CancellationToken.None, options, TaskScheduler.Current);
+		}
+		
+		public Task ContinueWith (Action<Task<TResult>> a, CancellationToken token)
+		{
+			return ContinueWith (a, token, TaskContinuationOptions.None, TaskScheduler.Current);
 		}
 		
 		public Task ContinueWith (Action<Task<TResult>> a, TaskScheduler scheduler)
 		{
-			return ContinueWith (a, TaskContinuationOptions.None, scheduler);
+			return ContinueWith (a, CancellationToken.None, TaskContinuationOptions.None, scheduler);
 		}
 		
-		public Task ContinueWith (Action<Task<TResult>> a, TaskContinuationOptions options, TaskScheduler scheduler)
+		public Task ContinueWith (Action<Task<TResult>> a, CancellationToken token,
+		                          TaskContinuationOptions options, TaskScheduler scheduler)
 		{
-			Task t = new Task ((o) => a ((Task<TResult>)o), this, TaskCreationOptions.None);
+			Task t = new Task ((o) => a ((Task<TResult>)o), this, token, GetCreationOptions (options));
 			ContinueWithCore (t, options, scheduler);
 			
 			return t;
@@ -121,20 +143,26 @@ namespace System.Threading.Tasks
 			return ContinueWith<TNewResult> (a, TaskContinuationOptions.None);
 		}
 		
+		public Task<TNewResult> ContinueWith<TNewResult> (Func<Task<TResult>, TNewResult> a, CancellationToken token)
+		{
+			return ContinueWith<TNewResult> (a, token, TaskContinuationOptions.None, TaskScheduler.Current);
+		}
+		
 		public Task<TNewResult> ContinueWith<TNewResult> (Func<Task<TResult>, TNewResult> a, TaskContinuationOptions options)
 		{
-			return ContinueWith<TNewResult> (a, options, TaskScheduler.Current);
+			return ContinueWith<TNewResult> (a, CancellationToken.None, options, TaskScheduler.Current);
 		}
 		
 		public Task<TNewResult> ContinueWith<TNewResult> (Func<Task<TResult>, TNewResult> a, TaskScheduler scheduler)
 		{
-			return ContinueWith<TNewResult> (a, TaskContinuationOptions.None, scheduler);
+			return ContinueWith<TNewResult> (a, CancellationToken.None, TaskContinuationOptions.None, scheduler);
 		}
 		
-		public Task<TNewResult> ContinueWith<TNewResult> (Func<Task<TResult>, TNewResult> a, TaskContinuationOptions options,
+		public Task<TNewResult> ContinueWith<TNewResult> (Func<Task<TResult>, TNewResult> a, CancellationToken token,
+		                                                  TaskContinuationOptions options,
 		                                                  TaskScheduler scheduler)
 		{
-			Task<TNewResult> t = new Task<TNewResult> ((o) => a ((Task<TResult>)o), this, TaskCreationOptions.None);
+			Task<TNewResult> t = new Task<TNewResult> ((o) => a ((Task<TResult>)o), this, token, GetCreationOptions (options));
 			ContinueWithCore (t, options, scheduler);
 			
 			return t;

+ 17 - 10
mcs/class/corlib/System.Threading.Tasks/Internal/ThreadWorker.cs

@@ -29,7 +29,7 @@ using System.Collections.Concurrent;
 
 namespace System.Threading.Tasks
 {
-	internal class ThreadWorker: IDisposable
+	internal class ThreadWorker : IDisposable
 	{
 		static Random r = new Random ();
 		
@@ -66,12 +66,6 @@ namespace System.Threading.Tasks
 		{
 			this.others          = others;
 
-//			if (!string.IsNullOrEmpty (Environment.GetEnvironmentVariable ("USE_CYCLIC"))) {
-//				Console.WriteLine ("Using cyclic deque");
-//				this.dDeque = new CyclicDeque<Task> ();
-//			} else {
-//				this.dDeque = new DynamicDeque<Task> ();
-//			}
 			this.dDeque = new CyclicDeque<Task> ();
 			
 			this.sharedWorkQueue = sharedWorkQueue;
@@ -217,6 +211,8 @@ namespace System.Threading.Tasks
 		// 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)
+		// Predicate should be really fast and not blocking as it is called a good deal of time
+		// Also, the method skip tasks that are LongRunning to avoid blocking (Task are not LongRunning by default)
 		public static void WorkerMethod (Func<bool> predicate, IProducerConsumerCollection<Task> sharedWorkQueue,
 		                                 ThreadWorker[] others)
 		{
@@ -226,7 +222,10 @@ namespace System.Threading.Tasks
 				// Dequeue only one item as we have restriction
 				if (sharedWorkQueue.TryTake (out value)) {
 					if (value != null) {
-						value.Execute (null);
+						if (CheckTaskFitness (value))
+							value.Execute (null);
+						else
+							sharedWorkQueue.TryAdd (value);
 					}
 				}
 				
@@ -243,7 +242,10 @@ namespace System.Threading.Tasks
 					
 					if (other.dDeque.PopTop (out value) == PopResult.Succeed) {
 						if (value != null) {
-							value.Execute (null);
+							if (CheckTaskFitness (value))
+								value.Execute (null);
+							else
+								sharedWorkQueue.TryAdd (value);
 						}
 					}
 					
@@ -254,9 +256,14 @@ namespace System.Threading.Tasks
 			}
 		}
 		
+		static bool CheckTaskFitness (Task t)
+		{
+			return (t.CreationOptions | TaskCreationOptions.LongRunning) > 0;
+		}
+		
 		public bool Finished {
 			get {
-				return started == 0;	
+				return started == 0;
 			}
 		}
 		

+ 71 - 97
mcs/class/corlib/System.Threading.Tasks/Parallel.cs

@@ -42,6 +42,18 @@ namespace System.Threading.Tasks
 			return scheduler.MaximumConcurrencyLevel;
 		}
 		
+		static int GetBestWorkerNumber (int from, int to, ParallelOptions options, out int step)
+		{
+			int num = Math.Min (GetBestWorkerNumber (),
+			                    options != null && options.MaxDegreeOfParallelism != -1 ? options.MaxDegreeOfParallelism : int.MaxValue);
+			// Integer range that each task process
+			step = Math.Min (5, (to - from) / num);
+			if (step <= 0)
+				step = 1;
+			
+			return num;
+		}
+		
 		static void HandleExceptions (IEnumerable<Task> tasks)
 		{
 			HandleExceptions (tasks, null);
@@ -51,7 +63,7 @@ namespace System.Threading.Tasks
 		{
 			List<Exception> exs = new List<Exception> ();
 			foreach (Task t in tasks) {
-				if (t.Exception != null && !(t.Exception is TaskCanceledException))
+				if (t.Exception != null)
 					exs.Add (t.Exception);
 			}
 			
@@ -63,20 +75,15 @@ namespace System.Threading.Tasks
 			}
 		}
 		
-		static void InitTasks (Task[] tasks, Action action, int count)
-		{
-			InitTasks (tasks, count, () => Task.Factory.StartNew (action, TaskCreationOptions.DetachedFromParent));
-		}
-		
-		static void InitTasks (Task[] tasks, Action action, int count, TaskScheduler scheduler)
-		{
-			InitTasks (tasks, count, () => Task.Factory.StartNew (action, TaskCreationOptions.DetachedFromParent, scheduler));
-		}
-		
-		static void InitTasks (Task[] tasks, int count, Func<Task> taskCreator)
+		static void InitTasks (Task[] tasks, int count, Action action, ParallelOptions options)
 		{
+			TaskCreationOptions creation = TaskCreationOptions.LongRunning;
+			
 			for (int i = 0; i < count; i++) {
-				tasks [i] = taskCreator ();
+				if (options == null)
+					tasks [i] = Task.Factory.StartNew (action, creation);
+				else
+					tasks [i] = Task.Factory.StartNew (action, options.CancellationToken, creation, options.TaskScheduler);
 			}
 		}
 		#region For
@@ -106,8 +113,8 @@ namespace System.Threading.Tasks
 		{
 			return For<TLocal> (from, to, null, init, action, destruct);
 		}
+	
 		
-		[MonoTODO]
 		public static ParallelLoopResult For<TLocal> (int from, int to, ParallelOptions options, 
 		                                              Func<TLocal> init, 
 		                                              Func<int, ParallelLoopState, TLocal, TLocal> action,
@@ -117,52 +124,53 @@ namespace System.Threading.Tasks
 				throw new ArgumentNullException ("action");
 			
 			// Number of task to be launched (normally == Env.ProcessorCount)
-			int num = Math.Min (GetBestWorkerNumber (), 
-			                    options != null && options.MaxDegreeOfParallelism != -1 ? options.MaxDegreeOfParallelism : int.MaxValue);
-			// Integer range that each task process
-			int step = Math.Min (5, (to - from) / num);
-			if (step <= 0)
-				step = 1;
-			
-			throw new NotImplementedException ();
-/*
+			int step;
+			int num = GetBestWorkerNumber (from, to, options, out step);
+
 			// Each worker put the indexes it's responsible for here
 			// so that other worker may steal if they starve.
-			ConcurrentBag<int> bag = new ConcurrentBag<int> ();
+			SimpleConcurrentBag<int> bag = new SimpleConcurrentBag<int> (num);
 			Task[] tasks = new Task [num];
 			ParallelLoopState.ExternalInfos infos = new ParallelLoopState.ExternalInfos ();
 			
+			Func<ParallelLoopState, bool> cancellationTokenTest = (s) => {
+				if (options != null && options.CancellationToken.IsCancellationRequested) {
+					s.Stop ();
+					return true;
+				}
+				return false;
+			};
+			
+			Func<int, bool> breakTest = (i) => infos.LowestBreakIteration != null && infos.LowestBreakIteration > i;
+			
 			int currentIndex = from;
-		
+			
 			Action workerMethod = delegate {
 				int index, actual;
 				TLocal local = (init == null) ? default (TLocal) : init ();
 				
-				ParallelLoopState state = new ParallelLoopState (tasks, infos);
+				ParallelLoopState state = new ParallelLoopState (infos);
+				int workIndex = bag.GetNextIndex ();
 				
 				try {
-					while ((index = Interlocked.Add (ref currentIndex, step) - step) < to) {
+					while (currentIndex < to && (index = Interlocked.Add (ref currentIndex, step) - step) < to) {
 						if (infos.IsStopped.Value)
 							return;
 						
-						if (options != null && options.CancellationToken.IsCancellationRequested) {
-							state.Stop ();
+						if (cancellationTokenTest (state))
 							return;
-						}
 						
 						for (int i = index; i < to && i < index + step; i++)
-							bag.Add (i);
+							bag.Add (workIndex, i);
 						
-						for (int i = index; i < to && i < index + step && bag.TryTake (out actual); i++) {
+						for (int i = index; i < to && i < index + step && bag.TryTake (workIndex, out actual); i++) {
 							if (infos.IsStopped.Value)
 								return;
 							
-							if (options != null && options.CancellationToken.IsCancellationRequested) {
-								state.Stop ();
+							if (cancellationTokenTest (state))
 								return;
-							}
 							
-							if (infos.LowestBreakIteration != null && infos.LowestBreakIteration > actual)
+							if (breakTest (actual))
 								return;
 							
 							state.CurrentIteration = actual;
@@ -170,16 +178,14 @@ namespace System.Threading.Tasks
 						}
 					}
 					
-					while (bag.TryTake (out actual)) {
+					while (bag.TrySteal (workIndex, out actual)) {
 						if (infos.IsStopped.Value)
 							return;
 						
-						if (options != null && options.CancellationToken.IsCancellationRequested) {
-							state.Stop ();
+						if (cancellationTokenTest (state))
 							return;
-						}
 						
-						if (infos.LowestBreakIteration != null && infos.LowestBreakIteration > actual)
+						if (breakTest (actual))
 							continue;
 						
 						state.CurrentIteration = actual;
@@ -190,11 +196,8 @@ namespace System.Threading.Tasks
 						destruct (local);
 				}
 			};
-		
-			if (options != null && options.TaskScheduler != null)
-				InitTasks (tasks, workerMethod, num, options.TaskScheduler);
-			else
-				InitTasks (tasks, workerMethod, num);
+
+			InitTasks (tasks, num, workerMethod, options);
 			
 			try {
 				Task.WaitAll (tasks);
@@ -202,14 +205,12 @@ namespace System.Threading.Tasks
 				HandleExceptions (tasks, infos);
 			}
 			
-			return new ParallelLoopResult (infos.LowestBreakIteration, !(infos.IsStopped.Value || infos.IsExceptional));
-*/			
+			return new ParallelLoopResult (infos.LowestBreakIteration, !(infos.IsStopped.Value || infos.IsExceptional));	
 		}
 
 		#endregion
 		
 		#region Foreach
-		[MonoTODO]
 		static ParallelLoopResult ForEach<TSource, TLocal> (Func<int, IList<IEnumerator<TSource>>> enumerable, ParallelOptions options,
 		                                                    Func<TLocal> init, Func<TSource, ParallelLoopState, TLocal, TLocal> action,
 		                                                    Action<TLocal> destruct)
@@ -220,19 +221,27 @@ namespace System.Threading.Tasks
 			Task[] tasks = new Task[num];
 			ParallelLoopState.ExternalInfos infos = new ParallelLoopState.ExternalInfos ();
 			
-			throw new NotImplementedException ();
-/*			
-			ConcurrentBag<TSource> bag = new ConcurrentBag<TSource> ();
+			SimpleConcurrentBag<TSource> bag = new SimpleConcurrentBag<TSource> (num);
 			const int bagCount = 5;
 			
 			IList<IEnumerator<TSource>> slices = enumerable (num);
+			
 			int sliceIndex = 0;
+			
+			Func<ParallelLoopState, bool> cancellationTokenTest = (s) => {
+				if (options != null && options.CancellationToken.IsCancellationRequested) {
+					s.Stop ();
+					return true;
+				}
+				return false;
+			};
 
 			Action workerMethod = delegate {
 				IEnumerator<TSource> slice = slices[Interlocked.Increment (ref sliceIndex) - 1];
 				
 				TLocal local = (init != null) ? init () : default (TLocal);
-				ParallelLoopState state = new ParallelLoopState (tasks, infos);
+				ParallelLoopState state = new ParallelLoopState (infos);
+				int workIndex = bag.GetNextIndex ();
 				
 				try {
 					bool cont = true;
@@ -242,36 +251,30 @@ namespace System.Threading.Tasks
 						if (infos.IsStopped.Value)
 							return;
 						
-						if (options != null && options.CancellationToken.IsCancellationRequested) {
-							state.Stop ();
+						if (cancellationTokenTest (state))
 							return;
-						}
 						
 						for (int i = 0; i < bagCount && (cont = slice.MoveNext ()); i++) {
-							bag.Add (slice.Current);
+							bag.Add (workIndex, slice.Current);
 						}
 						
-						for (int i = 0; i < bagCount && bag.TryTake (out element); i++) {
+						for (int i = 0; i < bagCount && bag.TryTake (workIndex, out element); i++) {
 							if (infos.IsStopped.Value)
 								return;
 							
-							if (options != null && options.CancellationToken.IsCancellationRequested) {
-								state.Stop ();
+							if (cancellationTokenTest (state))
 								return;
-							}
 							
 							local = action (element, state, local);
 						}
 					}
 					
-					while (bag.TryTake (out element)) {
+					while (bag.TrySteal (workIndex, out element)) {
 						if (infos.IsStopped.Value)
 							return;
 						
-						if (options != null && options.CancellationToken.IsCancellationRequested) {
-							state.Stop ();
+						if (cancellationTokenTest (state))
 							return;
-						}
 						
 						local = action (element, state, local);
 					}
@@ -281,10 +284,7 @@ namespace System.Threading.Tasks
 				}
 			};
 			
-			if (options != null && options.TaskScheduler != null)
-				InitTasks (tasks, workerMethod, num, options.TaskScheduler);
-			else
-				InitTasks (tasks, workerMethod, num);
+			InitTasks (tasks, num, workerMethod, options);
 			
 			try {
 				Task.WaitAll (tasks);
@@ -293,7 +293,7 @@ namespace System.Threading.Tasks
 			}
 			
 			return new ParallelLoopResult (infos.LowestBreakIteration, !(infos.IsStopped.Value || infos.IsExceptional));
-			*/
+			
 		}
 		
 		public static ParallelLoopResult ForEach<TSource> (IEnumerable<TSource> enumerable, Action<TSource> action)
@@ -436,32 +436,6 @@ namespace System.Threading.Tasks
 			                                                    init, (e, s, l) => action (e.Value, s, e.Key, l), destruct);
 		}
 		#endregion
-		
-		/* Disabled as this is an API addition
-		#region While		
-		public static void While (Func<bool> predicate, Action body)
-		{
-			if (body == null)
-				throw new ArgumentNullException ("body");
-			if (predicate == null)
-				throw new ArgumentNullException ("predicate");
-			
-			int num = GetBestWorkerNumber ();
-			
-			Task[] tasks = new Task [num];
-			
-			Action action = delegate {
-				while (predicate ())
-				body ();
-			};
-			
-			InitTasks (tasks, action, num);
-			Task.WaitAll (tasks);
-			HandleExceptions (tasks);
-		}
-		
-		#endregion
-		*/
 
 		#region Invoke
 		public static void Invoke (params Action[] actions)
@@ -479,7 +453,7 @@ namespace System.Threading.Tasks
 			if (actions == null)
 				throw new ArgumentNullException ("actions");
 			
-			Invoke (actions, (Action a) => Task.Factory.StartNew (a, TaskCreationOptions.None, parallelOptions.TaskScheduler));
+			Invoke (actions, (Action a) => Task.Factory.StartNew (a, CancellationToken.None, TaskCreationOptions.None, parallelOptions.TaskScheduler));
 		}
 		
 		static void Invoke (Action[] actions, Func<Action, Task> taskCreator)

+ 2 - 11
mcs/class/corlib/System.Threading.Tasks/ParallelLoopState.cs

@@ -38,12 +38,10 @@ namespace System.Threading.Tasks
 			public long? LowestBreakIteration;
 		}
 		
-		Task[] tasks;
 		ExternalInfos extInfos;
 		
-		internal ParallelLoopState (Task[] tasks, ExternalInfos extInfos)
+		internal ParallelLoopState (ExternalInfos extInfos)
 		{
-			this.tasks = tasks;
 			this.extInfos = extInfos;
 		}
 		
@@ -85,14 +83,7 @@ namespace System.Threading.Tasks
 		
 		public void Stop ()
 		{
-			bool result = extInfos.IsStopped.Exchange (true);
-			if (!result) {
-				foreach (var t in tasks) {
-					if (t == null)
-						continue;
-					t.Cancel ();
-				}
-			}
+			extInfos.IsStopped.Exchange (true);
 		}
 	}
 	

+ 90 - 0
mcs/class/corlib/System.Threading.Tasks/SimpleConcurrentBag.cs

@@ -0,0 +1,90 @@
+#if NET_4_0
+// 
+// SimpleConcurrentBag.cs
+//  
+// Author:
+//       Jérémie "Garuma" Laval <[email protected]>
+// 
+// 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;
+
+namespace System.Threading.Tasks
+{
+
+	internal class SimpleConcurrentBag<T>
+	{
+		readonly IDequeOperations<T>[] deques;
+		readonly bool unique;
+		int index = -1;
+		
+		[ThreadStatic]
+		int stealIndex;
+		
+		public SimpleConcurrentBag (int num)
+		{
+			deques = new CyclicDeque<T>[num];
+			for (int i = 0; i < deques.Length; i++) {
+				deques[i] = new CyclicDeque<T> ();
+			}
+			unique = num <= 1;
+		}
+		
+		public int GetNextIndex ()
+		{
+			return Interlocked.Increment (ref index);
+		}
+		
+		public bool TryTake (int index, out T value)
+		{
+			value = default (T);
+			
+			return deques[index].PopBottom (out value) == PopResult.Succeed;
+		}
+		
+		public bool TrySteal (int index, out T value)
+		{
+			value = default (T);
+			
+			if (unique)
+				return false;
+			
+			const int roundThreshold = 3;
+			
+			for (int round = 0; round < roundThreshold; ++round) {
+				if (stealIndex == index)
+					stealIndex = (stealIndex + 1) % deques.Length;
+			
+				if (deques[(stealIndex = (stealIndex + 1) % deques.Length)].PopTop (out value) == PopResult.Succeed)
+					return true;
+			}
+			
+			return false;
+		}
+		
+		public void Add (int index, T value)
+		{
+			deques[index].PushBottom (value);
+		}
+	}
+}
+#endif

+ 85 - 126
mcs/class/corlib/System.Threading.Tasks/Task.cs

@@ -38,62 +38,75 @@ namespace System.Threading.Tasks
 		[System.ThreadStatic]
 		static Action<Task> childWorkAdder;
 		
+		Task parent;
+		
 		static int          id = -1;
 		static TaskFactory  defaultFactory = new TaskFactory ();
 		
 		CountdownEvent childTasks = new CountdownEvent (1);
 		
-		Task parent = current;
-		
 		int                 taskId;
-		bool                respectParentCancellation;
 		TaskCreationOptions taskCreationOptions;
 		
 		IScheduler          scheduler;
 		TaskScheduler       taskScheduler;
 		
-		volatile Exception  exception;
-		volatile bool       exceptionObserved;
-		volatile TaskStatus status;
+		volatile AggregateException  exception;
+		volatile bool                exceptionObserved;
+		volatile TaskStatus          status;
 		
 		Action<object> action;
 		object         state;
 		EventHandler   completed;
 		
-		CancellationTokenSource src = new CancellationTokenSource ();
-			
+		CancellationToken token;			
 		
 		public Task (Action action) : this (action, TaskCreationOptions.None)
-		{
-			
+		{	
+		}
+		
+		public Task (Action action, TaskCreationOptions options) : this (action, CancellationToken.None, options)
+		{	
 		}
 		
-		public Task (Action action, TaskCreationOptions options) : this ((o) => action (), null, options)
+		public Task (Action action, CancellationToken token) : this (action, token, TaskCreationOptions.None)
+		{	
+		}
+		
+		public Task (Action action, CancellationToken token, TaskCreationOptions options)
+			: this ((o) => action (), null, token, options)
 		{
-			
 		}
 		
 		public Task (Action<object> action, object state) : this (action, state, TaskCreationOptions.None)
-		{
-			
+		{	
 		}
 		
 		public Task (Action<object> action, object state, TaskCreationOptions options)
+			: this (action, state, CancellationToken.None, options)
+		{
+		}
+		
+		public Task (Action<object> action, object state, CancellationToken token)
+			: this (action, state, token, TaskCreationOptions.None)
+		{	
+		}
+		
+		public Task (Action<object> action, object state, CancellationToken token, TaskCreationOptions options)
 		{
 			this.taskCreationOptions = options;
-			this.action = action == null ? EmptyFunc : action;
-			this.state = state;
-			this.taskId = Interlocked.Increment (ref id);
-			this.status = TaskStatus.Created;
+			this.action              = action == null ? EmptyFunc : action;
+			this.state               = state;
+			this.taskId              = Interlocked.Increment (ref id);
+			this.status              = TaskStatus.Created;
+			this.token               = token;
 
 			// Process taskCreationOptions
-			if (CheckTaskOptions (taskCreationOptions, TaskCreationOptions.DetachedFromParent))
-				parent = null;
-			else if (parent != null)
-				parent.AddChild ();
-
-			respectParentCancellation =
-				CheckTaskOptions (taskCreationOptions, TaskCreationOptions.RespectParentCancellation);
+			if (CheckTaskOptions (taskCreationOptions, TaskCreationOptions.AttachedToParent)) {
+				parent = current;
+				if (parent != null)
+					parent.AddChild ();
+			}
 		}
 		
 		~Task ()
@@ -156,17 +169,22 @@ namespace System.Threading.Tasks
 		
 		public Task ContinueWith (Action<Task> a, TaskContinuationOptions kind)
 		{
-			return ContinueWith (a, kind, TaskScheduler.Current);
+			return ContinueWith (a, CancellationToken.None, kind, TaskScheduler.Current);
+		}
+		
+		public Task ContinueWith (Action<Task> a, CancellationToken token)
+		{
+			return ContinueWith (a, token, TaskContinuationOptions.None, TaskScheduler.Current);
 		}
 		
 		public Task ContinueWith (Action<Task> a, TaskScheduler scheduler)
 		{
-			return ContinueWith (a, TaskContinuationOptions.None, scheduler);
+			return ContinueWith (a, CancellationToken.None, TaskContinuationOptions.None, scheduler);
 		}
 		
-		public Task ContinueWith (Action<Task> a, TaskContinuationOptions kind, TaskScheduler scheduler)
+		public Task ContinueWith (Action<Task> a, CancellationToken token, TaskContinuationOptions kind, TaskScheduler scheduler)
 		{
-			Task continuation = new Task ((o) => a ((Task)o), this, GetCreationOptions (kind));
+			Task continuation = new Task ((o) => a ((Task)o), this, token, GetCreationOptions (kind));
 			ContinueWithCore (continuation, kind, scheduler);
 			return continuation;
 		}
@@ -178,17 +196,23 @@ namespace System.Threading.Tasks
 		
 		public Task<TResult> ContinueWith<TResult> (Func<Task, TResult> a, TaskContinuationOptions options)
 		{
-			return ContinueWith<TResult> (a, options, TaskScheduler.Current);
+			return ContinueWith<TResult> (a, CancellationToken.None, options, TaskScheduler.Current);
+		}
+		
+		public Task<TResult> ContinueWith<TResult> (Func<Task, TResult> a, CancellationToken token)
+		{
+			return ContinueWith<TResult> (a, token, TaskContinuationOptions.None, TaskScheduler.Current);
 		}
 		
 		public Task<TResult> ContinueWith<TResult> (Func<Task, TResult> a, TaskScheduler scheduler)
 		{
-			return ContinueWith<TResult> (a, TaskContinuationOptions.None, scheduler);
+			return ContinueWith<TResult> (a, CancellationToken.None, TaskContinuationOptions.None, scheduler);
 		}
 		
-		public Task<TResult> ContinueWith<TResult> (Func<Task, TResult> a, TaskContinuationOptions kind, TaskScheduler scheduler)
+		public Task<TResult> ContinueWith<TResult> (Func<Task, TResult> a, CancellationToken token,
+		                                            TaskContinuationOptions kind, TaskScheduler scheduler)
 		{
-			Task<TResult> t = new Task<TResult> ((o) => a ((Task)o), this, GetCreationOptions (kind));
+			Task<TResult> t = new Task<TResult> ((o) => a ((Task)o), this, token, GetCreationOptions (kind));
 			
 			ContinueWithCore (t, kind, scheduler);
 			
@@ -213,7 +237,6 @@ namespace System.Threading.Tasks
 				
 				if (!launched.Value && !launched.Exchange (true)) {
 					if (!ContinuationStatusCheck (kind)) {
-						continuation.Cancel ();
 						continuation.CancelReal ();
 						continuation.Dispose ();
 						
@@ -273,20 +296,21 @@ namespace System.Threading.Tasks
 		
 		void CheckAndSchedule (Task continuation, TaskContinuationOptions options, TaskScheduler scheduler)
 		{
-			if (options == TaskContinuationOptions.None || (options & TaskContinuationOptions.ExecuteSynchronously) > 0) {
+			if (options == TaskContinuationOptions.None || (options & TaskContinuationOptions.ExecuteSynchronously) > 0)
 				continuation.ThreadStart ();
-			} else {
+			else
 				continuation.Start (scheduler);
-			}
 		}
 		
-		static TaskCreationOptions GetCreationOptions (TaskContinuationOptions kind)
+		internal TaskCreationOptions GetCreationOptions (TaskContinuationOptions kind)
 		{
 			TaskCreationOptions options = TaskCreationOptions.None;
-			if ((kind & TaskContinuationOptions.DetachedFromParent) > 0)
-				options |= TaskCreationOptions.DetachedFromParent;
-			if ((kind & TaskContinuationOptions.RespectParentCancellation) > 0)
-				options |= TaskCreationOptions.RespectParentCancellation;
+			if ((kind & TaskContinuationOptions.AttachedToParent) > 0)
+				options |= TaskCreationOptions.AttachedToParent;
+			if ((kind & TaskContinuationOptions.PreferFairness) > 0)
+				options |= TaskCreationOptions.PreferFairness;
+			if ((kind & TaskContinuationOptions.LongRunning) > 0)
+				options |= TaskCreationOptions.LongRunning;
 			
 			return options;
 		}
@@ -298,11 +322,8 @@ namespace System.Threading.Tasks
 			status = TaskStatus.WaitingToRun;
 			
 			// If worker is null it means it is a local one, revert to the old behavior
-			if (current == null || childWorkAdder == null || parent == null
-			    || CheckTaskOptions (taskCreationOptions, TaskCreationOptions.PreferFairness)) {
-				
+			if (childWorkAdder == null || CheckTaskOptions (taskCreationOptions, TaskCreationOptions.PreferFairness)) {
 				scheduler.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
@@ -317,19 +338,20 @@ namespace System.Threading.Tasks
 			current = this;
 			TaskScheduler.Current = taskScheduler;
 			
-			if (!src.IsCancellationRequested
-			    && (!respectParentCancellation || (respectParentCancellation && parent != null && !parent.IsCanceled))) {
+			if (!token.IsCancellationRequested) {
 				
 				status = TaskStatus.Running;
 				
 				try {
 					InnerInvoke ();
 				} catch (Exception e) {
-					exception = e;
+					exception = new AggregateException (e);
 					status = TaskStatus.Faulted;
+					if (taskScheduler.FireUnobservedEvent (Exception).Observed)
+						exceptionObserved = true;
 				}
 			} else {
-				AcknowledgeCancellation ();
+				CancelReal ();
 			}
 			
 			Finish ();
@@ -386,7 +408,7 @@ namespace System.Threading.Tasks
 			TaskScheduler.Current = null;
 			
 			// Tell parent that we are finished
-			if (!CheckTaskOptions (taskCreationOptions, TaskCreationOptions.DetachedFromParent) && parent != null){
+			if (CheckTaskOptions (taskCreationOptions, TaskCreationOptions.AttachedToParent) && parent != null){
 				parent.ChildCompleted ();
 			}
 			
@@ -394,65 +416,21 @@ namespace System.Threading.Tasks
 		}
 		#endregion
 		
-		#region Cancel and Wait related methods
-		public void AcknowledgeCancellation ()
-		{
-			if (this != current)
-				throw new InvalidOperationException ("The Task object is different from the currently executing"
-				                                     + "task or the current task hasn't been "
-				                                     + "marked for cancellation.");
-			
-			CancelReal ();
-		}
+		#region Cancel and Wait related method
 		
 		internal void CancelReal ()
 		{
-			exception = new TaskCanceledException (this);
+			exception = new AggregateException (new TaskCanceledException (this));
 			status = TaskStatus.Canceled;
 		}
 		
-		public void Cancel ()
-		{
-			src.Cancel ();
-		}
-		
-		public void CancelAndWait ()
-		{
-			Cancel ();
-			Wait ();
-		}
-		
-		public void CancelAndWait (CancellationToken token)
-		{
-			Cancel ();
-			Wait (token);
-		}
-		
-		public bool CancelAndWait (TimeSpan ts)
-		{
-			Cancel ();
-			return Wait (ts);
-		}
-		
-		public bool CancelAndWait (int millisecondsTimeout)
-		{
-			Cancel ();
-			return Wait (millisecondsTimeout);
-		}
-		
-		public bool CancelAndWait (int millisecondsTimeout, CancellationToken token)
-		{
-			Cancel ();
-			return Wait (millisecondsTimeout, token);
-		}
-		
 		public void Wait ()
 		{
 			if (scheduler == null)
 				throw new InvalidOperationException ("The Task hasn't been Started and thus can't be waited on");
 			
 			scheduler.ParticipateUntil (this);
-			if (exception != null && !(exception is TaskCanceledException))
+			if (exception != null)
 				throw exception;
 		}
 
@@ -463,13 +441,12 @@ namespace System.Threading.Tasks
 		
 		public bool Wait (TimeSpan ts)
 		{
-			return Wait ((int)ts.TotalMilliseconds);
+			return Wait ((int)ts.TotalMilliseconds, CancellationToken.None);
 		}
 		
 		public bool Wait (int millisecondsTimeout)
 		{
-			Watch sw = Watch.StartNew ();
-			return Wait (() => sw.ElapsedMilliseconds >= millisecondsTimeout, null);
+			return Wait (millisecondsTimeout, CancellationToken.None);
 		}
 		
 		public bool Wait (int millisecondsTimeout, CancellationToken token)
@@ -478,20 +455,19 @@ namespace System.Threading.Tasks
 			return Wait (() => sw.ElapsedMilliseconds >= millisecondsTimeout, token);
 		}
 
-		bool Wait (Func<bool> stopFunc, CancellationToken? token)
+		bool Wait (Func<bool> stopFunc, CancellationToken token)
 		{
 			if (scheduler == null)
 				throw new InvalidOperationException ("The Task hasn't been Started and thus can't be waited on");
 			
 			bool result = scheduler.ParticipateUntil (this, delegate { 
-				if (token.HasValue && token.Value.IsCancellationRequested)
+				if (token.IsCancellationRequested)
 					throw new OperationCanceledException ("The CancellationToken has had cancellation requested.");
 				
-				
 				return (stopFunc != null) ? stopFunc () : false;
 			});
 
-			if (exception != null && !(exception is TaskCanceledException))
+			if (exception != null)
 				throw exception;
 			
 			return !result;
@@ -663,19 +639,14 @@ namespace System.Threading.Tasks
 			}
 		}
 		
-		public static Task Current {
-			get {
-				return current;
-			}
-		}
-		
-		public CancellationToken CancellationToken {
+		public static int? CurrentId {
 			get {
-				return src.Token;
+				Task t = current;
+				return t == null ? (int?)null : t.Id;
 			}
 		}
 		
-		public Exception Exception {
+		public AggregateException Exception {
 			get {
 				exceptionObserved = true;
 				
@@ -692,12 +663,6 @@ namespace System.Threading.Tasks
 			}
 		}
 
-		public bool IsCancellationRequested {
-			get {
-				return src.IsCancellationRequested;
-			}
-		}
-
 		public bool IsCompleted {
 			get {
 				return status == TaskStatus.RanToCompletion ||
@@ -711,12 +676,6 @@ namespace System.Threading.Tasks
 			}
 		}
 
-		public Task Parent {
-			get {
-				return parent;
-			}
-		}
-
 		public TaskCreationOptions CreationOptions {
 			get {
 				return taskCreationOptions;

+ 16 - 4
mcs/class/corlib/System.Threading.Tasks/TaskCompletionSource.cs

@@ -26,6 +26,7 @@
 // THE SOFTWARE.
 
 using System;
+using System.Collections.Generic;
 
 namespace System.Threading.Tasks
 {
@@ -55,13 +56,18 @@ namespace System.Threading.Tasks
 		
 		public void SetCanceled ()
 		{
-			if (!ApplyOperation (TaskStatus.Canceled, () => { source.Cancel (); source.CancelReal (); }))
+			if (!ApplyOperation (TaskStatus.Canceled, source.CancelReal))
 				ThrowInvalidException ();
 		}
 		
 		public void SetException (Exception e)
 		{
-			if (!ApplyOperation (TaskStatus.Faulted, () => source.Exception = e))
+			SetException (new Exception[] { e });
+		}
+		
+		public void SetException (IEnumerable<Exception> e)
+		{
+			if (!ApplyOperation (TaskStatus.Faulted, () => source.Exception = new AggregateException (e)))
 				ThrowInvalidException ();
 		}
 		
@@ -78,12 +84,18 @@ namespace System.Threading.Tasks
 		
 		public bool TrySetCanceled ()
 		{
-			return ApplyOperation (TaskStatus.Canceled, () => { source.Cancel (); source.CancelReal (); });
+			return ApplyOperation (TaskStatus.Canceled, source.CancelReal);
 		}
 		
 		public bool TrySetException (Exception e)
 		{
-			return ApplyOperation (TaskStatus.Faulted, () => source.Exception = e);
+			return TrySetException (new Exception[] { e });
+		}
+		
+		
+		public bool TrySetException (IEnumerable<Exception> e)
+		{
+			return ApplyOperation (TaskStatus.Faulted, () => source.Exception = new AggregateException (e));
 		}
 		
 		public bool TrySetResult (TResult result)

+ 1 - 2
mcs/class/corlib/System.Threading.Tasks/TaskContinuationOptions.cs

@@ -32,9 +32,8 @@ namespace System.Threading.Tasks
 	{
 		None = 0x0,
 		PreferFairness = 0x1,
-		RespectParentCancellation = 0x2,
 		LongRunning = 0x4,
-		DetachedFromParent = 0x8,
+		AttachedToParent = 0x8,
 		ExecuteSynchronously = 0x10,
 		NotOnRanToCompletion = 0x20,
 		NotOnFaulted = 0x40,

+ 1 - 2
mcs/class/corlib/System.Threading.Tasks/TaskCreationOptions.cs

@@ -32,9 +32,8 @@ namespace System.Threading.Tasks
 	{
 		None = 0x0,
 		PreferFairness = 0x1,
-		RespectParentCancellation = 0x2,
 		LongRunning = 0x8,
-		DetachedFromParent = 0x10
+		AttachedToParent = 0x10
 	}
 }
 #endif

+ 350 - 85
mcs/class/corlib/System.Threading.Tasks/TaskFactory.cs

@@ -35,24 +35,34 @@ namespace System.Threading.Tasks
 	{
 		TaskScheduler scheduler;
 		TaskCreationOptions options;
-		TaskContinuationOptions contOptions;		
+		TaskContinuationOptions contOptions;
+		CancellationToken token;
 		
 		#region ctors
-		public TaskFactory () : this (TaskScheduler.Current, TaskCreationOptions.None, TaskContinuationOptions.None)
+		public TaskFactory ()
+			: this (CancellationToken.None, TaskCreationOptions.None, TaskContinuationOptions.None, TaskScheduler.Current)
+		{
+		}
+
+		public TaskFactory (CancellationToken token)
+			: this (token, TaskCreationOptions.None, TaskContinuationOptions.None, TaskScheduler.Current)
 		{	
 		}
-		
-		public TaskFactory (TaskScheduler scheduler) : this (scheduler, TaskCreationOptions.None, TaskContinuationOptions.None)
+
+		public TaskFactory (TaskScheduler scheduler)
+			: this (CancellationToken.None, TaskCreationOptions.None, TaskContinuationOptions.None, scheduler)
 		{	
 		}
 		
 		public TaskFactory (TaskCreationOptions options, TaskContinuationOptions contOptions)
-			: this (TaskScheduler.Current, options, contOptions)
+			: this (CancellationToken.None, options, contOptions, TaskScheduler.Current)
 		{	
 		}
 		
-		public TaskFactory (TaskScheduler scheduler, TaskCreationOptions options, TaskContinuationOptions contOptions)
+		public TaskFactory (CancellationToken token, TaskCreationOptions options, TaskContinuationOptions contOptions,
+		                    TaskScheduler scheduler)
 		{
+			this.token = token;
 			this.scheduler = scheduler;
 			this.options = options;
 			this.contOptions = contOptions;
@@ -62,30 +72,41 @@ namespace System.Threading.Tasks
 		#region StartNew for Task
 		public Task StartNew (Action action)
 		{
-			return StartNew (action, options, scheduler);
+			return StartNew (action, token, options, scheduler);
 		}
 		
-		public Task StartNew (Action action, TaskCreationOptions options)
+		public Task StartNew (Action action, CancellationToken token)
 		{
-			return StartNew (action, options, scheduler);
+			return StartNew (action, token, options, scheduler);
 		}
 		
-		public Task StartNew (Action action, TaskCreationOptions options, TaskScheduler scheduler)
+		public Task StartNew (Action action, TaskCreationOptions options)
 		{
-			return StartNew ((o) => action (), null, options, scheduler);
+			return StartNew (action, token, options, scheduler);
 		}
 		
 		public Task StartNew (Action<object> action, object state)
 		{
-			return StartNew (action, state, options, scheduler);
+			return StartNew (action, state, token, options, scheduler);
+		}
+		
+		public Task StartNew (Action<object> action, object state, CancellationToken token)
+		{
+			return StartNew (action, state, token, options, scheduler);
 		}
 		
 		public Task StartNew (Action<object> action, object state, TaskCreationOptions options)
 		{
-			return StartNew (action, state, options, scheduler);
+			return StartNew (action, state, token, options, scheduler);
+		}
+		
+		public Task StartNew (Action action, CancellationToken token, TaskCreationOptions options, TaskScheduler scheduler)
+		{
+			return StartNew ((o) => action (), null, token, options, scheduler);
 		}
 		
-		public Task StartNew (Action<object> action, object state, TaskCreationOptions options, TaskScheduler scheduler)
+		public Task StartNew (Action<object> action, object state, CancellationToken token, TaskCreationOptions options,
+		                      TaskScheduler scheduler)
 		{
 			Task t = new Task (action, state, options);
 			t.Start (scheduler);
@@ -97,33 +118,48 @@ namespace System.Threading.Tasks
 		#region StartNew for Task<TResult>	
 		public Task<TResult> StartNew<TResult> (Func<TResult> function)
 		{
-			return StartNew<TResult> (function, options, scheduler);
+			return StartNew<TResult> (function, token, options, scheduler);
 		}
 		
 		public Task<TResult> StartNew<TResult> (Func<TResult> function, TaskCreationOptions options)
 		{
-			return StartNew<TResult> (function, options, scheduler);
+			return StartNew<TResult> (function, token, options, scheduler);
+		}
+		
+		public Task<TResult> StartNew<TResult> (Func<TResult> function, CancellationToken token)
+		{
+			return StartNew<TResult> (function, token, options, scheduler);
 		}
 		
-		public Task<TResult> StartNew<TResult> (Func<TResult> function, TaskCreationOptions options, TaskScheduler scheduler)
+		public Task<TResult> StartNew<TResult> (Func<TResult> function,
+		                                        CancellationToken token,
+		                                        TaskCreationOptions options,
+		                                        TaskScheduler scheduler)
 		{
-			return StartNew<TResult> ((o) => function (), null, options, scheduler);
+			return StartNew<TResult> ((o) => function (), null, token, options, scheduler);
 		}
 		
 		public Task<TResult> StartNew<TResult> (Func<object, TResult> function, object state)
 		{
-			return StartNew<TResult> (function, state, options, scheduler);
+			return StartNew<TResult> (function, state, token, options, scheduler);
+		}
+		
+		public Task<TResult> StartNew<TResult> (Func<object, TResult> function, object state, CancellationToken token)
+		{
+			return StartNew<TResult> (function, state, token, options, scheduler);
 		}
 		
 		public Task<TResult> StartNew<TResult> (Func<object, TResult> function, object state, TaskCreationOptions options)
 		{
-			return StartNew<TResult> (function, state, options, scheduler);
+			return StartNew<TResult> (function, state, token, options, scheduler);
 		}
 		
-		public Task<TResult> StartNew<TResult> (Func<object, TResult> function, object state, TaskCreationOptions options,
+		public Task<TResult> StartNew<TResult> (Func<object, TResult> function, object state,
+		                                        CancellationToken token,
+		                                        TaskCreationOptions options,
 		                                        TaskScheduler scheduler)
 		{
-			Task<TResult> t = new Task<TResult> (function, state, options);
+			Task<TResult> t = new Task<TResult> (function, state, token, options);
 			t.Start (scheduler);
 			
 			return t;
@@ -135,89 +171,235 @@ namespace System.Threading.Tasks
 		[MonoTODO]
 		public Task ContinueWhenAny (Task[] tasks, Action<Task> continuationAction)
 		{
-			return ContinueWhenAny (tasks, continuationAction, contOptions, scheduler);
+			return ContinueWhenAny (tasks, continuationAction, token, contOptions, scheduler);
+		}
+		
+		[MonoTODO]
+		public Task ContinueWhenAny (Task[] tasks, Action<Task> continuationAction, CancellationToken token)
+		{
+			return ContinueWhenAny (tasks, continuationAction, token, contOptions, scheduler);
 		}
 		
 		[MonoTODO]
 		public Task ContinueWhenAny (Task[] tasks, Action<Task> continuationAction, TaskContinuationOptions continuationOptions)
 		{
-			return ContinueWhenAny (tasks, continuationAction, continuationOptions, scheduler);
+			return ContinueWhenAny (tasks, continuationAction, token, continuationOptions, scheduler);
 		}
 
 		[MonoTODO]
-		public Task ContinueWhenAny (Task[] tasks, Action<Task> continuationAction, TaskContinuationOptions continuationOptions,
-		                             TaskScheduler scheduler)
+		public Task ContinueWhenAny (Task[] tasks, Action<Task> continuationAction, CancellationToken token, 
+		                             TaskContinuationOptions continuationOptions, TaskScheduler scheduler)
 		{
 			throw new NotImplementedException ();
 		}
 		
+		[MonoTODO]
+		public Task ContinueWhenAny<TAntecedentResult> (Task<TAntecedentResult>[] tasks, Action<Task<TAntecedentResult>> continuationAction)
+		{
+			return ContinueWhenAny (tasks, continuationAction, token, contOptions, scheduler);
+		}
+		
+		[MonoTODO]
+		public Task ContinueWhenAny<TAntecedentResult> (Task<TAntecedentResult>[] tasks, Action<Task<TAntecedentResult>> continuationAction,
+		                                                CancellationToken token)
+		{
+			return ContinueWhenAny (tasks, continuationAction, token, contOptions, scheduler);
+		}
+		
+		[MonoTODO]
+		public Task ContinueWhenAny<TAntecedentResult> (Task<TAntecedentResult>[] tasks, Action<Task<TAntecedentResult>> continuationAction,
+		                                                TaskContinuationOptions continuationOptions)
+		{
+			return ContinueWhenAny (tasks, continuationAction, token, continuationOptions, scheduler);
+		}
+
+		[MonoTODO]
+		public Task ContinueWhenAny<TAntecedentResult> (Task<TAntecedentResult>[] tasks, Action<Task<TAntecedentResult>> continuationAction,
+		                                                CancellationToken token, TaskContinuationOptions continuationOptions,
+		                                                TaskScheduler scheduler)
+		{
+			return ContinueWhenAny ((Task[]) tasks, (o) => continuationAction ((Task<TAntecedentResult>)o),
+			                        token, continuationOptions, scheduler);
+		}
+		
 		[MonoTODO]
 		public Task<TResult> ContinueWhenAny<TResult> (Task[] tasks, Func<Task, TResult> continuationAction)
 		{
-			return ContinueWhenAny (tasks, continuationAction, contOptions);
+			return ContinueWhenAny (tasks, continuationAction, token, contOptions, scheduler);
+		}
+		
+		[MonoTODO]
+		public Task<TResult> ContinueWhenAny<TResult> (Task[] tasks, Func<Task, TResult> continuationAction,
+		                                               CancellationToken token)
+		{
+			return ContinueWhenAny (tasks, continuationAction, token, contOptions, scheduler);
 		}
 		
 		[MonoTODO]
 		public Task<TResult> ContinueWhenAny<TResult> (Task[] tasks, Func<Task, TResult> continuationAction,
 		                                               TaskContinuationOptions continuationOptions)
 		{
-			return ContinueWhenAny (tasks, continuationAction, continuationOptions, scheduler);
+			return ContinueWhenAny (tasks, continuationAction, token, continuationOptions, scheduler);
 		}
 
 		[MonoTODO]
 		public Task<TResult> ContinueWhenAny<TResult> (Task[] tasks, Func<Task, TResult> continuationAction,
+		                                               CancellationToken token,
 		                                               TaskContinuationOptions continuationOptions,
 		                                               TaskScheduler scheduler)
 		{
 			throw new NotImplementedException ();
 		}
 		
+		[MonoTODO]
+		public Task<TResult> ContinueWhenAny<TAntecedentResult, TResult> (Task<TAntecedentResult>[] tasks,
+		                                                                  Func<Task<TAntecedentResult>, TResult> continuationAction)
+		{
+			return ContinueWhenAny (tasks, continuationAction, token, contOptions, scheduler);
+		}
+		
+		[MonoTODO]
+		public Task<TResult> ContinueWhenAny<TAntecedentResult, TResult> (Task<TAntecedentResult>[] tasks,
+		                                                                  Func<Task<TAntecedentResult>, TResult> continuationAction,
+		                                                                  CancellationToken token)
+		{
+			return ContinueWhenAny (tasks, continuationAction, token, contOptions, scheduler);
+		}
+		
+		[MonoTODO]
+		public Task<TResult> ContinueWhenAny<TAntecedentResult, TResult> (Task<TAntecedentResult>[] tasks,
+		                                                                  Func<Task<TAntecedentResult>, TResult> continuationAction,
+		                                                                  TaskContinuationOptions continuationOptions)
+		{
+			return ContinueWhenAny (tasks, continuationAction, token, continuationOptions, scheduler);
+		}
+
+		[MonoTODO]
+		public Task<TResult> ContinueWhenAny<TAntecedentResult, TResult> (Task<TAntecedentResult>[] tasks,
+		                                                                  Func<Task<TAntecedentResult>, TResult> continuationAction,
+		                                                                  CancellationToken token,
+		                                                                  TaskContinuationOptions continuationOptions,
+		                                                                  TaskScheduler scheduler)
+		{
+			return ContinueWhenAny<TResult> ((Task[])tasks, (t) => continuationAction((Task<TAntecedentResult>)t), token, continuationOptions, scheduler);
+		}
+		
 		public Task ContinueWhenAll (Task[] tasks, Action<Task[]> continuationFunction)
 		{
-			return ContinueWhenAll (tasks, continuationFunction, contOptions);
+			return ContinueWhenAll (tasks, continuationFunction, token, contOptions, scheduler);
+		}
+		
+		public Task ContinueWhenAll (Task[] tasks, Action<Task[]> continuationFunction, CancellationToken token)
+		{
+			return ContinueWhenAll (tasks, continuationFunction, token, contOptions, scheduler);
 		}
 		
 		public Task ContinueWhenAll (Task[] tasks, Action<Task[]> continuationFunction,
 		                             TaskContinuationOptions continuationOptions)
 		{
-			return ContinueWhenAll (tasks, continuationFunction, continuationOptions, scheduler);
+			return ContinueWhenAll (tasks, continuationFunction, token, continuationOptions, scheduler);
 		}
 		
-		public Task ContinueWhenAll (Task[] tasks, Action<Task[]> continuationFunction,
+		public Task ContinueWhenAll (Task[] tasks, Action<Task[]> continuationFunction, CancellationToken token,
 		                             TaskContinuationOptions continuationOptions, TaskScheduler scheduler)
 		{
 			CountdownEvent evt = new CountdownEvent (tasks.Length);
-			Task cont = new Task ((o) => continuationFunction ((Task[])o), tasks, options);
+			Task cont = new Task ((o) => continuationFunction ((Task[])o), tasks, token, options);
 			
 			foreach (Task t in tasks)
 				t.ContinueWithCore (cont, continuationOptions, scheduler, evt.Signal);
 			
 			return cont;
 		}
-
+		
+		public Task ContinueWhenAll<TAntecedentResult> (Task<TAntecedentResult>[] tasks,
+		                                                Action<Task<TAntecedentResult>[]> continuationFunction)
+		{
+			return ContinueWhenAll (tasks, continuationFunction, token, contOptions, scheduler);
+		}
+		
+		public Task ContinueWhenAll<TAntecedentResult> (Task<TAntecedentResult>[] tasks,
+		                                                Action<Task<TAntecedentResult>[]> continuationFunction, CancellationToken token)
+		{
+			return ContinueWhenAll (tasks, continuationFunction, token, contOptions, scheduler);
+		}
+		
+		public Task ContinueWhenAll<TAntecedentResult> (Task<TAntecedentResult>[] tasks, Action<Task<TAntecedentResult>[]> continuationFunction,
+		                                                TaskContinuationOptions continuationOptions)
+		{
+			return ContinueWhenAll (tasks, continuationFunction, token, continuationOptions, scheduler);
+		}
+		
+		public Task ContinueWhenAll<TAntecedentResult> (Task<TAntecedentResult>[] tasks, 
+		                                                Action<Task<TAntecedentResult>[]> continuationFunction,
+		                                                CancellationToken token, TaskContinuationOptions continuationOptions,
+		                                                TaskScheduler scheduler)
+		{
+			return ContinueWhenAll ((Task[]) tasks, (o) => continuationFunction (tasks), token,
+			                        continuationOptions, scheduler);
+		}
 		
 		public Task<TResult> ContinueWhenAll<TResult> (Task[] tasks, Func<Task[], TResult> continuationFunction)
 		{
-			return ContinueWhenAll<TResult> (tasks, continuationFunction, contOptions);
+			return ContinueWhenAll<TResult> (tasks, continuationFunction, token, contOptions, scheduler);
 		}
 		
 		public Task<TResult> ContinueWhenAll<TResult> (Task[] tasks, Func<Task[], TResult> continuationFunction,
 		                                               TaskContinuationOptions continuationOptions)
 		{
-			return ContinueWhenAll<TResult> (tasks, continuationFunction, continuationOptions, scheduler);
+			return ContinueWhenAll<TResult> (tasks, continuationFunction, token, continuationOptions, scheduler);
+		}
+		
+		public Task<TResult> ContinueWhenAll<TResult> (Task[] tasks, Func<Task[], TResult> continuationFunction,
+		                                               CancellationToken token)
+		{
+			return ContinueWhenAll<TResult> (tasks, continuationFunction, token, contOptions, scheduler);
 		}
 		
 		public Task<TResult> ContinueWhenAll<TResult> (Task[] tasks, Func<Task[], TResult> continuationFunction,
+		                                               CancellationToken token,
 		                                               TaskContinuationOptions continuationOptions, TaskScheduler scheduler)
 		{
 			CountdownEvent evt = new CountdownEvent (tasks.Length);
-			Task<TResult> cont = new Task<TResult> ((o) => continuationFunction ((Task[])o), tasks, options);
+			Task<TResult> cont = new Task<TResult> ((o) => continuationFunction ((Task[])o), tasks, token, options);
 			
 			foreach (Task t in tasks)
 				t.ContinueWithCore (cont, continuationOptions, scheduler, evt.Signal);
 			
 			return cont;
 		}
+		
+		public Task<TResult> ContinueWhenAll<TAntecedentResult, TResult> (Task<TAntecedentResult>[] tasks,
+		                                                                  Func<Task<TAntecedentResult>[], TResult> continuationFunction)
+		{
+			return ContinueWhenAll<TAntecedentResult, TResult> (tasks, continuationFunction, token, contOptions, scheduler);
+		}
+		
+		public Task<TResult> ContinueWhenAll<TAntecedentResult, TResult> (Task<TAntecedentResult>[] tasks, 
+		                                                                  Func<Task<TAntecedentResult>[], TResult> continuationFunction,
+		                                                                  TaskContinuationOptions continuationOptions)
+		{
+			return ContinueWhenAll<TAntecedentResult, TResult> (tasks, continuationFunction, token, continuationOptions, scheduler);
+		}
+		
+		public Task<TResult> ContinueWhenAll<TAntecedentResult, TResult> (Task<TAntecedentResult>[] tasks,
+		                                                                  Func<Task<TAntecedentResult>[], TResult> continuationFunction,
+		                                                                  CancellationToken token)
+		{
+			return ContinueWhenAll<TAntecedentResult, TResult> (tasks, continuationFunction, token, contOptions, scheduler);
+		}
+		
+		public Task<TResult> ContinueWhenAll<TAntecedentResult, TResult> (Task<TAntecedentResult>[] tasks, 
+		                                                                  Func<Task<TAntecedentResult>[], TResult> continuationFunction,
+		                                                                  CancellationToken token,
+		                                                                  TaskContinuationOptions continuationOptions,
+		                                                                  TaskScheduler scheduler)
+		{
+			return ContinueWhenAll<TResult> ((Task[]) tasks,
+			                                 (o) => continuationFunction (tasks),
+			                                 token,
+			                                 continuationOptions, scheduler);
+		}
 
 		#endregion
 		
@@ -409,6 +591,12 @@ namespace System.Threading.Tasks
 				return options;
 			}
 		}
+		
+		public CancellationToken CancellationToken {
+			get {
+				return token;
+			}
+		}
 	}
 	
 	public class TaskFactory<TResult>
@@ -416,124 +604,187 @@ namespace System.Threading.Tasks
 		TaskScheduler scheduler;
 		TaskCreationOptions options;
 		TaskContinuationOptions contOptions;
+		CancellationToken token;
 		
 		TaskFactory parent;
 		
 		#region ctors
-		public TaskFactory () : this (TaskScheduler.Current, TaskCreationOptions.None, TaskContinuationOptions.None)
+		public TaskFactory ()
+			: this (CancellationToken.None, TaskCreationOptions.None, TaskContinuationOptions.None, TaskScheduler.Current)
 		{	
 		}
 		
-		public TaskFactory (TaskScheduler scheduler) : this (scheduler, TaskCreationOptions.None, TaskContinuationOptions.None)
+		public TaskFactory (TaskScheduler scheduler)
+			: this (CancellationToken.None, TaskCreationOptions.None, TaskContinuationOptions.None, scheduler)
+		{	
+		}
+		
+		public TaskFactory (CancellationToken token)
+			: this (token, TaskCreationOptions.None, TaskContinuationOptions.None, TaskScheduler.Current)
 		{	
 		}
 		
 		public TaskFactory (TaskCreationOptions options, TaskContinuationOptions contOptions)
-			: this (TaskScheduler.Current, options, contOptions)
+			: this (CancellationToken.None, options, contOptions, TaskScheduler.Current)
 		{	
 		}
 		
-		public TaskFactory (TaskScheduler scheduler, TaskCreationOptions options, TaskContinuationOptions contOptions)
+		public TaskFactory (CancellationToken token, TaskCreationOptions options, TaskContinuationOptions contOptions,
+		                    TaskScheduler scheduler)
 		{
+			this.token = token;
 			this.scheduler = scheduler;
 			this.options = options;
 			this.contOptions = contOptions;
-			this.parent = new TaskFactory (scheduler, options, contOptions);
+			
+			this.parent = new TaskFactory (token, options, contOptions, scheduler);
 		}
+		
 		#endregion
 		
 		#region StartNew for Task<TResult>	
 		public Task<TResult> StartNew (Func<TResult> function)
 		{
-			return StartNew (function, options, scheduler);
+			return StartNew (function, token, options, scheduler);
 		}
 		
 		public Task<TResult> StartNew (Func<TResult> function, TaskCreationOptions options)
 		{
-			return StartNew (function, options, scheduler);
+			return StartNew (function, token, options, scheduler);
 		}
 		
-		public Task<TResult> StartNew (Func<TResult> function, TaskCreationOptions options, TaskScheduler scheduler)
+		public Task<TResult> StartNew (Func<TResult> function, CancellationToken token)
 		{
-			return StartNew ((o) => function (), null, options, scheduler);
+			return StartNew (function, token, options, scheduler);
+		}
+		
+		public Task<TResult> StartNew (Func<TResult> function, 
+		                               CancellationToken token,
+		                               TaskCreationOptions options,
+		                               TaskScheduler scheduler)
+		{
+			return StartNew ((o) => function (), null, token, options, scheduler);
 		}
 		
 		public Task<TResult> StartNew (Func<object, TResult> function, object state)
 		{
-			return StartNew (function, state, options, scheduler);
+			return StartNew (function, state, token, options, scheduler);
 		}
 		
 		public Task<TResult> StartNew (Func<object, TResult> function, object state, TaskCreationOptions options)
 		{
-			return StartNew (function, state, options, scheduler);
+			return StartNew (function, state, token, options, scheduler);
 		}
 		
-		public Task<TResult> StartNew (Func<object, TResult> function, object state, TaskCreationOptions options,
+		public Task<TResult> StartNew (Func<object, TResult> function, object state, CancellationToken token)
+		{
+			return StartNew (function, state, token, options, scheduler);
+		}
+		
+		public Task<TResult> StartNew (Func<object, TResult> function, object state, 
+		                               CancellationToken token,
+		                               TaskCreationOptions options,
 		                               TaskScheduler scheduler)
 		{
-			return parent.StartNew<TResult> (function, state, options, scheduler);
+			return parent.StartNew<TResult> (function, state, token, options, scheduler);
 		}
 		#endregion
 		
 		#region Continue
+		
 		[MonoTODO]
-		public Task ContinueWhenAny (Task<TResult>[] tasks, Action<Task<TResult>> continuationAction)
+		public Task<TResult> ContinueWhenAny (Task[] tasks,
+		                                      Func<Task, TResult> continuationAction)
 		{
-			return ContinueWhenAny (tasks, continuationAction, contOptions, scheduler);
+			return ContinueWhenAny (tasks, continuationAction, token, contOptions, scheduler);
 		}
 		
 		[MonoTODO]
-		public Task ContinueWhenAny (Task<TResult>[] tasks, Action<Task<TResult>> continuationAction,
-		                             TaskContinuationOptions continuationOptions)
+		public Task<TResult> ContinueWhenAny (Task[] tasks,
+		                                      Func<Task, TResult> continuationAction,
+		                                      CancellationToken token)
+		{
+			return ContinueWhenAny (tasks, continuationAction, token, contOptions, scheduler);
+		}
+		
+		[MonoTODO]
+		public Task<TResult> ContinueWhenAny (Task[] tasks,
+		                                      Func<Task, TResult> continuationAction,
+		                                      TaskContinuationOptions continuationOptions)
 		{
-			return ContinueWhenAny (tasks, continuationAction, continuationOptions, scheduler);
+			return ContinueWhenAny (tasks, continuationAction, token, continuationOptions, scheduler);
 		}
 
 		[MonoTODO]
-		public Task ContinueWhenAny (Task<TResult>[] tasks, Action<Task<TResult>> continuationAction,
-		                             TaskContinuationOptions continuationOptions,
-		                             TaskScheduler scheduler)
+		public Task<TResult> ContinueWhenAny (Task[] tasks,
+		                                      Func<Task, TResult> continuationAction,
+		                                      CancellationToken token,
+		                                      TaskContinuationOptions continuationOptions,
+		                                      TaskScheduler scheduler)
 		{
-		 	throw new NotImplementedException ();
+			throw new NotImplementedException ();
 		}
 		
 		[MonoTODO]
-		public Task<TNewResult> ContinueWhenAny<TNewResult> (Task<TResult>[] tasks, Func<Task<TResult>, TNewResult> continuationAction)
+		public Task<TResult> ContinueWhenAny<TAntecedentResult> (Task<TAntecedentResult>[] tasks,
+		                                                         Func<Task<TAntecedentResult>, TResult> continuationAction)
 		{
-			return ContinueWhenAny (tasks, continuationAction, contOptions);
+			return ContinueWhenAny (tasks, continuationAction, token, contOptions, scheduler);
 		}
 		
 		[MonoTODO]
-		public Task<TNewResult> ContinueWhenAny<TNewResult> (Task<TResult>[] tasks, Func<Task<TResult>, TNewResult> continuationAction,
-		                                                     TaskContinuationOptions continuationOptions)
+		public Task<TResult> ContinueWhenAny<TAntecedentResult> (Task<TAntecedentResult>[] tasks,
+		                                                         Func<Task<TAntecedentResult>, TResult> continuationAction,
+		                                                         CancellationToken token)
 		{
-			return ContinueWhenAny (tasks, continuationAction, continuationOptions, scheduler);
+			return ContinueWhenAny (tasks, continuationAction, token, contOptions, scheduler);
+		}
+		
+		[MonoTODO]
+		public Task<TResult> ContinueWhenAny<TAntecedentResult> (Task<TAntecedentResult>[] tasks,
+		                                                         Func<Task<TAntecedentResult>, TResult> continuationAction,
+		                                                         TaskContinuationOptions continuationOptions)
+		{
+			return ContinueWhenAny (tasks, continuationAction, token, continuationOptions, scheduler);
 		}
 
 		[MonoTODO]
-		public Task<TNewResult> ContinueWhenAny<TNewResult> (Task<TResult>[] tasks, Func<Task<TResult>, TNewResult> continuationAction,
-		                                                     TaskContinuationOptions continuationOptions,
-		                                                     TaskScheduler scheduler)
+		public Task<TResult> ContinueWhenAny<TAntecedentResult> (Task<TAntecedentResult>[] tasks,
+		                                                         Func<Task<TAntecedentResult>, TResult> continuationAction,
+		                                                         CancellationToken token,
+		                                                         TaskContinuationOptions continuationOptions,
+		                                                         TaskScheduler scheduler)
 		{
 			throw new NotImplementedException ();
 		}
 		
-		public Task ContinueWhenAll (Task<TResult>[] tasks, Action<Task<TResult>[]> continuationFunction)
+		public Task<TResult> ContinueWhenAll (Task[] tasks,
+		                                      Func<Task[], TResult> continuationFunction)
 		{
-			return ContinueWhenAll (tasks, continuationFunction, contOptions);
+			return ContinueWhenAll (tasks, continuationFunction, token, contOptions, scheduler);
 		}
 		
-		public Task ContinueWhenAll (Task<TResult>[] tasks, Action<Task<TResult>[]> continuationFunction,
-		                             TaskContinuationOptions continuationOptions)
+		public Task<TResult> ContinueWhenAll (Task[] tasks,
+		                                      Func<Task[], TResult> continuationFunction,
+		                                      TaskContinuationOptions continuationOptions)
 		{
-			return ContinueWhenAll (tasks, continuationFunction, continuationOptions, scheduler);
+			return ContinueWhenAll (tasks, continuationFunction, token, continuationOptions, scheduler);
 		}
 		
-		public Task ContinueWhenAll (Task<TResult>[] tasks, Action<Task<TResult>[]> continuationFunction,
-		                             TaskContinuationOptions continuationOptions, TaskScheduler scheduler)
+		public Task<TResult> ContinueWhenAll (Task[] tasks,
+		                                      Func<Task[], TResult> continuationFunction,
+		                                      CancellationToken token)
+		{
+			return ContinueWhenAll (tasks, continuationFunction, token, contOptions, scheduler);
+		}
+		
+		public Task<TResult> ContinueWhenAll (Task[] tasks,
+		                                      Func<Task[], TResult> continuationFunction,
+		                                      CancellationToken token,
+		                                      TaskContinuationOptions continuationOptions, TaskScheduler scheduler)
 		{
 			CountdownEvent evt = new CountdownEvent (tasks.Length);
-			Task cont = new Task ((o) => continuationFunction ((Task<TResult>[])o), tasks, options);
+			Task<TResult> cont = new Task<TResult> ((o) => continuationFunction (tasks), tasks, token, options);
 			
 			foreach (Task t in tasks)
 				t.ContinueWithCore (cont, continuationOptions, scheduler, evt.Signal);
@@ -541,25 +792,33 @@ namespace System.Threading.Tasks
 			return cont;
 		}
 		
-		public Task<TNewResult> ContinueWhenAll<TNewResult> (Task<TResult>[] tasks,
-		                                                     Func<Task<TResult>[], TNewResult> continuationFunction)
+		public Task<TResult> ContinueWhenAll<TAntecedentResult> (Task<TAntecedentResult>[] tasks,
+		                                                         Func<Task<TAntecedentResult>[], TResult> continuationFunction)
+		{
+			return ContinueWhenAll (tasks, continuationFunction, token, contOptions, scheduler);
+		}
+		
+		public Task<TResult> ContinueWhenAll<TAntecedentResult> (Task<TAntecedentResult>[] tasks,
+		                                                         Func<Task<TAntecedentResult>[], TResult> continuationFunction,
+		                                                         TaskContinuationOptions continuationOptions)
 		{
-			return ContinueWhenAll (tasks, continuationFunction, contOptions);
+			return ContinueWhenAll (tasks, continuationFunction, token, continuationOptions, scheduler);
 		}
 		
-		public Task<TNewResult> ContinueWhenAll<TNewResult> (Task<TResult>[] tasks,
-		                                                     Func<Task<TResult>[], TNewResult> continuationFunction,
-		                                                     TaskContinuationOptions continuationOptions)
+		public Task<TResult> ContinueWhenAll<TAntecedentResult> (Task<TAntecedentResult>[] tasks,
+		                                                         Func<Task<TAntecedentResult>[], TResult> continuationFunction,
+		                                                         CancellationToken token)
 		{
-			return ContinueWhenAll (tasks, continuationFunction, continuationOptions, scheduler);
+			return ContinueWhenAll (tasks, continuationFunction, token, contOptions, scheduler);
 		}
 		
-		public Task<TNewResult> ContinueWhenAll<TNewResult> (Task<TResult>[] tasks,
-		                                                     Func<Task<TResult>[], TNewResult> continuationFunction,
-		                                                     TaskContinuationOptions continuationOptions, TaskScheduler scheduler)
+		public Task<TResult> ContinueWhenAll<TAntecedentResult> (Task<TAntecedentResult>[] tasks,
+		                                                         Func<Task<TAntecedentResult>[], TResult> continuationFunction,
+		                                                         CancellationToken token,
+		                                                         TaskContinuationOptions continuationOptions, TaskScheduler scheduler)
 		{
 			CountdownEvent evt = new CountdownEvent (tasks.Length);
-			Task<TNewResult> cont = new Task<TNewResult> ((o) => continuationFunction ((Task<TResult>[])o), tasks, options);
+			Task<TResult> cont = new Task<TResult> ((o) => continuationFunction (tasks), tasks, token, options);
 			
 			foreach (Task t in tasks)
 				t.ContinueWithCore (cont, continuationOptions, scheduler, evt.Signal);
@@ -675,6 +934,12 @@ namespace System.Threading.Tasks
 				return options;
 			}
 		}
+		
+		public CancellationToken CancellationToken {
+			get {
+				return token;
+			}
+		}
 	}
 }
 #endif

+ 17 - 2
mcs/class/corlib/System.Threading.Tasks/TaskScheduler.cs

@@ -41,12 +41,14 @@ namespace System.Threading.Tasks
 		int id;
 		static int lastId = int.MinValue;
 		
+		public static event EventHandler<UnobservedTaskExceptionEventArgs> UnobservedTaskException;
+		
 		protected TaskScheduler ()
 		{
 			this.id = Interlocked.Increment (ref lastId);
 		}
 
-	  // FIXME: Probably not correct
+		// FIXME: Probably not correct
 		public static TaskScheduler FromCurrentSynchronizationContext ()
 		{
 			return Current;
@@ -60,7 +62,7 @@ namespace System.Threading.Tasks
 		
 		public static TaskScheduler Current  {
 			get {
-				if (Task.Current != null && currentScheduler != null)
+				if (currentScheduler != null)
 					return currentScheduler;
 				
 				return defaultScheduler;
@@ -95,6 +97,19 @@ namespace System.Threading.Tasks
 		}
 
 		protected abstract bool TryExecuteTaskInline (Task task, bool taskWasPreviouslyQueued);
+		
+		internal UnobservedTaskExceptionEventArgs FireUnobservedEvent (AggregateException e)
+		{
+			UnobservedTaskExceptionEventArgs args = new UnobservedTaskExceptionEventArgs (e);
+			
+			EventHandler<UnobservedTaskExceptionEventArgs> temp = UnobservedTaskException;
+			if (temp == null)
+				return args;
+			
+			temp (this, args);
+			
+			return args;
+		}
 	}
 }
 #endif

+ 60 - 0
mcs/class/corlib/System.Threading.Tasks/UnobservedTaskExceptionEventArgs.cs

@@ -0,0 +1,60 @@
+#if NET_4_0 || BOOTSTRAP_NET_4_0
+// 
+// UnobservedTaskExceptionEventArgs.cs
+//  
+// Author:
+//       Jérémie "Garuma" Laval <[email protected]>
+// 
+// Copyright (c) 2010 Jérémie "Garuma" Laval
+// 
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+// 
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+// 
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+namespace System.Threading.Tasks
+{
+	public class UnobservedTaskExceptionEventArgs : EventArgs
+	{
+		AggregateException exception;
+		bool wasObserved;
+		
+		public UnobservedTaskExceptionEventArgs (AggregateException exception)
+		{
+			this.exception = exception;
+		}
+		
+		public AggregateException Exception {
+			get {
+				return exception;
+			}
+		}
+		
+		public bool Observed {
+			get {
+				return wasObserved;
+			}
+		}
+		
+		public void SetObserved ()
+		{
+			wasObserved = true;
+		}
+	}
+}
+
+#endif
+//

+ 32 - 21
mcs/class/corlib/System.Threading/CancellationToken.cs

@@ -1,22 +1,21 @@
-#if NET_4_0 || BOOTSTRAP_NET_4_0
-// 
+//
 // CancellationToken.cs
-//  
+//
 // Author:
 //       Jérémie "Garuma" Laval <[email protected]>
-// 
+//
 // 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
@@ -29,6 +28,7 @@ using System;
 using System.Threading;
 using System.Collections.Generic;
 
+#if NET_4_0 || BOOTSTRAP_NET_4_0
 namespace System.Threading
 {
 	public struct CancellationToken
@@ -38,76 +38,87 @@ namespace System.Threading
 			// dummy, this is actually set by CancellationTokenSource when the token is created
 			Source = null;
 		}
-		
+
+		public static CancellationToken None {
+			get {
+				return CancellationTokenSource.NoneSource.Token;
+			}
+		}
+
 		public CancellationTokenRegistration Register (Action callback)
 		{
 			return Register (callback, false);
 		}
-		
+
 		public CancellationTokenRegistration Register (Action callback, bool useSynchronizationContext)
 		{
 			if (callback == null)
 				throw new ArgumentNullException ("callback");
-			
+
 			return Source.Register (callback, useSynchronizationContext);
 		}
-		
+
 		public CancellationTokenRegistration Register (Action<object> callback, object state)
 		{
 			return Register (callback, state, false);
 		}
-		
+
 		public CancellationTokenRegistration Register (Action<object> callback, object state, bool useSynchronizationContext)
 		{
 			if (callback == null)
 				throw new ArgumentNullException ("callback");
-			
+
 			return Register (() => callback (state), useSynchronizationContext);
 		}
 
+		public void ThrowIfCancellationRequested ()
+		{
+			Source.ThrowIfCancellationRequested ();
+		}
+
 		public bool Equals (CancellationToken other)
 		{
 			return this.Source == other.Source;
 		}
-		
+
 		public override bool Equals (object obj)
 		{
 			return (obj is CancellationToken) ? Equals ((CancellationToken)obj) : false;
 		}
-		
+
 		public override int GetHashCode ()
 		{
 			return Source.GetHashCode ();
 		}
-		
+
 		public static bool operator == (CancellationToken lhs, CancellationToken rhs)
 		{
 			return lhs.Equals (rhs);
 		}
-		
+
 		public static bool operator != (CancellationToken lhs, CancellationToken rhs)
 		{
 			return !lhs.Equals (rhs);
 		}
-		
+
 		public bool CanBeCanceled {
 			get {
 				return true;
 			}
 		}
-		
+
 		public bool IsCancellationRequested {
 			get {
 				return Source.IsCancellationRequested;
 			}
 		}
-		
+
 		public WaitHandle WaitHandle {
 			get {
 				return Source.WaitHandle;
 			}
 		}
-		
+
 		internal CancellationTokenSource Source {
 			get;
 			set;

+ 18 - 7
mcs/class/corlib/System.Threading/CancellationTokenSource.cs

@@ -31,7 +31,7 @@ using System.Collections.Generic;
 namespace System.Threading
 {
 	
-	public class CancellationTokenSource : IDisposable
+	public sealed class CancellationTokenSource : IDisposable
 	{
 		volatile bool canceled;
 		volatile bool processed;
@@ -43,9 +43,9 @@ namespace System.Threading
 		
 		ManualResetEvent handle = new ManualResetEvent (false);
 		
-//#if USE_MONITOR
 		object syncRoot = new object ();
-//#endif
+		
+		internal static readonly CancellationTokenSource NoneSource = new CancellationTokenSource ();
 		
 		public void Cancel ()
 		{
@@ -105,10 +105,7 @@ namespace System.Threading
 		
 		public CancellationToken Token {
 			get {
-				CancellationToken token = new CancellationToken (canceled);
-				token.Source = this;
-				
-				return token;
+				return CreateToken ();
 			}
 		}
 		
@@ -159,6 +156,12 @@ namespace System.Threading
 			
 		}
 		
+		internal void ThrowIfCancellationRequested ()
+		{
+			if (canceled)
+				throw new OperationCanceledException (CreateToken ());
+		}
+		
 		CancellationTokenRegistration GetTokenReg ()
 		{
 			CancellationTokenRegistration registration
@@ -166,6 +169,14 @@ namespace System.Threading
 			
 			return registration;
 		}
+		
+		CancellationToken CreateToken ()
+		{
+			CancellationToken tk = new CancellationToken (canceled);
+			tk.Source = this;
+			
+			return tk;
+		}
 	}
 }
 #endif

+ 10 - 0
mcs/class/corlib/System.Threading/ChangeLog

@@ -1,3 +1,13 @@
+2010-02-02  Jérémie Laval  <[email protected]>
+
+	* CancellationToken.cs:
+	* CancellationTokenSource.cs:
+	* ManualResetEventSlim.cs:
+	* SemaphoreSlim.cs:
+	* SpinLock.cs:
+	* SpinWait.cs:
+	* ThreadLocal.cs: Port to .NET 4 beta 2 API
+
 2009-12-09  Jb Evain  <[email protected]>
 
 	* ThreadPool.cs (QueueUserWorkItem): properly throw

+ 62 - 54
mcs/class/corlib/System.Threading/ManualResetEventSlim.cs

@@ -27,32 +27,36 @@ 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 ();
+		const int defaultSpinCount = 20;
 
 		int state;
+		readonly int spinCount;
+
+		ManualResetEvent handle;
 
-		
-		public ManualResetEventSlim () : this(false, 20)
+		public ManualResetEventSlim () : this(false, defaultSpinCount)
 		{
 		}
-		
-		public ManualResetEventSlim (bool initState) : this (initState, 20)
+
+		public ManualResetEventSlim (bool initState) : this (initState, defaultSpinCount)
 		{
 		}
-		
+
 		public ManualResetEventSlim (bool initState, int spinCount)
 		{
+			if (spinCount < 0)
+				throw new ArgumentOutOfRangeException ("spinCount is less than 0", "spinCount");
+
 			this.state = initState ? isSet : isNotSet;
 			this.spinCount = spinCount;
+			this.handle = new ManualResetEvent (initState);
 		}
-		
+
 		public bool IsSet {
 			get {
 				return state == isSet;
@@ -64,84 +68,88 @@ namespace System.Threading
 				return spinCount;
 			}
 		}
-		
+
 		public void Reset ()
 		{
 			Interlocked.Exchange (ref state, isNotSet);
 		}
-		
+
 		public void Set ()
 		{
 			Interlocked.Exchange (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);
-		}
-		
+			Wait (CancellationToken.None);
+		}
+
 		public bool Wait (int millisecondsTimeout)
+		{
+			return Wait (millisecondsTimeout, CancellationToken.None);
+		}
+
+		public bool Wait (TimeSpan ts)
+		{
+			return Wait ((int)ts.TotalMilliseconds, CancellationToken.None);
+		}
+
+		public void Wait (CancellationToken token)
+		{
+			Wait (-1, token);
+		}
+
+		public bool Wait (int millisecondsTimeout, CancellationToken token)
 		{
 			if (millisecondsTimeout < -1)
 				throw new ArgumentOutOfRangeException ("millisecondsTimeout",
 				                                       "millisecondsTimeout is a negative number other than -1");
-			
-			if (millisecondsTimeout == -1) {
-				Wait ();
-				return true;
-			}
-			
+
 			Watch s = Watch.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
+			SpinWait sw = new SpinWait ();
+			int count = 0;
+
 			while (state == isNotSet) {
-				if (s.ElapsedMilliseconds >= millisecondsTimeout)
+				if (token.IsCancellationRequested)
+					return false;
+
+				if (millisecondsTimeout > -1 && s.ElapsedMilliseconds > millisecondsTimeout)
 					return false;
-				
-				sw.SpinOnce ();
+
+				if (count < spinCount) {
+				    sw.SpinOnce ();
+					count++;
+				} else {
+					Thread.Sleep (0);
+				}
 			}
-			
+
 			return true;
 		}
-		
-		public bool Wait (TimeSpan ts)
+
+		public bool Wait (TimeSpan ts, CancellationToken token)
 		{
-			return Wait ((int)ts.TotalMilliseconds);
+			return Wait ((int)ts.TotalMilliseconds, token);
 		}
-		
-		[MonoTODO]
+
 		public WaitHandle WaitHandle {
 			get {
-				return null;
+				return handle;
 			}
 		}
-		
-		#region IDisposable implementation 
+
+		#region IDisposable implementation
 		public void Dispose ()
 		{
 			Dispose(true);
 		}
-		
+
 		protected virtual void Dispose(bool managedRes)
 		{
-			
+
 		}
-		#endregion 
-		
+		#endregion
+
 	}
 }
 #endif

+ 75 - 54
mcs/class/corlib/System.Threading/SemaphoreSlim.cs

@@ -1,4 +1,3 @@
-#if NET_4_0
 // SemaphoreSlim.cs
 //
 // Copyright (c) 2008 Jérémie "Garuma" Laval
@@ -26,69 +25,69 @@
 using System;
 using System.Diagnostics;
 
+#if NET_4_0
 namespace System.Threading
 {
 	public class SemaphoreSlim : IDisposable
 	{
 		readonly int max;
-		
 		int currCount;
-
 		bool isDisposed;
-		
-		SpinWait wait = new SpinWait ();
-		
+
+		ManualResetEvent handle;
+
 		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;
+			this.handle = new ManualResetEvent (initial == 0);
 		}
-		
+
 		~SemaphoreSlim ()
 		{
 			Dispose(false);
 		}
-		
+
 		public void Dispose ()
 		{
 			Dispose(true);
 		}
-		
+
 		protected virtual void Dispose (bool managedRes)
 		{
 			isDisposed = true;
 		}
-		
+
 		void CheckState ()
 		{
 			if (isDisposed)
 				throw new ObjectDisposedException ("The SemaphoreSlim has been disposed.");
 		}
-		
+
 		public int CurrentCount {
 			get {
 				return currCount;
 			}
 		}
-		
+
 		public int Release ()
 		{
 			return Release(1);
 		}
-		
+
 		public int Release (int releaseCount)
 		{
 			CheckState ();
-			if (releaseCount < 0)
-				throw new ArgumentOutOfRangeException ("releaseCount", "	The releaseCount must be positive.");
-			
+			if (releaseCount < 1)
+				throw new ArgumentOutOfRangeException ("releaseCount", "releaseCount is less than 1");
+
 			// As we have to take care of the max limit we resort to CAS
 			int oldValue, newValue;
 			do {
@@ -96,67 +95,89 @@ namespace System.Threading
 				newValue = (currCount + releaseCount);
 				newValue = newValue > max ? max : newValue;
 			} while (Interlocked.CompareExchange (ref currCount, newValue, oldValue) != oldValue);
-			
+
+			handle.Reset ();
+
 			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);
+			Wait (CancellationToken.None);
 		}
-		
+
 		public bool Wait (TimeSpan ts)
 		{
-			CheckState();
-			return Wait ((int)ts.TotalMilliseconds);
+			return Wait ((int)ts.TotalMilliseconds, CancellationToken.None);
 		}
-		
+
 		public bool Wait (int millisecondsTimeout)
+		{
+			return Wait (millisecondsTimeout, CancellationToken.None);
+		}
+
+		public void Wait (CancellationToken token)
+		{
+			Wait (-1, token);
+		}
+
+		public bool Wait (TimeSpan ts, CancellationToken token)
+		{
+			CheckState();
+			return Wait ((int)ts.TotalMilliseconds, token);
+		}
+
+		public bool Wait (int millisecondsTimeout, CancellationToken token)
 		{
 			CheckState ();
 			if (millisecondsTimeout < -1)
 				throw new ArgumentOutOfRangeException ("millisecondsTimeout",
 				                                       "millisecondsTimeout is a negative number other than -1");
-			if (millisecondsTimeout == -1) {
-				Wait ();
-				return true;
-			}
-			
+
+			Watch sw = Watch.StartNew ();
+
+			Func<bool> stopCondition =
+				() => token.IsCancellationRequested || (millisecondsTimeout >= 0 && sw.ElapsedMilliseconds > millisecondsTimeout);
+
 			do {
-				int result = Interlocked.Decrement (ref currCount);
-				if (result >= 0)
+				bool shouldWait;
+				int result;
+
+				do {
+					if (stopCondition ())
+						return false;
+
+					shouldWait = true;
+					result = currCount;
+
+					if (result > 0)
+						shouldWait = false;
+					else
+						break;
+				} while (Interlocked.CompareExchange (ref currCount, result - 1, result) != result);
+
+				if (!shouldWait) {
+					if (result == 1)
+						handle.Set ();
 					break;
-				
-				// We revert back the operation
-				result = Interlocked.Increment (ref currCount);
-				Watch sw = Watch.StartNew ();
+				}
+
+				SpinWait wait = new SpinWait ();
+
 				while (Thread.VolatileRead (ref currCount) <= 0) {
-					if (sw.ElapsedMilliseconds > millisecondsTimeout) {
-						sw.Stop ();
+					if (stopCondition ())
 						return false;
-					}
+
 					wait.SpinOnce ();
 				}
 			} while (true);
-			
+
 			return true;
 		}
-		
-		[MonoTODO ("Cf CountdownEvent for ManualResetEvent usage")]
+
 		public WaitHandle AvailableWaitHandle {
 			get {
-				return null;
+				return handle;
 			}
 		}
 	}

+ 28 - 24
mcs/class/corlib/System.Threading/SpinLock.cs

@@ -1,4 +1,3 @@
-#if NET_4_0
 // SpinLock.cs
 //
 // Copyright (c) 2008 Jérémie "Garuma" Laval
@@ -26,6 +25,7 @@
 using System;
 using System.Runtime.ConstrainedExecution;
 
+#if NET_4_0
 namespace System.Threading
 {
 	public struct SpinLock
@@ -75,6 +75,11 @@ namespace System.Threading
 		
 		public void Enter (ref bool lockTaken)
 		{
+			if (lockTaken)
+				throw new ArgumentException ("lockTaken", "lockTaken must be initialized to false");
+			if (isThreadOwnerTrackingEnabled && IsHeldByCurrentThread)
+				throw new LockRecursionException ();
+			
 			try {
 				Enter ();
 				lockTaken = lockState == isOwned && Thread.CurrentThread.ManagedThreadId == threadWhoTookLock;
@@ -87,22 +92,20 @@ namespace System.Threading
 		{
 			int result = Interlocked.Exchange (ref lockState, isOwned);
 			
-			//Thread.BeginCriticalRegion();
 			while (result == isOwned) {
-				// If resource available, set it to in-use and return
-				if (result == isFree) {
-					result = Interlocked.Exchange (ref lockState, isOwned);
-					if (result == isFree)
-						break;
-				}
+				sw.SpinOnce ();
 				
 				// 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 ();
-				//}
+				result = Thread.VolatileRead (ref lockState);
+				
+				if (result == isFree) {
+					result = Interlocked.Exchange (ref lockState, isOwned);
+					if (result == isFree)
+						break;
+				}
 			}
 			
 			CheckAndSetThreadId ();
@@ -110,8 +113,6 @@ namespace System.Threading
 		
 		bool TryEnter ()
 		{
-			//Thread.BeginCriticalRegion();
-
 			// If resource available, set it to in-use and return
 			if (Interlocked.Exchange (ref lockState, isOwned) == isFree) {
 				CheckAndSetThreadId ();
@@ -122,11 +123,7 @@ namespace System.Threading
 		
 		public void TryEnter (ref bool lockTaken)
 		{
-			try {
-				lockTaken = TryEnter ();
-			} catch {
-				lockTaken = false;
-			}
+			TryEnter (-1, ref lockTaken);
 		}
 		
 		public void TryEnter (TimeSpan timeout, ref bool lockTaken)
@@ -136,24 +133,32 @@ namespace System.Threading
 		
 		public void TryEnter (int milliSeconds, ref bool lockTaken)
 		{
-			//Thread.BeginCriticalRegion();
+			if (milliSeconds < -1)
+				throw new ArgumentOutOfRangeException ("milliSeconds", "millisecondsTimeout is a negative number other than -1");
+			if (lockTaken)
+				throw new ArgumentException ("lockTaken", "lockTaken must be initialized to false");
+			if (isThreadOwnerTrackingEnabled && IsHeldByCurrentThread)
+				throw new LockRecursionException ();
 			
 			Watch sw = Watch.StartNew ();
 			
-			while (sw.ElapsedMilliseconds < milliSeconds) {
-				TryEnter (ref lockTaken);
+			while (milliSeconds == -1 || sw.ElapsedMilliseconds < milliSeconds) {
+				lockTaken = TryEnter ();
 			}
+			
 			sw.Stop ();
 		}
 
-		//[ReliabilityContractAttribute]
 		public void Exit () 
 		{ 
 			Exit (false);
 		}
 
 		public void Exit (bool flushReleaseWrites) 
-		{ 
+		{
+			if (isThreadOwnerTrackingEnabled && !IsHeldByCurrentThread)
+				throw new SynchronizationLockException ("Current thread is not the owner of this lock");
+				
 			threadWhoTookLock = int.MinValue;
 			
 			// Mark the resource as available
@@ -162,7 +167,6 @@ namespace System.Threading
 			} else {
 				Interlocked.Exchange (ref lockState, isFree);
 			}
-			//Thread.EndCriticalRegion();
 		}
 	}
 	

+ 14 - 14
mcs/class/corlib/System.Threading/SpinWait.cs

@@ -27,16 +27,16 @@ using System;
 
 namespace System.Threading
 {
-	
+
 	public struct SpinWait
 	{
 		// The number of step until SpinOnce yield on multicore machine
-		const           int  step = 20;
+		const           int  step = 5;
 		static readonly bool isSingleCpu = (Environment.ProcessorCount == 1);
-		
+
 		int ntime;
-		
-		public void SpinOnce () 
+
+		public void SpinOnce ()
 		{
 			// On a single-CPU system, spinning does no good
 			if (isSingleCpu) {
@@ -50,51 +50,51 @@ namespace System.Threading
 				}
 			}
 		}
-		
+
 		public static void SpinUntil (Func<bool> predicate)
 		{
 			SpinWait sw = new SpinWait ();
 			while (!predicate ())
 				sw.SpinOnce ();
 		}
-		
+
 		public static bool SpinUntil (Func<bool> predicate, TimeSpan ts)
 		{
 			return SpinUntil (predicate, (int)ts.TotalMilliseconds);
 		}
-		
+
 		public static bool SpinUntil (Func<bool> predicate, int milliseconds)
 		{
 			SpinWait sw = new SpinWait ();
 			Watch watch = Watch.StartNew ();
-			
+
 			while (!predicate ()) {
 				if (watch.ElapsedMilliseconds > milliseconds)
 					return false;
 				sw.SpinOnce ();
 			}
-			
+
 			return true;
 		}
-		
+
 		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;

+ 11 - 1
mcs/class/corlib/System.Threading/ThreadLocal.cs

@@ -34,7 +34,7 @@ namespace System.Threading
 {
 	[HostProtectionAttribute(SecurityAction.LinkDemand, Synchronization = true, 
 	                         ExternalThreading = true)]
-	public class ThreadLocal<T>
+	public class ThreadLocal<T> : IDisposable
 	{
 		readonly Func<T> initializer;
 		LocalDataStoreSlot localStore;
@@ -58,6 +58,16 @@ namespace System.Threading
 			this.initializer = initializer;
 		}
 		
+		public void Dispose ()
+		{
+			Dispose(true);
+		}
+		
+		protected virtual void Dispose (bool dispManagedRes)
+		{
+			
+		}
+		
 		public bool IsValueCreated {
 			get {
 				return IsInitializedThreadLocal ();

+ 1 - 1
mcs/class/corlib/System/AggregateException.cs

@@ -115,7 +115,7 @@ namespace System
 			return this.Message;
 		}
 		
-		const string baseMessage = "Exception(s) occurred while inside the Parallel loop. {0}.";
+		const string baseMessage = "Exception(s) occurred : {0}.";
 		static string GetFormattedMessage (string customMessage, IEnumerable<Exception> inner)
 		{
 			System.Text.StringBuilder finalMessage

+ 5 - 0
mcs/class/corlib/System/ChangeLog

@@ -1,3 +1,8 @@
+2010-02-02  Jérémie Laval  <[email protected]>
+
+	* AggregateException.cs:
+	* OperationCanceledException.cs: Port to .NET 4 beta 2 API
+
 2010-01-31  Zoltan Varga  <[email protected]>
 
 	* Enum.cs: Fix a warning.

+ 38 - 1
mcs/class/corlib/System/OperationCanceledException.cs

@@ -1,7 +1,9 @@
 //
 // System.OperationCanceledException.cs
 //
-
+// Authors:
+//   Zoltan Varga  <[email protected]>
+//   Jérémie Laval <[email protected]>
 //
 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
 //
@@ -27,6 +29,7 @@
 
 using System.Runtime.Serialization;
 using System.Runtime.InteropServices;
+using System.Threading;
 
 namespace System
 {
@@ -35,6 +38,9 @@ namespace System
 	public class OperationCanceledException : SystemException
 	{
 		const int Result = unchecked ((int)0x8013153b);
+#if NET_4_0 || BOOTSTRAP_NET_4_0
+		CancellationToken? token;
+#endif
 
 		// Constructors
 		public OperationCanceledException ()
@@ -59,5 +65,36 @@ namespace System
 			: base (info, context)
 		{
 		}
+		
+#if NET_4_0 || BOOTSTRAP_NET_4_0
+		public OperationCanceledException (CancellationToken token)
+			: this ()
+		{
+			this.token = token;
+		}
+		
+		public OperationCanceledException (string message, CancellationToken token)
+			: this (message)
+		{
+			this.token = token;
+		}
+		
+		public OperationCanceledException (string message, Exception innerException, CancellationToken token)
+			: base (message, innerException)
+		{
+			this.token = token;
+		}
+		
+		public CancellationToken CancellationToken {
+			get {
+				if (token == null)
+					return CancellationToken.None;
+				return token.Value;
+			}
+			private set {
+				token = value;
+			}
+		}
+#endif
 	}
 }

+ 11 - 0
mcs/class/corlib/Test/System.Collections.Concurrent/ChangeLog

@@ -1,3 +1,14 @@
+2010-02-02  Jérémie Laval  <[email protected]>
+
+	* CollectionStressTestHelper.cs:
+	* ConcurrentBagTests.cs:
+	* ConcurrentDictionaryTests.cs:
+	* ConcurrentQueueTests.cs:
+	* ConcurrentSkipListTests.cs:
+	* ConcurrentStackTests.cs:
+	* ParallelConcurrentQueueTests.cs:
+	* ParallelConcurrentStackTests.cs: Update namespaces and tested methods
+
 2009-08-11  Jérémie Laval  <[email protected]>
 
 	* BlockingCollectionTests.cs: Moved file.

+ 1 - 1
mcs/class/corlib/Test/System.Collections.Concurrent/CollectionStressTestHelper.cs

@@ -37,7 +37,7 @@ using MonoTests.System.Threading.Tasks;
 using NUnit;
 using NUnit.Framework;
 
-namespace ParallelFxTests
+namespace MonoTests.System.Collections.Concurrent
 {
 	public enum CheckOrderingType {
 		InOrder,

+ 1 - 1
mcs/class/corlib/Test/System.Collections.Concurrent/ConcurrentBagTests.cs

@@ -36,7 +36,7 @@ using System.Linq;
 using NUnit;
 using NUnit.Framework;
 
-namespace ParallelFxTests
+namespace MonoTests.System.Collections.Concurrent
 {
 	[TestFixture]
 	public class ConcurrentBagTests

+ 2 - 1
mcs/class/corlib/Test/System.Collections.Concurrent/ConcurrentDictionaryTests.cs

@@ -31,7 +31,7 @@ using System.Collections.Concurrent;
 using NUnit;
 using NUnit.Framework;
 
-namespace ParallelFxTests
+namespace MonoTests.System.Collections.Concurrent
 {
 	[TestFixture]
 	public class ConcurrentDictionaryTests
@@ -75,6 +75,7 @@ namespace ParallelFxTests
 					int own = Interlocked.Increment (ref index);
 					
 					while (!map.TryAdd ("monkey" + own.ToString (), 3));
+					
 				}, 4);
 				
 				Assert.AreEqual (7, map.Count);

+ 1 - 1
mcs/class/corlib/Test/System.Collections.Concurrent/ConcurrentQueueTests.cs

@@ -31,7 +31,7 @@ using System.Collections.Concurrent;
 
 using NUnit.Framework;
 
-namespace ParallelFxTests
+namespace MonoTests.System.Collections.Concurrent
 {
 	
 	

+ 1 - 1
mcs/class/corlib/Test/System.Collections.Concurrent/ConcurrentSkipListTests.cs

@@ -30,7 +30,7 @@ using System.Collections.Concurrent;
 using NUnit;
 using NUnit.Framework;
 
-namespace ParallelFxTests
+namespace MonoTests.System.Collections.Concurrent
 {
 	[TestFixtureAttribute]
 	public class ConcurrentSkipListTests

+ 1 - 1
mcs/class/corlib/Test/System.Collections.Concurrent/ConcurrentStackTests.cs

@@ -29,7 +29,7 @@ using System.Linq;
 using System.Collections.Concurrent;
 using NUnit.Framework;
 
-namespace ParallelFxTests
+namespace MonoTests.System.Collections.Concurrent
 {
 	[TestFixture()]
 	public class ConcurrentStackTests

+ 1 - 1
mcs/class/corlib/Test/System.Collections.Concurrent/ParallelConcurrentQueueTests.cs

@@ -30,7 +30,7 @@ using MonoTests.System.Threading.Tasks;
 
 using NUnit.Framework;
 
-namespace ParallelFxTests
+namespace MonoTests.System.Collections.Concurrent
 {
 	[TestFixture()]
 	public class ParallelConcurrentQueueTests

+ 1 - 1
mcs/class/corlib/Test/System.Collections.Concurrent/ParallelConcurrentStackTests.cs

@@ -29,7 +29,7 @@ using System.Collections.Concurrent;
 
 using NUnit.Framework;
 
-namespace ParallelFxTests
+namespace MonoTests.System.Collections.Concurrent
 {
 	
 	[TestFixture()]

+ 9 - 0
mcs/class/corlib/Test/System.Threading.Tasks/ChangeLog

@@ -1,3 +1,12 @@
+2010-02-02  Jérémie Laval  <[email protected]>
+
+	* FutureTests.cs:
+	* ParallelTestHelper.cs:
+	* ParallelTests.cs:
+	* SnziTests.cs:
+	* TaskCompletionSourceTests.cs:
+	* TaskTest.cs: Update namespace and tested methods
+
 2009-07-30  Jérémie Laval  <[email protected]>
 
 	* FutureTests.cs:

+ 1 - 26
mcs/class/corlib/Test/System.Threading.Tasks/FutureTests.cs

@@ -29,7 +29,7 @@ using System.Threading.Tasks;
 
 using NUnit.Framework;
 
-namespace ParallelFxTests
+namespace MonoTests.System.Threading.Tasks
 {
 	[TestFixture]
 	public class FutureTests
@@ -62,31 +62,6 @@ namespace ParallelFxTests
 			Assert.IsTrue (result, "#2");
 			Assert.AreEqual (10, cont.Result);
 		}
-		
-		/* Not pertinent anymore
-		 * [Test]
-		public void EmptyTaskTestCase()
-		{
-			Task<int> f = Task.Factory.StartNew<int>(delegate {});
-			f.Value = 3;
-			
-			Assert.AreEqual(3, f.Value, "#1");
-		}
-			
-		/*[Test, ExpectedExceptionAttribute()]
-		public void ManualSetWhenFunctionProvidedTestCase()
-		{
-			Task<int> f = InitTestTask();
-			f.Value = 2;
-		}
-		
-		/*[Test, ExpectedExceptionAttribute()]
-		public void ManualSetTwoTimesTestCase()
-		{
-			Task<int> f = Task.Factory.StartNew<int>();
-			f.Value = 2;
-			f.Value = 3;
-		}*/
 	}
 }
 #endif

+ 0 - 1
mcs/class/corlib/Test/System.Threading.Tasks/ParallelTestHelper.cs

@@ -41,7 +41,6 @@ namespace MonoTests.System.Threading.Tasks
 		public static void Repeat (Action action, int numRun)
 		{
 			for (int i = 0; i < numRun; i++) {
-			  //Console.WriteLine ("Run " + i.ToString ());
 				action ();
 			}
 		}

+ 3 - 17
mcs/class/corlib/Test/System.Threading.Tasks/ParallelTests.cs

@@ -47,8 +47,9 @@ namespace MonoTests.System.Threading.Tasks
 		[Test]
 		public void ParallelForTestCase ()
 		{
-			ParallelTestHelper.Repeat (() => {
-				int[] expected = Enumerable.Range (1, 1000).Select ((e) => e * 2).ToArray ();
+			int[] expected = Enumerable.Range (1, 1000).Select ((e) => e * 2).ToArray ();
+			
+			ParallelTestHelper.Repeat (() => {	
 				int[] actual = Enumerable.Range (1, 1000).ToArray ();
 				SpinWait sw = new SpinWait ();
 				
@@ -106,21 +107,6 @@ namespace MonoTests.System.Threading.Tasks
 			IEnumerable<int> e = Enumerable.Repeat (1, 10);
 			Parallel.ForEach (e, delegate (int element) { throw new Exception ("foo"); });
 		}
-		
-		/* Disabled as this is an API addition
-		[Test]
-		public void ParallelWhileTestCase()
-		{
-			ParallelTestHelper.Repeat (() => {
-				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

+ 1 - 1
mcs/class/corlib/Test/System.Threading.Tasks/SnziTests.cs

@@ -30,7 +30,7 @@ using System.Threading;
 
 using NUnit.Framework;
 
-namespace ParallelFxTests
+namespace MonoTests.System.Threading.Tasks
 {
 	[TestFixtureAttribute]
 	public class SnziTests

+ 7 - 3
mcs/class/corlib/Test/System.Threading.Tasks/TaskCompletionSourceTests.cs

@@ -31,7 +31,7 @@ using System.Threading.Tasks;
 
 using NUnit.Framework;
 
-namespace ParallelFxTests
+namespace MonoTests.System.Threading.Tasks
 {
 	[TestFixture]
 	public class TaskCompletionSourceTests
@@ -85,10 +85,14 @@ namespace ParallelFxTests
 			Assert.IsNotNull (completionSource.Task, "#1");
 			Assert.IsTrue (completionSource.TrySetException (e), "#2");
 			Assert.AreEqual (TaskStatus.Faulted, completionSource.Task.Status, "#3");
-			Assert.AreEqual (e, completionSource.Task.Exception, "#4");
+			Assert.IsInstanceOfType (typeof (AggregateException), completionSource.Task.Exception, "#4.1");
+			
+			AggregateException aggr = (AggregateException)completionSource.Task.Exception;
+			Assert.AreEqual (1, aggr.InnerExceptions.Count, "#4.2");
+			Assert.AreEqual (e, aggr.InnerExceptions[0], "#4.3");
+			
 			Assert.IsFalse (completionSource.TrySetResult (42), "#5");
 			Assert.AreEqual (TaskStatus.Faulted, completionSource.Task.Status, "#6");
-			Assert.AreEqual (e, completionSource.Task.Exception, "#7");
 			Assert.IsFalse (completionSource.TrySetCanceled (), "#8");
 			Assert.AreEqual (TaskStatus.Faulted, completionSource.Task.Status, "#9");
 		}

+ 40 - 35
mcs/class/corlib/Test/System.Threading.Tasks/TaskTest.cs

@@ -31,7 +31,7 @@ using NUnit.Framework;
 
 namespace MonoTests.System.Threading.Tasks
 {
-	[TestFixture()]
+	[TestFixture]
 	public class TaskTests
 	{
 		Task[]      tasks;
@@ -91,23 +91,31 @@ namespace MonoTests.System.Threading.Tasks
 		[Test]
 		public void CancelTestCase()
 		{
-			int count = 1;
-			ParallelTestHelper.Repeat (delegate {
-				bool result = false;
-				
-				Task t = new Task (delegate {
-					result = true;
-				});
-				t.Cancel();
-				Assert.IsTrue (t.IsCancellationRequested, "#-1");
-				t.Start ();
+			bool result = false;
+			
+			CancellationTokenSource src = new CancellationTokenSource ();
+			
+			Task t = new Task (delegate {
+				result = true;
+			}, src.Token);
+			src.Cancel ();
+			
+			t.Start ();
+			Exception ex = null;
+			
+			try {
 				t.Wait ();
-				
-				Assert.IsInstanceOfType(typeof(TaskCanceledException), t.Exception, "#1 : " + count ++);
-				TaskCanceledException ex = (TaskCanceledException)t.Exception;
-				Assert.AreEqual(t, ex.Task, "#2");
-				Assert.IsFalse(result, "#3");
-			});
+			} catch (Exception e) {
+				ex = e;
+			}
+			
+			Assert.IsNotNull (ex, "#1");
+			Assert.IsInstanceOfType (typeof(AggregateException), t.Exception, "#2");
+			Assert.AreEqual (t.Exception, ex, "#3");
+			
+			AggregateException aggr = (AggregateException)ex;
+			Assert.AreEqual (1, aggr.InnerExceptions.Count, "#4");
+			Assert.IsInstanceOfType (typeof (OperationCanceledException), aggr.InnerExceptions[0], "#5");
 		}
 		
 		[Test]
@@ -151,13 +159,13 @@ namespace MonoTests.System.Threading.Tasks
 				bool result = false;
 				bool taskResult = false;
 				
-				Task t = new Task(delegate { taskResult = true; });
-				t.Cancel();
+				CancellationTokenSource src = new CancellationTokenSource ();
+				Task t = new Task(delegate { taskResult = true; }, src.Token);
+				src.Cancel ();
 				
-				Task cont = t.ContinueWith(delegate { result = true; }, TaskContinuationOptions.OnlyOnCanceled);
+				Task cont = t.ContinueWith (delegate { result = true; }, TaskContinuationOptions.OnlyOnCanceled);
 
 				t.Start();
-				t.Wait();
 				cont.Wait();
 				
 				Assert.IsFalse (taskResult, "#-1");
@@ -170,22 +178,22 @@ namespace MonoTests.System.Threading.Tasks
 			});
 		}
 		
-		/*[Test]
+		[Test]
 		public void ContinueWithOnFailedTestCase()
 		{
 			ParallelTestHelper.Repeat (delegate {
 				bool result = false;
 				
-				Task t = Task.Factory.StartNew(delegate {throw new Exception("foo"); });
-		//		Task cont = t.ContinueWith(delegate { result = true; }, TaskContinuationOptions.OnlyOnFaulted);
-			//	t.Wait();
-				//cont.Wait();
+				Task t = Task.Factory.StartNew(delegate { throw new Exception("foo"); });	
+				Task cont = t.ContinueWith(delegate { result = true; }, TaskContinuationOptions.OnlyOnFaulted);
+			
+				cont.Wait();
 				
-				//Assert.IsNotNull (t.Exception, "#1");
-		//		Assert.IsNotNull (cont, "#2");
+				Assert.IsNotNull (t.Exception, "#1");
+				Assert.IsNotNull (cont, "#2");
 				Assert.IsTrue (result, "#3");
 			});
-		}*/
+		}
 
 		[TestAttribute]
 		public void MultipleTaskTestCase()
@@ -223,20 +231,17 @@ namespace MonoTests.System.Threading.Tasks
 					Task.Factory.StartNew(delegate {
 						Thread.Sleep(50);
 						r1 = true;
-						//Console.WriteLine("finishing 1");
-					});
+					}, TaskCreationOptions.AttachedToParent);
 					Task.Factory.StartNew(delegate {
 						Thread.Sleep(300);
 						
 						r2 = true;
-						//Console.WriteLine("finishing 2");
-					});
+					}, TaskCreationOptions.AttachedToParent);
 					Task.Factory.StartNew(delegate {
 						Thread.Sleep(150);
 						
 						r3 = true;
-						//Console.WriteLine("finishing 3");
-					});
+					}, TaskCreationOptions.AttachedToParent);
 				});
 				
 				t.Wait();

+ 1 - 1
mcs/class/corlib/Test/System.Threading/CancellationTokenTests.cs

@@ -30,7 +30,7 @@ using System.Threading;
 
 using NUnit.Framework;
 
-namespace ParallelFxTests
+namespace MonoTests.System.Threading
 {
 	[TestFixtureAttribute]
 	public class CancellationTokenTests

+ 6 - 0
mcs/class/corlib/Test/System.Threading/ChangeLog

@@ -1,3 +1,9 @@
+2010-02-02  Jérémie Laval  <[email protected]>
+
+	* CancellationTokenTests.cs:
+	* LazyInitTests.cs:
+	* ThreadLazyTests.cs: Update namespace and tested methods
+
 2009-12-09  Jb Evain  <[email protected]>
 
 	* ThreadTest.cs: add a test for a null callback passed to

+ 1 - 1
mcs/class/corlib/Test/System.Threading/LazyInitTests.cs

@@ -30,7 +30,7 @@ using NUnit;
 using NUnit.Core;
 using NUnit.Framework;
 
-namespace ParallelFxTests
+namespace MonoTests.System.Threading
 {
 	[TestFixtureAttribute]
 	public class LazyInitTests

+ 1 - 1
mcs/class/corlib/Test/System.Threading/ThreadLazyTests.cs

@@ -32,7 +32,7 @@ using NUnit;
 using NUnit.Core;
 using NUnit.Framework;
 
-namespace ParallelFxTests
+namespace MonoTests.System.Threading
 {
 	[TestFixtureAttribute]
 	public class ThreadLazyTests

+ 4 - 2
mcs/class/corlib/corlib.dll.sources

@@ -1513,8 +1513,8 @@ System.Collections.Concurrent/ConcurrentDictionary.cs
 System.Collections.Concurrent/Partitioner.cs
 System.Collections.Concurrent/ConcurrentQueue.cs
 System.Collections.Concurrent/ConcurrentSkipList.cs
-System.Collections.Concurrent/Partitionners/ListPartitioner.cs
-System.Collections.Concurrent/Partitionners/EnumerablePartitioner.cs
+System.Collections.Concurrent/Partitioners/ListPartitioner.cs
+System.Collections.Concurrent/Partitioners/EnumerablePartitioner.cs
 System.Collections.Concurrent/IProducerConsumerCollection.cs
 System.Collections.Concurrent/ConcurrentStack.cs
 System.Threading/LazyInitializer.cs
@@ -1536,3 +1536,5 @@ System.Threading.Tasks/Parallel.cs
 System.Threading.Tasks/ParallelLoopResult.cs
 System.Threading.Tasks/ParallelLoopState.cs
 System/AggregateException.cs
+System.Threading.Tasks/SimpleConcurrentBag.cs
+System.Threading.Tasks/UnobservedTaskExceptionEventArgs.cs