2012-08-03 07:24:29 +00:00
|
|
|
// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
|
2011-10-05 06:22:36 +00:00
|
|
|
// 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.
|
|
|
|
|
2012-11-01 23:09:47 +00:00
|
|
|
library MandelIsolateTest;
|
2013-01-07 11:23:16 +00:00
|
|
|
import 'dart:async';
|
2012-11-01 23:09:47 +00:00
|
|
|
import 'dart:isolate';
|
|
|
|
import 'dart:math';
|
2013-11-25 08:19:53 +00:00
|
|
|
import 'package:unittest/unittest.dart';
|
|
|
|
import "remote_unittest_helper.dart";
|
2011-10-05 06:22:36 +00:00
|
|
|
|
2012-08-24 22:21:20 +00:00
|
|
|
const TERMINATION_MESSAGE = -1;
|
|
|
|
const N = 100;
|
|
|
|
const ISOLATES = 20;
|
2011-10-05 06:22:36 +00:00
|
|
|
|
2013-11-25 08:19:53 +00:00
|
|
|
void main([args, port]) {
|
|
|
|
if (testRemote(main, port)) return;
|
2013-08-31 13:46:07 +00:00
|
|
|
// Test is really slow in debug builds of the VM.
|
2013-11-25 08:19:53 +00:00
|
|
|
var configuration = unittestConfiguration;
|
2013-11-05 23:24:50 +00:00
|
|
|
configuration.timeout = const Duration(seconds: 480);
|
2012-04-25 22:31:04 +00:00
|
|
|
test("Render Mandelbrot in parallel", () {
|
|
|
|
final state = new MandelbrotState();
|
2014-03-31 18:33:18 +00:00
|
|
|
state._validated.future.then(expectAsync((result) {
|
2012-06-06 20:15:58 +00:00
|
|
|
expect(result, isTrue);
|
2012-04-25 22:31:04 +00:00
|
|
|
}));
|
2012-08-22 14:33:01 +00:00
|
|
|
for (int i = 0; i < min(ISOLATES, N); i++) state.startClient(i);
|
2011-10-05 06:22:36 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
class MandelbrotState {
|
|
|
|
|
|
|
|
MandelbrotState() {
|
|
|
|
_result = new List<List<int>>(N);
|
2013-02-27 08:45:04 +00:00
|
|
|
_lineProcessedBy = new List<LineProcessorClient>(N);
|
2011-10-05 06:22:36 +00:00
|
|
|
_sent = 0;
|
|
|
|
_missing = N;
|
2012-02-16 18:20:41 +00:00
|
|
|
_validated = new Completer<bool>();
|
2011-10-05 06:22:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void startClient(int id) {
|
|
|
|
assert(_sent < N);
|
2013-10-25 19:23:00 +00:00
|
|
|
int line = _sent++;
|
|
|
|
LineProcessorClient.create(this, id).then((final client) {
|
|
|
|
client.processLine(line);
|
|
|
|
});
|
2011-10-05 06:22:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void notifyProcessedLine(LineProcessorClient client, int y, List<int> line) {
|
2012-11-12 17:19:58 +00:00
|
|
|
assert(_result[y] == null);
|
2011-10-05 06:22:36 +00:00
|
|
|
_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++) {
|
2013-03-08 13:07:18 +00:00
|
|
|
if (line[j] < 10) output.write("0");
|
|
|
|
output.write(line[j]);
|
2011-10-05 06:22:36 +00:00
|
|
|
}
|
2013-03-08 13:07:18 +00:00
|
|
|
output.write("\n");
|
2011-10-05 06:22:36 +00:00
|
|
|
}
|
|
|
|
// print(output);
|
|
|
|
}
|
|
|
|
|
|
|
|
List<List<int>> _result;
|
|
|
|
List<LineProcessorClient> _lineProcessedBy;
|
|
|
|
int _sent;
|
|
|
|
int _missing;
|
2012-02-16 18:20:41 +00:00
|
|
|
Completer<bool> _validated;
|
2011-10-05 06:22:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
class LineProcessorClient {
|
2013-10-25 19:23:00 +00:00
|
|
|
MandelbrotState _state;
|
|
|
|
int _id;
|
|
|
|
SendPort _port;
|
|
|
|
|
|
|
|
LineProcessorClient(this._state, this._id, this._port);
|
2011-10-05 06:22:36 +00:00
|
|
|
|
2013-10-25 19:23:00 +00:00
|
|
|
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);
|
|
|
|
});
|
|
|
|
});
|
2011-10-05 06:22:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void processLine(int y) {
|
2013-10-25 19:23:00 +00:00
|
|
|
ReceivePort reply = new ReceivePort();
|
|
|
|
_port.send([y, reply.sendPort]);
|
|
|
|
reply.first.then((List<int> message) {
|
2012-08-03 07:24:29 +00:00
|
|
|
_state.notifyProcessedLine(this, y, message);
|
2011-10-05 06:22:36 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
void shutdown() {
|
2013-10-25 19:23:00 +00:00
|
|
|
_port.send(TERMINATION_MESSAGE);
|
2011-10-05 06:22:36 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-08-03 07:24:29 +00:00
|
|
|
List<int> processLine(int y) {
|
|
|
|
double inverseN = 2.0 / N;
|
|
|
|
double Civ = y * inverseN - 1.0;
|
2013-02-27 08:45:04 +00:00
|
|
|
List<int> result = new List<int>(N);
|
2012-08-03 07:24:29 +00:00
|
|
|
for (int x = 0; x < N; x++) {
|
|
|
|
double Crv = x * inverseN - 1.5;
|
2011-10-05 06:22:36 +00:00
|
|
|
|
2012-08-03 07:24:29 +00:00
|
|
|
double Zrv = Crv;
|
|
|
|
double Ziv = Civ;
|
2011-10-05 06:22:36 +00:00
|
|
|
|
2012-08-03 07:24:29 +00:00
|
|
|
double Trv = Crv * Crv;
|
|
|
|
double Tiv = Civ * Civ;
|
2011-10-05 06:22:36 +00:00
|
|
|
|
2012-08-03 07:24:29 +00:00
|
|
|
int i = 49;
|
|
|
|
do {
|
|
|
|
Ziv = (Zrv * Ziv) + (Zrv * Ziv) + Civ;
|
|
|
|
Zrv = Trv - Tiv + Crv;
|
2011-10-05 06:22:36 +00:00
|
|
|
|
2012-08-03 07:24:29 +00:00
|
|
|
Trv = Zrv * Zrv;
|
|
|
|
Tiv = Ziv * Ziv;
|
|
|
|
} while (((Trv + Tiv) <= 4.0) && (--i > 0));
|
2011-10-05 06:22:36 +00:00
|
|
|
|
2012-08-03 07:24:29 +00:00
|
|
|
result[x] = i;
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
2011-10-05 06:22:36 +00:00
|
|
|
|
2013-10-25 19:23:00 +00:00
|
|
|
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));
|
2012-08-03 07:24:29 +00:00
|
|
|
} else {
|
2013-10-25 19:23:00 +00:00
|
|
|
port.close();
|
2011-10-05 06:22:36 +00:00
|
|
|
}
|
2012-08-03 07:24:29 +00:00
|
|
|
});
|
2013-10-25 19:23:00 +00:00
|
|
|
replyPort.send(port.sendPort);
|
2011-10-05 06:22:36 +00:00
|
|
|
}
|