OLD | NEW |
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 import "dart:collection" show HashMap; | 5 import "dart:collection" show HashMap; |
6 | 6 |
7 patch class ReceivePort { | 7 patch class ReceivePort { |
8 /* patch */ factory ReceivePort() = _ReceivePortImpl; | 8 /* patch */ factory ReceivePort() = _ReceivePortImpl; |
9 | 9 |
10 /* patch */ factory ReceivePort.fromRawReceivePort(RawReceivePort rawPort) = | 10 /* patch */ factory ReceivePort.fromRawReceivePort(RawReceivePort rawPort) = |
(...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
190 typedef _MainFunctionArgs(args); | 190 typedef _MainFunctionArgs(args); |
191 typedef _MainFunctionArgsMessage(args, message); | 191 typedef _MainFunctionArgsMessage(args, message); |
192 | 192 |
193 /** | 193 /** |
194 * Takes the real entry point as argument and invokes it with the | 194 * Takes the real entry point as argument and invokes it with the |
195 * initial message. Defers execution of the entry point until the | 195 * initial message. Defers execution of the entry point until the |
196 * isolate is in the message loop. | 196 * isolate is in the message loop. |
197 */ | 197 */ |
198 void _startMainIsolate(Function entryPoint, | 198 void _startMainIsolate(Function entryPoint, |
199 List<String> args) { | 199 List<String> args) { |
200 RawReceivePort port = new RawReceivePort(); | 200 _startIsolate(null, // no parent port |
201 port.handler = (_) { | 201 entryPoint, |
202 port.close(); | 202 args, |
203 _startIsolate(null, // no parent port | 203 null, // no message |
204 entryPoint, | 204 true, // isSpawnUri |
205 args, | 205 null, // no control port |
206 null, // no message | 206 null); // no capabilities |
207 true, // isSpawnUri | |
208 null, // no control port | |
209 null); // no capabilities | |
210 }; | |
211 port.sendPort.send(null); | |
212 } | 207 } |
213 | 208 |
214 /** | 209 /** |
215 * Takes the real entry point as argument and invokes it with the initial | 210 * Takes the real entry point as argument and invokes it with the initial |
216 * message. | 211 * message. |
217 */ | 212 */ |
218 void _startIsolate(SendPort parentPort, | 213 void _startIsolate(SendPort parentPort, |
219 Function entryPoint, | 214 Function entryPoint, |
220 List<String> args, | 215 List<String> args, |
221 var message, | 216 var message, |
222 bool isSpawnUri, | 217 bool isSpawnUri, |
223 RawReceivePort controlPort, | 218 RawReceivePort controlPort, |
224 List capabilities) { | 219 List capabilities) { |
| 220 // The control port (aka the main isolate port) does not handle any messages. |
225 if (controlPort != null) { | 221 if (controlPort != null) { |
226 controlPort.handler = (_) {}; // Nobody home on the control port. | 222 controlPort.handler = (_) {}; // Nobody home on the control port. |
227 } | 223 } |
| 224 |
228 if (parentPort != null) { | 225 if (parentPort != null) { |
229 // Build a message to our parent isolate providing access to the | 226 // Build a message to our parent isolate providing access to the |
230 // current isolate's control port and capabilities. | 227 // current isolate's control port and capabilities. |
231 // | 228 // |
232 // TODO(floitsch): Send an error message if we can't find the entry point. | 229 // TODO(floitsch): Send an error message if we can't find the entry point. |
233 var readyMessage = new List(2); | 230 var readyMessage = new List(2); |
234 readyMessage[0] = controlPort.sendPort; | 231 readyMessage[0] = controlPort.sendPort; |
235 readyMessage[1] = capabilities; | 232 readyMessage[1] = capabilities; |
236 | 233 |
237 // Out of an excess of paranoia we clear the capabilities from the | 234 // Out of an excess of paranoia we clear the capabilities from the |
238 // stack. Not really necessary. | 235 // stack. Not really necessary. |
239 capabilities = null; | 236 capabilities = null; |
240 parentPort.send(readyMessage); | 237 parentPort.send(readyMessage); |
241 } | 238 } |
242 assert(capabilities == null); | 239 assert(capabilities == null); |
243 | 240 |
244 if (isSpawnUri) { | 241 // Delay all user code handling to the next run of the message loop. This |
245 if (entryPoint is _MainFunctionArgsMessage) { | 242 // allows us to intercept certain conditions in the event dispatch, such as |
246 entryPoint(args, message); | 243 // starting in paused state. |
247 } else if (entryPoint is _MainFunctionArgs) { | 244 RawReceivePort port = new RawReceivePort(); |
248 entryPoint(args); | 245 port.handler = (_) { |
| 246 port.close(); |
| 247 |
| 248 if (isSpawnUri) { |
| 249 if (entryPoint is _MainFunctionArgsMessage) { |
| 250 entryPoint(args, message); |
| 251 } else if (entryPoint is _MainFunctionArgs) { |
| 252 entryPoint(args); |
| 253 } else { |
| 254 entryPoint(); |
| 255 } |
249 } else { | 256 } else { |
250 entryPoint(); | 257 entryPoint(message); |
251 } | 258 } |
252 } else { | 259 }; |
253 entryPoint(message); | 260 // Make sure the message handler is triggered. |
254 } | 261 port.sendPort.send(null); |
255 _runPendingImmediateCallback(); | |
256 } | 262 } |
257 | 263 |
258 patch class Isolate { | 264 patch class Isolate { |
259 static final _currentIsolate = _getCurrentIsolate(); | 265 static final _currentIsolate = _getCurrentIsolate(); |
260 | 266 |
261 /* patch */ static Isolate get current => _currentIsolate; | 267 /* patch */ static Isolate get current => _currentIsolate; |
262 | 268 |
263 /* patch */ static Future<Isolate> spawn( | 269 /* patch */ static Future<Isolate> spawn( |
264 void entryPoint(message), var message, { bool paused: false }) { | 270 void entryPoint(message), var message, { bool paused: false }) { |
265 // `paused` isn't handled yet. | 271 // `paused` isn't handled yet. |
266 RawReceivePort readyPort; | 272 RawReceivePort readyPort; |
267 try { | 273 try { |
268 // The VM will invoke [_startIsolate] with entryPoint as argument. | 274 // The VM will invoke [_startIsolate] with entryPoint as argument. |
269 readyPort = new RawReceivePort(); | 275 readyPort = new RawReceivePort(); |
270 _spawnFunction(readyPort.sendPort, entryPoint, message); | 276 _spawnFunction(readyPort.sendPort, entryPoint, message, paused); |
271 Completer completer = new Completer<Isolate>.sync(); | 277 Completer completer = new Completer<Isolate>.sync(); |
272 readyPort.handler = (readyMessage) { | 278 readyPort.handler = (readyMessage) { |
273 readyPort.close(); | 279 readyPort.close(); |
274 assert(readyMessage is List); | 280 assert(readyMessage is List); |
275 assert(readyMessage.length == 2); | 281 assert(readyMessage.length == 2); |
276 SendPort controlPort = readyMessage[0]; | 282 SendPort controlPort = readyMessage[0]; |
277 List capabilities = readyMessage[1]; | 283 List capabilities = readyMessage[1]; |
278 completer.complete(new Isolate(controlPort, | 284 completer.complete(new Isolate(controlPort, |
279 pauseCapability: capabilities[0], | 285 pauseCapability: capabilities[0], |
280 terminateCapability: capabilities[1])); | 286 terminateCapability: capabilities[1])); |
(...skipping 10 matching lines...) Expand all Loading... |
291 /* patch */ static Future<Isolate> spawnUri( | 297 /* patch */ static Future<Isolate> spawnUri( |
292 Uri uri, List<String> args, var message, | 298 Uri uri, List<String> args, var message, |
293 { bool paused: false, Uri packageRoot }) { | 299 { bool paused: false, Uri packageRoot }) { |
294 // `paused` isn't handled yet. | 300 // `paused` isn't handled yet. |
295 RawReceivePort readyPort; | 301 RawReceivePort readyPort; |
296 try { | 302 try { |
297 // The VM will invoke [_startIsolate] and not `main`. | 303 // The VM will invoke [_startIsolate] and not `main`. |
298 readyPort = new RawReceivePort(); | 304 readyPort = new RawReceivePort(); |
299 var packageRootString = | 305 var packageRootString = |
300 (packageRoot == null) ? null : packageRoot.toString(); | 306 (packageRoot == null) ? null : packageRoot.toString(); |
301 _spawnUri( | 307 _spawnUri(readyPort.sendPort, uri.toString(), args, message, |
302 readyPort.sendPort, uri.toString(), args, message, packageRootString); | 308 paused, packageRootString); |
303 Completer completer = new Completer<Isolate>.sync(); | 309 Completer completer = new Completer<Isolate>.sync(); |
304 readyPort.handler = (readyMessage) { | 310 readyPort.handler = (readyMessage) { |
305 readyPort.close(); | 311 readyPort.close(); |
306 assert(readyMessage is List); | 312 assert(readyMessage is List); |
307 assert(readyMessage.length == 2); | 313 assert(readyMessage.length == 2); |
308 SendPort controlPort = readyMessage[0]; | 314 SendPort controlPort = readyMessage[0]; |
309 List capabilities = readyMessage[1]; | 315 List capabilities = readyMessage[1]; |
310 completer.complete(new Isolate(controlPort, | 316 completer.complete(new Isolate(controlPort, |
311 pauseCapability: capabilities[0], | 317 pauseCapability: capabilities[0], |
312 terminateCapability: capabilities[1])); | 318 terminateCapability: capabilities[1])); |
(...skipping 11 matching lines...) Expand all Loading... |
324 // TODO(iposva): Cleanup to have only one definition. | 330 // TODO(iposva): Cleanup to have only one definition. |
325 // These values need to be kept in sync with the class IsolateMessageHandler | 331 // These values need to be kept in sync with the class IsolateMessageHandler |
326 // in vm/isolate.cc. | 332 // in vm/isolate.cc. |
327 static const _PAUSE = 1; | 333 static const _PAUSE = 1; |
328 static const _RESUME = 2; | 334 static const _RESUME = 2; |
329 static const _PING = 3; | 335 static const _PING = 3; |
330 static const _KILL = 4; | 336 static const _KILL = 4; |
331 | 337 |
332 | 338 |
333 static SendPort _spawnFunction(SendPort readyPort, Function topLevelFunction, | 339 static SendPort _spawnFunction(SendPort readyPort, Function topLevelFunction, |
334 var message) | 340 var message, bool paused) |
335 native "Isolate_spawnFunction"; | 341 native "Isolate_spawnFunction"; |
336 | 342 |
337 static SendPort _spawnUri(SendPort readyPort, String uri, | 343 static SendPort _spawnUri(SendPort readyPort, String uri, |
338 List<String> args, var message, | 344 List<String> args, var message, |
339 String packageRoot) | 345 bool paused, String packageRoot) |
340 native "Isolate_spawnUri"; | 346 native "Isolate_spawnUri"; |
341 | 347 |
342 static void _sendOOB(port, msg) native "Isolate_sendOOB"; | 348 static void _sendOOB(port, msg) native "Isolate_sendOOB"; |
343 | 349 |
344 /* patch */ void _pause(Capability resumeCapability) { | 350 /* patch */ void _pause(Capability resumeCapability) { |
345 var msg = new List(4) | 351 var msg = new List(4) |
346 ..[0] = 0 // Make room for OOB message type. | 352 ..[0] = 0 // Make room for OOB message type. |
347 ..[1] = _PAUSE | 353 ..[1] = _PAUSE |
348 ..[2] = pauseCapability | 354 ..[2] = pauseCapability |
349 ..[3] = resumeCapability; | 355 ..[3] = resumeCapability; |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
400 static Isolate _getCurrentIsolate() { | 406 static Isolate _getCurrentIsolate() { |
401 List portAndCapabilities = _getPortAndCapabilitiesOfCurrentIsolate(); | 407 List portAndCapabilities = _getPortAndCapabilitiesOfCurrentIsolate(); |
402 return new Isolate(portAndCapabilities[0], | 408 return new Isolate(portAndCapabilities[0], |
403 pauseCapability: portAndCapabilities[1], | 409 pauseCapability: portAndCapabilities[1], |
404 terminateCapability: portAndCapabilities[2]); | 410 terminateCapability: portAndCapabilities[2]); |
405 } | 411 } |
406 | 412 |
407 static List _getPortAndCapabilitiesOfCurrentIsolate() | 413 static List _getPortAndCapabilitiesOfCurrentIsolate() |
408 native "Isolate_getPortAndCapabilitiesOfCurrentIsolate"; | 414 native "Isolate_getPortAndCapabilitiesOfCurrentIsolate"; |
409 } | 415 } |
OLD | NEW |