cf23dbad75
demonstrates how to create a custom isolate abstraction. In this test, we use an event queue to share a single thread among our custom isolates. Add a callback which allows embedders to see when a port is created. Not sure if I should keep this or not. New apis: Dart_CreatePort() -- allocates a port id and adds a port->isolate mapping. Dart_IsolateHasActivePorts() -- does the current isolate have open ports? (this name a bit awkward...) Bail out of PortMap::ClosePorts() early if there are no open ports. This suppresses calls to the close_port_callback when there are no open ports. Use DART_CHECK_VALID to provide better error output when the test lib has errors. ------------------------- Sample output of the test: -- (isolate=0x815600) Constructing isolate -- Enter: CustomIsolateImpl_start -- -- Adding port (7111) -> isolate (0x830800) -- -- Adding StartEvent to queue -- -- Exit: CustomIsolateImpl_start -- -- Adding port (7112) -> isolate (0x815600) -- -- Posting message dest(7111) reply(0) -- -- Adding MessageEvent to queue -- -- Starting event loop -- >> StartEvent with isolate(0x830800)-- -- (isolate=0x830800) Running isolateMain $$ MessageEvent with dest port 7111-- -- (isolate=0x830800) Received: 42 -- Posting message dest(7112) reply(0) -- -- Adding MessageEvent to queue -- $$ MessageEvent with dest port 7112-- -- Closing port (7112) -- -- Adding ShutdownEvent to queue -- -- (isolate=0x815600) Received: 43 << ShutdownEvent with isolate(0x815600)-- -- Finished event loop -- Review URL: http://codereview.chromium.org//8588040 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@1906 260f80e4-7a28-3924-810f-c04153c831b5
158 lines
4.0 KiB
Dart
158 lines
4.0 KiB
Dart
// Copyright (c) 2011, 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.
|
|
|
|
class ReceivePortFactory {
|
|
factory ReceivePort() {
|
|
return new ReceivePortImpl();
|
|
}
|
|
|
|
factory ReceivePort.singleShot() {
|
|
return new ReceivePortSingleShotImpl();
|
|
}
|
|
}
|
|
|
|
|
|
class ReceivePortImpl implements ReceivePort {
|
|
/*--- public interface ---*/
|
|
factory ReceivePortImpl() native "ReceivePortImpl_factory";
|
|
|
|
receive(void onMessage(var message, SendPort replyTo)) {
|
|
_onMessage = onMessage;
|
|
}
|
|
|
|
close() {
|
|
_portMap.remove(_id);
|
|
_closeInternal(_id);
|
|
}
|
|
|
|
SendPort toSendPort() {
|
|
return new SendPortImpl(_id);
|
|
}
|
|
|
|
/**** Internal implementation details ****/
|
|
// Called from the VM to create a new ReceivePort instance.
|
|
static ReceivePortImpl _get_or_create(int id) {
|
|
if (_portMap !== null) {
|
|
ReceivePortImpl port = _portMap[id];
|
|
if (port !== null) {
|
|
return port;
|
|
}
|
|
}
|
|
return new ReceivePortImpl._internal(id);
|
|
}
|
|
ReceivePortImpl._internal(int id) : _id = id {
|
|
if (_portMap === null) {
|
|
_portMap = new Map();
|
|
}
|
|
_portMap[id] = this;
|
|
}
|
|
|
|
// Called from the VM to dispatch to the handler.
|
|
static void _handleMessage(int id, int replyId, var message) {
|
|
assert(_portMap !== null);
|
|
ReceivePort port = _portMap[id];
|
|
SendPort replyTo = (replyId == 0) ? null : new SendPortImpl(replyId);
|
|
(port._onMessage)(message, replyTo);
|
|
}
|
|
|
|
// Call into the VM to close the VM maintained mappings.
|
|
static _closeInternal(int id) native "ReceivePortImpl_closeInternal";
|
|
|
|
final int _id;
|
|
var _onMessage;
|
|
|
|
// id to ReceivePort mapping.
|
|
static Map _portMap;
|
|
}
|
|
|
|
|
|
class ReceivePortSingleShotImpl implements ReceivePort {
|
|
|
|
ReceivePortSingleShotImpl() : _port = new ReceivePortImpl() { }
|
|
|
|
void receive(void callback(var message, SendPort replyTo)) {
|
|
_port.receive((var message, SendPort replyTo) {
|
|
_port.close();
|
|
callback(message, replyTo);
|
|
});
|
|
}
|
|
|
|
void close() {
|
|
_port.close();
|
|
}
|
|
|
|
SendPort toSendPort() {
|
|
return _port.toSendPort();
|
|
}
|
|
|
|
final ReceivePortImpl _port;
|
|
|
|
}
|
|
|
|
|
|
class SendPortImpl implements SendPort {
|
|
/*--- public interface ---*/
|
|
void send(var message, [SendPort replyTo = null]) {
|
|
this._sendNow(message, replyTo);
|
|
}
|
|
|
|
void _sendNow(var message, SendPort replyTo) {
|
|
int replyId = (replyTo === null) ? 0 : replyTo._id;
|
|
_sendInternal(_id, replyId, message);
|
|
}
|
|
|
|
ReceivePortSingleShotImpl call(var message) {
|
|
final result = new ReceivePortSingleShotImpl();
|
|
this.send(message, result.toSendPort());
|
|
return result;
|
|
}
|
|
|
|
ReceivePortSingleShotImpl _callNow(var message) {
|
|
final result = new ReceivePortSingleShotImpl();
|
|
this._sendNow(message, result.toSendPort());
|
|
return result;
|
|
}
|
|
|
|
bool operator==(var other) {
|
|
return (other is SendPortImpl) && _id == other._id;
|
|
}
|
|
|
|
int hashCode() {
|
|
return _id;
|
|
}
|
|
|
|
/*--- private implementation ---*/
|
|
const SendPortImpl(int id) : _id = id;
|
|
|
|
// SendPortImpl._create is called from the VM when a new SendPort instance is
|
|
// needed by the VM code.
|
|
static SendPort _create(int id) {
|
|
return new SendPortImpl(id);
|
|
}
|
|
|
|
// Forward the implementation of sending messages to the VM. Only port ids
|
|
// are being handed to the VM.
|
|
static _sendInternal(int sendId, int replyId, var message)
|
|
native "SendPortImpl_sendInternal_";
|
|
|
|
final int _id;
|
|
}
|
|
|
|
|
|
class IsolateNatives {
|
|
static Future<SendPort> spawn(Isolate isolate, bool isLight) {
|
|
Completer<SendPort> completer = new Completer<SendPort>();
|
|
SendPort port = _start(isolate, isLight);
|
|
completer.complete(port);
|
|
return completer.future;
|
|
}
|
|
|
|
// Starts a new isolate calling the run method on a new instance of the
|
|
// remote class's type.
|
|
// Returns the send port which is passed to the newly created isolate.
|
|
// This method is being dispatched to from the public core library code.
|
|
static SendPort _start(Isolate isolate, bool light)
|
|
native "IsolateNatives_start";
|
|
}
|