OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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 * Concurrent programming using _isolates_: | 6 * Concurrent programming using _isolates_: |
7 * independent workers that are similar to threads | 7 * independent workers that are similar to threads |
8 * but don't share memory, | 8 * but don't share memory, |
9 * communicating only via messages. | 9 * communicating only via messages. |
10 * | 10 * |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
43 * object representing the new isolate when the spawn operation succeeds. | 43 * object representing the new isolate when the spawn operation succeeds. |
44 * | 44 * |
45 * Isolates run code in its own event loop, and each event may run smaller tasks | 45 * Isolates run code in its own event loop, and each event may run smaller tasks |
46 * in a nested microtask queue. | 46 * in a nested microtask queue. |
47 * | 47 * |
48 * An `Isolate` object allows other isolates to control the event loop | 48 * An `Isolate` object allows other isolates to control the event loop |
49 * of the isolate that it represents, and to inspect the isolate, | 49 * of the isolate that it represents, and to inspect the isolate, |
50 * for example by pausing the isolate or by getting events when the isolate | 50 * for example by pausing the isolate or by getting events when the isolate |
51 * has an uncaught error. | 51 * has an uncaught error. |
52 * | 52 * |
53 * The [controlPort] gives access to controlling the isolate, and the | 53 * The [controlPort] identifies and gives access to controlling the isolate, |
54 * [pauseCapability] and [terminateCapability] guard access to some control | 54 * and the [pauseCapability] and [terminateCapability] guard access |
55 * operations. | 55 * to some control operations. |
| 56 * For example, calling [pause] on an `Isolate` object created without a |
| 57 * [pauseCapability], has no effect. |
| 58 * |
56 * The `Isolate` object provided by a spawn operation will have the | 59 * The `Isolate` object provided by a spawn operation will have the |
57 * control port and capabilities needed to control the isolate. | 60 * control port and capabilities needed to control the isolate. |
58 * New isolates objects can be created without some of these capabilities | 61 * New isolate objects can be created without some of these capabilities |
59 * if necessary. | 62 * if necessary, using the [Isolate.Isolate] constructor. |
60 * | 63 * |
61 * An `Isolate` object cannot be sent over a `SendPort`, but the control port | 64 * An `Isolate` object cannot be sent over a `SendPort`, but the control port |
62 * and capabilities can be sent, and can be used to create a new functioning | 65 * and capabilities can be sent, and can be used to create a new functioning |
63 * `Isolate` object in the receiving port's isolate. | 66 * `Isolate` object in the receiving port's isolate. |
64 */ | 67 */ |
65 class Isolate { | 68 class Isolate { |
66 /** Argument to `ping` and `kill`: Ask for immediate action. */ | 69 /** Argument to `ping` and `kill`: Ask for immediate action. */ |
67 static const int IMMEDIATE = 0; | 70 static const int IMMEDIATE = 0; |
68 /** Argument to `ping` and `kill`: Ask for action before the next event. */ | 71 /** Argument to `ping` and `kill`: Ask for action before the next event. */ |
69 static const int BEFORE_NEXT_EVENT = 1; | 72 static const int BEFORE_NEXT_EVENT = 1; |
70 | 73 |
71 /** | 74 /** |
72 * Control port used to send control messages to the isolate. | 75 * Control port used to send control messages to the isolate. |
73 * | 76 * |
74 * This class provides helper functions that sends control messages | 77 * The control port identifies the isolate. |
75 * to the control port. | |
76 * | 78 * |
77 * The control port identifies the isolate. | 79 * An `Isolate` object allows sending control messages |
| 80 * through the control port. |
| 81 * |
| 82 * Some control messages require a specific capability to be passed along |
| 83 * with the message (see [pauseCapability] and [terminateCapaibility]), |
| 84 * otherwise the message is ignored by the isolate. |
78 */ | 85 */ |
79 final SendPort controlPort; | 86 final SendPort controlPort; |
80 | 87 |
81 /** | 88 /** |
82 * Capability granting the ability to pause the isolate. | 89 * Capability granting the ability to pause the isolate. |
83 * | 90 * |
84 * This capability is used by [pause]. | 91 * This capability is required by [pause]. |
85 * If the capability is not the correct pause capability of the isolate, | 92 * If the capability is `null`, or if it is not the correct pause capability |
86 * including if the capability is `null`, then calls to `pause` will have no | 93 * of the isolate identified by [controlPort], |
87 * effect. | 94 * then calls to [pause] will have no effect. |
88 * | 95 * |
89 * If the isolate is started in a paused state, use this capability as | 96 * If the isolate is spawned in a paused state, use this capability as |
90 * argument to [resume] to resume the isolate. | 97 * argument to [resume] to resume the isolate. |
91 */ | 98 */ |
92 final Capability pauseCapability; | 99 final Capability pauseCapability; |
93 | 100 |
94 /** | 101 /** |
95 * Capability granting the ability to terminate the isolate. | 102 * Capability granting the ability to terminate the isolate. |
96 * | 103 * |
97 * This capability is used by [kill] and [setErrorsFatal]. | 104 * This capability is required by [kill] and [setErrorsFatal]. |
98 * If the capability is not the correct termination capability of the isolate, | 105 * If the capability is `null`, or if it is not the correct termination |
99 * including if the capability is `null`, then calls to those methods will | 106 * capability of the isolate identified by [controlPort], |
100 * have no effect. | 107 * then calls to those methods will have no effect. |
101 */ | 108 */ |
102 final Capability terminateCapability; | 109 final Capability terminateCapability; |
103 | 110 |
104 /** | 111 /** |
105 * Create a new [Isolate] object with a restricted set of capabilities. | 112 * Create a new [Isolate] object with a restricted set of capabilities. |
106 * | 113 * |
107 * The port should be a control port for an isolate, as taken from | 114 * The port should be a control port for an isolate, as taken from |
108 * another `Isolate` object. | 115 * another `Isolate` object. |
109 * | 116 * |
110 * The capabilities should be the subset of the capabilities that are | 117 * The capabilities should be the subset of the capabilities that are |
111 * available to the original isolate. | 118 * available to the original isolate. |
112 * Capabilities of an isolate are locked to that isolate, and have no effect | 119 * Capabilities of an isolate are locked to that isolate, and have no effect |
113 * anywhere else, so the capabilities should come from the same isolate as | 120 * anywhere else, so the capabilities should come from the same isolate as |
114 * the control port. | 121 * the control port. |
115 * | 122 * |
116 * If all the available capabilities are included, | 123 * Can also be used to create an [Isolate] object from a control port, and |
117 * there is no reason to create a new object, | 124 * any available capabilities, that have been sent through a [SendPort]. |
118 * since the behavior is defined entirely | 125 * |
119 * by the control port and capabilities. | 126 * Example: |
| 127 * ```dart |
| 128 * Isolate isolate = findSomeIsolate(); |
| 129 * Isolate restrictedIsolate = new Isolate(isolate.controlPort); |
| 130 * untrustedCode(restrictedIsolate); |
| 131 * ``` |
| 132 * This example creates a new `Isolate` object that cannot be used to |
| 133 * pause or terminate the isolate. All the untrusted code can do is to |
| 134 * inspect the isolate and see uncaught errors or when it terminates. |
120 */ | 135 */ |
121 Isolate(this.controlPort, {this.pauseCapability, | 136 Isolate(this.controlPort, {this.pauseCapability, |
122 this.terminateCapability}); | 137 this.terminateCapability}); |
123 | 138 |
124 /** | 139 /** |
125 * Return the current [Isolate]. | 140 * Return the current [Isolate]. |
126 * | 141 * |
127 * The isolate gives access to the capabilities needed to inspect, | 142 * The isolate gives access to the capabilities needed to inspect, |
128 * pause or kill the isolate, and allows granting these capabilities | 143 * pause or kill the isolate, and allows granting these capabilities |
129 * to others. | 144 * to others. |
(...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
298 Uri packageRoot, | 313 Uri packageRoot, |
299 Uri packageConfig, | 314 Uri packageConfig, |
300 bool automaticPackageResolution: false}); | 315 bool automaticPackageResolution: false}); |
301 | 316 |
302 /** | 317 /** |
303 * Requests the isolate to pause. | 318 * Requests the isolate to pause. |
304 * | 319 * |
305 * When the isolate receives the pause command, it stops | 320 * When the isolate receives the pause command, it stops |
306 * processing events from the event loop queue. | 321 * processing events from the event loop queue. |
307 * It may still add new events to the queue in response to, e.g., timers | 322 * It may still add new events to the queue in response to, e.g., timers |
308 * or receive-port messages. When the isolate is resumed, it handles | 323 * or receive-port messages. When the isolate is resumed, |
309 * the already enqueued events. | 324 * it starts handling the already enqueued events. |
310 * | 325 * |
311 * The pause request is sent through the isolate's command port, | 326 * The pause request is sent through the isolate's command port, |
312 * which bypasses the receiving isolate's event loop. | 327 * which bypasses the receiving isolate's event loop. |
313 * The pause takes effect when it is received, pausing the event loop | 328 * The pause takes effect when it is received, pausing the event loop |
314 * as it is at that time. | 329 * as it is at that time. |
315 * | 330 * |
316 * If [resumeCapability] is provided, it is used to identity the pause, | 331 * The [resumeCapability] is used to identity the pause, |
317 * and must be used again to end the pause using [resume]. | 332 * and must be used again to end the pause using [resume]. |
318 * Otherwise a new resume capability is created and returned. | 333 * If [resumeCapability] is omitted, a new capability object is created |
| 334 * and used instead. |
319 * | 335 * |
320 * If an isolate is paused more than once using the same capability, | 336 * If an isolate is paused more than once using the same capability, |
321 * only one resume with that capability is needed to end the pause. | 337 * only one resume with that capability is needed to end the pause. |
322 * | 338 * |
323 * If an isolate is paused using more than one capability, | 339 * If an isolate is paused using more than one capability, |
324 * each pause must be individually ended before the isolate resumes. | 340 * each pause must be individually ended before the isolate resumes. |
325 * | 341 * |
326 * Returns the capability that must be used to end the pause. | 342 * Returns the capability that must be used to end the pause. |
| 343 * This is either [resumeCapability], or a new capability when |
| 344 * [resumeCapability] is omitted. |
| 345 * |
| 346 * If [pauseCapability] is `null`, or it's not the pause capability |
| 347 * of the isolate identified by [controlPort], |
| 348 * the pause request is ignored by the receiving isolate. |
327 */ | 349 */ |
328 Capability pause([Capability resumeCapability]) { | 350 Capability pause([Capability resumeCapability]) { |
329 resumeCapability ??= new Capability(); | 351 resumeCapability ??= new Capability(); |
330 _pause(resumeCapability); | 352 _pause(resumeCapability); |
331 return resumeCapability; | 353 return resumeCapability; |
332 } | 354 } |
333 | 355 |
334 /** Internal implementation of [pause]. */ | 356 /** Internal implementation of [pause]. */ |
335 external void _pause(Capability resumeCapability); | 357 external void _pause(Capability resumeCapability); |
336 | 358 |
337 /** | 359 /** |
338 * Resumes a paused isolate. | 360 * Resumes a paused isolate. |
339 * | 361 * |
340 * Sends a message to an isolate requesting that it ends a pause | 362 * Sends a message to an isolate requesting that it ends a pause |
341 * that was requested using the [resumeCapability]. | 363 * that was previously requested. |
342 * | 364 * |
343 * When all active pause requests have been cancelled, the isolate | 365 * When all active pause requests have been cancelled, the isolate |
344 * will continue processing events and handling normal messages. | 366 * will continue processing events and handling normal messages. |
345 * | 367 * |
346 * The capability must be one returned by a call to [pause] on this | 368 * If the [resumeCapability] is not one that has previously been used |
347 * isolate, otherwise the resume call does nothing. | 369 * to pause the isolate, or it has already been used to resume from |
| 370 * that pause, the resume call has no effect. |
348 */ | 371 */ |
349 external void resume(Capability resumeCapability); | 372 external void resume(Capability resumeCapability); |
350 | 373 |
351 /** | 374 /** |
352 * Asks the isolate to send [response] on [responsePort] when it terminates. | 375 * Asks the isolate to send [response] on [responsePort] when it terminates. |
353 * | 376 * |
354 * The isolate will send a `response` message on `responsePort` as the last | 377 * The isolate will send a `response` message on `responsePort` as the last |
355 * thing before it terminates. It will run no further code after the message | 378 * thing before it terminates. It will run no further code after the message |
356 * has been sent. | 379 * has been sent. |
357 * | 380 * |
(...skipping 28 matching lines...) Expand all Loading... |
386 */ | 409 */ |
387 external void removeOnExitListener(SendPort responsePort); | 410 external void removeOnExitListener(SendPort responsePort); |
388 | 411 |
389 /** | 412 /** |
390 * Set whether uncaught errors will terminate the isolate. | 413 * Set whether uncaught errors will terminate the isolate. |
391 * | 414 * |
392 * If errors are fatal, any uncaught error will terminate the isolate | 415 * If errors are fatal, any uncaught error will terminate the isolate |
393 * event loop and shut down the isolate. | 416 * event loop and shut down the isolate. |
394 * | 417 * |
395 * This call requires the [terminateCapability] for the isolate. | 418 * This call requires the [terminateCapability] for the isolate. |
396 * If the capability is not correct, no change is made. | 419 * If the capability absent or wrong, no change is made. |
397 * | 420 * |
398 * Since isolates run concurrently, it's possible for it to exit due to an | 421 * Since isolates run concurrently, it's possible for it to exit due to an |
399 * error before errors are set non-fatal. | 422 * error before errors are set non-fatal. |
400 * To avoid this, either use the corresponding parameter to the spawn | 423 * To avoid this, either use the corresponding parameter to the spawn |
401 * function, or start the isolate paused, set errors non-fatal and | 424 * function, or start the isolate paused, set errors non-fatal and |
402 * then resume the isolate. | 425 * then resume the isolate. |
403 */ | 426 */ |
404 external void setErrorsFatal(bool errorsAreFatal); | 427 external void setErrorsFatal(bool errorsAreFatal); |
405 | 428 |
406 /** | 429 /** |
407 * Requests the isolate to shut down. | 430 * Requests the isolate to shut down. |
408 * | 431 * |
409 * The isolate is requested to terminate itself. | 432 * The isolate is requested to terminate itself. |
410 * The [priority] argument specifies when this must happen. | 433 * The [priority] argument specifies when this must happen. |
411 * | 434 * |
412 * The [priority] must be one of [IMMEDIATE] or [BEFORE_NEXT_EVENT]. | 435 * The [priority] must be one of [IMMEDIATE] or [BEFORE_NEXT_EVENT]. |
413 * The shutdown is performed at different times depending on the priority: | 436 * The shutdown is performed at different times depending on the priority: |
414 * | 437 * |
415 * * `IMMEDIATE`: The isolate shuts down as soon as possible. | 438 * * `IMMEDIATE`: The isolate shuts down as soon as possible. |
416 * Control messages are handled in order, so all previously sent control | 439 * Control messages are handled in order, so all previously sent control |
417 * events from this isolate will all have been processed. | 440 * events from this isolate will all have been processed. |
418 * The shutdown should happen no later than if sent with | 441 * The shutdown should happen no later than if sent with |
419 * `BEFORE_NEXT_EVENT`. | 442 * `BEFORE_NEXT_EVENT`. |
420 * It may happen earlier if the system has a way to shut down cleanly | 443 * It may happen earlier if the system has a way to shut down cleanly |
421 * at an earlier time, even during the execution of another event. | 444 * at an earlier time, even during the execution of another event. |
422 * * `BEFORE_NEXT_EVENT`: The shutdown is scheduled for the next time | 445 * * `BEFORE_NEXT_EVENT`: The shutdown is scheduled for the next time |
423 * control returns to the event loop of the receiving isolate, | 446 * control returns to the event loop of the receiving isolate, |
424 * after the current event, and any already scheduled control events, | 447 * after the current event, and any already scheduled control events, |
425 * are completed. | 448 * are completed. |
| 449 * |
| 450 * If [terminateCapability] is `null`, or it's not the terminate capability |
| 451 * of the isolate identified by [controlPort], |
| 452 * the kill request is ignored by the receiving isolate. |
426 */ | 453 */ |
427 external void kill({int priority: BEFORE_NEXT_EVENT}); | 454 external void kill({int priority: BEFORE_NEXT_EVENT}); |
428 | 455 |
429 /** | 456 /** |
430 * Request that the isolate send [response] on the [responsePort]. | 457 * Request that the isolate send [response] on the [responsePort]. |
431 * | 458 * |
432 * If the isolate is alive, it will eventually send `response` | 459 * If the isolate is alive, it will eventually send `response` |
433 * (defaulting to `null`) on the response port. | 460 * (defaulting to `null`) on the response port. |
434 * | 461 * |
435 * The [priority] must be one of [IMMEDIATE] or [BEFORE_NEXT_EVENT]. | 462 * The [priority] must be one of [IMMEDIATE] or [BEFORE_NEXT_EVENT]. |
(...skipping 234 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
670 * as the original error, but has no other features of the original error. | 697 * as the original error, but has no other features of the original error. |
671 */ | 698 */ |
672 class RemoteError implements Error { | 699 class RemoteError implements Error { |
673 final String _description; | 700 final String _description; |
674 final StackTrace stackTrace; | 701 final StackTrace stackTrace; |
675 RemoteError(String description, String stackDescription) | 702 RemoteError(String description, String stackDescription) |
676 : _description = description, | 703 : _description = description, |
677 stackTrace = new StackTrace.fromString(stackDescription); | 704 stackTrace = new StackTrace.fromString(stackDescription); |
678 String toString() => _description; | 705 String toString() => _description; |
679 } | 706 } |
OLD | NEW |