Files
sdk/runtime/lib/isolate.dart
T
turnidge@google.com cf23dbad75 Add a mid-sized integration test for the Dart Embedding Api which
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
2011-11-29 21:55:13 +00:00

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";
}