Add Isolate.current getter, returning the current isolate as an Isolate object.

R=floitsch@google.com

Review URL: https://codereview.chromium.org//771993003

git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@42499 260f80e4-7a28-3924-810f-c04153c831b5
This commit is contained in:
lrn@google.com 2014-12-19 07:04:29 +00:00
parent efad8e46a1
commit cf724d70a9
7 changed files with 184 additions and 0 deletions

View file

@ -267,6 +267,17 @@ DEFINE_NATIVE_ENTRY(Isolate_spawnUri, 5) {
}
DEFINE_NATIVE_ENTRY(Isolate_getPortAndCapabilitiesOfCurrentIsolate, 0) {
const Array& result = Array::Handle(Array::New(3));
result.SetAt(0, SendPort::Handle(SendPort::New(isolate->main_port())));
result.SetAt(1, Capability::Handle(
Capability::New(isolate->pause_capability())));
result.SetAt(2, Capability::Handle(
Capability::New(isolate->terminate_capability())));
return result.raw();
}
DEFINE_NATIVE_ENTRY(Isolate_sendOOB, 2) {
GET_NON_NULL_NATIVE_ARGUMENT(SendPort, port, arguments->NativeArgAt(0));
GET_NON_NULL_NATIVE_ARGUMENT(Array, msg, arguments->NativeArgAt(1));

View file

@ -256,6 +256,10 @@ void _startIsolate(SendPort parentPort,
}
patch class Isolate {
static final _currentIsolate = _getCurrentIsolate();
/* patch */ static Isolate get current => _currentIsolate;
/* patch */ static Future<Isolate> spawn(
void entryPoint(message), var message, { bool paused: false }) {
// `paused` isn't handled yet.
@ -392,4 +396,14 @@ patch class Isolate {
/* patch */ void removeErrorListener(SendPort port) {
throw new UnsupportedError("removeErrorListener");
}
static Isolate _getCurrentIsolate() {
List portAndCapabilities = _getPortAndCapabilitiesOfCurrentIsolate();
return new Isolate(portAndCapabilities[0],
pauseCapability: portAndCapabilities[1],
terminateCapability: portAndCapabilities[2]);
}
static List _getPortAndCapabilitiesOfCurrentIsolate()
native "Isolate_getPortAndCapabilitiesOfCurrentIsolate";
}

View file

@ -294,6 +294,7 @@ namespace dart {
V(Int32x4_select, 3) \
V(Isolate_spawnFunction, 3) \
V(Isolate_spawnUri, 5) \
V(Isolate_getPortAndCapabilitiesOfCurrentIsolate, 0) \
V(Isolate_sendOOB, 2) \
V(Mirrors_evalInLibraryWithPrivateKey, 2) \
V(Mirrors_makeLocalClassMirror, 1) \

View file

@ -1035,6 +1035,13 @@ class IsolateNatives {
}, 'nonworker start');
}
static Isolate get currentIsolate {
_IsolateContext context = JS_CURRENT_ISOLATE_CONTEXT();
return new Isolate(context.controlPort.sendPort,
pauseCapability: context.pauseCapability,
terminateCapability: context.terminateCapability);
}
static void _startIsolate(Function topLevel,
List<String> args, message,
bool isSpawnUri,

View file

@ -14,6 +14,13 @@ import 'dart:_isolate_helper' show CapabilityImpl,
@patch
class Isolate {
static final _currentIsolateCache = IsolateNatives.currentIsolate;
// `current` must be a getter, not just a final field,
// to match the external declaration.
@patch
static Isolate get current => _currentIsolateCache;
@patch
static Future<Isolate> spawn(void entryPoint(message), var message,
{ bool paused: false }) {

View file

@ -119,6 +119,15 @@ class Isolate {
Isolate(this.controlPort, {this.pauseCapability,
this.terminateCapability});
/**
* Return the current [Isolate].
*
* The isolate gives access to the capabilities needed to inspect,
* pause or kill the isolate, and allows granting these capabilities
* to others.
*/
external static Isolate get current;
/**
* Creates and spawns an isolate that shares the same code as the current
* isolate.

View file

@ -0,0 +1,135 @@
// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
library isolate_current_test;
import "dart:isolate";
import "dart:async";
import "package:expect/expect.dart";
import "package:async_helper/async_helper.dart";
void main() {
asyncStart();
Expect.isNotNull(Isolate.current);
// Sending controlPort and capabilities as list.
testSend(i2l, l2i);
testSpawnReturnVsCurrent(true);
testSpawnReturnVsCurrent2(true);
// Sending Isolate itself.
testSend(id, id);
testSpawnReturnVsCurrent(false);
testSpawnReturnVsCurrent2(false);
asyncEnd();
}
/** Test sending the isolate data or isolate through a [SendPort]. */
void testSend(i2l, l2i) {
asyncStart();
RawReceivePort p = new RawReceivePort();
Isolate isolate = Isolate.current;
p.handler = (list) {
var isolate2 = l2i(list);
Expect.equals(isolate.controlPort, isolate2.controlPort);
Expect.equals(isolate.pauseCapability, isolate2.pauseCapability);
Expect.equals(isolate.terminateCapability, isolate2.terminateCapability);
p.close();
asyncEnd();
};
p.sendPort.send(i2l(isolate));
}
/**
* Test that the isolate returned by [Isolate.spawn] is the same as
* the one returned by [Isolate.current] in the spawned isolate.
* Checked in the spawning isolate.
*/
void testSpawnReturnVsCurrent(bool asList) {
asyncStart();
Function transform = asList ? l2i : id;
Completer response = new Completer();
var p = new RawReceivePort();
p.handler = (v) {
response.complete(transform(v));
p.close();
};
Isolate.spawn(replyCurrent, [p.sendPort, asList]).then((Isolate isolate) {
return response.future.then((Isolate isolate2) {
expectIsolateEquals(isolate, isolate2);
asyncEnd();
});
});
}
void replyCurrent(args) {
SendPort responsePort = args[0];
Function transform = args[1] ? i2l : id;
responsePort.send(transform(Isolate.current));
}
/**
* Test that the isolate returned by [Isolate.spawn] is the same as
* the one returned by [Isolate.current] in the spawned isolate.
* Checked in the spawned isolate.
*/
void testSpawnReturnVsCurrent2(bool asList) {
asyncStart();
Function transform = asList ? i2l : id;
Completer response = new Completer();
var p = new RawReceivePort();
int state = 0;
p.handler = (v) {
switch (state) {
case 0:
response.complete(v);
state++;
break;
case 1:
p.close();
Expect.isTrue(v);
asyncEnd();
}
};
Isolate.spawn(expectCurrent, [p.sendPort, asList]).then((Isolate isolate) {
return response.future.then((SendPort port) {
port.send(transform(isolate));
});
});
}
void expectCurrent(args) {
SendPort responsePort = args[0];
Function transform = args[1] ? l2i : id;
RawReceivePort port = new RawReceivePort();
port.handler = (isoData) {
Isolate isolate2 = transform(isoData);
port.close();
Isolate isolate = Isolate.current;
expectIsolateEquals(isolate, isolate2);
responsePort.send(true);
};
responsePort.send(port.sendPort);
}
/** Convert isolate to list (of control port and capabilities). */
i2l(Isolate isolate) => [isolate.controlPort,
isolate.pauseCapability,
isolate.terminateCapability];
/** Convert list to isolate. */
l2i(List list) => new Isolate(list[0], pauseCapability: list[1],
terminateCapability: list[2]);
/** Identity transformation. */
id(Isolate isolate) => isolate;
void expectIsolateEquals(Isolate expect, Isolate actual) {
Expect.equals(expect.controlPort, actual.controlPort);
Expect.equals(expect.pauseCapability, actual.pauseCapability);
Expect.equals(expect.terminateCapability, actual.terminateCapability);
}