Merge branch 'BigIntegerParse'
[mono.git] / mcs / class / corlib / System.Threading.Tasks / Task.cs
index cc94983247f6e980010a262e07b76a2c2321f23d..bb023257b4769978f0db08de9d5a5a4a03119811 100644 (file)
@@ -182,8 +182,11 @@ namespace System.Threading.Tasks
                        if (IsContinuation)
                                throw new InvalidOperationException ("Start may not be called on a continuation task");
 
+                       if (IsPromise)
+                               throw new InvalidOperationException ("Start may not be called on a promise-style task");
+
                        SetupScheduler (scheduler);
-                       Schedule ();
+                       Schedule (true);
                }
 
                internal void SetupScheduler (TaskScheduler scheduler)
@@ -208,10 +211,13 @@ namespace System.Threading.Tasks
                        if (IsContinuation)
                                throw new InvalidOperationException ("RunSynchronously may not be called on a continuation task");
 
-                       RunSynchronouslyCore (scheduler);
+                       if (IsPromise)
+                               throw new InvalidOperationException ("RunSynchronously may not be called on a promise-style task");
+
+                       RunSynchronouslyCore (scheduler, true);
                }
 
-               internal void RunSynchronouslyCore (TaskScheduler scheduler)
+               internal void RunSynchronouslyCore (TaskScheduler scheduler, bool throwException)
                {
                        SetupScheduler (scheduler);
                        Status = TaskStatus.WaitingToRun;
@@ -220,10 +226,15 @@ namespace System.Threading.Tasks
                                if (scheduler.RunInline (this, false))
                                        return;
                        } catch (Exception inner) {
-                               throw new TaskSchedulerException (inner);
+                               var ex = new TaskSchedulerException (inner);
+                               TrySetException (new AggregateException (ex), false, true);
+                               if (throwException)
+                                       throw ex;
+
+                               return;
                        }
 
-                       Schedule ();
+                       Schedule (throwException);
                        WaitCore (Timeout.Infinite, CancellationToken.None, false);
                }
                #endregion
@@ -343,8 +354,7 @@ namespace System.Threading.Tasks
                        continuations.Add (continuation);
                        
                        // Retry in case completion was achieved but event adding was too late
-                       if (IsCompleted) {
-                               continuations.Remove (continuation);
+                       if (IsCompleted && continuations.Remove (continuation)) {
                                if (!canExecuteInline)
                                        return false;
 
@@ -374,10 +384,17 @@ namespace System.Threading.Tasks
                #endregion
                
                #region Internal and protected thingies
-               internal void Schedule ()
+               internal void Schedule (bool throwException)
                {
                        Status = TaskStatus.WaitingToRun;
-                       scheduler.QueueTask (this);
+                       try {
+                               scheduler.QueueTask (this);
+                       } catch (Exception inner) {
+                               var ex = new TaskSchedulerException (inner);
+                               TrySetException (new AggregateException (ex), false, true);
+                               if (throwException)
+                                       throw ex;
+                       }
                }
                
                void ThreadStart ()
@@ -448,7 +465,7 @@ namespace System.Threading.Tasks
                        return true;
                }
 
-               internal bool TrySetException (AggregateException aggregate)
+               internal bool TrySetException (AggregateException aggregate, bool cancellation, bool observed)
                {
                        if (IsCompleted)
                                return false;
@@ -460,8 +477,19 @@ namespace System.Threading.Tasks
 
                                return false;
                        }
-                       
-                       HandleGenericException (aggregate);
+
+                       if (cancellation) {
+                               ExceptionSlot.Exception = aggregate;
+                               Thread.MemoryBarrier ();
+
+                               CancelReal ();
+                       } else {
+                               HandleGenericException (aggregate);
+                       }
+
+                       if (observed)
+                               exSlot.Observed = true;
+
                        return true;
                }
 
@@ -669,8 +697,13 @@ namespace System.Threading.Tasks
                                return true;
 
                        // If the task is ready to be run and we were supposed to wait on it indefinitely without cancellation, just run it
-                       if (runInline && Status == TaskStatus.WaitingToRun && millisecondsTimeout == Timeout.Infinite && scheduler != null && !cancellationToken.CanBeCanceled)
-                               scheduler.RunInline (this, true);
+                       if (runInline && Status == TaskStatus.WaitingToRun && millisecondsTimeout == Timeout.Infinite && scheduler != null && !cancellationToken.CanBeCanceled) {
+                               try {
+                                       scheduler.RunInline (this, true);
+                               } catch (Exception e) {
+                                       throw new TaskSchedulerException (e);
+                               }
+                       }
 
                        bool result = true;
 
@@ -1255,7 +1288,7 @@ namespace System.Threading.Tasks
                
                public AggregateException Exception {
                        get {
-                               if (exSlot == null)
+                               if (exSlot == null || !IsFaulted)
                                        return null;
                                exSlot.Observed = true;
                                return exSlot.Exception;
@@ -1296,7 +1329,7 @@ namespace System.Threading.Tasks
                        }
                }
 
-               TaskExceptionSlot ExceptionSlot {
+               internal TaskExceptionSlot ExceptionSlot {
                        get {
                                if (exSlot != null)
                                        return exSlot;
@@ -1341,6 +1374,12 @@ namespace System.Threading.Tasks
                        }
                }
 
+               bool IsPromise {
+                       get {
+                               return invoker == TaskActionInvoker.Promise;
+                       }
+               }
+
                internal Task ContinuationAncestor {
                        get {
                                return contAncestor;