Skip to content

Commit 1b208bd

Browse files
committed
Update Isolate API.
Remove AS_EVENT as priority of ping/kill. It wasn't very usable or predictable. Make priority consistently named and a named parameter. Add response object to ping/addExitListener so it doesn't have to send null. This is useful for cases where you want to use the same receive port for multiple purposes. [email protected] Review URL: https://codereview.chromium.org//1074223002 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@45092 260f80e4-7a28-3924-810f-c04153c831b5
1 parent 9557f01 commit 1b208bd

13 files changed

+144
-149
lines changed

runtime/lib/isolate_patch.dart

+11-7
Original file line numberDiff line numberDiff line change
@@ -371,11 +371,13 @@ patch class Isolate {
371371
_sendOOB(controlPort, msg);
372372
}
373373

374-
/* patch */ void addOnExitListener(SendPort responsePort) {
375-
var msg = new List(3)
374+
/* patch */ void addOnExitListener(SendPort responsePort,
375+
{Object response}) {
376+
var msg = new List(4)
376377
..[0] = 0 // Make room for OOB message type.
377378
..[1] = _ADD_EXIT
378-
..[2] = responsePort;
379+
..[2] = responsePort
380+
..[3] = response;
379381
_sendOOB(controlPort, msg);
380382
}
381383

@@ -396,7 +398,7 @@ patch class Isolate {
396398
_sendOOB(controlPort, msg);
397399
}
398400

399-
/* patch */ void kill([int priority = BEFORE_NEXT_EVENT]) {
401+
/* patch */ void kill({int priority: BEFORE_NEXT_EVENT}) {
400402
var msg = new List(4)
401403
..[0] = 0 // Make room for OOB message type.
402404
..[1] = _KILL
@@ -405,12 +407,14 @@ patch class Isolate {
405407
_sendOOB(controlPort, msg);
406408
}
407409

408-
/* patch */ void ping(SendPort responsePort, [int pingType = IMMEDIATE]) {
409-
var msg = new List(4)
410+
/* patch */ void ping(SendPort responsePort, {Object response,
411+
int priority: IMMEDIATE}) {
412+
var msg = new List(5)
410413
..[0] = 0 // Make room for OOM message type.
411414
..[1] = _PING
412415
..[2] = responsePort
413-
..[3] = pingType;
416+
..[3] = priority
417+
..[4] = response;
414418
_sendOOB(controlPort, msg);
415419
}
416420

runtime/vm/isolate.cc

+33-12
Original file line numberDiff line numberDiff line change
@@ -202,18 +202,22 @@ bool IsolateMessageHandler::HandleLibMessage(const Array& message) {
202202
break;
203203
}
204204
case kPingMsg: {
205-
// [ OOB, kPingMsg, responsePort, priority ]
206-
if (message.Length() != 4) return true;
205+
// [ OOB, kPingMsg, responsePort, priority, response ]
206+
if (message.Length() != 5) return true;
207207
const Object& obj2 = Object::Handle(I, message.At(2));
208208
if (!obj2.IsSendPort()) return true;
209209
const SendPort& send_port = SendPort::Cast(obj2);
210210
const Object& obj3 = Object::Handle(I, message.At(3));
211211
if (!obj3.IsSmi()) return true;
212212
const intptr_t priority = Smi::Cast(obj3).Value();
213+
const Object& obj4 = Object::Handle(I, message.At(4));
214+
if (!obj4.IsInstance() && !obj4.IsNull()) return true;
215+
const Instance& response =
216+
obj4.IsNull() ? Instance::null_instance() : Instance::Cast(obj4);
213217
if (priority == kImmediateAction) {
214218
uint8_t* data = NULL;
215219
intptr_t len = 0;
216-
SerializeObject(Object::null_instance(), &data, &len, false);
220+
SerializeObject(response, &data, &len, false);
217221
PortMap::PostMessage(new Message(send_port.Id(),
218222
data, len,
219223
Message::kNormalPriority));
@@ -268,21 +272,31 @@ bool IsolateMessageHandler::HandleLibMessage(const Array& message) {
268272
case kAddErrorMsg:
269273
case kDelErrorMsg: {
270274
// [ OOB, msg, listener port ]
271-
if (message.Length() != 3) return true;
275+
if (message.Length() < 3) return true;
272276
const Object& obj = Object::Handle(I, message.At(2));
273277
if (!obj.IsSendPort()) return true;
274278
const SendPort& listener = SendPort::Cast(obj);
275279
switch (msg_type) {
276-
case kAddExitMsg:
277-
I->AddExitListener(listener);
280+
case kAddExitMsg: {
281+
if (message.Length() != 4) return true;
282+
// [ OOB, msg, listener port, response object ]
283+
const Object& response = Object::Handle(I, message.At(3));
284+
if (!response.IsInstance() && !response.IsNull()) return true;
285+
I->AddExitListener(listener,
286+
response.IsNull() ? Instance::null_instance()
287+
: Instance::Cast(response));
278288
break;
289+
}
279290
case kDelExitMsg:
291+
if (message.Length() != 3) return true;
280292
I->RemoveExitListener(listener);
281293
break;
282294
case kAddErrorMsg:
295+
if (message.Length() != 3) return true;
283296
I->AddErrorListener(listener);
284297
break;
285298
case kDelErrorMsg:
299+
if (message.Length() != 3) return true;
286300
I->RemoveErrorListener(listener);
287301
break;
288302
default:
@@ -1002,21 +1016,23 @@ bool Isolate::RemoveResumeCapability(const Capability& capability) {
10021016

10031017
// TODO(iposva): Remove duplicated code and start using some hash based
10041018
// structure instead of these linear lookups.
1005-
void Isolate::AddExitListener(const SendPort& listener) {
1019+
void Isolate::AddExitListener(const SendPort& listener,
1020+
const Instance& response) {
10061021
// Ensure a limit for the number of listeners remembered.
1007-
static const intptr_t kMaxListeners = kSmiMax / (6 * kWordSize);
1022+
static const intptr_t kMaxListeners = kSmiMax / (12 * kWordSize);
10081023

10091024
const GrowableObjectArray& listeners = GrowableObjectArray::Handle(
10101025
this, object_store()->exit_listeners());
10111026
SendPort& current = SendPort::Handle(this);
10121027
intptr_t insertion_index = -1;
1013-
for (intptr_t i = 0; i < listeners.Length(); i++) {
1028+
for (intptr_t i = 0; i < listeners.Length(); i += 2) {
10141029
current ^= listeners.At(i);
10151030
if (current.IsNull()) {
10161031
if (insertion_index < 0) {
10171032
insertion_index = i;
10181033
}
10191034
} else if (current.Id() == listener.Id()) {
1035+
listeners.SetAt(i + 1, response);
10201036
return;
10211037
}
10221038
}
@@ -1028,8 +1044,10 @@ void Isolate::AddExitListener(const SendPort& listener) {
10281044
return;
10291045
}
10301046
listeners.Add(listener);
1047+
listeners.Add(response);
10311048
} else {
10321049
listeners.SetAt(insertion_index, listener);
1050+
listeners.SetAt(insertion_index + 1, response);
10331051
}
10341052
}
10351053

@@ -1038,12 +1056,13 @@ void Isolate::RemoveExitListener(const SendPort& listener) {
10381056
const GrowableObjectArray& listeners = GrowableObjectArray::Handle(
10391057
this, object_store()->exit_listeners());
10401058
SendPort& current = SendPort::Handle(this);
1041-
for (intptr_t i = 0; i < listeners.Length(); i++) {
1059+
for (intptr_t i = 0; i < listeners.Length(); i += 2) {
10421060
current ^= listeners.At(i);
10431061
if (!current.IsNull() && (current.Id() == listener.Id())) {
10441062
// Remove the matching listener from the list.
10451063
current = SendPort::null();
10461064
listeners.SetAt(i, current);
1065+
listeners.SetAt(i + 1, Object::null_instance());
10471066
return;
10481067
}
10491068
}
@@ -1056,13 +1075,15 @@ void Isolate::NotifyExitListeners() {
10561075
if (listeners.IsNull()) return;
10571076

10581077
SendPort& listener = SendPort::Handle(this);
1059-
for (intptr_t i = 0; i < listeners.Length(); i++) {
1078+
Instance& response = Instance::Handle(this);
1079+
for (intptr_t i = 0; i < listeners.Length(); i += 2) {
10601080
listener ^= listeners.At(i);
10611081
if (!listener.IsNull()) {
10621082
Dart_Port port_id = listener.Id();
10631083
uint8_t* data = NULL;
10641084
intptr_t len = 0;
1065-
SerializeObject(Object::null_instance(), &data, &len, false);
1085+
response ^= listeners.At(i + 1);
1086+
SerializeObject(response, &data, &len, false);
10661087
Message* msg = new Message(port_id, data, len, Message::kNormalPriority);
10671088
PortMap::PostMessage(msg);
10681089
}

runtime/vm/isolate.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -421,7 +421,7 @@ class Isolate : public BaseIsolate {
421421
bool AddResumeCapability(const Capability& capability);
422422
bool RemoveResumeCapability(const Capability& capability);
423423

424-
void AddExitListener(const SendPort& listener);
424+
void AddExitListener(const SendPort& listener, const Instance& response);
425425
void RemoveExitListener(const SendPort& listener);
426426
void NotifyExitListeners();
427427

sdk/lib/_internal/compiler/js_lib/isolate_helper.dart

+11-23
Original file line numberDiff line numberDiff line change
@@ -311,7 +311,7 @@ class _IsolateContext implements IsolateContext {
311311
List<_IsolateEvent> delayedEvents = [];
312312
Set<Capability> pauseTokens = new Set();
313313

314-
// Container with the "on exit" handler send-ports.
314+
// Container with the "on exit" handler send-ports and responses.
315315
var doneHandlers;
316316

317317
/**
@@ -355,14 +355,12 @@ class _IsolateContext implements IsolateContext {
355355
_updateGlobalState();
356356
}
357357

358-
void addDoneListener(SendPort responsePort) {
358+
void addDoneListener(SendPort responsePort, Object response) {
359359
if (doneHandlers == null) {
360-
doneHandlers = [];
360+
// TODO(lrn): Use map optimized for few keys.
361+
doneHandlers = new HashMap();
361362
}
362-
// If necessary, we can switch doneHandlers to a Set if it gets larger.
363-
// That is not expected to happen in practice.
364-
if (doneHandlers.contains(responsePort)) return;
365-
doneHandlers.add(responsePort);
363+
doneHandlers[responsePort] = response;
366364
}
367365

368366
void removeDoneListener(SendPort responsePort) {
@@ -375,18 +373,14 @@ class _IsolateContext implements IsolateContext {
375373
this.errorsAreFatal = errorsAreFatal;
376374
}
377375

378-
void handlePing(SendPort responsePort, int pingType) {
376+
void handlePing(SendPort responsePort, int pingType, Object response) {
379377
if (pingType == Isolate.IMMEDIATE ||
380378
(pingType == Isolate.BEFORE_NEXT_EVENT &&
381379
!_isExecutingEvent)) {
382-
responsePort.send(null);
383-
return;
384-
}
385-
void respond() { responsePort.send(null); }
386-
if (pingType == Isolate.AS_EVENT) {
387-
_globalState.topEventLoop.enqueue(this, respond, "ping");
380+
responsePort.send(response);
388381
return;
389382
}
383+
void respond() { responsePort.send(response); }
390384
assert(pingType == Isolate.BEFORE_NEXT_EVENT);
391385
if (_scheduledControlEvents == null) {
392386
_scheduledControlEvents = new Queue();
@@ -402,10 +396,6 @@ class _IsolateContext implements IsolateContext {
402396
kill();
403397
return;
404398
}
405-
if (priority == Isolate.AS_EVENT) {
406-
_globalState.topEventLoop.enqueue(this, kill, "kill");
407-
return;
408-
}
409399
assert(priority == Isolate.BEFORE_NEXT_EVENT);
410400
if (_scheduledControlEvents == null) {
411401
_scheduledControlEvents = new Queue();
@@ -499,7 +489,7 @@ class _IsolateContext implements IsolateContext {
499489
removePause(message[1]);
500490
break;
501491
case 'add-ondone':
502-
addDoneListener(message[1]);
492+
addDoneListener(message[1], message[2]);
503493
break;
504494
case 'remove-ondone':
505495
removeDoneListener(message[1]);
@@ -508,7 +498,7 @@ class _IsolateContext implements IsolateContext {
508498
setErrorsFatal(message[1], message[2]);
509499
break;
510500
case "ping":
511-
handlePing(message[1], message[2]);
501+
handlePing(message[1], message[2], message[3]);
512502
break;
513503
case "kill":
514504
handleKill(message[1], message[2]);
@@ -574,9 +564,7 @@ class _IsolateContext implements IsolateContext {
574564
_globalState.isolates.remove(id); // indicate this isolate is not active
575565
errorPorts.clear();
576566
if (doneHandlers != null) {
577-
for (SendPort port in doneHandlers) {
578-
port.send(null);
579-
}
567+
doneHandlers.forEach((port, response) { port.send(response); });
580568
doneHandlers = null;
581569
}
582570
}

sdk/lib/_internal/compiler/js_lib/isolate_patch.dart

+10-7
Original file line numberDiff line numberDiff line change
@@ -76,12 +76,13 @@ class Isolate {
7676
}
7777

7878
@patch
79-
void addOnExitListener(SendPort responsePort) {
79+
void addOnExitListener(SendPort responsePort, {Object response}) {
8080
// TODO(lrn): Can we have an internal method that checks if the receiving
8181
// isolate of a SendPort is still alive?
82-
var message = new List(2)
82+
var message = new List(3)
8383
..[0] = "add-ondone"
84-
..[1] = responsePort;
84+
..[1] = responsePort
85+
..[2] = response;
8586
controlPort.send(message);
8687
}
8788

@@ -103,16 +104,18 @@ class Isolate {
103104
}
104105

105106
@patch
106-
void kill([int priority = BEFORE_NEXT_EVENT]) {
107+
void kill({int priority: BEFORE_NEXT_EVENT}) {
107108
controlPort.send(["kill", terminateCapability, priority]);
108109
}
109110

110111
@patch
111-
void ping(SendPort responsePort, [int pingType = IMMEDIATE]) {
112-
var message = new List(3)
112+
void ping(SendPort responsePort, {Object response,
113+
int priority: IMMEDIATE}) {
114+
var message = new List(4)
113115
..[0] = "ping"
114116
..[1] = responsePort
115-
..[2] = pingType;
117+
..[2] = priority
118+
..[3] = response;
116119
controlPort.send(message);
117120
}
118121

0 commit comments

Comments
 (0)