From e143f6c81f17e1cf7ef162b2e911d8d165de8667 Mon Sep 17 00:00:00 2001 From: "floitsch@google.com" Date: Fri, 7 Oct 2011 15:46:33 +0000 Subject: [PATCH] Improve doc for isolates. Also make Isolate.main abstract. Review URL: https://chromereviews.googleplex.com/3567015 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@230 260f80e4-7a28-3924-810f-c04153c831b5 --- corelib/src/isolate.dart | 123 ++++++++++++++++++++++++++++++++------- 1 file changed, 103 insertions(+), 20 deletions(-) diff --git a/corelib/src/isolate.dart b/corelib/src/isolate.dart index 94d2a3d722a..fa1df775dda 100644 --- a/corelib/src/isolate.dart +++ b/corelib/src/isolate.dart @@ -4,30 +4,40 @@ // Dart core library. - +/** + * [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. + */ interface SendPort extends Hashable { - /* Sends an asynchronous message to this send port. The message is + /** + * Sends an asynchronous [message] to this send port. The message is * copied to the receiving isolate. If the message contains any * receive ports, they are translated to the corresponding send port - * before being transmitted. If specified, the replyTo port will be + * before being transmitted. If specified, the [replyTo] port will be * provided to the receiver to facilitate exchanging sequences of * messages. */ void send(var message, [SendPort replyTo]); - /* Creates a new single-shot receive port, sends a message to this + /** + * Creates a new single-shot receive port, sends a message to this * send port with replyTo set to the opened port, and returns the * receive port. */ ReceivePort call(var message); - /* Tests whether [other] is a SendPort pointing to the same - * ReceivePort as this one. + /** + * 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 + /** + * Returns an immutable hash code for this send port that is * consistent with the == operator. */ int hashCode(); @@ -35,26 +45,39 @@ interface SendPort extends Hashable { } +/** + * [ReceivePort]s, together with [SendPort]s, are 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. + */ interface ReceivePort factory ReceivePortFactory { - /* Opens a long-lived port for receiving messages. The returned port + /** + * Opens a long-lived port for receiving messages. The returned port * must be explicitly closed through [ReceivePort.close]. */ ReceivePort(); - /* Opens a single-shot reply port. Once a message has been received + /** + * Opens a single-shot reply port. Once a message has been received * on this port, it is automatically closed -- obviously without * throwing the message away before it can be processed. This * constructor is used indirectly through [SendPort.call]. */ ReceivePort.singleShot(); - /* Sets up a callback function for receiving pending or future + /** + * 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 + /** + * Closes this receive port immediately. Pending messages will not * be processed and it is impossible to re-open the port. Reply * ports possibly created through [SendPort.call] are automatically * closed when the reply has been received. Multiple invocations of @@ -62,24 +85,65 @@ interface ReceivePort factory ReceivePortFactory { */ void close(); - /* Converts this receive port to a send port. The send port is - * canonicalized so repeated invocations of this method are - * guaranteed to return the same (===) send port. + /** + * Converts this receive port to a send port. It is legal to create several + * [SendPort]s from the same [ReceivePort]. */ SendPort toSendPort(); } - +/** + * The [Isolate] class serves two purposes: (1) as template for spawning a new + * isolate, and (2) as entry-point for the newly spawned isolate. + * + * New isolates are spawned by sub-classing [Isolate] and then invoking + * [:spawn:] on the instance. This will spawn a new isolate, which creates a + * new instance of the class, initializes the instance's [port] field + * and invokes the instance method [main]. + * + * The new instance is created by invoking the default constructor of the + * class that served as template for spawning the new isolate. This means, that + * sub-classes must have a default constructor (i.e. no-argument constructor). + * + * Isolates may be "heavy" or "light". Heavy isolates live in their own thread, + * whereas "light" isolates live in the same thread as the isolate which spawned + * them. + */ class Isolate { + /** + * Redirects to [Isolate.light]. + */ Isolate() : this.light(); + + /** + * Creates a new isolate-template for a light isolate. + */ Isolate.light() : _isLight = true; + + /** + * Creates a new isolate-template for a heavy isolate. + */ Isolate.heavy() : _isLight = false; - bool isLight() { return _isLight; } - bool isHeavy() { return !_isLight; } - + /** + * Spawns a new isolate, using this instance as template. + * + * The new isolate lives in a new thread (for heavy templates) + * or in the same thread as the current isolate (for light templates), if + * possible. + * + * During the initialization of the new isolate a [ReceivePort] is created + * inside the new isolate and stored in [port]. A corresponding + * [SendPort] is sent to the isolate that invoked [spawn]. Since spawning an + * isolate is an asynchronous operation this method returns a [Promise] of + * this [SendPort]. + * + * A common pattern to instantiate new isolates is to enqueue the instructions + * in [Promise.then]. + * [:myIsolate.spawn().then((SendPort port) { port.send('hi there'); });:] + */ Promise spawn() { return IsolateNatives.spawn(this, _isLight); } @@ -92,16 +156,35 @@ class Isolate { main(); } + /** + * When [Isolate]s are used as entry-points, the [port] field contains a + * [ReceivePort]. The isolate that initiated the spawn holds a corresponding + * [SendPort]. + * + * Note that isolates should generally close their [ReceivePort]s when they + * are done, including this port. + */ ReceivePort get port() { return _port; } - void main() { - } + /** + * When isolates are created, an instance of the template's class is + * instantiated in the new isolate. After the [port] has been set up, this + * [main] method is invoked on the instance. + */ + abstract void main(); final bool _isLight; ReceivePort _port; + /** + * Before callbacks can be registered in the DOM, they need to be bound + * to the current isolate. + * + * This is necessary due to a bug in the Dart-to-JavaScript pipeline and + * should soon be fixed. + */ // BUG(5151491): Remove this once we automatically bind functions to // the isolate they live in. static Function bind(Function f) {