| OLD | NEW |
| (Empty) |
| 1 // Copyright 2012 Google Inc. All Rights Reserved. | |
| 2 // Dart core library. | |
| 3 | |
| 4 class FutureImpl<T> implements Future<T> { | |
| 5 | |
| 6 bool _isComplete = false; | |
| 7 | |
| 8 /** | |
| 9 * Value that was provided to this Future by the Completer | |
| 10 */ | |
| 11 T _value; | |
| 12 | |
| 13 /** | |
| 14 * Exception that occured, if there was a problem providing | |
| 15 * Value. | |
| 16 */ | |
| 17 Object _exception; | |
| 18 | |
| 19 /** | |
| 20 * Stack trace associated with [_exception], if one was provided. | |
| 21 */ | |
| 22 Object _stackTrace; | |
| 23 | |
| 24 /** | |
| 25 * true, if any onException handler handled the exception. | |
| 26 */ | |
| 27 bool _exceptionHandled = false; | |
| 28 | |
| 29 /** | |
| 30 * Listeners waiting to receive the value of this future. | |
| 31 */ | |
| 32 final List<Function> _successListeners; | |
| 33 | |
| 34 /** | |
| 35 * Exception handlers waiting for exceptions. | |
| 36 */ | |
| 37 final List<Function> _exceptionHandlers; | |
| 38 | |
| 39 /** | |
| 40 * Listeners waiting to be called when the future completes. | |
| 41 */ | |
| 42 final List<Function> _completionListeners; | |
| 43 | |
| 44 FutureImpl() | |
| 45 : _successListeners = [], | |
| 46 _exceptionHandlers = [], | |
| 47 _completionListeners = []; | |
| 48 | |
| 49 factory FutureImpl.immediate(T value) { | |
| 50 final res = new FutureImpl(); | |
| 51 res._setValue(value); | |
| 52 return res; | |
| 53 } | |
| 54 | |
| 55 T get value() { | |
| 56 if (!isComplete) { | |
| 57 throw new FutureNotCompleteException(); | |
| 58 } | |
| 59 if (_exception !== null) { | |
| 60 throw _exception; | |
| 61 } | |
| 62 return _value; | |
| 63 } | |
| 64 | |
| 65 Object get exception() { | |
| 66 if (!isComplete) { | |
| 67 throw new FutureNotCompleteException(); | |
| 68 } | |
| 69 return _exception; | |
| 70 } | |
| 71 | |
| 72 Object get stackTrace() { | |
| 73 if (!isComplete) { | |
| 74 throw new FutureNotCompleteException(); | |
| 75 } | |
| 76 return _stackTrace; | |
| 77 } | |
| 78 | |
| 79 bool get isComplete() { | |
| 80 return _isComplete; | |
| 81 } | |
| 82 | |
| 83 bool get hasValue() { | |
| 84 return isComplete && _exception === null; | |
| 85 } | |
| 86 | |
| 87 void then(void onSuccess(T value)) { | |
| 88 if (hasValue) { | |
| 89 onSuccess(value); | |
| 90 } else if (!isComplete) { | |
| 91 _successListeners.add(onSuccess); | |
| 92 } else if (!_exceptionHandled) { | |
| 93 throw _exception; | |
| 94 } | |
| 95 } | |
| 96 | |
| 97 void handleException(bool onException(Object exception)) { | |
| 98 if (_exceptionHandled) return; | |
| 99 if (_isComplete) { | |
| 100 if (_exception != null) { | |
| 101 _exceptionHandled = onException(_exception); | |
| 102 } | |
| 103 } else { | |
| 104 _exceptionHandlers.add(onException); | |
| 105 } | |
| 106 } | |
| 107 | |
| 108 void onComplete(void complete(Future<T> future)) { | |
| 109 if (_isComplete) { | |
| 110 try { | |
| 111 complete(this); | |
| 112 } catch (e) {} | |
| 113 } else { | |
| 114 _completionListeners.add(complete); | |
| 115 } | |
| 116 } | |
| 117 | |
| 118 void _complete() { | |
| 119 _isComplete = true; | |
| 120 | |
| 121 try { | |
| 122 if (_exception !== null) { | |
| 123 for (Function handler in _exceptionHandlers) { | |
| 124 // Explicitly check for true here so that if the handler returns null, | |
| 125 // we don't get an exception in checked mode. | |
| 126 if (handler(_exception) == true) { | |
| 127 _exceptionHandled = true; | |
| 128 break; | |
| 129 } | |
| 130 } | |
| 131 } | |
| 132 | |
| 133 if (hasValue) { | |
| 134 for (Function listener in _successListeners) { | |
| 135 listener(value); | |
| 136 } | |
| 137 } else { | |
| 138 if (!_exceptionHandled && _successListeners.length > 0) { | |
| 139 throw _exception; | |
| 140 } | |
| 141 } | |
| 142 } finally { | |
| 143 for (Function listener in _completionListeners) { | |
| 144 try { | |
| 145 listener(this); | |
| 146 } catch (e) {} | |
| 147 } | |
| 148 } | |
| 149 } | |
| 150 | |
| 151 void _setValue(T value) { | |
| 152 if (_isComplete) { | |
| 153 throw new FutureAlreadyCompleteException(); | |
| 154 } | |
| 155 _value = value; | |
| 156 _complete(); | |
| 157 } | |
| 158 | |
| 159 void _setException(Object exception, Object stackTrace) { | |
| 160 if (exception === null) { | |
| 161 // null is not a legal value for the exception of a Future. | |
| 162 throw new IllegalArgumentException(null); | |
| 163 } | |
| 164 if (_isComplete) { | |
| 165 throw new FutureAlreadyCompleteException(); | |
| 166 } | |
| 167 _exception = exception; | |
| 168 _stackTrace = stackTrace; | |
| 169 _complete(); | |
| 170 } | |
| 171 | |
| 172 Future transform(Function transformation) { | |
| 173 final completer = new Completer(); | |
| 174 handleException((e) { | |
| 175 completer.completeException(e, this.stackTrace); | |
| 176 return true; | |
| 177 }); | |
| 178 then((v) { | |
| 179 var transformed = null; | |
| 180 try { | |
| 181 transformed = transformation(v); | |
| 182 } catch (ex, stackTrace) { | |
| 183 completer.completeException(ex, stackTrace); | |
| 184 return; | |
| 185 } | |
| 186 completer.complete(transformed); | |
| 187 }); | |
| 188 return completer.future; | |
| 189 } | |
| 190 | |
| 191 Future chain(Function transformation) { | |
| 192 final completer = new Completer(); | |
| 193 handleException((e) { | |
| 194 completer.completeException(e, this.stackTrace); | |
| 195 return true; | |
| 196 }); | |
| 197 then((v) { | |
| 198 var future = null; | |
| 199 try { | |
| 200 future = transformation(v); | |
| 201 } catch (ex, stackTrace) { | |
| 202 completer.completeException(ex, stackTrace); | |
| 203 return; | |
| 204 } | |
| 205 future.handleException((e) { | |
| 206 completer.completeException(e, future.stackTrace); | |
| 207 return true; | |
| 208 }); | |
| 209 future.then((b) => completer.complete(b)); | |
| 210 }); | |
| 211 return completer.future; | |
| 212 } | |
| 213 } | |
| 214 | |
| 215 class CompleterImpl<T> implements Completer<T> { | |
| 216 | |
| 217 final FutureImpl<T> _futureImpl; | |
| 218 | |
| 219 CompleterImpl() : _futureImpl = new FutureImpl() {} | |
| 220 | |
| 221 Future<T> get future() { | |
| 222 return _futureImpl; | |
| 223 } | |
| 224 | |
| 225 void complete(T value) { | |
| 226 _futureImpl._setValue(value); | |
| 227 } | |
| 228 | |
| 229 void completeException(Object exception, [Object stackTrace]) { | |
| 230 _futureImpl._setException(exception, stackTrace); | |
| 231 } | |
| 232 } | |
| OLD | NEW |