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

Side by Side Diff: sdk/lib/_internal/lib/isolate_helper.dart

Issue 179823002: Add Isolate.onExit. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 10 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/_internal/lib/isolate_patch.dart » ('j') | sdk/lib/isolate/isolate.dart » ('J')
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 library _isolate_helper; 5 library _isolate_helper;
6 6
7 import 'dart:async'; 7 import 'dart:async';
8 import 'dart:collection' show Queue, HashMap; 8 import 'dart:collection' show Queue, HashMap;
9 import 'dart:isolate'; 9 import 'dart:isolate';
10 import 'dart:_js_helper' show 10 import 'dart:_js_helper' show
(...skipping 14 matching lines...) Expand all
25 /** 25 /**
26 * Called by the compiler to support switching 26 * Called by the compiler to support switching
27 * between isolates when we get a callback from the DOM. 27 * between isolates when we get a callback from the DOM.
28 */ 28 */
29 _callInIsolate(_IsolateContext isolate, Function function) { 29 _callInIsolate(_IsolateContext isolate, Function function) {
30 var result = isolate.eval(function); 30 var result = isolate.eval(function);
31 _globalState.topEventLoop.run(); 31 _globalState.topEventLoop.run();
32 return result; 32 return result;
33 } 33 }
34 34
35 /// Marks entering a javascript async operation to keep the worker alive.
36 /// Marks entering a JavaScript async operation to keep the worker alive. 35 /// Marks entering a JavaScript async operation to keep the worker alive.
37 /// 36 ///
38 /// To be called by library code before starting an async operation controlled 37 /// To be called by library code before starting an async operation controlled
39 /// by the JavaScript event handler. 38 /// by the JavaScript event handler.
40 /// 39 ///
41 /// Also call [leaveJsAsync] in all callback handlers marking the end of that 40 /// Also call [leaveJsAsync] in all callback handlers marking the end of that
42 /// async operation (also error handlers) so the worker can be released. 41 /// async operation (also error handlers) so the worker can be released.
43 /// 42 ///
44 /// These functions only has to be called for code that can be run from a 43 /// These functions only has to be called for code that can be run from a
45 /// worker-isolate (so not for general dom operations). 44 /// worker-isolate (so not for general dom operations).
(...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after
263 /** Registry of weak receive ports currently active on this isolate. */ 262 /** Registry of weak receive ports currently active on this isolate. */
264 final Set<int> weakPorts = new Set<int>(); 263 final Set<int> weakPorts = new Set<int>();
265 264
266 /** Holds isolate globals (statics and top-level properties). */ 265 /** Holds isolate globals (statics and top-level properties). */
267 // native object containing all globals of an isolate. 266 // native object containing all globals of an isolate.
268 final isolateStatics = JS_CREATE_ISOLATE(); 267 final isolateStatics = JS_CREATE_ISOLATE();
269 268
270 final RawReceivePortImpl controlPort = new RawReceivePortImpl._controlPort(); 269 final RawReceivePortImpl controlPort = new RawReceivePortImpl._controlPort();
271 270
272 final Capability pauseCapability = new Capability(); 271 final Capability pauseCapability = new Capability();
272 final Capability inspectCapability = new Capability();
273 273
274 // TODO(lrn): Store these in single "PauseState" object, so they don't take 274 // TODO(lrn): Store these in single "PauseState" object, so they don't take
275 // up as much room when not pausing. 275 // up as much room when not pausing.
276 bool isPaused = false; 276 bool isPaused = false;
277 List<_IsolateEvent> delayedEvents = []; 277 List<_IsolateEvent> delayedEvents = [];
278 Set<Capability> pauseTokens = new Set(); 278 Set<Capability> pauseTokens = new Set();
279 279
280 // Container with the "on exit" handler send-ports.
281 var doneHandlers;
282
280 _IsolateContext() { 283 _IsolateContext() {
281 this.registerWeak(controlPort._id, controlPort); 284 this.registerWeak(controlPort._id, controlPort);
282 } 285 }
283 286
284 void addPause(Capability authentification, Capability resume) { 287 void addPause(Capability authentification, Capability resume) {
285 if (pauseCapability != authentification) return; 288 if (pauseCapability != authentification) return;
286 if (pauseTokens.add(resume) && !isPaused) { 289 if (pauseTokens.add(resume) && !isPaused) {
287 isPaused = true; 290 isPaused = true;
288 } 291 }
289 _updateGlobalState(); 292 _updateGlobalState();
290 } 293 }
291 294
292 void removePause(Capability resume) { 295 void removePause(Capability resume) {
293 if (!isPaused) return; 296 if (!isPaused) return;
294 pauseTokens.remove(resume); 297 pauseTokens.remove(resume);
295 if (pauseTokens.isEmpty) { 298 if (pauseTokens.isEmpty) {
296 while(delayedEvents.isNotEmpty) { 299 while(delayedEvents.isNotEmpty) {
297 _IsolateEvent event = delayedEvents.removeLast(); 300 _IsolateEvent event = delayedEvents.removeLast();
298 _globalState.topEventLoop.prequeue(event); 301 _globalState.topEventLoop.prequeue(event);
299 } 302 }
300 isPaused = false; 303 isPaused = false;
301 } 304 }
302 _updateGlobalState(); 305 _updateGlobalState();
303 } 306 }
304 307
308 void addDoneListener(Capability inspect, SendPort response) {
309 if (inspectCapability != inspect) return;
310 if (doneHandlers == null) {
311 doneHandlers = [];
312 }
313 // If necessary, we can switch doneHandlers to a Set if it gets larget.
floitsch 2014/02/25 19:25:48 larger.
314 // That is not expected to happen in practice.
315 if (doneHandlers.contains(response)) return;
316 doneHandlers.add(response);
317 }
318
305 /** 319 /**
306 * Run [code] in the context of the isolate represented by [this]. 320 * Run [code] in the context of the isolate represented by [this].
307 */ 321 */
308 dynamic eval(Function code) { 322 dynamic eval(Function code) {
309 var old = _globalState.currentContext; 323 var old = _globalState.currentContext;
310 _globalState.currentContext = this; 324 _globalState.currentContext = this;
311 this._setGlobals(); 325 this._setGlobals();
312 var result = null; 326 var result = null;
313 try { 327 try {
314 result = code(); 328 result = code();
315 } finally { 329 } finally {
316 _globalState.currentContext = old; 330 _globalState.currentContext = old;
317 if (old != null) old._setGlobals(); 331 if (old != null) old._setGlobals();
318 } 332 }
319 return result; 333 return result;
320 } 334 }
321 335
322 void _setGlobals() { 336 void _setGlobals() {
323 JS_SET_CURRENT_ISOLATE(isolateStatics); 337 JS_SET_CURRENT_ISOLATE(isolateStatics);
324 } 338 }
325 339
326 void handleControlMessage(message) { 340 void handleControlMessage(message) {
327 switch (message[0]) { 341 switch (message[0]) {
328 case "pause": 342 case "pause":
329 addPause(message[1], message[2]); 343 addPause(message[1], message[2]);
330 break; 344 break;
331 case "resume": 345 case "resume":
332 removePause(message[1]); 346 removePause(message[1]);
333 break; 347 break;
348 case 'ondone':
349 addDoneListener(message[1], message[2]);
350 break;
334 default: 351 default:
335 print("UNKOWN MESSAGE: $message"); 352 print("UNKNOWN MESSAGE: $message");
336 } 353 }
337 } 354 }
338 355
339 /** Looks up a port registered for this isolate. */ 356 /** Looks up a port registered for this isolate. */
340 RawReceivePortImpl lookup(int portId) => ports[portId]; 357 RawReceivePortImpl lookup(int portId) => ports[portId];
341 358
342 void _addRegistration(int portId, RawReceivePortImpl port) { 359 void _addRegistration(int portId, RawReceivePortImpl port) {
343 if (ports.containsKey(portId)) { 360 if (ports.containsKey(portId)) {
344 throw new Exception("Registry: ports must be registered only once."); 361 throw new Exception("Registry: ports must be registered only once.");
345 } 362 }
346 ports[portId] = port; 363 ports[portId] = port;
347 } 364 }
348 365
349 /** Registers a port on this isolate. */ 366 /** Registers a port on this isolate. */
350 void register(int portId, RawReceivePortImpl port) { 367 void register(int portId, RawReceivePortImpl port) {
351 _addRegistration(portId, port); 368 _addRegistration(portId, port);
352 _updateGlobalState(); 369 _updateGlobalState();
353 } 370 }
354 371
355 /** 372 /**
356 * Registers a weak port on this isolate. 373 * Registers a weak port on this isolate.
357 * 374 *
358 * The port does not keep the isolate active. 375 * The port does not keep the isolate active.
359 */ 376 */
360 void registerWeak(int portId, RawReceivePortImpl port) { 377 void registerWeak(int portId, RawReceivePortImpl port) {
361 weakPorts.add(portId); 378 weakPorts.add(portId);
362 _addRegistration(portId, port); 379 _addRegistration(portId, port);
363 } 380 }
364 381
365 _updateGlobalState() { 382 void _updateGlobalState() {
366 if (ports.length - weakPorts.length > 0 || isPaused) { 383 if (ports.length - weakPorts.length > 0 || isPaused) {
367 _globalState.isolates[id] = this; // indicate this isolate is active 384 _globalState.isolates[id] = this; // indicate this isolate is active
368 } else { 385 } else {
369 _globalState.isolates.remove(id); // indicate this isolate is not active 386 _shutdown();
370 } 387 }
371 } 388 }
372 389
390 void _shutdown() {
391 _globalState.isolates.remove(id); // indicate this isolate is not active
floitsch 2014/02/25 19:25:48 "I"ndicate ... active"."
392 // Send "done" event to all listeners. This must be done after deactivating
393 // the current isolate, or it may get events if listening to itself.
394 if (doneHandlers != null) {
395 for (SendPort port in doneHandlers) {
396 port.send(null);
397 }
398 }
399 }
400
373 /** Unregister a port on this isolate. */ 401 /** Unregister a port on this isolate. */
374 void unregister(int portId) { 402 void unregister(int portId) {
375 ports.remove(portId); 403 ports.remove(portId);
376 weakPorts.remove(portId); 404 weakPorts.remove(portId);
377 _updateGlobalState(); 405 _updateGlobalState();
378 } 406 }
379 } 407 }
380 408
381 /** Represent the event loop on a javascript thread (DOM or worker). */ 409 /** Represent the event loop on a javascript thread (DOM or worker). */
382 class _EventLoop { 410 class _EventLoop {
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after
513 /// Note: IsolateNatives depends on _globalState which is only set up correctly 541 /// Note: IsolateNatives depends on _globalState which is only set up correctly
514 /// when 'dart:isolate' has been imported. 542 /// when 'dart:isolate' has been imported.
515 class IsolateNatives { 543 class IsolateNatives {
516 544
517 static String thisScript = computeThisScript(); 545 static String thisScript = computeThisScript();
518 546
519 /// Associates an ID with a native worker object. 547 /// Associates an ID with a native worker object.
520 static final Expando<int> workerIds = new Expando<int>(); 548 static final Expando<int> workerIds = new Expando<int>();
521 549
522 /** 550 /**
523 * The src url for the script tag that loaded this code. Used to create 551 * The src url for the script tag that loaded this Used to create
floitsch 2014/02/25 19:25:48 missing ".".
524 * JavaScript workers. 552 * JavaScript workers.
525 */ 553 */
526 static String computeThisScript() { 554 static String computeThisScript() {
527 var currentScript = JS('', r'init.currentScript'); 555 var currentScript = JS('', r'init.currentScript');
528 if (currentScript != null) { 556 if (currentScript != null) {
529 return JS('String', 'String(#.src)', currentScript); 557 return JS('String', 'String(#.src)', currentScript);
530 } 558 }
531 if (Primitives.isD8) return computeThisScriptD8(); 559 if (Primitives.isD8) return computeThisScriptD8();
532 if (Primitives.isJsshell) return computeThisScriptJsshell(); 560 if (Primitives.isJsshell) return computeThisScriptJsshell();
533 // A worker has no script tag - so get an url from a stack-trace. 561 // A worker has no script tag - so get an url from a stack-trace.
(...skipping 247 matching lines...) Expand 10 before | Expand all | Expand 10 after
781 static void _startIsolate(Function topLevel, 809 static void _startIsolate(Function topLevel,
782 List<String> args, message, 810 List<String> args, message,
783 bool isSpawnUri, 811 bool isSpawnUri,
784 bool startPaused, 812 bool startPaused,
785 SendPort replyTo) { 813 SendPort replyTo) {
786 _IsolateContext context = JS_CURRENT_ISOLATE_CONTEXT(); 814 _IsolateContext context = JS_CURRENT_ISOLATE_CONTEXT();
787 Primitives.initializeStatics(context.id); 815 Primitives.initializeStatics(context.id);
788 // The isolate's port does not keep the isolate open. 816 // The isolate's port does not keep the isolate open.
789 replyTo.send([_SPAWNED_SIGNAL, 817 replyTo.send([_SPAWNED_SIGNAL,
790 context.controlPort.sendPort, 818 context.controlPort.sendPort,
791 context.pauseCapability]); 819 context.pauseCapability,
820 context.inspectCapability]);
792 821
793 void runStartFunction() { 822 void runStartFunction() {
794 if (!isSpawnUri) { 823 if (!isSpawnUri) {
795 topLevel(message); 824 topLevel(message);
796 } else if (topLevel is _MainFunctionArgsMessage) { 825 } else if (topLevel is _MainFunctionArgsMessage) {
797 topLevel(args, message); 826 topLevel(args, message);
798 } else if (topLevel is _MainFunctionArgs) { 827 } else if (topLevel is _MainFunctionArgs) {
799 topLevel(args); 828 topLevel(args);
800 } else { 829 } else {
801 topLevel(); 830 topLevel();
(...skipping 721 matching lines...) Expand 10 before | Expand all | Expand 10 after
1523 } 1552 }
1524 1553
1525 bool operator==(Object other) { 1554 bool operator==(Object other) {
1526 if (identical(other, this)) return true; 1555 if (identical(other, this)) return true;
1527 if (other is CapabilityImpl) { 1556 if (other is CapabilityImpl) {
1528 return identical(_id, other._id); 1557 return identical(_id, other._id);
1529 } 1558 }
1530 return false; 1559 return false;
1531 } 1560 }
1532 } 1561 }
OLDNEW
« no previous file with comments | « no previous file | sdk/lib/_internal/lib/isolate_patch.dart » ('j') | sdk/lib/isolate/isolate.dart » ('J')

Powered by Google App Engine
This is Rietveld 408576698