Update Wait and WaitAny with event disposal and single execution flow
[mono.git] / mcs / class / corlib / System.Threading.Tasks / Task_T.cs
1 //
2 // Task_T.cs
3 //
4 // Authors:
5 //    Marek Safar  <marek.safar@gmail.com>
6 //
7 // Copyright (c) 2008 Jérémie "Garuma" Laval
8 // Copyright 2011 Xamarin Inc.
9 //
10 // Permission is hereby granted, free of charge, to any person obtaining a copy
11 // of this software and associated documentation files (the "Software"), to deal
12 // in the Software without restriction, including without limitation the rights
13 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 // copies of the Software, and to permit persons to whom the Software is
15 // furnished to do so, subject to the following conditions:
16 //
17 // The above copyright notice and this permission notice shall be included in
18 // all copies or substantial portions of the Software.
19 //
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
26 // THE SOFTWARE.
27 //
28 //
29
30 #if NET_4_0 || MOBILE
31 using System;
32 using System.Runtime.CompilerServices;
33
34 namespace System.Threading.Tasks
35 {
36         [System.Diagnostics.DebuggerDisplay ("Id = {Id}, Status = {Status}, Result = {ResultAsString}")]
37         [System.Diagnostics.DebuggerTypeProxy (typeof (TaskDebuggerView))]
38         public class Task<TResult> : Task
39         {
40                 static readonly TaskFactory<TResult> factory = new TaskFactory<TResult> ();
41                 static readonly Action<object> emptyAction = delegate (object o) {};
42
43                 TResult value;
44                 Func<object, TResult> function;
45                 Func<TResult> simpleFunction;
46                 object state;
47                 
48                 [System.Diagnostics.DebuggerBrowsable (System.Diagnostics.DebuggerBrowsableState.Never)]
49                 public TResult Result {
50                         get {
51                                 if (!IsCompleted)
52                                         Wait ();
53                                 if (IsCanceled)
54                                         throw new AggregateException (new TaskCanceledException (this));
55                                 if (Exception != null)
56                                         throw Exception;
57                                 return value;
58                         }
59                         internal set {
60                                 this.value = value;
61                         }
62                 }
63
64                 string ResultAsString {
65                         get {
66                                 if ((Status & (TaskStatus.RanToCompletion)) != 0)
67                                         return "" + value;
68                                 
69                                 return "<value not available>";
70                         }
71                 }
72                 
73                 public static new TaskFactory<TResult> Factory {
74                         get {
75                                 return factory;
76                         }
77                 }
78                 
79                 public Task (Func<TResult> function) : this (function, TaskCreationOptions.None)
80                 {
81                         
82                 }
83                 
84                 public Task (Func<TResult> function, CancellationToken cancellationToken)
85                         : this (function, cancellationToken, TaskCreationOptions.None)
86                 {
87                         
88                 }
89                 
90                 public Task (Func<TResult> function, TaskCreationOptions creationOptions)
91                         : this (function, CancellationToken.None, creationOptions)
92                 {
93                         
94                 }
95                 
96                 public Task (Func<TResult> function, CancellationToken cancellationToken, TaskCreationOptions creationOptions)
97                         : base (emptyAction, null, cancellationToken, creationOptions)
98                 {
99                         if (function == null)
100                                 throw new ArgumentNullException ("function");
101
102                         this.simpleFunction = function;
103                         this.state = null;
104                 }
105                 
106                 public Task (Func<object, TResult> function, object state) : this (function, state, TaskCreationOptions.None)
107                 {
108                         
109                 }
110                 
111                 public Task (Func<object, TResult> function, object state, CancellationToken cancellationToken)
112                         : this (function, state, cancellationToken, TaskCreationOptions.None)
113                 {
114                         
115                 }
116                 
117                 public Task (Func<object, TResult> function, object state, TaskCreationOptions creationOptions)
118                         : this (function, state, CancellationToken.None, creationOptions)
119                 {
120                         
121                 }
122
123                 public Task (Func<object, TResult> function, object state, CancellationToken cancellationToken, TaskCreationOptions creationOptions)
124                         : base (emptyAction, state, cancellationToken, creationOptions)
125                 {
126                         if (function == null)
127                                 throw new ArgumentNullException ("function");
128
129                         this.function = function;
130                         this.state = state;
131                 }
132
133                 internal Task (Func<object, TResult> function,
134                                object state,
135                                CancellationToken cancellationToken,
136                                TaskCreationOptions creationOptions,
137                                Task parent)
138                         : base (emptyAction, state, cancellationToken, creationOptions, parent)
139                 {
140                         this.function = function;
141                         this.state = state;
142                 }
143                 
144                 internal override void InnerInvoke ()
145                 {
146                         if (function != null)
147                                 value = function (state);
148                         else if (simpleFunction != null)
149                                 value = simpleFunction ();
150                         
151                         function = null;
152                         simpleFunction = null;
153                         state = null;
154                 }
155                 
156                 public Task ContinueWith (Action<Task<TResult>> continuationAction)
157                 {
158                         return ContinueWith (continuationAction, TaskContinuationOptions.None);
159                 }
160                 
161                 public Task ContinueWith (Action<Task<TResult>> continuationAction, TaskContinuationOptions continuationOptions)
162                 {
163                         return ContinueWith (continuationAction, CancellationToken.None, continuationOptions, TaskScheduler.Current);
164                 }
165                 
166                 public Task ContinueWith (Action<Task<TResult>> continuationAction, CancellationToken cancellationToken)
167                 {
168                         return ContinueWith (continuationAction, cancellationToken, TaskContinuationOptions.None, TaskScheduler.Current);
169                 }
170                 
171                 public Task ContinueWith (Action<Task<TResult>> continuationAction, TaskScheduler scheduler)
172                 {
173                         return ContinueWith (continuationAction, CancellationToken.None, TaskContinuationOptions.None, scheduler);
174                 }
175                 
176                 public Task ContinueWith (Action<Task<TResult>> continuationAction, CancellationToken cancellationToken,
177                                           TaskContinuationOptions continuationOptions, TaskScheduler scheduler)
178                 {
179                         if (continuationAction == null)
180                                 throw new ArgumentNullException ("continuationAction");
181                         if (scheduler == null)
182                                 throw new ArgumentNullException ("scheduler");
183
184                         Task t = new Task (l => continuationAction ((Task<TResult>)l),
185                                            this,
186                                            cancellationToken,
187                                            GetCreationOptions (continuationOptions),
188                                            this);
189                         ContinueWithCore (t, continuationOptions, scheduler);
190                         
191                         return t;
192                 }
193
194                 public Task<TNewResult> ContinueWith<TNewResult> (Func<Task<TResult>, TNewResult> continuationFunction)
195                 {
196                         return ContinueWith<TNewResult> (continuationFunction, CancellationToken.None, TaskContinuationOptions.None, TaskScheduler.Current);
197                 }
198                 
199                 public Task<TNewResult> ContinueWith<TNewResult> (Func<Task<TResult>, TNewResult> continuationFunction, CancellationToken cancellationToken)
200                 {
201                         return ContinueWith<TNewResult> (continuationFunction, cancellationToken, TaskContinuationOptions.None, TaskScheduler.Current);
202                 }
203                 
204                 public Task<TNewResult> ContinueWith<TNewResult> (Func<Task<TResult>, TNewResult> continuationFunction, TaskContinuationOptions continuationOptions)
205                 {
206                         return ContinueWith<TNewResult> (continuationFunction, CancellationToken.None, continuationOptions, TaskScheduler.Current);
207                 }
208                 
209                 public Task<TNewResult> ContinueWith<TNewResult> (Func<Task<TResult>, TNewResult> continuationFunction, TaskScheduler scheduler)
210                 {
211                         return ContinueWith<TNewResult> (continuationFunction, CancellationToken.None, TaskContinuationOptions.None, scheduler);
212                 }
213                 
214                 public Task<TNewResult> ContinueWith<TNewResult> (Func<Task<TResult>, TNewResult> continuationFunction,
215                                                                   CancellationToken cancellationToken,
216                                                                   TaskContinuationOptions continuationOptions,
217                                                                   TaskScheduler scheduler)
218                 {
219                         if (continuationFunction == null)
220                                 throw new ArgumentNullException ("continuationFunction");
221                         if (scheduler == null)
222                                 throw new ArgumentNullException ("scheduler");
223
224                         Task<TNewResult> t = new Task<TNewResult> ((o) => continuationFunction ((Task<TResult>)o),
225                                                                    this,
226                                                                    cancellationToken,
227                                                                    GetCreationOptions (continuationOptions),
228                                                                    this);
229                         ContinueWithCore (t, continuationOptions, scheduler);
230                         
231                         return t;
232                 }
233                 
234 #if NET_4_5
235
236                 public Task ContinueWith (Action<Task<TResult>, object> continuationAction, object state)
237                 {
238                         return ContinueWith (continuationAction, state, CancellationToken.None, TaskContinuationOptions.None, TaskScheduler.Current);
239                 }
240
241                 public Task ContinueWith (Action<Task<TResult>, object> continuationAction, object state, CancellationToken cancellationToken)
242                 {
243                         return ContinueWith (continuationAction, state, cancellationToken, TaskContinuationOptions.None, TaskScheduler.Current);
244                 }
245
246                 public Task ContinueWith (Action<Task<TResult>, object> continuationAction, object state, TaskContinuationOptions continuationOptions)
247                 {
248                         return ContinueWith (continuationAction, state, CancellationToken.None, continuationOptions, TaskScheduler.Current);
249                 }
250
251                 public Task ContinueWith (Action<Task<TResult>, object> continuationAction, object state, TaskScheduler scheduler)
252                 {
253                         return ContinueWith (continuationAction, state, CancellationToken.None, TaskContinuationOptions.None, scheduler);
254                 }
255
256                 public Task ContinueWith (Action<Task<TResult>, object> continuationAction, object state, CancellationToken cancellationToken,
257                                                                   TaskContinuationOptions continuationOptions, TaskScheduler scheduler)
258                 {
259                         if (continuationAction == null)
260                                 throw new ArgumentNullException ("continuationAction");
261                         if (scheduler == null)
262                                 throw new ArgumentNullException ("scheduler");
263
264                         var t = new Task (l => continuationAction (this, l),
265                                                            state,
266                                                            cancellationToken,
267                                                            GetCreationOptions (continuationOptions),
268                                                            this);
269
270                         ContinueWithCore (t, continuationOptions, scheduler);
271
272                         return t;
273                 }
274
275                 public Task<TNewResult> ContinueWith<TNewResult> (Func<Task<TResult>, object, TNewResult> continuationFunction, object state)
276                 {
277                         return ContinueWith<TNewResult> (continuationFunction, state, CancellationToken.None, TaskContinuationOptions.None, TaskScheduler.Current);
278                 }
279
280                 public Task<TNewResult> ContinueWith<TNewResult> (Func<Task<TResult>, object, TNewResult> continuationFunction, object state, CancellationToken cancellationToken)
281                 {
282                         return ContinueWith<TNewResult> (continuationFunction, state, cancellationToken, TaskContinuationOptions.None, TaskScheduler.Current);
283                 }
284
285                 public Task<TNewResult> ContinueWith<TNewResult> (Func<Task<TResult>, object, TNewResult> continuationFunction, object state, TaskContinuationOptions continuationOptions)
286                 {
287                         return ContinueWith<TNewResult> (continuationFunction, state, CancellationToken.None, continuationOptions, TaskScheduler.Current);
288                 }
289
290                 public Task<TNewResult> ContinueWith<TNewResult> (Func<Task<TResult>, object, TNewResult> continuationFunction, object state, TaskScheduler scheduler)
291                 {
292                         return ContinueWith<TNewResult> (continuationFunction, state, CancellationToken.None, TaskContinuationOptions.None, scheduler);
293                 }
294
295                 public Task<TNewResult> ContinueWith<TNewResult> (Func<Task<TResult>, object, TNewResult> continuationFunction, object state,
296                                                                                                                   CancellationToken cancellationToken,
297                                                                                                                   TaskContinuationOptions continuationOptions,
298                                                                                                                   TaskScheduler scheduler)
299                 {
300                         if (continuationFunction == null)
301                                 throw new ArgumentNullException ("continuationFunction");
302                         if (scheduler == null)
303                                 throw new ArgumentNullException ("scheduler");
304
305                         var t = new Task<TNewResult> (l => continuationFunction (this, l),
306                                                            state,
307                                                            cancellationToken,
308                                                            GetCreationOptions (continuationOptions),
309                                                            this);
310
311                         ContinueWithCore (t, continuationOptions, scheduler);
312
313                         return t;
314                 }
315
316                 public new ConfiguredTaskAwaitable<TResult> ConfigureAwait (bool continueOnCapturedContext)
317                 {
318                         return new ConfiguredTaskAwaitable<TResult> (this, continueOnCapturedContext);
319                 }
320
321                 public new TaskAwaiter<TResult> GetAwaiter ()
322                 {
323                         return new TaskAwaiter<TResult> (this);
324                 }
325 #endif
326         }
327 }
328 #endif