Fix more argument checking for Task<T>
[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                 internal static new readonly Task<TResult> Canceled = new Task<TResult> (TaskStatus.Canceled);
41                 static readonly TaskFactory<TResult> factory = new TaskFactory<TResult> ();
42
43                 TResult value;
44                 internal Func<object, TResult> function;
45                 object state;
46                 
47                 [System.Diagnostics.DebuggerBrowsable (System.Diagnostics.DebuggerBrowsableState.Never)]
48                 public TResult Result {
49                         get {
50                                 if (function != null)
51                                         Wait ();
52                                 else if (Exception != null)
53                                         throw Exception;
54                                 return value;
55                         }
56                         internal set {
57                                 this.value = value;
58                         }
59                 }
60
61                 string ResultAsString {
62                         get {
63                                 if ((Status & (TaskStatus.RanToCompletion)) != 0)
64                                         return "" + value;
65                                 
66                                 return "<value not available>";
67                         }
68                 }
69                 
70                 public static new TaskFactory<TResult> Factory {
71                         get {
72                                 return factory;
73                         }
74                 }
75                 
76                 public Task (Func<TResult> function) : this (function, TaskCreationOptions.None)
77                 {
78                         
79                 }
80                 
81                 public Task (Func<TResult> function, CancellationToken cancellationToken)
82                         : this (function == null ? (Func<object, TResult>)null : (o) => function(), null, cancellationToken, TaskCreationOptions.None)
83                 {
84                         
85                 }
86                 
87                 public Task (Func<TResult> function, TaskCreationOptions creationOptions)
88                         : this (function == null ? (Func<object, TResult>)null : (o) => function(), null, CancellationToken.None, creationOptions)
89                 {
90                         
91                 }
92                 
93                 public Task (Func<TResult> function, CancellationToken cancellationToken, TaskCreationOptions creationOptions)
94                         : this (function == null ? (Func<object, TResult>)null : (o) => function(), null, cancellationToken, creationOptions)
95                 {
96                         
97                 }
98                 
99                 public Task (Func<object, TResult> function, object state) : this (function, state, TaskCreationOptions.None)
100                 {
101                         
102                 }
103                 
104                 public Task (Func<object, TResult> function, object state, CancellationToken cancellationToken)
105                         : this (function, state, cancellationToken, TaskCreationOptions.None)
106                 {
107                         
108                 }
109                 
110                 public Task (Func<object, TResult> function, object state, TaskCreationOptions creationOptions)
111                         : this (function, state, CancellationToken.None, creationOptions)
112                 {
113                         
114                 }
115
116                 public Task (Func<object, TResult> function, object state, CancellationToken cancellationToken, TaskCreationOptions creationOptions)
117                         : base (delegate { }, state, cancellationToken, creationOptions)
118                 {
119                         if (function == null)
120                                 throw new ArgumentNullException ("function");
121
122                         this.function = function;
123                         this.state = state;
124                 }
125
126                 internal Task (Func<object, TResult> function,
127                                object state,
128                                CancellationToken cancellationToken,
129                                TaskCreationOptions creationOptions,
130                                Task parent)
131                         : base (emptyAction, state, cancellationToken, creationOptions, parent)
132                 {
133                         this.function = function;
134                         this.state = state;
135                 }
136
137
138                 internal Task (TaskStatus status)
139                         : base (status)
140                 {
141                 }
142                 
143                 internal override void InnerInvoke ()
144                 {
145                         if (function != null)
146                                 value = function (state);
147                         
148                         function = null;
149                         state = null;
150                 }
151                 
152                 public Task ContinueWith (Action<Task<TResult>> continuationAction)
153                 {
154                         return ContinueWith (continuationAction, TaskContinuationOptions.None);
155                 }
156                 
157                 public Task ContinueWith (Action<Task<TResult>> continuationAction, TaskContinuationOptions continuationOptions)
158                 {
159                         return ContinueWith (continuationAction, CancellationToken.None, continuationOptions, TaskScheduler.Current);
160                 }
161                 
162                 public Task ContinueWith (Action<Task<TResult>> continuationAction, CancellationToken cancellationToken)
163                 {
164                         return ContinueWith (continuationAction, cancellationToken, TaskContinuationOptions.None, TaskScheduler.Current);
165                 }
166                 
167                 public Task ContinueWith (Action<Task<TResult>> continuationAction, TaskScheduler scheduler)
168                 {
169                         return ContinueWith (continuationAction, CancellationToken.None, TaskContinuationOptions.None, scheduler);
170                 }
171                 
172                 public Task ContinueWith (Action<Task<TResult>> continuationAction, CancellationToken cancellationToken,
173                                           TaskContinuationOptions continuationOptions, TaskScheduler scheduler)
174                 {
175                         if (continuationAction == null)
176                                 throw new ArgumentNullException ("continuationAction");
177                         if (scheduler == null)
178                                 throw new ArgumentNullException ("scheduler");
179
180                         Task t = new Task (l => continuationAction ((Task<TResult>)l),
181                                            this,
182                                            cancellationToken,
183                                            GetCreationOptions (continuationOptions),
184                                            this);
185                         ContinueWithCore (t, continuationOptions, scheduler);
186                         
187                         return t;
188                 }
189
190                 public Task<TNewResult> ContinueWith<TNewResult> (Func<Task<TResult>, TNewResult> continuationFunction)
191                 {
192                         return ContinueWith<TNewResult> (continuationFunction, CancellationToken.None, TaskContinuationOptions.None, TaskScheduler.Current);
193                 }
194                 
195                 public Task<TNewResult> ContinueWith<TNewResult> (Func<Task<TResult>, TNewResult> continuationFunction, CancellationToken cancellationToken)
196                 {
197                         return ContinueWith<TNewResult> (continuationFunction, cancellationToken, TaskContinuationOptions.None, TaskScheduler.Current);
198                 }
199                 
200                 public Task<TNewResult> ContinueWith<TNewResult> (Func<Task<TResult>, TNewResult> continuationFunction, TaskContinuationOptions continuationOptions)
201                 {
202                         return ContinueWith<TNewResult> (continuationFunction, CancellationToken.None, continuationOptions, TaskScheduler.Current);
203                 }
204                 
205                 public Task<TNewResult> ContinueWith<TNewResult> (Func<Task<TResult>, TNewResult> continuationFunction, TaskScheduler scheduler)
206                 {
207                         return ContinueWith<TNewResult> (continuationFunction, CancellationToken.None, TaskContinuationOptions.None, scheduler);
208                 }
209                 
210                 public Task<TNewResult> ContinueWith<TNewResult> (Func<Task<TResult>, TNewResult> continuationFunction,
211                                                                   CancellationToken cancellationToken,
212                                                                   TaskContinuationOptions continuationOptions,
213                                                                   TaskScheduler scheduler)
214                 {
215                         if (continuationFunction == null)
216                                 throw new ArgumentNullException ("continuationFunction");
217                         if (scheduler == null)
218                                 throw new ArgumentNullException ("scheduler");
219
220                         Task<TNewResult> t = new Task<TNewResult> ((o) => continuationFunction ((Task<TResult>)o),
221                                                                    this,
222                                                                    cancellationToken,
223                                                                    GetCreationOptions (continuationOptions),
224                                                                    this);
225                         ContinueWithCore (t, continuationOptions, scheduler);
226                         
227                         return t;
228                 }
229                 
230 #if NET_4_5
231
232                 public Task ContinueWith (Action<Task<TResult>, object> continuationAction, object state)
233                 {
234                         return ContinueWith (continuationAction, state, CancellationToken.None, TaskContinuationOptions.None, TaskScheduler.Current);
235                 }
236
237                 public Task ContinueWith (Action<Task<TResult>, object> continuationAction, object state, CancellationToken cancellationToken)
238                 {
239                         return ContinueWith (continuationAction, state, cancellationToken, TaskContinuationOptions.None, TaskScheduler.Current);
240                 }
241
242                 public Task ContinueWith (Action<Task<TResult>, object> continuationAction, object state, TaskContinuationOptions continuationOptions)
243                 {
244                         return ContinueWith (continuationAction, state, CancellationToken.None, continuationOptions, TaskScheduler.Current);
245                 }
246
247                 public Task ContinueWith (Action<Task<TResult>, object> continuationAction, object state, TaskScheduler scheduler)
248                 {
249                         return ContinueWith (continuationAction, state, CancellationToken.None, TaskContinuationOptions.None, scheduler);
250                 }
251
252                 public Task ContinueWith (Action<Task<TResult>, object> continuationAction, object state, CancellationToken cancellationToken,
253                                                                   TaskContinuationOptions continuationOptions, TaskScheduler scheduler)
254                 {
255                         if (continuationAction == null)
256                                 throw new ArgumentNullException ("continuationAction");
257                         if (scheduler == null)
258                                 throw new ArgumentNullException ("scheduler");
259
260                         var t = new Task (l => continuationAction (this, l),
261                                                            state,
262                                                            cancellationToken,
263                                                            GetCreationOptions (continuationOptions),
264                                                            this);
265
266                         ContinueWithCore (t, continuationOptions, scheduler);
267
268                         return t;
269                 }
270
271                 public Task<TNewResult> ContinueWith<TNewResult> (Func<Task<TResult>, object, TNewResult> continuationFunction, object state)
272                 {
273                         return ContinueWith<TNewResult> (continuationFunction, state, CancellationToken.None, TaskContinuationOptions.None, TaskScheduler.Current);
274                 }
275
276                 public Task<TNewResult> ContinueWith<TNewResult> (Func<Task<TResult>, object, TNewResult> continuationFunction, object state, CancellationToken cancellationToken)
277                 {
278                         return ContinueWith<TNewResult> (continuationFunction, state, cancellationToken, TaskContinuationOptions.None, TaskScheduler.Current);
279                 }
280
281                 public Task<TNewResult> ContinueWith<TNewResult> (Func<Task<TResult>, object, TNewResult> continuationFunction, object state, TaskContinuationOptions continuationOptions)
282                 {
283                         return ContinueWith<TNewResult> (continuationFunction, state, CancellationToken.None, continuationOptions, TaskScheduler.Current);
284                 }
285
286                 public Task<TNewResult> ContinueWith<TNewResult> (Func<Task<TResult>, object, TNewResult> continuationFunction, object state, TaskScheduler scheduler)
287                 {
288                         return ContinueWith<TNewResult> (continuationFunction, state, CancellationToken.None, TaskContinuationOptions.None, scheduler);
289                 }
290
291                 public Task<TNewResult> ContinueWith<TNewResult> (Func<Task<TResult>, object, TNewResult> continuationFunction, object state,
292                                                                                                                   CancellationToken cancellationToken,
293                                                                                                                   TaskContinuationOptions continuationOptions,
294                                                                                                                   TaskScheduler scheduler)
295                 {
296                         if (continuationFunction == null)
297                                 throw new ArgumentNullException ("continuationFunction");
298                         if (scheduler == null)
299                                 throw new ArgumentNullException ("scheduler");
300
301                         var t = new Task<TNewResult> (l => continuationFunction (this, l),
302                                                            state,
303                                                            cancellationToken,
304                                                            GetCreationOptions (continuationOptions),
305                                                            this);
306
307                         ContinueWithCore (t, continuationOptions, scheduler);
308
309                         return t;
310                 }
311
312                 public new ConfiguredTaskAwaitable<TResult> ConfigureAwait (bool continueOnCapturedContext)
313                 {
314                         return new ConfiguredTaskAwaitable<TResult> (this, continueOnCapturedContext);
315                 }
316
317                 public new TaskAwaiter<TResult> GetAwaiter ()
318                 {
319                         return new TaskAwaiter<TResult> (this);
320                 }
321 #endif
322         }
323 }
324 #endif