blob: 3cfc4fc3b8849e3ed11893c2d83301252d6cfd75 [file] [log] [blame]
// 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 ")}';
}
}