[corlib] Mark all promise-style task exceptions observed. Fixes #17015
[mono.git] / mcs / class / corlib / System.Runtime.CompilerServices / AsyncTaskMethodBuilder_T.cs
index a119df5d6d5bc53f1fa7dc8a83eb03ccda7aee28..9d539dfc42dc4f5bc56c71e5d94b8371432b5298 100644 (file)
@@ -37,10 +37,12 @@ namespace System.Runtime.CompilerServices
        public struct AsyncTaskMethodBuilder<TResult>
        {
                readonly Task<TResult> task;
+               IAsyncStateMachine stateMachine;
 
                private AsyncTaskMethodBuilder (Task<TResult> task)
                {
                        this.task = task;
+                       this.stateMachine = null;
                }
 
                public Task<TResult> Task {
@@ -49,17 +51,46 @@ namespace System.Runtime.CompilerServices
                        }
                }
                
+               public void AwaitOnCompleted<TAwaiter, TStateMachine> (ref TAwaiter awaiter, ref TStateMachine stateMachine)
+                       where TAwaiter : INotifyCompletion
+                       where TStateMachine : IAsyncStateMachine
+               {
+                       var action = new Action (stateMachine.MoveNext);
+                       awaiter.OnCompleted (action);
+               }
+               
+               public void AwaitUnsafeOnCompleted<TAwaiter, TStateMachine> (ref TAwaiter awaiter, ref TStateMachine stateMachine)
+                       where TAwaiter : ICriticalNotifyCompletion
+                       where TStateMachine : IAsyncStateMachine
+               {
+                       var action = new Action (stateMachine.MoveNext);
+                       awaiter.UnsafeOnCompleted (action);     
+               }
+               
                public static AsyncTaskMethodBuilder<TResult> Create ()
                {
-                       var task = new Task<TResult> (TaskActionInvoker.Empty, null, CancellationToken.None, TaskCreationOptions.None, null);
+                       var task = new Task<TResult> (TaskActionInvoker.Promise, null, CancellationToken.None, TaskCreationOptions.None, null);
                        task.SetupScheduler (TaskScheduler.Current);
                        return new AsyncTaskMethodBuilder<TResult> (task);
                }
 
                public void SetException (Exception exception)
                {
-                       if (!task.TrySetException (new AggregateException (exception)))
-                               throw new InvalidOperationException ("The task has already completed");
+                       if (Task.TrySetException (new AggregateException (exception), exception is OperationCanceledException, true))
+                               return;
+
+                       throw new InvalidOperationException ("The task has already completed");
+               }
+
+               public void SetStateMachine (IAsyncStateMachine stateMachine)
+               {
+                       if (stateMachine == null)
+                               throw new ArgumentNullException ("stateMachine");
+                       
+                       if (this.stateMachine != null)
+                               throw new InvalidOperationException ("The state machine was previously set");
+                       
+                       this.stateMachine = stateMachine;
                }
 
                public void SetResult (TResult result)
@@ -67,6 +98,14 @@ namespace System.Runtime.CompilerServices
                        if (!task.TrySetResult (result))
                                throw new InvalidOperationException ("The task has already completed");
                }
+               
+               public void Start<TStateMachine> (ref TStateMachine stateMachine) where TStateMachine : IAsyncStateMachine
+               {
+                       if (stateMachine == null)
+                               throw new ArgumentNullException ("stateMachine");
+                       
+                       stateMachine.MoveNext ();
+               }
        }
 }