Chromium Code Reviews| 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 * |
| 11 * See also: | 11 * See also: |
| 12 * [dart:isolate - Concurrency with Isolates](https://www.dartlang.org/docs/dart -up-and-running/contents/ch03.html#ch03-dartisolate---concurrency-with-isolates) | 12 * [dart:isolate - Concurrency with Isolates](https://www.dartlang.org/docs/dart -up-and-running/contents/ch03.html#ch03-dartisolate---concurrency-with-isolates) |
| 13 * in the library tour. | 13 * in the library tour. |
| 14 */ | 14 */ |
| 15 library dart.isolate; | 15 library dart.isolate; |
| 16 | 16 |
| 17 import "dart:async"; | 17 import "dart:async"; |
| 18 | 18 |
| 19 part "isolate_stream.dart"; | 19 /** |
| 20 | 20 * Thrown when an isolate cannot be created. |
| 21 */ | |
| 21 class IsolateSpawnException implements Exception { | 22 class IsolateSpawnException implements Exception { |
| 23 // TODO(floitsch): clean up spawn exception. | |
| 22 const IsolateSpawnException(String this._s); | 24 const IsolateSpawnException(String this._s); |
| 23 String toString() => "IsolateSpawnException: '$_s'"; | 25 String toString() => "IsolateSpawnException: '$_s'"; |
| 24 final String _s; | 26 final String _s; |
| 25 } | 27 } |
| 26 | 28 |
| 27 /** | 29 class Isolate { |
| 28 * The initial ReceivePort available by default for this isolate. | 30 |
| 29 * | 31 final SendPort _controlPort; |
| 30 * This ReceivePort is created automatically | 32 |
| 31 * and is commonly used to establish | 33 Isolate._fromControlPort(this._controlPort); |
| 32 * the first communication between isolates. | 34 |
| 33 * (See [spawnFunction] and [spawnUri].) | 35 /** |
| 34 */ | 36 * Creates and spawns an isolate that shares the same code as the current |
| 35 ReceivePort get port => _Isolate.port; | 37 * isolate. |
| 38 * | |
| 39 * The argument [entryPoint] specifies the entry point of the spawned | |
| 40 * isolate. It must be a static top-level function or a static method that | |
| 41 * takes no arguments. It is not allowed to pass a function closure. | |
| 42 * | |
| 43 * The entry-point function is invoked with the initial [message]. | |
| 44 * Usually the initial [message] contains a [SendPort] so | |
| 45 * that the spawner and spawnee can communicate with each other. | |
| 46 * | |
| 47 * Returns a future that will complete with an [Isolate] instance. The | |
| 48 * isolate instance can be used to control the spawned isolate. | |
| 49 */ | |
| 50 external static Future<Isolate> spawn(void entryPoint(message), var message); | |
| 51 | |
| 52 /** | |
| 53 * Creates and spawns an isolate that runs the code from the library with | |
| 54 * the specified URI. | |
| 55 * | |
| 56 * The isolate starts executing the top-level `main` function of the library | |
| 57 * with the given URI. | |
| 58 * | |
| 59 * The target `main` may have one of the four following signatures: | |
| 60 * | |
| 61 * * `main()` | |
| 62 * * `main(args)` | |
| 63 * * `main(args, message)` | |
| 64 * | |
| 65 * When present, the argument `message` is set to the initial [message]. | |
| 66 * When present, the argument `args` is set to the provided [args] list. | |
| 67 * | |
| 68 * Returns a future that will complete with an [Isolate] instance. The | |
| 69 * isolate instance can be used to control the spawned isolate. | |
| 70 */ | |
| 71 external static Future<Isolate> spawnUri( | |
| 72 Uri uri, List<String> args, var message); | |
| 73 } | |
| 36 | 74 |
| 37 /** | 75 /** |
| 38 * Creates and spawns an isolate | 76 * Sends messages to its [ReceivePort]s. |
| 39 * that shares the same code as the current isolate, | |
| 40 * but that starts from the specified function. | |
| 41 * | |
| 42 * The [topLevelFunction] argument must be | |
| 43 * a static top-level function or a static method that takes no | |
| 44 * arguments. It is illegal to pass a function closure. | |
| 45 * | |
| 46 * When any isolate starts (even the main script of the application), a default | |
| 47 * [ReceivePort] is created for it. This port is available from the top-level | |
| 48 * getter [port] defined in this library. | |
| 49 * | |
| 50 * This function returns a [SendPort] derived from | |
| 51 * the child isolate's default port. | |
| 52 * | |
| 53 * The optional [unhandledExceptionCallback] argument is invoked whenever an | |
| 54 * exception inside the isolate is unhandled. It can be seen as a big | |
| 55 * `try/catch` around everything that is executed inside the isolate. The | |
| 56 * callback should return `true` if it was able to handle the exception. | |
| 57 */ | |
| 58 SendPort spawnFunction(void topLevelFunction(), | |
| 59 [bool unhandledExceptionCallback(IsolateUnhandledException e)]) | |
| 60 => _Isolate.spawnFunction(topLevelFunction, unhandledExceptionCallback); | |
| 61 | |
| 62 /** | |
| 63 * Creates and spawns an isolate that runs the code from the specified URI. | |
| 64 * | |
| 65 * As with [spawnFunction], | |
| 66 * the child isolate has a default [ReceivePort], | |
| 67 * and this function returns a [SendPort] derived from it. | |
| 68 */ | |
| 69 SendPort spawnUri(String uri) => _Isolate.spawnUri(uri); | |
| 70 | |
| 71 /** | |
| 72 * Together with [ReceivePort], | |
| 73 * the only means of communication between isolates. | |
| 74 * | 77 * |
| 75 * [SendPort]s are created from [ReceivePort]s. Any message sent through | 78 * [SendPort]s are created from [ReceivePort]s. Any message sent through |
| 76 * a [SendPort] is delivered to its respective [ReceivePort]. There might be | 79 * a [SendPort] is delivered to its respective [ReceivePort]. There might be |
| 77 * many [SendPort]s for the same [ReceivePort]. | 80 * many [SendPort]s for the same [ReceivePort]. |
| 78 * | 81 * |
| 79 * [SendPort]s can be transmitted to other isolates. | 82 * [SendPort]s can be transmitted to other isolates. |
| 80 */ | 83 */ |
| 81 abstract class SendPort { | 84 abstract class SendPort { |
| 82 | 85 |
| 83 /** | 86 /** |
| 84 * Sends an asynchronous [message] to this send port. The message is copied to | 87 * Sends an asynchronous [message] to this send port. The message is copied to |
| 85 * the receiving isolate. If specified, the [replyTo] port will be provided to | 88 * the receiving isolate. |
| 86 * the receiver to facilitate exchanging sequences of messages. | |
| 87 * | 89 * |
| 88 * The content of [message] can be: primitive values (null, num, bool, double, | 90 * The content of [message] can be: primitive values (null, num, bool, double, |
| 89 * String), instances of [SendPort], and lists and maps whose elements are any | 91 * String), instances of [SendPort], and lists and maps whose elements are any |
| 90 * of these. List and maps are also allowed to be cyclic. | 92 * of these. List and maps are also allowed to be cyclic. |
| 91 * | 93 * |
| 92 * In the special circumstances when two isolates share the same code and are | 94 * In the special circumstances when two isolates share the same code and are |
| 93 * running in the same process (e.g. isolates created via [spawnFunction]), it | 95 * running in the same process (e.g. isolates created via [spawnFunction]), it |
| 94 * is also possible to send object instances (which would be copied in the | 96 * is also possible to send object instances (which would be copied in the |
| 95 * process). This is currently only supported by the dartvm. For now, the | 97 * process). This is currently only supported by the dartvm. For now, the |
| 96 * dart2js compiler only supports the restricted messages described above. | 98 * dart2js compiler only supports the restricted messages described above. |
| 97 * | 99 * |
| 98 * Deprecation note: it is no longer valid to transmit a [ReceivePort] in a | 100 * The second argument [replyTo] is deprecated. |
|
Ivan Posva
2013/10/25 07:01:46
If this is being deprecated now, then that should
Lasse Reichstein Nielsen
2013/10/25 09:42:49
Agree. We have broken almost everything else about
floitsch
2013/10/25 13:11:01
We can't. It is used by the C API. We need to be a
floitsch
2013/10/25 13:11:01
can't yet. See reply to Lasse.
| |
| 99 * message. Previously they were translated to the corresponding send port | |
| 100 * before being transmitted. | |
| 101 */ | 101 */ |
| 102 void send(var message, [SendPort replyTo]); | 102 void send(var message, [SendPort replyTo]); |
| 103 | 103 |
| 104 /** | 104 /** |
| 105 * Sends a message to this send port and returns a [Future] of the reply. | |
| 106 * Basically, this internally creates a new receive port, sends a | |
| 107 * message to this send port with replyTo set to such receive port, and, when | |
| 108 * a reply is received, it closes the receive port and completes the returned | |
| 109 * future. | |
| 110 */ | |
| 111 Future call(var message); | |
| 112 | |
| 113 /** | |
| 114 * Tests whether [other] is a [SendPort] pointing to the same | 105 * Tests whether [other] is a [SendPort] pointing to the same |
| 115 * [ReceivePort] as this one. | 106 * [ReceivePort] as this one. |
| 116 */ | 107 */ |
| 117 bool operator==(var other); | 108 bool operator==(var other); |
| 118 | 109 |
| 119 /** | 110 /** |
| 120 * Returns an immutable hash code for this send port that is | 111 * Returns an immutable hash code for this send port that is |
| 121 * consistent with the == operator. | 112 * consistent with the == operator. |
| 122 */ | 113 */ |
| 123 int get hashCode; | 114 int get hashCode; |
| 124 | |
| 125 } | |
| 126 | |
| 127 /** | |
| 128 * Together with [SendPort], the only means of | |
| 129 * communication between isolates. | |
| 130 * | |
| 131 * [ReceivePort]s have a [:toSendPort:] method | |
| 132 * which returns a [SendPort]. Any message that is sent through this [SendPort] | |
| 133 * is delivered to the [ReceivePort] it has been created from. There, they are | |
| 134 * dispatched to the callback that has been registered on the receive port. | |
| 135 * | |
| 136 * A [ReceivePort] may have many [SendPort]s. | |
| 137 */ | |
| 138 abstract class ReceivePort { | |
| 139 | |
| 140 /** | |
| 141 * Opens a long-lived port for receiving messages. The returned port | |
| 142 * must be explicitly closed through [ReceivePort.close]. | |
| 143 */ | |
| 144 external factory ReceivePort(); | |
| 145 | |
| 146 /** | |
| 147 * Sets up a callback function for receiving pending or future | |
| 148 * messages on this receive port. | |
| 149 */ | |
| 150 void receive(void callback(var message, SendPort replyTo)); | |
| 151 | |
| 152 /** | |
| 153 * Closes this receive port immediately. Pending messages will not | |
| 154 * be processed and it is impossible to re-open the port. Single-shot | |
| 155 * reply ports, such as those created through [SendPort.call], are | |
| 156 * automatically closed when the reply has been received. Multiple | |
| 157 * invocations of [close] are allowed but ignored. | |
| 158 */ | |
| 159 void close(); | |
| 160 | |
| 161 /** | |
| 162 * Creates a new send port that sends to this receive port. It is legal to | |
| 163 * create several [SendPort]s from the same [ReceivePort]. | |
| 164 */ | |
| 165 SendPort toSendPort(); | |
| 166 | |
| 167 } | |
| 168 | |
| 169 /** | |
| 170 * [SendPortSync]s are created from [ReceivePortSync]s. Any message sent through | |
| 171 * a [SendPortSync] is delivered to its respective [ReceivePortSync]. There | |
| 172 * might be many [SendPortSync]s for the same [ReceivePortSync]. | |
| 173 * | |
| 174 * [SendPortSync]s can be transmitted to other isolates. | |
| 175 */ | |
| 176 abstract class SendPortSync { | |
| 177 /** | |
| 178 * Sends a synchronous message to this send port and returns the result. | |
| 179 */ | |
| 180 callSync(var message); | |
| 181 | |
| 182 /** | |
| 183 * Tests whether [other] is a [SendPortSync] pointing to the same | |
| 184 * [ReceivePortSync] as this one. | |
| 185 */ | |
| 186 bool operator==(var other); | |
| 187 | |
| 188 /** | |
| 189 * Returns an immutable hash code for this send port that is | |
| 190 * consistent with the == operator. | |
| 191 */ | |
| 192 int get hashCode; | |
| 193 } | 115 } |
| 194 | 116 |
| 195 // The VM doesn't support accessing external globals in the same library. We | 117 /** |
| 196 // therefore create this wrapper class. | 118 * Together with [SendPort], the only means of communication between isolates. |
| 197 // TODO(6997): Don't go through static class for external variables. | 119 * |
| 198 abstract class _Isolate { | 120 * [ReceivePort]s have a `sendport` getter which returns a [SendPort]. |
| 199 external static ReceivePort get port; | 121 * Any message that is sent through this [SendPort] |
| 200 external static SendPort spawnFunction(void topLevelFunction(), | 122 * is delivered to the [ReceivePort] it has been created from. There, the |
| 201 [bool unhandledExceptionCallback(IsolateUnhandledException e)]); | 123 * message is dispatched to its listener. |
| 202 external static SendPort spawnUri(String uri); | 124 * |
| 125 * A [ReceivePort] is a non-broadcast stream. This means that it buffers | |
| 126 * incoming messages until a listener is registered. Only one listener can | |
| 127 * receive messages. See [Stream.asBroadcastStream] for transforming the port | |
| 128 * to a broadcast stream. | |
| 129 * | |
| 130 * A [ReceivePort] may have many [SendPort]s. | |
| 131 */ | |
| 132 abstract class ReceivePort implements Stream { | |
| 133 | |
| 134 /** | |
| 135 * Opens a long-lived port for receiving messages. | |
| 136 * | |
| 137 * A [ReceivePort] is a non-broadcast stream. This means that it buffers | |
| 138 * incoming messages until a listener is registered. Only one listener can | |
| 139 * receive messages. See [Stream.asBroadcastStream] for transforming the port | |
| 140 * to a broadcast stream. | |
| 141 * | |
| 142 * A receive port is closed by canceling its subscription. | |
| 143 */ | |
| 144 external factory ReceivePort(); | |
| 145 | |
| 146 /** | |
| 147 * Creates a [ReceivePort] from a [RawReceivePort]. | |
| 148 * | |
| 149 * The handler of the given [rawPort] is overwritten during the construction | |
| 150 * of the result. | |
| 151 */ | |
| 152 external factory ReceivePort.fromRawReceivePort(RawReceivePort rawPort); | |
| 153 | |
| 154 /** | |
| 155 * Inherited from [Stream]. | |
| 156 * | |
| 157 * Note that all named arguments are ignored since a ReceivePort will never | |
| 158 * receive an error, or done message. | |
| 159 */ | |
| 160 StreamSubscription listen(void onData(var message), | |
| 161 { Function onError, | |
| 162 void onDone(), | |
| 163 bool cancelOnError }); | |
| 164 | |
| 165 /** | |
| 166 * Closes `this`. | |
| 167 * | |
| 168 * If the stream has not been canceled yet, adds a close-event to the event | |
| 169 * queue and discards any further incoming messages. | |
| 170 * | |
| 171 * If the stream has already been canceled this method has no effect. | |
| 172 */ | |
| 173 void close(); | |
| 174 | |
| 175 /** | |
| 176 * Returns a send port that sends to this receive port. | |
| 177 */ | |
| 178 SendPort get sendPort; | |
| 179 } | |
| 180 | |
| 181 abstract class RawReceivePort { | |
| 182 /** | |
| 183 * Opens a long-lived port for receiving messages. | |
| 184 * | |
| 185 * A [RawReceivePort] is low level and does not work with [Zone]s. It | |
| 186 * can not be paused. The data-handler must be set before the first | |
| 187 * event is received. | |
| 188 */ | |
| 189 external factory RawReceivePort([void handler(event)]); | |
| 190 | |
| 191 /** | |
| 192 * Sets the handler that is invoked for every incoming message. | |
| 193 * | |
| 194 * The handler is invoked in the root-zone ([Zone.ROOT]). | |
| 195 */ | |
| 196 void set handler(Function newHandler); | |
| 197 | |
| 198 /** | |
| 199 * Closes the port. | |
| 200 * | |
| 201 * After a call to this method any incoming message is silently dropped. | |
| 202 */ | |
| 203 void close(); | |
| 203 } | 204 } |
| 204 | 205 |
| 205 /** | 206 /** |
| 206 * Wraps unhandled exceptions thrown during isolate execution. It is | 207 * Wraps unhandled exceptions thrown during isolate execution. It is |
| 207 * used to show both the error message and the stack trace for unhandled | 208 * used to show both the error message and the stack trace for unhandled |
| 208 * exceptions. | 209 * exceptions. |
| 209 */ | 210 */ |
| 210 class IsolateUnhandledException implements Exception { | 211 // TODO(floitsch): probably going to remove and replace with something else. |
|
Ivan Posva
2013/10/25 07:01:46
I would think we can safely remove this code for n
| |
| 212 class _IsolateUnhandledException implements Exception { | |
| 211 /** Message being handled when exception occurred. */ | 213 /** Message being handled when exception occurred. */ |
| 212 final message; | 214 final message; |
| 213 | 215 |
| 214 /** Wrapped exception. */ | 216 /** Wrapped exception. */ |
| 215 final source; | 217 final source; |
| 216 | 218 |
| 217 /** Trace for the wrapped exception. */ | 219 /** Trace for the wrapped exception. */ |
| 218 final Object stackTrace; | 220 final Object stackTrace; |
| 219 | 221 |
| 220 const IsolateUnhandledException(this.message, this.source, this.stackTrace); | 222 const _IsolateUnhandledException(this.message, this.source, this.stackTrace); |
| 221 | 223 |
| 222 String toString() { | 224 String toString() { |
| 223 return 'IsolateUnhandledException: exception while handling message: ' | 225 return 'IsolateUnhandledException: exception while handling message: ' |
| 224 '${message} \n ' | 226 '${message} \n ' |
| 225 '${source.toString().replaceAll("\n", "\n ")}\n' | 227 '${source.toString().replaceAll("\n", "\n ")}\n' |
| 226 'original stack trace:\n ' | 228 'original stack trace:\n ' |
| 227 '${stackTrace.toString().replaceAll("\n","\n ")}'; | 229 '${stackTrace.toString().replaceAll("\n","\n ")}'; |
| 228 } | 230 } |
| 229 } | 231 } |
| OLD | NEW |