Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(523)

Side by Side Diff: sdk/lib/isolate/isolate.dart

Issue 20703003: Proposal for new Isolate library. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Using capabilities. Created 7 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | sdk/lib/isolate/isolate_stream.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 {
22 const IsolateSpawnException(String this._s); 23 const IsolateSpawnException(String this._s);
23 String toString() => "IsolateSpawnException: '$_s'"; 24 String toString() => "IsolateSpawnException: '$_s'";
24 final String _s; 25 final String _s;
25 } 26 }
26 27
27 /** 28 /**
28 * The initial ReceivePort available by default for this isolate. 29 * This class should be part of dart:isolate.
29 * 30 *
30 * This ReceivePort is created automatically 31 * A capability is unique among all isolates and can be shared with
31 * and is commonly used to establish 32 * other isolates.
Søren Gjesse 2013/09/27 07:04:11 Maybe say that instances of Capability are opaque
floitsch 2013/10/12 17:04:38 Done.
32 * the first communication between isolates.
33 * (See [spawnFunction] and [spawnUri].)
34 */ 33 */
35 ReceivePort get port => _Isolate.port; 34 class Capability {
35 }
36 36
37 /** 37 /**
38 * Creates and spawns an isolate 38 * An enum that enumeratos permissions that are required to control isolates.
39 * that shares the same code as the current isolate,
40 * but that starts from the specified function.
41 * 39 *
42 * The [topLevelFunction] argument must be 40 * Some control messages require capabilities to be accepted by the isolate.
43 * a static top-level function or a static method that takes no 41 * The [Permission] enum gives these capabilities names.
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 */ 42 */
58 SendPort spawnFunction(void topLevelFunction(), 43 class Permission {
kasperl 2013/09/27 07:42:19 Not sure you're going to need this class. It feels
floitsch 2013/10/12 17:04:38 Yes, but I think there will be many Permissions.
59 [bool unhandledExceptionCallback(IsolateUnhandledException e)]) 44 final Symbol _permission;
60 => _Isolate.spawnFunction(topLevelFunction, unhandledExceptionCallback); 45 const Permission(this._permission);
46
Søren Gjesse 2013/09/27 07:04:11 FULL_CONTROL premission?
floitsch 2013/10/12 17:04:38 Done.
47 // Mirror-modify basically allows everything, since we can just modify the
48 // program to our liking.
49 static const MIRROR_MODIFY = const Permission(#mirror_modify);
50 static const MIRROR_INSPECT = const Permission(#mirror_inspect);
51 static const SHUTDOWN = const Permission(#shutdown);
52 // Allows to control resources (maybe even giving more than usual?).
53 static const RESOURCE = const Permission(#resource);
54 }
55
56 class Isolate {
57 /**
58 * Creates and spawns an isolate that shares the same code as the current
59 * isolate.
60 *
61 * The argument [entryPoint] specifies the entry point of the spawned
62 * isolate. It must be a static top-level function or a static method that
63 * takes no arguments. It is illegal to pass a function closure.
64 *
65 * The entryPoint function is invoked with the initial [message].
66 * Usually the initial [message] contains a [SendPort] so
67 * that the spawner and spawnee can communicate with each other.
68 */
69 static Future<Isolate> spawn(void entryPoint(message), var message,
70 { startPaused, or, other, Arguments, we, will, find, useful }) {
71 }
72
73 /**
74 * Creates and spawns an isolate that runs the code from the specified URI.
75 *
76 * The entry point of the spawned isolate is automatically set to
77 * `main`. Otherwise similar to [spawn].
Søren Gjesse 2013/09/27 07:04:11 How about the arguments here vs. message above can
floitsch 2013/10/12 17:04:38 Yes. It is crucial to be able to send Sendports.
78 */
79 static Future<Isolate> spawnUri(Uri uri, var arguments, { named, args }) {
80
81 }
82
83 /**
84 * Creates a new isolate instance controlling an existing isolate.
85 *
86 * The new instance controls the isolate that is controlled by the
87 * argument [controlPort].
88 *
89 * The given [permissions] map specifies what the returned instance can
90 * do with the existing isolate.
91 */
92 Isolate.fromControlPort(SendPort controlPort,
93 Map<Permission, Capability> permissions)
94 : _permissions = permissions,
95 controlPort = controlPort;
96
97 /**
98 * Listening to this stream will install an error handler on the isolate.
99 *
100 * The installation of the error handler is an asynchronous operation.
101 * If one wants to be sure to see all errors, one should start the isolate in
102 * a paused state, start listening to the errors, and then only resume the
103 * other isolate.
104 */
105 Stream uncaughtErrors;
106
107 /**
108 * Pauses the isolate.
Søren Gjesse 2013/09/27 07:04:11 How immediate is this pause? Pause when returning
floitsch 2013/10/12 17:04:38 There will be different ways to pause: either at t
109 */
110 Future pause() {}
111
112 /**
113 * Resumes the isolate.
114 */
115 Future resume() {}
116
117 Future kill() {
Søren Gjesse 2013/09/27 07:04:11 Should there be a optional Capability argument to
floitsch 2013/10/12 17:04:38 Interesting idea. I will think about it.
118 // Proposed implementation:
119 return controlPort.call([_someInternalObjectIdentifyingKillAction,
120 _permissions[Permission.SHUTDOWN]]);
121 }
122
123 /**
124 * Since this is an asynchronous operation the state might change before
125 * we get a chance to act on it (if someone else has the capability to
126 * resume the isolate).
127 */
128 Future<bool> queryIsPaused() {}
129
130 /// This id uniquely identifies the spawned isolate.
Søren Gjesse 2013/09/27 07:04:11 "This id"?
floitsch 2013/10/12 17:04:38 Old comment. Updated.
131 final SendPort controlPort;
Søren Gjesse 2013/09/27 07:04:11 I assume corresponding receive port is not directl
floitsch 2013/10/12 17:04:38 Correct.
132
133 final Map<Permission, Capability> _permissions;
134
135 /**
136 * Clones this Isolate but with limited permissions.
Søren Gjesse 2013/09/27 07:04:11 By "clone" don't you mean just making a new refere
floitsch 2013/10/12 17:04:38 Correct.
137 *
138 * When handing out isolates, one should always
139 */
140 Map<Permission, Capability> extractPermissions(
141 Iterable<Permission> permissions) {
142 }
143 }
61 144
62 /** 145 /**
63 * Creates and spawns an isolate that runs the code from the specified URI. 146 * When a SendPort sends a message to a ReceivePort the receiving end receives
64 * 147 * an instance of this class.
65 * As with [spawnFunction],
66 * the child isolate has a default [ReceivePort],
67 * and this function returns a [SendPort] derived from it.
68 */ 148 */
69 SendPort spawnUri(String uri) => _Isolate.spawnUri(uri); 149 class IsolateMessage {
kasperl 2013/09/27 07:42:19 I'm not too keen on wrapping all messages in new o
Ivan Posva 2013/09/30 02:59:41 Agree with Kasper, no extra wrapping.
floitsch 2013/10/12 17:04:38 Done.
150 final message;
151 final SendPort replyPort;
152 final SendPort sourceIsolate; // should we have this?
153
154 void reply(msg, { replyTo }) {
155 if (replyPort != null) replyPort.send(msg, replyTo: replyTo);
156 }
157
158 IsolateMessage._(this.message, this.replyPort, this.sourceIsolate);
159 }
70 160
71 /** 161 /**
72 * Together with [ReceivePort], 162 * Sends messages to its [ReceivePort]s.
73 * the only means of communication between isolates.
74 * 163 *
75 * [SendPort]s are created from [ReceivePort]s. Any message sent through 164 * [SendPort]s are created from [ReceivePort]s. Any message sent through
76 * a [SendPort] is delivered to its respective [ReceivePort]. There might be 165 * a [SendPort] is delivered to its respective [ReceivePort]. There might be
77 * many [SendPort]s for the same [ReceivePort]. 166 * many [SendPort]s for the same [ReceivePort].
78 * 167 *
79 * [SendPort]s can be transmitted to other isolates. 168 * [SendPort]s can be transmitted to other isolates.
80 */ 169 */
81 abstract class SendPort { 170 abstract class SendPort {
82 171
83 /** 172 /**
84 * Sends an asynchronous [message] to this send port. The message is copied to 173 * 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 174 * the receiving isolate. If specified, the [replyTo] port will be provided to
86 * the receiver to facilitate exchanging sequences of messages. 175 * the receiver to facilitate exchanging sequences of messages.
87 * 176 *
88 * The content of [message] can be: primitive values (null, num, bool, double, 177 * 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 178 * String), instances of [SendPort], and lists and maps whose elements are any
90 * of these. List and maps are also allowed to be cyclic. 179 * of these. List and maps are also allowed to be cyclic.
91 * 180 *
92 * In the special circumstances when two isolates share the same code and are 181 * 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 182 * 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 183 * 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 184 * process). This is currently only supported by the dartvm. For now, the
96 * dart2js compiler only supports the restricted messages described above. 185 * dart2js compiler only supports the restricted messages described above.
97 * 186 *
98 * Deprecation note: it is no longer valid to transmit a [ReceivePort] in a 187 * Deprecation note: it is no longer valid to transmit a [ReceivePort] in a
99 * message. Previously they were translated to the corresponding send port 188 * message. Previously they were translated to the corresponding send port
100 * before being transmitted. 189 * before being transmitted.
101 */ 190 */
102 void send(var message, [SendPort replyTo]); 191 void send(var message, { SendPort replyTo });
kasperl 2013/09/27 07:42:19 I think we should drop the replyTo argument (and l
Ivan Posva 2013/09/30 02:59:41 I do not see how the replyTo port is accessed on t
floitsch 2013/10/12 17:04:38 It would have been in the IsolateMessage. But gone
103 192
104 /** 193 /**
105 * Sends a message to this send port and returns a [Future] of the reply. 194 * 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 195 * Basically, this internally creates a new receive port, sends a
Ivan Posva 2013/09/30 02:59:41 This internal description is too detailed and we a
floitsch 2013/10/12 17:04:38 call is gone.
107 * message to this send port with replyTo set to such receive port, and, when 196 * 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 197 * a reply is received, it closes the receive port and completes the returned
109 * future. 198 * future.
199 *
200 * The [Future] extracts the message from the [IsolateMessage].
kasperl 2013/09/27 07:42:19 I don't like IsolateMessage in this context either
floitsch 2013/10/12 17:04:38 call is gone.
110 */ 201 */
111 Future call(var message); 202 Future call(var message);
112 203
113 /** 204 /**
114 * Tests whether [other] is a [SendPort] pointing to the same 205 * Tests whether [other] is a [SendPort] pointing to the same
115 * [ReceivePort] as this one. 206 * [ReceivePort] as this one.
116 */ 207 */
117 bool operator==(var other); 208 bool operator==(var other);
118 209
119 /** 210 /**
120 * Returns an immutable hash code for this send port that is 211 * Returns an immutable hash code for this send port that is
121 * consistent with the == operator. 212 * consistent with the == operator.
122 */ 213 */
123 int get hashCode; 214 int get hashCode;
124 215
125 } 216 }
126 217
127 /** 218 /**
128 * Together with [SendPort], the only means of 219 * Together with [SendPort], the only means of
129 * communication between isolates. 220 * communication between isolates.
130 * 221 *
131 * [ReceivePort]s have a [:toSendPort:] method 222 * [ReceivePort]s have a `sendport` getter
132 * which returns a [SendPort]. Any message that is sent through this [SendPort] 223 * 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 224 * 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. 225 * dispatched to the callback that has been registered on the receive port.
135 * 226 *
136 * A [ReceivePort] may have many [SendPort]s. 227 * A [ReceivePort] may have many [SendPort]s.
137 */ 228 */
138 abstract class ReceivePort { 229 // TODO(floitsch): should the ReceivePort be a broadcast stream or not?
230 // Broadcast stream: allows multiple listeners. May drop messages if nobody
231 // is listening.
232 // Non broadcast stream: one listener only. Buffers messages is nobody listens.
233 // I vote for non-broadcast.
kasperl 2013/09/27 07:42:19 Non-broadcast gives us the option to add broadcast
floitsch 2013/10/12 17:04:38 Non-broadcast it is.
234 abstract class ReceivePort implements Stream<IsolateMessage> {
139 235
140 /** 236 /**
141 * Opens a long-lived port for receiving messages. The returned port 237 * Opens a long-lived port for receiving messages. The returned port
142 * must be explicitly closed through [ReceivePort.close]. 238 * must be explicitly closed through [ReceivePort.close].
143 */ 239 */
144 external factory ReceivePort(); 240 external factory ReceivePort();
145 241
146 /** 242 /**
147 * Sets up a callback function for receiving pending or future 243 * Inherited from [Stream].
148 * messages on this receive port.
149 */ 244 */
150 void receive(void callback(var message, SendPort replyTo)); 245 StreamSubscription<IsolateMessage> listen(
246 void callback(IsolateMessage message),
247 { void onError(e) ,
248 void onDone(),
249 bool cancelOnError });
151 250
152 /** 251 /**
153 * Closes this receive port immediately. Pending messages will not 252 * Closes this receive port immediately. Pending messages will not
154 * be processed and it is impossible to re-open the port. Single-shot 253 * be processed and it is impossible to re-open the port. Single-shot
155 * reply ports, such as those created through [SendPort.call], are 254 * reply ports, such as those created through [SendPort.call], are
156 * automatically closed when the reply has been received. Multiple 255 * automatically closed when the reply has been received. Multiple
157 * invocations of [close] are allowed but ignored. 256 * invocations of [close] are allowed but ignored.
158 */ 257 */
159 void close(); 258 void close();
160 259
161 /** 260 /**
162 * Creates a new send port that sends to this receive port. It is legal to 261 * Returns a send port that sends to this receive port.
163 * create several [SendPort]s from the same [ReceivePort].
164 */ 262 */
165 SendPort toSendPort(); 263 SendPort get sendPort;
166
167 } 264 }
168 265
169 /** 266 /**
170 * [SendPortSync]s are created from [ReceivePortSync]s. Any message sent through 267 * [SendPortSync]s are created from [ReceivePortSync]s. Any message sent through
171 * a [SendPortSync] is delivered to its respective [ReceivePortSync]. There 268 * a [SendPortSync] is delivered to its respective [ReceivePortSync]. There
172 * might be many [SendPortSync]s for the same [ReceivePortSync]. 269 * might be many [SendPortSync]s for the same [ReceivePortSync].
173 * 270 *
174 * [SendPortSync]s can be transmitted to other isolates. 271 * [SendPortSync]s can be transmitted to other isolates.
175 */ 272 */
176 abstract class SendPortSync { 273 abstract class SendPortSync {
(...skipping 23 matching lines...) Expand all
200 external static SendPort spawnFunction(void topLevelFunction(), 297 external static SendPort spawnFunction(void topLevelFunction(),
201 [bool unhandledExceptionCallback(IsolateUnhandledException e)]); 298 [bool unhandledExceptionCallback(IsolateUnhandledException e)]);
202 external static SendPort spawnUri(String uri); 299 external static SendPort spawnUri(String uri);
203 } 300 }
204 301
205 /** 302 /**
206 * Wraps unhandled exceptions thrown during isolate execution. It is 303 * Wraps unhandled exceptions thrown during isolate execution. It is
207 * used to show both the error message and the stack trace for unhandled 304 * used to show both the error message and the stack trace for unhandled
208 * exceptions. 305 * exceptions.
209 */ 306 */
307 // TODO(floitsch): probably going to remove and replace with something else.
210 class IsolateUnhandledException implements Exception { 308 class IsolateUnhandledException implements Exception {
211 /** Message being handled when exception occurred. */ 309 /** Message being handled when exception occurred. */
212 final message; 310 final message;
213 311
214 /** Wrapped exception. */ 312 /** Wrapped exception. */
215 final source; 313 final source;
216 314
217 /** Trace for the wrapped exception. */ 315 /** Trace for the wrapped exception. */
218 final Object stackTrace; 316 final Object stackTrace;
219 317
220 const IsolateUnhandledException(this.message, this.source, this.stackTrace); 318 const IsolateUnhandledException(this.message, this.source, this.stackTrace);
221 319
222 String toString() { 320 String toString() {
223 return 'IsolateUnhandledException: exception while handling message: ' 321 return 'IsolateUnhandledException: exception while handling message: '
224 '${message} \n ' 322 '${message} \n '
225 '${source.toString().replaceAll("\n", "\n ")}\n' 323 '${source.toString().replaceAll("\n", "\n ")}\n'
226 'original stack trace:\n ' 324 'original stack trace:\n '
227 '${stackTrace.toString().replaceAll("\n","\n ")}'; 325 '${stackTrace.toString().replaceAll("\n","\n ")}';
228 } 326 }
229 } 327 }
OLDNEW
« no previous file with comments | « no previous file | sdk/lib/isolate/isolate_stream.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698