| // 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. | |
| library MandelIsolateTest; | |
| import 'dart:async'; | |
| import 'dart:isolate'; | |
| import 'dart:math'; | |
| import 'package:expect/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((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); | |
| } |