Index: sdk/lib/isolate/isolate.dart |
diff --git a/sdk/lib/isolate/isolate.dart b/sdk/lib/isolate/isolate.dart |
index 3cfc4fc3b8849e3ed11893c2d83301252d6cfd75..2ca5c45552e9302436c4a8aec35d2bb143019801 100644 |
--- a/sdk/lib/isolate/isolate.dart |
+++ b/sdk/lib/isolate/isolate.dart |
@@ -16,61 +16,133 @@ library dart.isolate; |
import "dart:async"; |
-part "isolate_stream.dart"; |
- |
+/** |
+ * Thrown when an isolate cannot be created. |
+ */ |
class IsolateSpawnException implements Exception { |
- const IsolateSpawnException(String this._s); |
- String toString() => "IsolateSpawnException: '$_s'"; |
- final String _s; |
+ const IsolateSpawnException(); |
} |
/** |
- * The initial ReceivePort available by default for this isolate. |
+ * A capability is unique among all isolates and can be shared with |
+ * other isolates. |
* |
- * This ReceivePort is created automatically |
- * and is commonly used to establish |
- * the first communication between isolates. |
- * (See [spawnFunction] and [spawnUri].) |
+ * Capabilities are opaque objects. They do not expose what they can be used |
+ * for. |
*/ |
-ReceivePort get port => _Isolate.port; |
+class Capability { |
+} |
/** |
- * 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. |
+ * An enum that enumerates permissions that are required to control isolates. |
* |
- * 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. |
+ * Some control messages require capabilities to be accepted by the isolate. |
+ * The [Permission] enum gives these capabilities names. |
*/ |
-SendPort spawnFunction(void topLevelFunction(), |
- [bool unhandledExceptionCallback(IsolateUnhandledException e)]) |
- => _Isolate.spawnFunction(topLevelFunction, unhandledExceptionCallback); |
+class Permission { |
+ final Symbol _permission; |
+ const Permission(this._permission); |
-/** |
- * 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); |
+ // Mirror-modify basically allows everything, since we can just modify the |
+ // program to our liking. |
+ static const FULL_CONTROL = const Permission(#full_control); |
+ static const MIRROR_INSPECT = const Permission(#mirror_inspect); |
+ static const SHUTDOWN = const Permission(#shutdown); |
+ // Allows to control resources (maybe even giving more than usual?). |
+ static const RESOURCE = const Permission(#resource); |
+} |
+ |
+class Isolate { |
+ /** |
+ * Creates and spawns an isolate that shares the same code as the current |
+ * isolate. |
+ * |
+ * The argument [entryPoint] specifies the entry point of the spawned |
+ * isolate. It must be a static top-level function or a static method that |
+ * takes no arguments. It is illegal to pass a function closure. |
Lasse Reichstein Nielsen
2013/10/14 14:26:48
illegal -> not allowed
floitsch
2013/10/14 17:22:41
Done.
|
+ * |
+ * The entryPoint function is invoked with the initial [message]. |
Lasse Reichstein Nielsen
2013/10/14 14:26:48
`entryPoint`
floitsch
2013/10/14 17:22:41
changed to "entry-point".
|
+ * Usually the initial [message] contains a [SendPort] so |
+ * that the spawner and spawnee can communicate with each other. |
Lasse Reichstein Nielsen
2013/10/14 14:26:48
Document return value.
floitsch
2013/10/14 17:22:41
Done, although more needs to be done.
|
+ */ |
+ static Future<Isolate> spawn(void entryPoint(message), var message, |
+ { startPaused, or, other, Arguments, we, will, find, useful }) { |
+ } |
+ |
+ /** |
+ * Creates and spawns an isolate that runs the code from the specified URI. |
+ * |
+ * The entry point of the spawned isolate is automatically set to |
Lasse Reichstein Nielsen
2013/10/14 14:26:48
"... that runs the code from the library with the
floitsch
2013/10/14 17:22:41
Done.
|
+ * `main`. Otherwise similar to [spawn]. |
+ */ |
+ static Future<Isolate> spawnUri(Uri uri, var arguments, { named, args }) { |
+ |
+ } |
+ |
+ /** |
+ * Creates a new isolate instance controlling an existing isolate. |
+ * |
+ * The new instance controls the isolate that is controlled by the |
+ * argument [controlPort]. |
+ * |
+ * The given [permissions] map specifies what the returned instance can |
+ * do with the existing isolate. |
+ */ |
+ Isolate.fromControlPort(SendPort controlPort, |
+ Map<Permission, Capability> permissions) |
+ : _permissions = permissions, |
+ controlPort = controlPort; |
+ |
+ /** |
+ * Listening to this stream will install an error handler on the isolate. |
+ * |
+ * The installation of the error handler is an asynchronous operation. |
+ * If one wants to be sure to see all errors, one should start the isolate in |
+ * a paused state, start listening to the errors, and then only resume the |
+ * other isolate. |
+ */ |
+ Stream uncaughtErrors; |
+ |
+ /** |
+ * Pauses the isolate. |
+ */ |
+ Future pause() {} |
+ |
+ /** |
+ * Resumes the isolate. |
+ */ |
+ Future resume() {} |
+ |
+ Future kill() { |
+ // Proposed implementation: |
+ return controlPort.send([_someInternalObjectIdentifyingKillAction, |
+ _permissions[Permission.SHUTDOWN]]); |
+ } |
+ |
+ /** |
+ * Since this is an asynchronous operation the state might change before |
+ * we get a chance to act on it (if someone else has the capability to |
+ * resume the isolate). |
+ */ |
+ Future<bool> queryIsPaused() {} |
Lasse Reichstein Nielsen
2013/10/14 14:26:48
drop "query". We just have "isPaused" elsewhere, a
floitsch
2013/10/14 17:22:41
Let's discuss this. If we call it "isPaused" it ne
|
+ |
+ /// This port uniquely identifies the spawned isolate. |
+ final SendPort controlPort; |
+ |
+ final Map<Permission, Capability> _permissions; |
+ |
+ /** |
+ * Clones this Isolate but with limited permissions. |
+ * |
+ * When handing out isolates, one should always |
+ */ |
+ Map<Permission, Capability> extractPermissions( |
+ Iterable<Permission> permissions) { |
+ } |
+} |
/** |
- * Together with [ReceivePort], |
- * the only means of communication between isolates. |
+ * Sends messages to its [ReceivePort]s. |
* |
* [SendPort]s are created from [ReceivePort]s. Any message sent through |
* a [SendPort] is delivered to its respective [ReceivePort]. There might be |
@@ -82,8 +154,7 @@ 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 receiving isolate. |
* |
* The content of [message] can be: primitive values (null, num, bool, double, |
* String), instances of [SendPort], and lists and maps whose elements are any |
@@ -94,21 +165,8 @@ abstract class SendPort { |
* 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); |
+ void send(var message); |
/** |
* Tests whether [other] is a [SendPort] pointing to the same |
@@ -121,75 +179,52 @@ abstract class SendPort { |
* consistent with the == operator. |
*/ |
int get hashCode; |
- |
} |
/** |
- * Together with [SendPort], the only means of |
- * communication between isolates. |
+ * 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. |
+ * [ReceivePort]s have a `sendport` getter which returns a [SendPort]. |
+ * Any message that is sent through this [SendPort] |
+ * is delivered to the [ReceivePort] it has been created from. There, the |
+ * message is dispatched to its listener. |
+ * |
+ * A [ReceivePort] is a non-broadcast stream. This means that it buffers |
+ * incoming messages until a listener is registered. Only one listener can |
+ * receive messages. See [Stream.asBroadcastStream] for transforming the port |
+ * to a broadcast stream. |
* |
* A [ReceivePort] may have many [SendPort]s. |
*/ |
-abstract class ReceivePort { |
+abstract class ReceivePort implements Stream { |
/** |
- * Opens a long-lived port for receiving messages. The returned port |
- * must be explicitly closed through [ReceivePort.close]. |
+ * Opens a long-lived port for receiving messages. |
+ * |
+ * A [ReceivePort] is a non-broadcast stream. This means that it buffers |
+ * incoming messages until a listener is registered. Only one listener can |
+ * receive messages. See [Stream.asBroadcastStream] for transforming the port |
+ * to a broadcast stream. |
+ * |
+ * A receive port is closed by canceling its subscription. |
*/ |
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. |
+ * Inherited from [Stream]. |
+ * |
+ * Note that all named arguments are ignored since a ReceivePort will never |
+ * receive an error, or done message. |
*/ |
- bool operator==(var other); |
+ StreamSubscription listen(void callback(var message), |
+ { Function onError, |
+ void onDone(), |
+ bool cancelOnError }); |
/** |
- * Returns an immutable hash code for this send port that is |
- * consistent with the == operator. |
+ * Returns a send port that sends to this receive port. |
*/ |
- int get hashCode; |
+ SendPort get sendPort; |
} |
// The VM doesn't support accessing external globals in the same library. We |
@@ -207,6 +242,7 @@ abstract class _Isolate { |
* used to show both the error message and the stack trace for unhandled |
* exceptions. |
*/ |
+// TODO(floitsch): probably going to remove and replace with something else. |
class IsolateUnhandledException implements Exception { |
/** Message being handled when exception occurred. */ |
final message; |