| // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| // for details. All rights reserved. Use of this source code is governed by a |
| // BSD-style license that can be found in the LICENSE file. |
| |
| /** |
| * Concurrent programming using _isolates_: |
| * independent workers that are similar to threads |
| * but don't share memory, |
| * communicating only via messages. |
| * |
| * See also: |
| * [dart:isolate - Concurrency with Isolates](https://www.dartlang.org/docs/dart-up-and-running/contents/ch03.html#ch03-dartisolate---concurrency-with-isolates) |
| * in the library tour. |
| */ |
| library dart.isolate; |
| |
| import "dart:async"; |
| |
| part "isolate_stream.dart"; |
| |
| class IsolateSpawnException implements Exception { |
| const IsolateSpawnException(String this._s); |
| String toString() => "IsolateSpawnException: '$_s'"; |
| final String _s; |
| } |
| |
| /** |
| * The initial ReceivePort available by default for this isolate. |
| * |
| * This ReceivePort is created automatically |
| * and is commonly used to establish |
| * the first communication between isolates. |
| * (See [spawnFunction] and [spawnUri].) |
| */ |
| ReceivePort get port => _Isolate.port; |
| |
| /** |
| * Creates and spawns an isolate |
| * that shares the same code as the current isolate, |
| * but that starts from the specified function. |
| * |
| * The [topLevelFunction] argument must be |
| * a static top-level function or a static method that takes no |
| * arguments. It is illegal to pass a function closure. |
| * |
| * When any isolate starts (even the main script of the application), a default |
| * [ReceivePort] is created for it. This port is available from the top-level |
| * getter [port] defined in this library. |
| * |
| * This function returns a [SendPort] derived from |
| * the child isolate's default port. |
| * |
| * The optional [unhandledExceptionCallback] argument is invoked whenever an |
| * exception inside the isolate is unhandled. It can be seen as a big |
| * `try/catch` around everything that is executed inside the isolate. The |
| * callback should return `true` if it was able to handle the exception. |
| */ |
| SendPort spawnFunction(void topLevelFunction(), |
| [bool unhandledExceptionCallback(IsolateUnhandledException e)]) |
| => _Isolate.spawnFunction(topLevelFunction, unhandledExceptionCallback); |
| |
| /** |
| * Creates and spawns an isolate that runs the code from the specified URI. |
| * |
| * As with [spawnFunction], |
| * the child isolate has a default [ReceivePort], |
| * and this function returns a [SendPort] derived from it. |
| */ |
| SendPort spawnUri(String uri) => _Isolate.spawnUri(uri); |
| |
| /** |
| * Together with [ReceivePort], |
| * the only means of communication between isolates. |
| * |
| * [SendPort]s are created from [ReceivePort]s. Any message sent through |
| * a [SendPort] is delivered to its respective [ReceivePort]. There might be |
| * many [SendPort]s for the same [ReceivePort]. |
| * |
| * [SendPort]s can be transmitted to other isolates. |
| */ |
| abstract class SendPort { |
| |
| /** |
| * Sends an asynchronous [message] to this send port. The message is copied to |
| * the receiving isolate. If specified, the [replyTo] port will be provided to |
| * the receiver to facilitate exchanging sequences of messages. |
| * |
| * The content of [message] can be: primitive values (null, num, bool, double, |
| * String), instances of [SendPort], and lists and maps whose elements are any |
| * of these. List and maps are also allowed to be cyclic. |
| * |
| * In the special circumstances when two isolates share the same code and are |
| * running in the same process (e.g. isolates created via [spawnFunction]), it |
| * is also possible to send object instances (which would be copied in the |
| * process). This is currently only supported by the dartvm. For now, the |
| * dart2js compiler only supports the restricted messages described above. |
| * |
| * Deprecation note: it is no longer valid to transmit a [ReceivePort] in a |
| * message. Previously they were translated to the corresponding send port |
| * before being transmitted. |
| */ |
| void send(var message, [SendPort replyTo]); |
| |
| /** |
| * Sends a message to this send port and returns a [Future] of the reply. |
| * Basically, this internally creates a new receive port, sends a |
| * message to this send port with replyTo set to such receive port, and, when |
| * a reply is received, it closes the receive port and completes the returned |
| * future. |
| */ |
| Future call(var message); |
| |
| /** |
| * Tests whether [other] is a [SendPort] pointing to the same |
| * [ReceivePort] as this one. |
| */ |
| bool operator==(var other); |
| |
| /** |
| * Returns an immutable hash code for this send port that is |
| * consistent with the == operator. |
| */ |
| int get hashCode; |
| |
| } |
| |
| /** |
| * Together with [SendPort], the only means of |
| * communication between isolates. |
| * |
| * [ReceivePort]s have a [:toSendPort:] method |
| * which returns a [SendPort]. Any message that is sent through this [SendPort] |
| * is delivered to the [ReceivePort] it has been created from. There, they are |
| * dispatched to the callback that has been registered on the receive port. |
| * |
| * A [ReceivePort] may have many [SendPort]s. |
| */ |
| abstract class ReceivePort { |
| |
| /** |
| * Opens a long-lived port for receiving messages. The returned port |
| * must be explicitly closed through [ReceivePort.close]. |
| */ |
| external factory ReceivePort(); |
| |
| /** |
| * Sets up a callback function for receiving pending or future |
| * messages on this receive port. |
| */ |
| void receive(void callback(var message, SendPort replyTo)); |
| |
| /** |
| * Closes this receive port immediately. Pending messages will not |
| * be processed and it is impossible to re-open the port. Single-shot |
| * reply ports, such as those created through [SendPort.call], are |
| * automatically closed when the reply has been received. Multiple |
| * invocations of [close] are allowed but ignored. |
| */ |
| void close(); |
| |
| /** |
| * Creates a new send port that sends to this receive port. It is legal to |
| * create several [SendPort]s from the same [ReceivePort]. |
| */ |
| SendPort toSendPort(); |
| |
| } |
| |
| /** |
| * [SendPortSync]s are created from [ReceivePortSync]s. Any message sent through |
| * a [SendPortSync] is delivered to its respective [ReceivePortSync]. There |
| * might be many [SendPortSync]s for the same [ReceivePortSync]. |
| * |
| * [SendPortSync]s can be transmitted to other isolates. |
| */ |
| abstract class SendPortSync { |
| /** |
| * Sends a synchronous message to this send port and returns the result. |
| */ |
| callSync(var message); |
| |
| /** |
| * Tests whether [other] is a [SendPortSync] pointing to the same |
| * [ReceivePortSync] as this one. |
| */ |
| bool operator==(var other); |
| |
| /** |
| * Returns an immutable hash code for this send port that is |
| * consistent with the == operator. |
| */ |
| int get hashCode; |
| } |
| |
| // The VM doesn't support accessing external globals in the same library. We |
| // therefore create this wrapper class. |
| // TODO(6997): Don't go through static class for external variables. |
| abstract class _Isolate { |
| external static ReceivePort get port; |
| external static SendPort spawnFunction(void topLevelFunction(), |
| [bool unhandledExceptionCallback(IsolateUnhandledException e)]); |
| external static SendPort spawnUri(String uri); |
| } |
| |
| /** |
| * Wraps unhandled exceptions thrown during isolate execution. It is |
| * used to show both the error message and the stack trace for unhandled |
| * exceptions. |
| */ |
| class IsolateUnhandledException implements Exception { |
| /** Message being handled when exception occurred. */ |
| final message; |
| |
| /** Wrapped exception. */ |
| final source; |
| |
| /** Trace for the wrapped exception. */ |
| final Object stackTrace; |
| |
| const IsolateUnhandledException(this.message, this.source, this.stackTrace); |
| |
| String toString() { |
| return 'IsolateUnhandledException: exception while handling message: ' |
| '${message} \n ' |
| '${source.toString().replaceAll("\n", "\n ")}\n' |
| 'original stack trace:\n ' |
| '${stackTrace.toString().replaceAll("\n","\n ")}'; |
| } |
| } |