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

Unified 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: Fix test kill2_test Created 6 years, 8 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | sdk/lib/isolate/isolate.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: sdk/lib/_internal/lib/isolate_helper.dart
diff --git a/sdk/lib/_internal/lib/isolate_helper.dart b/sdk/lib/_internal/lib/isolate_helper.dart
index 8a19dc68f8ec115055d8fa9849269fa69506318b..9245d07bae5e092ba92b947cac2b4a7c7e35e7bf 100644
--- a/sdk/lib/_internal/lib/isolate_helper.dart
+++ b/sdk/lib/_internal/lib/isolate_helper.dart
@@ -280,6 +280,16 @@ class _IsolateContext implements IsolateContext {
// Container with the "on exit" handler send-ports.
var doneHandlers;
+ /**
+ * Queue of functions to call when the current event is complete.
+ *
+ * These events are not just put at the front of the event queue, because
+ * they represent control messages, and should be handled even if the
+ * event queue is paused.
+ */
+ var _scheduledControlEvents;
+ bool _isExecutingEvent = false;
+
/** Whether errors are considered fatal. */
// This doesn't do anything yet. We need to be able to catch uncaught errors
// (oxymoronically) in order to take lethal action. This is waiting for the
@@ -332,15 +342,41 @@ class _IsolateContext implements IsolateContext {
}
void handlePing(SendPort responsePort, int pingType) {
- if (pingType == Isolate.PING_EVENT) {
- _globalState.topEventLoop.enqueue(this, () {
- responsePort.send(null);
- }, "ping");
- } else {
- // There is no difference between PING_ALIVE and PING_CONTROL
- // since we don't handle it before the control event queue.
+ if (pingType == Isolate.IMMEDIATE ||
+ (pingType == Isolate.BEFORE_NEXT_EVENT &&
+ !_isExecutingEvent)) {
responsePort.send(null);
+ return;
+ }
+ void respond() { responsePort.send(null); }
+ if (pingType == Isolate.AS_EVENT) {
+ _globalState.topEventLoop.enqueue(this, respond, "ping");
+ return;
+ }
+ assert(pingType == Isolate.BEFORE_NEXT_EVENT);
+ if (_scheduledControlEvents == null) {
+ _scheduledControlEvents = new Queue();
+ }
+ _scheduledControlEvents.addLast(respond);
+ }
+
+ void handleKill(Capability authentification, int priority) {
+ if (this.terminateCapability != authentification) return;
+ if (priority == Isolate.IMMEDIATE ||
+ (priority == Isolate.BEFORE_NEXT_EVENT &&
+ !_isExecutingEvent)) {
+ kill();
+ return;
+ }
+ if (priority == Isolate.AS_EVENT) {
+ _globalState.topEventLoop.enqueue(this, kill, "kill");
+ return;
+ }
+ assert(priority == Isolate.BEFORE_NEXT_EVENT);
+ if (_scheduledControlEvents == null) {
+ _scheduledControlEvents = new Queue();
}
+ _scheduledControlEvents.addLast(kill);
}
/**
@@ -351,11 +387,18 @@ class _IsolateContext implements IsolateContext {
_globalState.currentContext = this;
this._setGlobals();
var result = null;
+ _isExecutingEvent = true;
try {
result = code();
} finally {
+ _isExecutingEvent = false;
_globalState.currentContext = old;
if (old != null) old._setGlobals();
+ if (_scheduledControlEvents != null) {
+ while (_scheduledControlEvents.isNotEmpty) {
+ (_scheduledControlEvents.removeFirst())();
+ }
+ }
}
return result;
}
@@ -364,6 +407,13 @@ class _IsolateContext implements IsolateContext {
JS_SET_CURRENT_ISOLATE(isolateStatics);
}
+ /**
+ * Handle messages comming in on the control port.
+ *
+ * These events do not go through the event queue.
+ * The `_globalState.currentContext` context is not set to this context
+ * during the handling.
+ */
void handleControlMessage(message) {
switch (message[0]) {
case "pause":
@@ -384,8 +434,10 @@ class _IsolateContext implements IsolateContext {
case "ping":
handlePing(message[1], message[2]);
break;
+ case "kill":
+ handleKill(message[1], message[2]);
+ break;
default:
- print("UNKNOWN MESSAGE: $message");
}
}
@@ -419,18 +471,30 @@ class _IsolateContext implements IsolateContext {
if (ports.length - weakPorts.length > 0 || isPaused) {
_globalState.isolates[id] = this; // indicate this isolate is active
} else {
- _shutdown();
+ kill();
}
}
- void _shutdown() {
+ void kill() {
+ if (_scheduledControlEvents != null) {
+ // Kill all pending events.
+ _scheduledControlEvents.clear();
+ }
+ // Stop listening on all ports.
+ // This should happen before sending events to done handlers, in case
+ // we are listening on ourselves.
+ // Closes all ports, including control port.
+ for (var port in ports.values) {
+ port._close();
+ }
+ ports.clear();
+ weakPorts.clear();
_globalState.isolates.remove(id); // indicate this isolate is not active
- // Send "done" event to all listeners. This must be done after deactivating
- // the current isolate, or it may get events if listening to itself.
if (doneHandlers != null) {
for (SendPort port in doneHandlers) {
port.send(null);
}
+ doneHandlers = null;
}
}
@@ -1046,6 +1110,13 @@ class RawReceivePortImpl implements RawReceivePort {
_handler = newHandler;
}
+ // Close the port without unregistering it.
+ // Used by an isolate context to close all ports when shutting down.
+ void _close() {
+ _isClosed = true;
+ _handler = null;
+ }
+
void close() {
if (_isClosed) return;
_isClosed = true;
« 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