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 library dart.pkg.isolate.isolaterunner; | 5 library dart.pkg.isolate.isolaterunner; |
6 | 6 |
7 import "dart:isolate"; | 7 import "dart:isolate"; |
8 import "dart:async"; | 8 import "dart:async"; |
9 import "runner.dart"; | 9 import "runner.dart"; |
10 import "ports.dart"; | 10 import "ports.dart"; |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
52 * Create a new [Isolate], as by [Isolate.spawn] and wrap that. | 52 * Create a new [Isolate], as by [Isolate.spawn] and wrap that. |
53 * | 53 * |
54 * The returned [IsolateRunner] forwards operations to the new isolate, | 54 * The returned [IsolateRunner] forwards operations to the new isolate, |
55 * and keeps a port open in the new isolate that receives commands | 55 * and keeps a port open in the new isolate that receives commands |
56 * from the `IsolateRunner`. Remember to [close] the `IsolateRunner` when | 56 * from the `IsolateRunner`. Remember to [close] the `IsolateRunner` when |
57 * it's no longer needed. | 57 * it's no longer needed. |
58 */ | 58 */ |
59 static Future<IsolateRunner> spawn() { | 59 static Future<IsolateRunner> spawn() { |
60 Completer portCompleter = new Completer.sync(); | 60 Completer portCompleter = new Completer.sync(); |
61 SendPort initPort = singleCompletePort(portCompleter); | 61 SendPort initPort = singleCompletePort(portCompleter); |
62 return Isolate.spawn(IsolateRunnerRemote._create, initPort) | 62 return Isolate.spawn(IsolateRunnerRemote._create, initPort).then( |
63 .then((Isolate isolate) { | 63 (Isolate isolate) { |
Lasse Reichstein Nielsen
2015/02/26 10:59:14
Also has body less indented than its delimiter lin
| |
64 // TODO: Add when VM supports it. | 64 // TODO: Add when VM supports it. |
65 // isolate.setErrorsFatal(false); | 65 // isolate.setErrorsFatal(false); |
66 return portCompleter.future.then((SendPort commandPort) { | 66 return portCompleter.future.then((SendPort commandPort) { |
67 var result = new IsolateRunner(isolate, commandPort); | 67 var result = new IsolateRunner(isolate, commandPort); |
68 // Guarantees that setErrorsFatal has completed. | 68 // Guarantees that setErrorsFatal has completed. |
69 return result.ping().then((_) => result); | 69 return result.ping().then((_) => result); |
70 }); | 70 }); |
71 }); | 71 }); |
72 } | 72 } |
73 | 73 |
74 /** | 74 /** |
75 * Closes the `IsolateRunner` communication down. | 75 * Closes the `IsolateRunner` communication down. |
76 * | 76 * |
77 * If the isolate isn't running something else to keep it alive, | 77 * If the isolate isn't running something else to keep it alive, |
78 * this will also make the isolate shut down. | 78 * this will also make the isolate shut down. |
79 * | 79 * |
80 * Can be used to create an isolate, use [run] to start a service, and | 80 * Can be used to create an isolate, use [run] to start a service, and |
81 * then drop the connection and let the service control the isolate's | 81 * then drop the connection and let the service control the isolate's |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
131 * or doesn't answer within [timeout] for any other reason, | 131 * or doesn't answer within [timeout] for any other reason, |
132 * the returned future completes with `false`. | 132 * the returned future completes with `false`. |
133 * | 133 * |
134 * Guaranteed to only complete after all previous sent isolate commands | 134 * Guaranteed to only complete after all previous sent isolate commands |
135 * (like pause and resume) have been handled. | 135 * (like pause and resume) have been handled. |
136 * Paused isolates do respond to ping requests. | 136 * Paused isolates do respond to ping requests. |
137 */ | 137 */ |
138 Future<bool> ping({Duration timeout: const Duration(seconds: 1)}) { | 138 Future<bool> ping({Duration timeout: const Duration(seconds: 1)}) { |
139 Completer completer = new Completer<bool>(); | 139 Completer completer = new Completer<bool>(); |
140 SendPort port = singleCompletePort(completer, | 140 SendPort port = singleCompletePort(completer, |
141 callback: _kTrue, | 141 callback: _kTrue, timeout: timeout, onTimeout: _kFalse); |
Lasse Reichstein Nielsen
2015/02/26 10:59:13
I prefer the original.
| |
142 timeout: timeout, | |
143 onTimeout: _kFalse); | |
144 isolate.ping(port); | 142 isolate.ping(port); |
145 return completer.future; | 143 return completer.future; |
146 } | 144 } |
147 | 145 |
148 static bool _kTrue(_) => true; | 146 static bool _kTrue(_) => true; |
149 static bool _kFalse() => false; | 147 static bool _kFalse() => false; |
150 | 148 |
151 /** | 149 /** |
152 * Pauses the isolate. | 150 * Pauses the isolate. |
153 * | 151 * |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
197 * | 195 * |
198 * Example: | 196 * Example: |
199 * | 197 * |
200 * IsolateRunner iso = await IsolateRunner.spawn(); | 198 * IsolateRunner iso = await IsolateRunner.spawn(); |
201 * try { | 199 * try { |
202 * return await iso.run(heavyComputation, argument); | 200 * return await iso.run(heavyComputation, argument); |
203 * } finally { | 201 * } finally { |
204 * await iso.close(); | 202 * await iso.close(); |
205 * } | 203 * } |
206 */ | 204 */ |
207 Future run(function(argument), argument, | 205 Future run(function(argument), argument, {Duration timeout, onTimeout()}) { |
208 {Duration timeout, onTimeout()}) { | |
209 return singleResultFuture((SendPort port) { | 206 return singleResultFuture((SendPort port) { |
210 _commandPort.send( | 207 _commandPort |
211 list4(_RUN, FunctionRef.from(function), argument, port)); | 208 .send(list4(_RUN, FunctionRef.from(function), argument, port)); |
212 }, timeout: timeout, onTimeout: onTimeout); | 209 }, timeout: timeout, onTimeout: onTimeout); |
213 } | 210 } |
214 | 211 |
215 /** | 212 /** |
216 * A broadcast stream of uncaught errors from the isolate. | 213 * A broadcast stream of uncaught errors from the isolate. |
217 * | 214 * |
218 * When listening on the stream, errors from the isolate will be reported | 215 * When listening on the stream, errors from the isolate will be reported |
219 * as errors in the stream. Be ready to handle the errors. | 216 * as errors in the stream. Be ready to handle the errors. |
220 * | 217 * |
221 * The stream closes when the isolate shuts down. | 218 * The stream closes when the isolate shuts down. |
222 */ | 219 */ |
223 Stream get errors { | 220 Stream get errors { |
224 StreamController controller; | 221 StreamController controller; |
225 RawReceivePort port; | 222 RawReceivePort port; |
226 void handleError(message) { | 223 void handleError(message) { |
227 if (message == null) { | 224 if (message == null) { |
228 // Isolate shutdown. | 225 // Isolate shutdown. |
229 port.close(); | 226 port.close(); |
230 controller.close(); | 227 controller.close(); |
231 } else { | 228 } else { |
232 // Uncaught error. | 229 // Uncaught error. |
233 String errorDescription = message[0]; | 230 String errorDescription = message[0]; |
234 String stackDescription = message[1]; | 231 String stackDescription = message[1]; |
235 var error = new RemoteError(errorDescription, stackDescription); | 232 var error = new RemoteError(errorDescription, stackDescription); |
236 controller.addError(error, error.stackTrace); | 233 controller.addError(error, error.stackTrace); |
237 } | 234 } |
238 } | 235 } |
239 controller = new StreamController.broadcast( | 236 controller = new StreamController.broadcast(sync: true, onListen: () { |
240 sync: true, | 237 port = new RawReceivePort(handleError); |
241 onListen: () { | 238 // TODO: When supported, uncomment this. |
242 port = new RawReceivePort(handleError); | 239 // isolate.addErrorListener(port.sendPort); |
243 // TODO: When supported, uncomment this. | 240 // isolate.addOnExitListener(port.sendPort); |
244 // isolate.addErrorListener(port.sendPort); | 241 // And remove the send below, which acts as an immediate close. |
245 // isolate.addOnExitListener(port.sendPort); | 242 port.sendPort.send(null); |
246 // And remove the send below, which acts as an immediate close. | 243 }, onCancel: () { |
247 port.sendPort.send(null); | 244 port.close(); |
248 }, | 245 // this.removeErrorListener(port.sendPort); |
249 onCancel: () { | 246 // this.removeOnExitListener(port.sendPort); |
250 port.close(); | 247 port = null; |
251 // this.removeErrorListener(port.sendPort); | 248 }); |
Lasse Reichstein Nielsen
2015/02/26 10:59:13
Less consistently indented. I'd prefer the onListe
| |
252 // this.removeOnExitListener(port.sendPort); | |
253 port = null; | |
254 }); | |
255 return controller.stream; | 249 return controller.stream; |
256 } | 250 } |
257 | 251 |
258 /** | 252 /** |
259 * Waits for the [isolate] to terminate. | 253 * Waits for the [isolate] to terminate. |
260 * | 254 * |
261 * Completes the returned future when the isolate terminates. | 255 * Completes the returned future when the isolate terminates. |
262 * | 256 * |
263 * If the isolate has already stopped responding to commands, | 257 * If the isolate has already stopped responding to commands, |
264 * the returned future will never terminate. | 258 * the returned future will never terminate. |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
305 switch (command[0]) { | 299 switch (command[0]) { |
306 case _SHUTDOWN: | 300 case _SHUTDOWN: |
307 SendPort responsePort = command[1]; | 301 SendPort responsePort = command[1]; |
308 _commandPort.close(); | 302 _commandPort.close(); |
309 responsePort.send(null); | 303 responsePort.send(null); |
310 return; | 304 return; |
311 case _RUN: | 305 case _RUN: |
312 Function function = command[1].function; | 306 Function function = command[1].function; |
313 var argument = command[2]; | 307 var argument = command[2]; |
314 SendPort responsePort = command[3]; | 308 SendPort responsePort = command[3]; |
315 sendFutureResult(new Future.sync(() => function(argument)), | 309 sendFutureResult( |
316 responsePort); | 310 new Future.sync(() => function(argument)), responsePort); |
Lasse Reichstein Nielsen
2015/02/26 10:59:14
It's not as visible that responsePort is a second
| |
317 return; | 311 return; |
318 } | 312 } |
319 } | 313 } |
320 } | 314 } |
OLD | NEW |