blob: 22f776087672a5f08ee10a33149b323b7c2217c3 [file] [log] [blame]
// 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.
// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
// VMOptions=--no-enable-isolate-groups
library MandelIsolateTest;
import 'dart:async';
import 'dart:isolate';
import 'dart:math';
import 'package:async_helper/async_helper.dart';
import 'package:expect/expect.dart';
const TERMINATION_MESSAGE = -1;
const N = 100;
const ISOLATES = 20;
void main([args, port]) {
final state = new MandelbrotState();
asyncStart();
state._validated.future.then((result) {
Expect.isTrue(result);
asyncEnd();
});
for (int i = 0; i < min(ISOLATES, N); i++) state.startClient(i);
}
class MandelbrotState {
MandelbrotState() {
_result = new List<List<int>>.filled(N, []);
_lineProcessedBy = new List<LineProcessorClient?>.filled(N, null);
_sent = 0;
_missing = N;
_validated = new Completer<bool>();
}
void startClient(int id) {
assert(_sent < N);
int line = _sent++;
LineProcessorClient.create(this, id).then((final client) {
client.processLine(line);
});
}
void notifyProcessedLine(LineProcessorClient client, int y, List<int> line) {
assert(_result[y].isEmpty);
_result[y] = line;
_lineProcessedBy[y] = client;
if (_sent != N) {
client.processLine(_sent++);
} else {
client.shutdown();
}
// If all lines have been computed, validate the result.
if (--_missing == 0) {
_printResult();
_validateResult();
}
}
void _validateResult() {
// TODO(ngeoffray): Implement this.
_validated.complete(true);
}
void _printResult() {
var output = new StringBuffer();
for (int i = 0; i < _result.length; i++) {
List<int> line = _result[i];
for (int j = 0; j < line.length; j++) {
if (line[j] < 10) output.write("0");
output.write(line[j]);
}
output.write("\n");
}
// print(output);
}
late List<List<int>> _result;
late List<LineProcessorClient?> _lineProcessedBy;
late int _sent;
late int _missing;
late Completer<bool> _validated;
}
class LineProcessorClient {
MandelbrotState _state;
int _id;
SendPort _port;
LineProcessorClient(this._state, this._id, this._port);
static Future<LineProcessorClient> create(MandelbrotState state, int id) {
ReceivePort reply = new ReceivePort();
return Isolate.spawn(processLines, reply.sendPort).then((_) {
return reply.first.then((port) {
return new LineProcessorClient(state, id, port);
});
});
}
void processLine(int y) {
ReceivePort reply = new ReceivePort();
_port.send([y, reply.sendPort]);
reply.first.then((message) {
_state.notifyProcessedLine(this, y, message as List<int>);
});
}
void shutdown() {
_port.send(TERMINATION_MESSAGE);
}
}
List<int> processLine(int y) {
double inverseN = 2.0 / N;
double Civ = y * inverseN - 1.0;
List<int> result = new List<int>.filled(N, 0);
for (int x = 0; x < N; x++) {
double Crv = x * inverseN - 1.5;
double Zrv = Crv;
double Ziv = Civ;
double Trv = Crv * Crv;
double Tiv = Civ * Civ;
int i = 49;
do {
Ziv = (Zrv * Ziv) + (Zrv * Ziv) + Civ;
Zrv = Trv - Tiv + Crv;
Trv = Zrv * Zrv;
Tiv = Ziv * Ziv;
} while (((Trv + Tiv) <= 4.0) && (--i > 0));
result[x] = i;
}
return result;
}
void processLines(SendPort replyPort) {
ReceivePort port = new ReceivePort();
port.listen((message) {
if (message != TERMINATION_MESSAGE) {
int line = message[0];
SendPort replyTo = message[1];
replyTo.send(processLine(line));
} else {
port.close();
}
});
replyPort.send(port.sendPort);
}