Dart Web Developmentからコピーされた恥知らずな
› Isolate.spawn の使用例
作者が気にしないことを願っています
スポーンされた分離株は、親にどこでどのように応答するかわかりません。
親では、子の分離からすべてのメッセージを受信する ReceivePort を作成できます。アイソレートをスポーンするときはいつでも、(Isolate.spawn のメッセージ引数を介して) ReceivePort から SendPort インスタンスを渡します。
子アイソレートは、メッセージを受信できるように、独自の ReceivePort も作成する必要があります。インスタンス化されると、子のisolateは、(親のSendPortを介して)親に(自身のReceivePortから)独自のSendPortを送信する必要があります。
現在の API は、それ自体ではまったく役に立ちません。しかし、本格的な実装に必要なすべてのビルディング ブロックを提供します。
次の行に沿って、メッセージをヘッダー内にラップする必要がある場合があります。
class _Request {
/// The ID of the request so the response may be associated to the request's future completer.
final Capability requestId;
/// The SendPort we must respond to, because the message could come from any isolate.
final SendPort responsePort;
/// The actual message of the request.
final dynamic message
const _Request(this.requestId, this.responsePort, this.message);
}
class _Response {
/// The ID of the request this response is meant to.
final Capability requestId;
/// Indicates if the request succeeded.
final bool success;
/// If [success] is true, holds the response message.
/// Otherwise, holds the error that occured.
final dynamic message;
const _Response.ok(this.requestId, this.message): success = true;
const _Response.error(this.requestId, this.message): success = false;
}
すべてのisolateは、次のようなシングルトン メッセージ バスを持つことができます:
final isolateBus = new IsolateBus();
class IsolateBus {
final ReceivePort _receivePort = new ReceivePort();
final Map<Capability, Completer> _completers = {};
IsolateBus() {
_receivePort.listen(_handleMessage, onError: _handleError);
}
void _handleMessage(portMessage) {
if (portMessage is _Request) {
// This is a request, we should process.
// Here we send back the same message
portMessage.responsePort.send(
new _Response.ok(portMessage.requestId, portMessage.message));
} else if (portMessage is _Response) {
// We received a response
final completer = _completers[portMessage.requestId];
if (completer == null) {
print("Invalid request ID received.");
} else if (portMessage.success) {
completer.complete(portMessage.message);
} else {
completer.completeError(portMessage.message);
}
} else {
print("Invalid message received: $portMessage");
}
}
void _handleError(error) {
print("A ReceivePort error occured: $error");
}
Future request(SendPort port, message) {
final completer = new Completer();
final requestId = new Capability();
_completers[requestId] = completer;
port.send(new _Request(requestId, _receivePort.sendPort, message));
return completer.future;
}
}
SendPort anotherIsolatePort = ...
isolateBus.request(anotherIsolatePort, "Some message");
これは、アーキテクチャの一例にすぎません。もちろん、独自に展開することもできます。これは、通知 (応答のない要求)、ストリームなどをサポートするように拡張できます。
すべての分離からのすべての SendPort インスタンスを追跡し、最終的にそれらをサービスとして登録するには、グローバルな分離レジストリが必要になる場合があります。