2010-01-20 Zoltan Varga <vargaz@gmail.com>
[mono.git] / mcs / class / corlib / System.Threading.Tasks / TaskCompletionSource.cs
1 #if NET_4_0
2 // 
3 // TaskCompletionSource.cs
4 //  
5 // Author:
6 //       Jérémie "Garuma" Laval <jeremie.laval@gmail.com>
7 // 
8 // Copyright (c) 2009 Jérémie "Garuma" Laval
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 using System;
29
30 namespace System.Threading.Tasks
31 {
32         public class TaskCompletionSource<TResult>
33         {
34                 Task<TResult> source;
35
36                 public TaskCompletionSource ()
37                 {
38                         source = new Task<TResult> (null);
39                 }
40                 
41                 public TaskCompletionSource (object state)
42                 {
43                         source = new Task<TResult> (null, state);
44                 }
45                 
46                 public TaskCompletionSource (TaskCreationOptions options)
47                 {
48                         source = new Task<TResult> (null, options);
49                 }
50                 
51                 public TaskCompletionSource (object state, TaskCreationOptions options)
52                 {
53                         source = new Task<TResult> (null, state, options);
54                 }
55                 
56                 public void SetCanceled ()
57                 {
58                         if (!ApplyOperation (TaskStatus.Canceled, () => { source.Cancel (); source.CancelReal (); }))
59                                 ThrowInvalidException ();
60                 }
61                 
62                 public void SetException (Exception e)
63                 {
64                         if (!ApplyOperation (TaskStatus.Faulted, () => source.Exception = e))
65                                 ThrowInvalidException ();
66                 }
67                 
68                 public void SetResult (TResult result)
69                 {
70                         if (!ApplyOperation (TaskStatus.RanToCompletion, () => source.Result = result))
71                                 ThrowInvalidException ();
72                 }
73                                 
74                 void ThrowInvalidException ()
75                 {
76                         throw new InvalidOperationException ("The underlying Task is already in one of the three final states: RanToCompletion, Faulted, or Canceled.");
77                 }
78                 
79                 public bool TrySetCanceled ()
80                 {
81                         return ApplyOperation (TaskStatus.Canceled, () => { source.Cancel (); source.CancelReal (); });
82                 }
83                 
84                 public bool TrySetException (Exception e)
85                 {
86                         return ApplyOperation (TaskStatus.Faulted, () => source.Exception = e);
87                 }
88                 
89                 public bool TrySetResult (TResult result)
90                 {
91                         return ApplyOperation (TaskStatus.RanToCompletion, () => source.Result = result);
92                 }
93                                 
94                 bool ApplyOperation (TaskStatus newStatus, Action action)
95                 {
96                         if (CheckInvalidState ())
97                                 return false;
98                         
99                         if (action != null)
100                                 action ();
101                         source.Status = newStatus;
102                         
103                         return true;
104                 }
105                 
106                 bool CheckInvalidState ()
107                 {
108                         return source.Status == TaskStatus.RanToCompletion ||
109                                    source.Status == TaskStatus.Faulted || 
110                                    source.Status == TaskStatus.Canceled;
111                                         
112                 }
113                 
114                 public Task<TResult> Task {
115                         get {
116                                 return source;
117                         }
118                 }
119         }
120 }
121 #endif