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

Unified Diff: frog/lib/isolate.dart

Issue 9317068: isolate lib: small refactor to distinguish protocols at the port level (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: '' Created 8 years, 10 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
Index: frog/lib/isolate.dart
diff --git a/frog/lib/isolate.dart b/frog/lib/isolate.dart
index cd156fc4d3ef84bc4b6c387ff202db1f7623bb46..5d9a4060b27d106ef795b894f7d4157eb9bbc5bc 100644
--- a/frog/lib/isolate.dart
+++ b/frog/lib/isolate.dart
@@ -326,21 +326,12 @@ class IsolateEvent {
}
}
-/** Implementation of a send port on top of JavaScript. */
-class SendPortImpl implements SendPort {
-
- const SendPortImpl(this._workerId, this._isolateId, this._receivePortId);
-
- void send(var message, [SendPort replyTo = null]) {
- if (replyTo !== null && !(replyTo is SendPortImpl)) {
- throw "SendPort::send: Illegal replyTo type.";
- }
- IsolateNatives._sendMessage(_workerId, _isolateId, _receivePortId,
- _serializeMessage(message), _serializeMessage(replyTo));
- }
+/** Common functionality to all send ports. */
+class BaseSendPort implements SendPort {
+ /** Id for the destination isolate. */
+ final int _isolateId;
- // TODO(sigmund): get rid of _sendNow (still used in corelib code)
- void _sendNow(var message, replyTo) { send(message, replyTo); }
+ BaseSendPort(this._isolateId);
ReceivePortSingleShotImpl call(var message) {
final result = new ReceivePortSingleShotImpl();
@@ -348,26 +339,111 @@ class SendPortImpl implements SendPort {
return result;
}
- ReceivePortSingleShotImpl _callNow(var message) {
- final result = new ReceivePortSingleShotImpl();
- send(message, result.toSendPort());
- return result;
+ static void checkReplyTo(SendPort replyTo) {
+ if (replyTo !== null && replyTo is! NativeJsSendPort
+ && replyTo is! WorkerSendPort) {
+ throw "SendPort.send: Illegal replyTo port type.";
+ }
+ }
+
+ // TODO(sigmund): replace the current SendPort.call with the following:
+ //Future call(var message) {
+ //  final completer = new Completer();
+ //  final port = new ReceivePort.singleShot();
+ //  send(message, port.toSendPort());
+ //  port.receive((value, ignoreReplyTo) {
+ //    if (value is Exception) {
+ //  completer.completeException(value);
+ // } else {
+ // completer.complete(value);
+ // }
+ // });
+ //  return completer.future;
+ //}
+
+ abstract void send(var message, [SendPort replyTo]);
+ abstract bool operator ==(var other);
+ abstract int hashCode();
+}
+
+/** A send port that delivers messages in-memory via native JavaScript calls. */
+class NativeJsSendPort extends BaseSendPort implements SendPort {
+ final ReceivePortImpl _receivePort;
+
+ const NativeJsSendPort(this._receivePort, int isolateId) : super(isolateId);
+
+ void send(var message, [SendPort replyTo = null]) {
+ checkReplyTo(replyTo);
+ // Check that the isolate still runs and the port is still open
+ final isolate = _globalState.isolates[_isolateId];
+ if (isolate == null) return;
+ if (_receivePort._callback == null) return;
+
+ // We force serialization/deserialization as a simple way to ensure isolate
+ // communication restrictions are respected between isolates that live in
+ // the same worker. NativeJsSendPort delivers both messages from the same
+ // worker and messages from other workers. In particular, messages sent from
+ // a worker via a WorkerSendPort are received at [_processWorkerMessage] and
+ // forwarded to a native port. In such cases, here we'll see
+ // [_globalState.currentContext == null].
+ final shouldSerialize = _globalState.currentContext != null
+ && _globalState.currentContext.id != _isolateId;
+ if (shouldSerialize) {
+ message = _serializeMessage(message);
+ replyTo = _serializeMessage(replyTo);
+ }
+ _globalState.topEventLoop.enqueue(isolate, () {
+ if (_receivePort._callback != null) {
+ if (shouldSerialize) {
eub 2012/02/10 21:20:57 I liked your previous version with the serialize-d
Siggi Cherem (dart-lang) 2012/02/10 22:09:22 Me too - when I did some testing, I realized that
eub 2012/02/10 22:11:50 Can we come up with a simple comment explaining to
+ message = _deserializeMessage(message);
+ replyTo = _deserializeMessage(replyTo);
+ }
+ _receivePort._callback(message, replyTo);
+ }
+ }, 'receive ' + message);
+ }
+
+ bool operator ==(var other) => (other is NativeJsSendPort) &&
+ (_receivePort == other._receivePort);
+
+ int hashCode() => _receivePort._id;
+}
+
+/** A send port that delivers messages via worker.postMessage. */
+class WorkerSendPort extends BaseSendPort implements SendPort {
+ final int _workerId;
+ final int _receivePortId;
+
+ const WorkerSendPort(this._workerId, int isolateId, this._receivePortId)
+ : super(isolateId);
+
+ void send(var message, [SendPort replyTo = null]) {
+ checkReplyTo(replyTo);
+ final workerMessage = _serializeMessage({
+ 'command': 'message',
+ 'port': this,
+ 'msg': message,
+ 'replyTo': replyTo});
+
+ if (_globalState.isWorker) {
+ // communication from one worker to another go through the main worker:
+ _globalState.mainWorker.postMessage(workerMessage);
+ } else {
+ _globalState.workers[_workerId].postMessage(workerMessage);
+ }
}
- bool operator==(var other) {
- return (other is SendPortImpl) &&
+ bool operator ==(var other) {
+ return (other is WorkerSendPort) &&
(_workerId == other._workerId) &&
(_isolateId == other._isolateId) &&
(_receivePortId == other._receivePortId);
}
int hashCode() {
+ // TODO(sigmund): use a standard hash when we get one available in corelib.
return (_workerId << 16) ^ (_isolateId << 8) ^ _receivePortId;
}
-
- final int _receivePortId;
- final int _isolateId;
- final int _workerId;
}
/** Default factory for receive ports. */
@@ -384,6 +460,10 @@ class ReceivePortFactory {
/** Implementation of a multi-use [ReceivePort] on top of JavaScript. */
class ReceivePortImpl implements ReceivePort {
+ int _id;
+ Function _callback;
+ static int _nextFreeId = 1;
+
ReceivePortImpl()
: _id = _nextFreeId++ {
_globalState.currentContext.register(_id, this);
@@ -398,19 +478,9 @@ class ReceivePortImpl implements ReceivePort {
_globalState.currentContext.unregister(_id);
}
- /**
- * Returns a fresh [SendPort]. The implementation is not allowed to cache
- * existing ports.
- */
SendPort toSendPort() {
- return new SendPortImpl(
- _globalState.currentWorkerId, _globalState.currentContext.id, _id);
+ return new NativeJsSendPort(this, _globalState.currentContext.id);
}
-
- int _id;
- Function _callback;
-
- static int _nextFreeId = 1;
}
/** Implementation of a single-shot [ReceivePort]. */
@@ -551,8 +621,7 @@ class IsolateNatives {
_spawnWorker(msg['factoryName'], msg['replyPort']);
break;
case 'message':
- _sendMessage(msg['workerId'], msg['isolateId'], msg['portId'],
- msg['msg'], msg['replyTo']);
+ msg['port'].send(msg['msg'], msg['replyTo']);
_globalState.topEventLoop.run();
break;
case 'close':
@@ -638,37 +707,4 @@ class IsolateNatives {
replyTo.send(_SPAWNED_SIGNAL, port.toSendPort());
isolate._run(port);
}
-
- static void _sendMessage(int workerId, int isolateId, int receivePortId,
- message, replyTo) {
- // Both the message and the replyTo are already serialized.
- if (workerId == _globalState.currentWorkerId) {
- var isolate = _globalState.isolates[isolateId];
- if (isolate == null) return; // Isolate has been closed.
- var receivePort = isolate.lookup(receivePortId);
- if (receivePort == null) return; // ReceivePort has been closed.
- _globalState.topEventLoop.enqueue(isolate, () {
- if (receivePort._callback != null) {
- receivePort._callback(
- _deserializeMessage(message), _deserializeMessage(replyTo));
- }
- }, 'receive ' + message);
- } else {
- var worker;
- // communication between workers go through the main worker
- if (_globalState.isWorker) {
- worker = _globalState.mainWorker;
- } else {
- // TODO(sigmund): make sure this works
- worker = _globalState.workers[workerId];
- }
- worker.postMessage(_serializeMessage({
- 'command': 'message',
- 'workerId': workerId,
- 'isolateId': isolateId,
- 'portId': receivePortId,
- 'msg': message,
- 'replyTo': replyTo }));
- }
- }
}

Powered by Google App Engine
This is Rietveld 408576698