| // Copyright (c) 2012, 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 _CloseToken { |
| /// This token is sent from [IsolateSink]s to [IsolateStream]s to ask them to |
| /// close themselves. |
| const _CloseToken(); |
| } |
| |
| patch bool _isCloseToken(var object) { |
| // TODO(floitsch): can we compare against const _CloseToken()? |
| return object is _CloseToken; |
| } |
| |
| patch class MessageBox { |
| /* patch */ MessageBox.oneShot() : this._oneShot(new ReceivePort()); |
| MessageBox._oneShot(ReceivePort receivePort) |
| : stream = new IsolateStream._fromOriginalReceivePortOneShot(receivePort), |
| sink = new _IsolateSink._fromPort(receivePort.toSendPort()); |
| |
| /* patch */ MessageBox() : this._(new ReceivePort()); |
| MessageBox._(ReceivePort receivePort) |
| : stream = new IsolateStream._fromOriginalReceivePort(receivePort), |
| sink = new _IsolateSink._fromPort(receivePort.toSendPort()); |
| } |
| |
| class _IsolateSink implements IsolateSink { |
| bool _isClosed = false; |
| final SendPort _port; |
| _IsolateSink._fromPort(this._port); |
| |
| void add(dynamic message) { |
| _port.send(message); |
| } |
| |
| void addError(Object errorEvent) { |
| throw new UnimplementedError("addError on isolate streams"); |
| } |
| |
| void close() { |
| if (_isClosed) return; |
| add(const _CloseToken()); |
| _isClosed = true; |
| } |
| |
| bool operator==(var other) { |
| return other is IsolateSink && _port == other._port; |
| } |
| |
| int get hashCode => _port.hashCode + 499; |
| } |
| |
| patch IsolateSink streamSpawnFunction( |
| void topLevelFunction(), |
| [bool unhandledExceptionCallback(IsolateUnhandledException e)]) { |
| SendPort sendPort = spawnFunction(topLevelFunction, |
| unhandledExceptionCallback); |
| return new _IsolateSink._fromPort(sendPort); |
| } |
| |
| patch class ReceivePort { |
| /* patch */ factory ReceivePort() { |
| return new _ReceivePortImpl(); |
| } |
| } |
| |
| class _ReceivePortImpl implements ReceivePort { |
| 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 retrieve the ReceivePort for a message. |
| static _ReceivePortImpl _lookupReceivePort(int id) { |
| assert(_portMap != null); |
| return _portMap[id]; |
| } |
| |
| // Called from the VM to dispatch to the handler. |
| static void _handleMessage(_ReceivePortImpl port, int replyId, var message) { |
| assert(port != null); |
| 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 _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); |
| } |
| |
| Future call(var message) { |
| final completer = new Completer.sync(); |
| final port = new _ReceivePortImpl(); |
| send(message, port.toSendPort()); |
| port.receive((value, ignoreReplyTo) { |
| port.close(); |
| if (value is Exception) { |
| completer.completeError(value); |
| } else { |
| completer.complete(value); |
| } |
| }); |
| return completer.future; |
| } |
| |
| bool operator==(var other) { |
| return (other is _SendPortImpl) && _id == other._id; |
| } |
| |
| int get 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; |
| } |
| |
| _getPortInternal() native "isolate_getPortInternal"; |
| |
| ReceivePort _portInternal; |
| |
| patch class _Isolate { |
| /* patch */ static ReceivePort get port { |
| if (_portInternal == null) { |
| _portInternal = _getPortInternal(); |
| } |
| return _portInternal; |
| } |
| |
| /* patch */ static spawnFunction(void topLevelFunction(), |
| [bool unhandledExceptionCallback(IsolateUnhandledException e)]) |
| native "isolate_spawnFunction"; |
| |
| /* patch */ static spawnUri(String uri) native "isolate_spawnUri"; |
| } |