Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(799)

Side by Side Diff: corelib/src/implementation/future_implementation.dart

Issue 10517006: Adds a callback to Future that is invoked upon completion, whether success or failure. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright 2012 Google Inc. All Rights Reserved. 1 // Copyright 2012 Google Inc. All Rights Reserved.
2 // Dart core library. 2 // Dart core library.
3 3
4 class FutureImpl<T> implements Future<T> { 4 class FutureImpl<T> implements Future<T> {
5 5
6 bool _isComplete = false; 6 bool _isComplete = false;
7 7
8 /** 8 /**
9 * Value that was provided to this Future by the Completer 9 * Value that was provided to this Future by the Completer
10 */ 10 */
11 T _value; 11 T _value;
12 12
13 /** 13 /**
14 * Exception that occured, if there was a problem providing 14 * Exception that occured, if there was a problem providing
15 * Value. 15 * Value.
16 */ 16 */
17 Object _exception; 17 Object _exception;
18 18
19 /** 19 /**
20 * true, if any onException handler handled the exception. 20 * true, if any onException handler handled the exception.
21 */ 21 */
22 bool _exceptionHandled = false; 22 bool _exceptionHandled = false;
23 23
24 /** 24 /**
25 * Listeners waiting to receive the value of this future. 25 * Listeners waiting to receive the value of this future.
26 */ 26 */
27 final List<Function> _listeners; 27 final List<Function> _successListeners;
28 28
29 /** 29 /**
30 * Exception handlers waiting for exceptions. 30 * Exception handlers waiting for exceptions.
31 */ 31 */
32 final List<Function> _exceptionHandlers; 32 final List<Function> _exceptionHandlers;
33 33
34 /**
35 * Listeners waiting to be called when the future completes.
36 */
37 final List<Function> _completionListeners;
38
34 FutureImpl() 39 FutureImpl()
35 : _listeners = [], 40 : _successListeners = [],
36 _exceptionHandlers = []; 41 _exceptionHandlers = [],
42 _completionListeners = [];
37 43
38 factory FutureImpl.immediate(T value) { 44 factory FutureImpl.immediate(T value) {
39 final res = new FutureImpl(); 45 final res = new FutureImpl();
40 res._setValue(value); 46 res._setValue(value);
41 return res; 47 return res;
42 } 48 }
43 49
44 T get value() { 50 T get value() {
45 if (!isComplete) { 51 if (!isComplete) {
46 throw new FutureNotCompleteException(); 52 throw new FutureNotCompleteException();
(...skipping 12 matching lines...) Expand all
59 } 65 }
60 66
61 bool get isComplete() { 67 bool get isComplete() {
62 return _isComplete; 68 return _isComplete;
63 } 69 }
64 70
65 bool get hasValue() { 71 bool get hasValue() {
66 return isComplete && _exception === null; 72 return isComplete && _exception === null;
67 } 73 }
68 74
69 void then(void onComplete(T value)) { 75 void then(void onSuccess(T value)) {
70 if (hasValue) { 76 if (hasValue) {
71 onComplete(value); 77 onSuccess(value);
72 } else if (!isComplete) { 78 } else if (!isComplete) {
73 _listeners.add(onComplete); 79 _successListeners.add(onSuccess);
74 } else if (!_exceptionHandled) { 80 } else if (!_exceptionHandled) {
75 throw _exception; 81 throw _exception;
76 } 82 }
77 } 83 }
78 84
79 void handleException(bool onException(Object exception)) { 85 void handleException(bool onException(Object exception)) {
80 if (_exceptionHandled) return; 86 if (_exceptionHandled) return;
81 if (_isComplete) { 87 if (_isComplete) {
82 if (_exception != null) { 88 if (_exception != null) {
83 _exceptionHandled = onException(_exception); 89 _exceptionHandled = onException(_exception);
84 } 90 }
85 } else { 91 } else {
86 _exceptionHandlers.add(onException); 92 _exceptionHandlers.add(onException);
87 } 93 }
88 } 94 }
89 95
96 void onComplete(void complete(Future<T> future)) {
97 if (_isComplete) {
98 try {
99 complete(this);
100 } catch (final e) {}
101 } else {
102 _completionListeners.add(complete);
103 }
104 }
105
90 void _complete() { 106 void _complete() {
91 _isComplete = true; 107 _isComplete = true;
108
109 for (Function listener in _completionListeners) {
Jennifer Messerly 2012/06/04 20:11:17 shouldn't this come after we run _exceptionHandler
Bob Nystrom 2012/06/04 20:20:40 +1
sam.mccall 2012/06/04 21:35:57 Yeah, that's probably less surprising. When e.g. a
110 try {
111 listener(this);
112 } catch (final e) {}
113 }
114
92 if (_exception !== null) { 115 if (_exception !== null) {
93 for (Function handler in _exceptionHandlers) { 116 for (Function handler in _exceptionHandlers) {
94 // Explicitly check for true here so that if the handler returns null, 117 // Explicitly check for true here so that if the handler returns null,
95 // we don't get an exception in checked mode. 118 // we don't get an exception in checked mode.
96 if (handler(_exception) == true) { 119 if (handler(_exception) == true) {
97 _exceptionHandled = true; 120 _exceptionHandled = true;
98 break; 121 break;
99 } 122 }
100 } 123 }
101 } 124 }
102 125
103 if (hasValue) { 126 if (hasValue) {
104 for (Function listener in _listeners) { 127 for (Function listener in _successListeners) {
105 listener(value); 128 listener(value);
106 } 129 }
107 } else { 130 } else {
108 if (!_exceptionHandled && _listeners.length > 0) { 131 if (!_exceptionHandled && _successListeners.length > 0) {
109 throw _exception; 132 throw _exception;
110 } 133 }
111 } 134 }
112 } 135 }
113 136
114 void _setValue(T value) { 137 void _setValue(T value) {
115 if (_isComplete) { 138 if (_isComplete) {
116 throw new FutureAlreadyCompleteException(); 139 throw new FutureAlreadyCompleteException();
117 } 140 }
118 _value = value; 141 _value = value;
119 _complete(); 142 _complete();
120 } 143 }
121 144
122 void _setException(var exception) { 145 void _setException(var exception) {
123 if (exception === null) { 146 if (exception === null) {
124 // null is not a legal value for the exception of a Future 147 // null is not a legal value for the exception of a Future
125 throw new IllegalArgumentException(null); 148 throw new IllegalArgumentException(null);
126 } 149 }
127 if (_isComplete) { 150 if (_isComplete) {
128 throw new FutureAlreadyCompleteException(); 151 throw new FutureAlreadyCompleteException();
129 } 152 }
130 _exception = exception; 153 _exception = exception;
131 _complete(); 154 _complete();
132 } 155 }
133 156
134 Future transform(Function transformation) { 157 Future transform(Function transformation) {
135 final completer = new Completer(); 158 final completer = new Completer();
136 handleException((e) { 159 this.onComplete((f) {
Jennifer Messerly 2012/06/04 20:11:17 do you need "this." here?
sam.mccall 2012/06/04 21:35:57 Nope, oops
137 completer.completeException(e); 160 if (!f.hasValue) {
138 return true; 161 completer.completeException(f.exception);
139 }); 162 return;
140 then((v) { 163 }
141 var transformed = null; 164 var transformed = null;
142 try { 165 try {
143 transformed = transformation(v); 166 transformed = transformation(f.value);
144 } catch (final e) { 167 } catch (final e) {
145 completer.completeException(e); 168 completer.completeException(e);
146 return; 169 return;
147 } 170 }
148 completer.complete(transformed); 171 completer.complete(transformed);
149 }); 172 });
150 return completer.future; 173 return completer.future;
151 } 174 }
152 175
153 Future chain(Function transformation) { 176 Future chain(Function transformation) {
154 final completer = new Completer(); 177 final completer = new Completer();
155 handleException((e) { 178 onComplete((f) {
156 completer.completeException(e); 179 if (!f.hasValue) {
157 return true; 180 completer.completeException(f.exception);
158 }); 181 return;
159 then((v) { 182 }
160 var future = null; 183 var future = null;
161 try { 184 try {
162 future = transformation(v); 185 future = transformation(f.value);
163 } catch (final e) { 186 } catch (final e) {
164 completer.completeException(e); 187 completer.completeException(e);
165 return; 188 return;
166 } 189 }
167 future.handleException((e) { 190 future.onComplete((g) {
168 completer.completeException(e); 191 if (g.hasValue) completer.complete(g.value);
169 return true; 192 else completer.completeException(g.exception);
Jennifer Messerly 2012/06/04 20:22:28 This is interesting ... it almost suggests we shou
sam.mccall 2012/06/04 21:35:57 Yeah, I can't see any obvious other uses, so I'm n
Jennifer Messerly 2012/06/04 22:12:49 sgtm
170 }); 193 });
171 future.then((b) => completer.complete(b));
172 }); 194 });
173 return completer.future; 195 return completer.future;
174 } 196 }
175 } 197 }
176 198
177 class CompleterImpl<T> implements Completer<T> { 199 class CompleterImpl<T> implements Completer<T> {
178 200
179 final FutureImpl<T> _futureImpl; 201 final FutureImpl<T> _futureImpl;
180 202
181 CompleterImpl() : _futureImpl = new FutureImpl() {} 203 CompleterImpl() : _futureImpl = new FutureImpl() {}
182 204
183 Future<T> get future() { 205 Future<T> get future() {
184 return _futureImpl; 206 return _futureImpl;
185 } 207 }
186 208
187 void complete(T value) { 209 void complete(T value) {
188 _futureImpl._setValue(value); 210 _futureImpl._setValue(value);
189 } 211 }
190 212
191 void completeException(var exception) { 213 void completeException(var exception) {
192 _futureImpl._setException(exception); 214 _futureImpl._setException(exception);
193 } 215 }
194 } 216 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698