Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 /** | 5 /** |
| 6 * Utility functions for setting up ports and sending data. | 6 * Utility functions for setting up ports and sending data. |
| 7 * | 7 * |
| 8 * This library contains a number of functions that handle the | 8 * This library contains a number of functions that handle the |
| 9 * boiler-plate of setting up a receive port and receiving a | 9 * boiler-plate of setting up a receive port and receiving a |
| 10 * single message on the port. | 10 * single message on the port. |
| (...skipping 28 matching lines...) Expand all Loading... | |
| 39 * | 39 * |
| 40 * Returns the `SendPort` expecting the single message. | 40 * Returns the `SendPort` expecting the single message. |
| 41 * | 41 * |
| 42 * Equivalent to: | 42 * Equivalent to: |
| 43 * | 43 * |
| 44 * (new ReceivePort() | 44 * (new ReceivePort() |
| 45 * ..first.timeout(duration, () => timeoutValue).then(callback)) | 45 * ..first.timeout(duration, () => timeoutValue).then(callback)) |
| 46 * .sendPort | 46 * .sendPort |
| 47 */ | 47 */ |
| 48 SendPort singleCallbackPort(void callback(response), | 48 SendPort singleCallbackPort(void callback(response), |
| 49 {Duration timeout, | 49 {Duration timeout, var timeoutValue}) { |
|
Lasse Reichstein Nielsen
2015/02/26 10:59:14
Indent '{' to after '('.
| |
| 50 var timeoutValue}) { | |
| 51 RawReceivePort responsePort = new RawReceivePort(); | 50 RawReceivePort responsePort = new RawReceivePort(); |
| 52 Zone zone = Zone.current; | 51 Zone zone = Zone.current; |
| 53 callback = zone.registerUnaryCallback(callback); | 52 callback = zone.registerUnaryCallback(callback); |
| 54 var timer; | 53 var timer; |
| 55 responsePort.handler = (response) { | 54 responsePort.handler = (response) { |
| 56 responsePort.close(); | 55 responsePort.close(); |
| 57 if (timer != null) timer.cancel(); | 56 if (timer != null) timer.cancel(); |
| 58 zone.runUnary(callback, response); | 57 zone.runUnary(callback, response); |
| 59 }; | 58 }; |
| 60 if (timeout != null) { | 59 if (timeout != null) { |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 87 * as long as the initial message is received in time. | 86 * as long as the initial message is received in time. |
| 88 * If `onTimeout` is omitted, it defaults to completing the `completer` with | 87 * If `onTimeout` is omitted, it defaults to completing the `completer` with |
| 89 * a [TimeoutException]. | 88 * a [TimeoutException]. |
| 90 * | 89 * |
| 91 * The [completer] may be a synchronous completer. It is only | 90 * The [completer] may be a synchronous completer. It is only |
| 92 * completed in response to another event, either a port message or a timer. | 91 * completed in response to another event, either a port message or a timer. |
| 93 * | 92 * |
| 94 * Returns the `SendPort` expecting the single message. | 93 * Returns the `SendPort` expecting the single message. |
| 95 */ | 94 */ |
| 96 SendPort singleCompletePort(Completer completer, | 95 SendPort singleCompletePort(Completer completer, |
| 97 {callback(message), | 96 {callback(message), Duration timeout, onTimeout()}) { |
|
Lasse Reichstein Nielsen
2015/02/26 10:59:14
Indent '{' to after '(' or put the completer on a
| |
| 98 Duration timeout, | |
| 99 onTimeout()}) { | |
| 100 if (callback == null && timeout == null) { | 97 if (callback == null && timeout == null) { |
| 101 return singleCallbackPort(completer.complete); | 98 return singleCallbackPort(completer.complete); |
| 102 } | 99 } |
| 103 RawReceivePort responsePort = new RawReceivePort(); | 100 RawReceivePort responsePort = new RawReceivePort(); |
| 104 var timer; | 101 var timer; |
| 105 if (callback == null) { | 102 if (callback == null) { |
| 106 responsePort.handler = (response) { | 103 responsePort.handler = (response) { |
| 107 responsePort.close(); | 104 responsePort.close(); |
| 108 if (timer != null) timer.cancel(); | 105 if (timer != null) timer.cancel(); |
| 109 completer.complete(response); | 106 completer.complete(response); |
| 110 }; | 107 }; |
| 111 } else { | 108 } else { |
| 112 Zone zone = Zone.current; | 109 Zone zone = Zone.current; |
| 113 Function action = zone.registerUnaryCallback((response) { | 110 Function action = zone.registerUnaryCallback((response) { |
| 114 completer.complete(new Future.sync(() => callback(response))); | 111 completer.complete(new Future.sync(() => callback(response))); |
| 115 }); | 112 }); |
| 116 responsePort.handler = (response) { | 113 responsePort.handler = (response) { |
| 117 responsePort.close(); | 114 responsePort.close(); |
| 118 if (timer != null) timer.cancel(); | 115 if (timer != null) timer.cancel(); |
| 119 zone.runUnary(action, response); | 116 zone.runUnary(action, response); |
| 120 }; | 117 }; |
| 121 } | 118 } |
| 122 if (timeout != null) { | 119 if (timeout != null) { |
| 123 timer = new Timer(timeout, () { | 120 timer = new Timer(timeout, () { |
| 124 responsePort.close(); | 121 responsePort.close(); |
| 125 if (onTimeout != null) { | 122 if (onTimeout != null) { |
| 126 completer.complete(new Future.sync(onTimeout)); | 123 completer.complete(new Future.sync(onTimeout)); |
| 127 } else { | 124 } else { |
| 128 completer.completeError(new TimeoutException("Future not completed", | 125 completer.completeError( |
| 129 timeout)); | 126 new TimeoutException("Future not completed", timeout)); |
| 130 } | 127 } |
| 131 }); | 128 }); |
| 132 } | 129 } |
| 133 return responsePort.sendPort; | 130 return responsePort.sendPort; |
| 134 } | 131 } |
| 135 | 132 |
| 136 /** | 133 /** |
| 137 * Creates a [Future], and a [SendPort] that can be used to complete that | 134 * Creates a [Future], and a [SendPort] that can be used to complete that |
| 138 * future. | 135 * future. |
| 139 * | 136 * |
| 140 * Calls [action] with the response `SendPort`, then waits for someone | 137 * Calls [action] with the response `SendPort`, then waits for someone |
| 141 * to send a value on that port | 138 * to send a value on that port |
| 142 * The returned `Future` is completed with the value sent on the port. | 139 * The returned `Future` is completed with the value sent on the port. |
| 143 * | 140 * |
| 144 * If [action] throws, which it shouldn't, | 141 * If [action] throws, which it shouldn't, |
| 145 * the returned future is completed with that error. | 142 * the returned future is completed with that error. |
| 146 * Any return value of `action` is ignored, and if it is asynchronous, | 143 * Any return value of `action` is ignored, and if it is asynchronous, |
| 147 * it should handle its own errors. | 144 * it should handle its own errors. |
| 148 * | 145 * |
| 149 * If [timeout] is supplied, it is used as a limit on how | 146 * If [timeout] is supplied, it is used as a limit on how |
| 150 * long it can take before the message is received. If a | 147 * long it can take before the message is received. If a |
| 151 * message isn't received in time, the [timeoutValue] used | 148 * message isn't received in time, the [timeoutValue] used |
| 152 * as the returned future's value instead. | 149 * as the returned future's value instead. |
| 153 * | 150 * |
| 154 * If you want a timeout on the returned future, it's recommended to | 151 * If you want a timeout on the returned future, it's recommended to |
| 155 * use the [timeout] parameter, and not [Future.timeout] on the result. | 152 * use the [timeout] parameter, and not [Future.timeout] on the result. |
| 156 * The `Future` method won't be able to close the underlying [ReceivePort]. | 153 * The `Future` method won't be able to close the underlying [ReceivePort]. |
| 157 */ | 154 */ |
| 158 Future singleResponseFuture(void action(SendPort responsePort), | 155 Future singleResponseFuture(void action(SendPort responsePort), |
| 159 {Duration timeout, | 156 {Duration timeout, var timeoutValue}) { |
|
Lasse Reichstein Nielsen
2015/02/26 10:59:14
Indentation again.
| |
| 160 var timeoutValue}) { | |
| 161 Completer completer = new Completer.sync(); | 157 Completer completer = new Completer.sync(); |
| 162 RawReceivePort responsePort = new RawReceivePort(); | 158 RawReceivePort responsePort = new RawReceivePort(); |
| 163 Timer timer; | 159 Timer timer; |
| 164 Zone zone = Zone.current; | 160 Zone zone = Zone.current; |
| 165 responsePort.handler = (v) { | 161 responsePort.handler = (v) { |
| 166 responsePort.close(); | 162 responsePort.close(); |
| 167 if (timer != null) timer.cancel(); | 163 if (timer != null) timer.cancel(); |
| 168 zone.run(() { | 164 zone.run(() { |
| 169 completer.complete(v); | 165 completer.complete(v); |
| 170 }); | 166 }); |
| 171 }; | 167 }; |
| 172 if (timeout != null) { | 168 if (timeout != null) { |
| 173 timer = new Timer(timeout, () { | 169 timer = new Timer(timeout, () { |
| 174 responsePort.close(); | 170 responsePort.close(); |
| 175 completer.complete(timeoutValue); | 171 completer.complete(timeoutValue); |
| 176 }); | 172 }); |
| 177 } | 173 } |
| 178 try { | 174 try { |
| 179 action(responsePort.sendPort); | 175 action(responsePort.sendPort); |
| 180 } catch (e, s) { | 176 } catch (e, s) { |
| 181 responsePort.close(); | 177 responsePort.close(); |
| 182 if (timer != null) timer.cancel(); | 178 if (timer != null) timer.cancel(); |
| 183 // Delay completion because completer is sync. | 179 // Delay completion because completer is sync. |
| 184 scheduleMicrotask(() { completer.completeError(e, s); }); | 180 scheduleMicrotask(() { |
| 181 completer.completeError(e, s); | |
| 182 }); | |
| 185 } | 183 } |
| 186 return completer.future; | 184 return completer.future; |
| 187 } | 185 } |
| 188 | 186 |
| 189 | |
| 190 /** | 187 /** |
| 191 * Send the result of a future, either value or error, as a message. | 188 * Send the result of a future, either value or error, as a message. |
| 192 * | 189 * |
| 193 * The result of [future] is sent on [resultPort] in a form expected by | 190 * The result of [future] is sent on [resultPort] in a form expected by |
| 194 * either [receiveFutureResult], [completeFutureResult], or | 191 * either [receiveFutureResult], [completeFutureResult], or |
| 195 * by the port of [singleResultFuture]. | 192 * by the port of [singleResultFuture]. |
| 196 */ | 193 */ |
| 197 void sendFutureResult(Future future, SendPort resultPort) { | 194 void sendFutureResult(Future future, SendPort resultPort) { |
| 198 future.then((v) { resultPort.send(list1(v)); }, | 195 future.then((v) { |
| 199 onError: (e, s) { resultPort.send(list2("$e", "$s")); }); | 196 resultPort.send(list1(v)); |
| 197 }, onError: (e, s) { | |
| 198 resultPort.send(list2("$e", "$s")); | |
| 199 }); | |
| 200 } | 200 } |
| 201 | 201 |
| 202 | |
| 203 /** | 202 /** |
| 204 * Creates a [Future], and a [SendPort] that can be used to complete that | 203 * Creates a [Future], and a [SendPort] that can be used to complete that |
| 205 * future. | 204 * future. |
| 206 * | 205 * |
| 207 * Calls [action] with the response `SendPort`, then waits for someone | 206 * Calls [action] with the response `SendPort`, then waits for someone |
| 208 * to send a future result on that port using [sendFutureResult]. | 207 * to send a future result on that port using [sendFutureResult]. |
| 209 * The returned `Future` is completed with the future result sent on the port. | 208 * The returned `Future` is completed with the future result sent on the port. |
| 210 * | 209 * |
| 211 * If [action] throws, which it shouldn't, | 210 * If [action] throws, which it shouldn't, |
| 212 * the returned future is completed with that error, | 211 * the returned future is completed with that error, |
| 213 * unless someone manages to send a message on the port before `action` throws. | 212 * unless someone manages to send a message on the port before `action` throws. |
| 214 * | 213 * |
| 215 * If [timeout] is supplied, it is used as a limit on how | 214 * If [timeout] is supplied, it is used as a limit on how |
| 216 * long it can take before the message is received. If a | 215 * long it can take before the message is received. If a |
| 217 * message isn't received in time, the [onTimeout] is called, | 216 * message isn't received in time, the [onTimeout] is called, |
| 218 * and the future is completed with the result of that call | 217 * and the future is completed with the result of that call |
| 219 * instead. | 218 * instead. |
| 220 * If `onTimeout` is omitted, it defaults to throwing | 219 * If `onTimeout` is omitted, it defaults to throwing |
| 221 * a [TimeoutException]. | 220 * a [TimeoutException]. |
| 222 */ | 221 */ |
| 223 Future singleResultFuture(void action(SendPort responsePort), | 222 Future singleResultFuture(void action(SendPort responsePort), |
| 224 {Duration timeout, | 223 {Duration timeout, onTimeout()}) { |
|
Lasse Reichstein Nielsen
2015/02/26 10:59:14
Indent '{'.
| |
| 225 onTimeout()}) { | |
| 226 Completer completer = new Completer.sync(); | 224 Completer completer = new Completer.sync(); |
| 227 SendPort port = singleCompletePort(completer, | 225 SendPort port = singleCompletePort(completer, |
| 228 callback: receiveFutureResult, | 226 callback: receiveFutureResult, timeout: timeout, onTimeout: onTimeout); |
|
Lasse Reichstein Nielsen
2015/02/26 10:59:14
Put completer on a new line too, or indent as orig
| |
| 229 timeout: timeout, | |
| 230 onTimeout: onTimeout); | |
| 231 try { | 227 try { |
| 232 action(port); | 228 action(port); |
| 233 } catch (e, s) { | 229 } catch (e, s) { |
| 234 // This should not happen. | 230 // This should not happen. |
| 235 sendFutureResult(new Future.error(e, s), port); | 231 sendFutureResult(new Future.error(e, s), port); |
| 236 } | 232 } |
| 237 return completer.future; | 233 return completer.future; |
| 238 } | 234 } |
| 239 | 235 |
| 240 /** | 236 /** |
| 241 * Completes a completer with a message created by [sendFutureResult] | 237 * Completes a completer with a message created by [sendFutureResult] |
| 242 * | 238 * |
| 243 * The [response] must be a message on the format sent by [sendFutureResult]. | 239 * The [response] must be a message on the format sent by [sendFutureResult]. |
| 244 */ | 240 */ |
| 245 void completeFutureResult(var response, Completer completer) { | 241 void completeFutureResult(var response, Completer completer) { |
| 246 if (response.length == 2) { | 242 if (response.length == 2) { |
| 247 var error = new RemoteError(response[0], response[1]); | 243 var error = new RemoteError(response[0], response[1]); |
| 248 completer.completeError(error, error.stackTrace); | 244 completer.completeError(error, error.stackTrace); |
| 249 } else { | 245 } else { |
| 250 var result = response[0]; | 246 var result = response[0]; |
| 251 completer.complete(result); | 247 completer.complete(result); |
| 252 } | 248 } |
| 253 } | 249 } |
| 254 | 250 |
| 255 | |
|
Lasse Reichstein Nielsen
2015/02/26 10:59:14
I'm not sure I always want single lines between fu
| |
| 256 /** | 251 /** |
| 257 * Convertes a received message created by [sendFutureResult] to a future | 252 * Convertes a received message created by [sendFutureResult] to a future |
| 258 * result. | 253 * result. |
| 259 * | 254 * |
| 260 * The [response] must be a message on the format sent by [sendFutureResult]. | 255 * The [response] must be a message on the format sent by [sendFutureResult]. |
| 261 */ | 256 */ |
| 262 Future receiveFutureResult(var response) { | 257 Future receiveFutureResult(var response) { |
| 263 if (response.length == 2) { | 258 if (response.length == 2) { |
| 264 var error = new RemoteError(response[0], response[1]); | 259 var error = new RemoteError(response[0], response[1]); |
| 265 return new Future.error(error, error.stackTrace); | 260 return new Future.error(error, error.stackTrace); |
| 266 } | 261 } |
| 267 var result = response[0]; | 262 var result = response[0]; |
| 268 return new Future.value(result); | 263 return new Future.value(result); |
| 269 } | 264 } |
| OLD | NEW |