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

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

Issue 190013005: Add Isolate.kill(). (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Changed naming and meaning of priorities Created 6 years, 9 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.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 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 262 matching lines...) Expand 10 before | Expand all | Expand 10 after
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. 280 // Container with the "on exit" handler send-ports.
281 var doneHandlers; 281 var doneHandlers;
282 282
283 /**
284 * Queue of functions to call when the current event is complete.
285 *
286 * These events are not just put at the front of the event queue, because
287 * they represent control messages, and should be handled even if the
288 * event queue is paused.
289 */
290 var _scheduledControlEvents;
291
283 /** Whether errors are considered fatal. */ 292 /** Whether errors are considered fatal. */
284 // This doesn't do anything yet. We need to be able to catch uncaught errors 293 // This doesn't do anything yet. We need to be able to catch uncaught errors
285 // (oxymoronically) in order to take lethal action. This is waiting for the 294 // (oxymoronically) in order to take lethal action. This is waiting for the
286 // same change as the uncaught error listeners. 295 // same change as the uncaught error listeners.
287 bool errorsAreFatal = false; 296 bool errorsAreFatal = false;
288 297
289 _IsolateContext() { 298 _IsolateContext() {
290 this.registerWeak(controlPort._id, controlPort); 299 this.registerWeak(controlPort._id, controlPort);
291 } 300 }
292 301
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
325 if (doneHandlers == null) return; 334 if (doneHandlers == null) return;
326 doneHandlers.remove(responsePort); 335 doneHandlers.remove(responsePort);
327 } 336 }
328 337
329 void setErrorsFatal(Capability authentification, bool errorsAreFatal) { 338 void setErrorsFatal(Capability authentification, bool errorsAreFatal) {
330 if (terminateCapability != authentification) return; 339 if (terminateCapability != authentification) return;
331 this.errorsAreFatal = errorsAreFatal; 340 this.errorsAreFatal = errorsAreFatal;
332 } 341 }
333 342
334 void handlePing(SendPort responsePort, int pingType) { 343 void handlePing(SendPort responsePort, int pingType) {
335 if (pingType == Isolate.PING_EVENT) { 344 if (pingType == Isolate.OUT_OF_BAND ||
336 _globalState.topEventLoop.enqueue(this, () { 345 (pingType == Isolate.BEFORE_NEXT_EVENT &&
337 responsePort.send(null); 346 !identical(_globalState.currentContext, this))) {
floitsch 2014/03/14 13:01:44 Create a helper function, so that it's more obviou
338 }, "ping");
339 } else {
340 // There is no difference between PING_ALIVE and PING_CONTROL
341 // since we don't handle it before the control event queue.
342 responsePort.send(null); 347 responsePort.send(null);
348 return;
343 } 349 }
350 void respond() { responsePort.send(null); }
351 if (pingType == Isolate.AS_EVENT) {
352 _globalState.topEventLoop.enqueue(this, respond, "ping");
353 return;
354 }
355 assert(pingType == Isolate.BEFORE_NEXT_EVENT);
356 if (_scheduledControlEvents == null) {
357 _scheduledControlEvents = new Queue();
358 }
359 _scheduledControlEvents.addLast(respond);
360 }
361
362 void handleKill(Capability authentification, int priority) {
363 if (this.terminateCapability != authentification) return;
364 if (priority == Isolate.OUT_OF_BAND ||
365 (priority == Isolate.BEFORE_NEXT_EVENT &&
366 !identical(_globalState.currentContext, this))) {
367 kill();
368 return;
369 }
370 if (priority == Isolate.AS_EVENT) {
371 _globalState.topEventLoop.enqueue(this, kill, "kill");
372 return;
373 }
374 assert(pingType == Isolate.BEFORE_NEXT_EVENT);
floitsch 2014/03/14 13:01:44 priority.
Lasse Reichstein Nielsen 2014/03/19 13:07:51 Ack.
375 if (_scheduledControlEvents == null) {
376 _scheduledControlEvents = new Queue();
377 }
378 _scheduledControlEvents.addLast(kill);
344 } 379 }
345 380
346 /** 381 /**
347 * Run [code] in the context of the isolate represented by [this]. 382 * Run [code] in the context of the isolate represented by [this].
348 */ 383 */
349 dynamic eval(Function code) { 384 dynamic eval(Function code) {
350 var old = _globalState.currentContext; 385 var old = _globalState.currentContext;
351 _globalState.currentContext = this; 386 _globalState.currentContext = this;
352 this._setGlobals(); 387 this._setGlobals();
353 var result = null; 388 var result = null;
354 try { 389 try {
355 result = code(); 390 result = code();
356 } finally { 391 } finally {
357 _globalState.currentContext = old; 392 _globalState.currentContext = old;
358 if (old != null) old._setGlobals(); 393 if (old != null) old._setGlobals();
394 if (_scheduledControlEvents != null) {
395 while (_scheduledControlEvents.isNotEmpty) {
396 (_scheduledControlEvents.removeFirst())();
397 }
398 }
359 } 399 }
360 return result; 400 return result;
361 } 401 }
362 402
363 void _setGlobals() { 403 void _setGlobals() {
364 JS_SET_CURRENT_ISOLATE(isolateStatics); 404 JS_SET_CURRENT_ISOLATE(isolateStatics);
365 } 405 }
366 406
407 /**
408 * Handle messages comming in on the control port.
409 *
410 * These events do not go through the event queue.
411 * The `_globalState.currentContext` context is not set to this context
412 * during the handling.
413 */
367 void handleControlMessage(message) { 414 void handleControlMessage(message) {
368 switch (message[0]) { 415 switch (message[0]) {
369 case "pause": 416 case "pause":
370 addPause(message[1], message[2]); 417 addPause(message[1], message[2]);
371 break; 418 break;
372 case "resume": 419 case "resume":
373 removePause(message[1]); 420 removePause(message[1]);
374 break; 421 break;
375 case 'add-ondone': 422 case 'add-ondone':
376 addDoneListener(message[1]); 423 addDoneListener(message[1]);
377 break; 424 break;
378 case 'remove-ondone': 425 case 'remove-ondone':
379 removeDoneListener(message[1]); 426 removeDoneListener(message[1]);
380 break; 427 break;
381 case 'set-errors-fatal': 428 case 'set-errors-fatal':
382 setErrorsFatal(message[1], message[2]); 429 setErrorsFatal(message[1], message[2]);
383 break; 430 break;
384 case "ping": 431 case "ping":
385 handlePing(message[1], message[2]); 432 handlePing(message[1], message[2]);
386 break; 433 break;
434 case "kill":
435 handleKill(message[1], message[2]);
436 break;
387 default: 437 default:
388 print("UNKNOWN MESSAGE: $message");
389 } 438 }
390 } 439 }
391 440
392 /** Looks up a port registered for this isolate. */ 441 /** Looks up a port registered for this isolate. */
393 RawReceivePortImpl lookup(int portId) => ports[portId]; 442 RawReceivePortImpl lookup(int portId) => ports[portId];
394 443
395 void _addRegistration(int portId, RawReceivePortImpl port) { 444 void _addRegistration(int portId, RawReceivePortImpl port) {
396 if (ports.containsKey(portId)) { 445 if (ports.containsKey(portId)) {
397 throw new Exception("Registry: ports must be registered only once."); 446 throw new Exception("Registry: ports must be registered only once.");
398 } 447 }
(...skipping 13 matching lines...) Expand all
412 */ 461 */
413 void registerWeak(int portId, RawReceivePortImpl port) { 462 void registerWeak(int portId, RawReceivePortImpl port) {
414 weakPorts.add(portId); 463 weakPorts.add(portId);
415 _addRegistration(portId, port); 464 _addRegistration(portId, port);
416 } 465 }
417 466
418 void _updateGlobalState() { 467 void _updateGlobalState() {
419 if (ports.length - weakPorts.length > 0 || isPaused) { 468 if (ports.length - weakPorts.length > 0 || isPaused) {
420 _globalState.isolates[id] = this; // indicate this isolate is active 469 _globalState.isolates[id] = this; // indicate this isolate is active
421 } else { 470 } else {
422 _shutdown(); 471 kill();
423 } 472 }
424 } 473 }
425 474
426 void _shutdown() { 475 void kill() {
476 if (_scheduledControlEvents != null) {
477 // Kill all pending events.
478 _scheduledControlEvents.clear();
479 }
480 // Stop listening on all ports.
481 // This should happen before sending events to done handlers, in case
482 // we are listening on ourselves.
483 // Closes all ports, including control port.
484 for (var port in ports.values) {
485 port._close();
486 }
487 ports.clear();
488 weakPorts.clear();
427 _globalState.isolates.remove(id); // indicate this isolate is not active 489 _globalState.isolates.remove(id); // indicate this isolate is not active
428 // Send "done" event to all listeners. This must be done after deactivating
429 // the current isolate, or it may get events if listening to itself.
430 if (doneHandlers != null) { 490 if (doneHandlers != null) {
431 for (SendPort port in doneHandlers) { 491 for (SendPort port in doneHandlers) {
432 port.send(null); 492 port.send(null);
433 } 493 }
494 doneHandlers = null;
434 } 495 }
435 } 496 }
436 497
437 /** Unregister a port on this isolate. */ 498 /** Unregister a port on this isolate. */
438 void unregister(int portId) { 499 void unregister(int portId) {
439 ports.remove(portId); 500 ports.remove(portId);
440 weakPorts.remove(portId); 501 weakPorts.remove(portId);
441 _updateGlobalState(); 502 _updateGlobalState();
442 } 503 }
443 } 504 }
(...skipping 595 matching lines...) Expand 10 before | Expand all | Expand 10 after
1039 1100
1040 // Creates the control port of an isolate. 1101 // Creates the control port of an isolate.
1041 // This is created before the isolate context object itself, 1102 // This is created before the isolate context object itself,
1042 // so it cannot access the static _nextFreeId field. 1103 // so it cannot access the static _nextFreeId field.
1043 RawReceivePortImpl._controlPort() : _handler = null, _id = 0; 1104 RawReceivePortImpl._controlPort() : _handler = null, _id = 0;
1044 1105
1045 void set handler(Function newHandler) { 1106 void set handler(Function newHandler) {
1046 _handler = newHandler; 1107 _handler = newHandler;
1047 } 1108 }
1048 1109
1110 // Close the port without unregistering it.
1111 // Used by an isolate context to close all ports when shutting down.
1112 void _close() {
1113 _isClosed = true;
1114 _handler = null;
1115 }
1116
1049 void close() { 1117 void close() {
1050 if (_isClosed) return; 1118 if (_isClosed) return;
1051 _isClosed = true; 1119 _isClosed = true;
1052 _handler = null; 1120 _handler = null;
1053 _globalState.currentContext.unregister(_id); 1121 _globalState.currentContext.unregister(_id);
1054 } 1122 }
1055 1123
1056 void _add(dataEvent) { 1124 void _add(dataEvent) {
1057 if (_isClosed) return; 1125 if (_isClosed) return;
1058 _handler(dataEvent); 1126 _handler(dataEvent);
(...skipping 529 matching lines...) Expand 10 before | Expand all | Expand 10 after
1588 } 1656 }
1589 1657
1590 bool operator==(Object other) { 1658 bool operator==(Object other) {
1591 if (identical(other, this)) return true; 1659 if (identical(other, this)) return true;
1592 if (other is CapabilityImpl) { 1660 if (other is CapabilityImpl) {
1593 return identical(_id, other._id); 1661 return identical(_id, other._id);
1594 } 1662 }
1595 return false; 1663 return false;
1596 } 1664 }
1597 } 1665 }
OLDNEW
« no previous file with comments | « no previous file | sdk/lib/isolate/isolate.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698