blob: d0c2f67d3f72b0e3ff591311ca4736e2e3404b3c [file] [log] [blame]
// Copyright (c) 2015, 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.
/**
* A multiplexing [RawReceivePort].
*
* Allows creating a number of [RawReceivePort] implementations that all send
* messages through the same real `RawReceivePort`.
*
* This allows reducing the number of receive ports created, but adds an
* overhead to each message.
* If a library creates many short-lived receive ports, multiplexing might be
* faster.
*
* To use multiplexing receive ports, create and store a
* [RawReceivePortMultiplexer], and create receive ports by calling
* `multiplexer.createRawReceivePort(handler)` where you would otherwise
* write `new RawReceivePort(handler)`.
*
* Remember to [close] the multiplexer when it is no longer needed.
* `
* (TODO: Check if it really is faster - creating a receive port requires a
* global mutex, so it may be a bottleneck, but it's not clear how slow it is).
*/
library pkg.isolate.multiplexreceiveport;
import "dart:isolate";
import "dart:collection";
import "lists.dart";
class _MultiplexRawReceivePort implements RawReceivePort {
final RawReceivePortMultiplexer _multiplexer;
final int _id;
Function _handler;
_MultiplexRawReceivePort(this._multiplexer, this._id, this._handler);
void set handler(void handler(response)) {
this._handler = handler;
}
void close() {
_multiplexer._closePort(_id);
}
SendPort get sendPort => _multiplexer._createSendPort(_id);
void _invokeHandler(message) { _handler(message); }
}
class _MultiplexSendPort implements SendPort {
final SendPort _sendPort;
final int _id;
_MultiplexSendPort(this._id, this._sendPort);
void send(message) {
_sendPort.send(list2(_id, message));
}
}
/**
* A shared [RawReceivePort] that distributes messages to
* [RawReceivePort] instances that it manages.
*/
class RawReceivePortMultiplexer {
final RawReceivePort _port = new RawReceivePort();
final Map<int, _MultiplexRawReceivePort> _map = new HashMap();
int _nextId = 0;
RawReceivePortMultiplexer() {
_port.handler = _multiplexResponse;
}
RawReceivePort createRawReceivePort([void handler(value)]) {
int id = _nextId++;
var result = new _MultiplexRawReceivePort(this, id, handler);
_map[id] = result;
return result;
}
void close() {
_port.close();
}
void _multiplexResponse(list) {
int id = list[0];
var message = list[1];
_MultiplexRawReceivePort receivePort = _map[id];
// If the receive port is closed, messages are dropped, just as for
// the normal ReceivePort.
if (receivePort == null) return; // Port closed.
receivePort._invokeHandler(message);
}
SendPort _createSendPort(int id) {
return new _MultiplexSendPort(id, _port.sendPort);
}
void _closePort(int id) {
_map.remove(id);
}
}