| // Copyright (c) 2025, 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. |
| // |
| // Tests IsolateGroup.runSync - what works, what doesn't. |
| // |
| // VMOptions=--experimental-shared-data |
| // VMOptions=--experimental-shared-data --use-slow-path |
| // VMOptions=--experimental-shared-data --use-slow-path --stacktrace-every=100 |
| // VMOptions=--experimental-shared-data --dwarf_stack_traces --no-retain_function_objects --no-retain_code_objects |
| // VMOptions=--experimental-shared-data --test_il_serialization |
| // VMOptions=--experimental-shared-data --profiler --profile_vm=true |
| // VMOptions=--experimental-shared-data --profiler --profile_vm=false |
| |
| import 'dart:async'; |
| import 'dart:concurrent'; |
| import 'dart:ffi'; |
| import 'dart:io'; |
| import 'dart:isolate'; |
| |
| import 'package:dart_internal/isolate_group.dart' show IsolateGroup; |
| import "package:expect/async_helper.dart"; |
| import "package:expect/expect.dart"; |
| import 'package:ffi/ffi.dart'; |
| |
| @pragma('vm:shared') |
| late final Mutex mutex; |
| |
| @pragma('vm:shared') |
| late final String shared_late_final_string = () { |
| return "${int.parse('123') + 42}"; |
| }(); |
| |
| @pragma('vm:shared') |
| late final String shared_late_final_throw = () { |
| throw "${int.parse('123') + 42}"; |
| }(); |
| |
| @pragma('vm:shared') |
| late final String foo = () { |
| return "${int.parse('123') + 42}"; |
| }(); |
| |
| testInitStrings() async { |
| const int nWorkers = 100; |
| mutex = Mutex(); |
| final rp = ReceivePort(); |
| final rpExitAndErrors = ReceivePort() |
| ..listen((e) { |
| print('e: $e'); |
| }); |
| final completer = Completer(); |
| int counter = 0; |
| rp.listen((data) { |
| counter++; |
| print('got $data, counter: $counter'); |
| Expect.equals("165", data); |
| if (counter == nWorkers) { |
| completer.complete(data); |
| } |
| }); |
| for (int i = 0; i < nWorkers; i++) { |
| Isolate.spawn( |
| (sendPort) { |
| IsolateGroup.runSync(() { |
| sendPort.send(shared_late_final_string); |
| }); |
| }, |
| rp.sendPort, |
| onExit: rpExitAndErrors.sendPort, |
| onError: rpExitAndErrors.sendPort, |
| ); |
| print("spawned isolate #$i"); |
| } |
| Expect.equals("165", await completer.future); |
| rpExitAndErrors.close(); |
| rp.close(); |
| } |
| |
| testInitThrows() async { |
| const int nWorkers = 100; |
| final rp = ReceivePort(); |
| int exitCounter = 0; |
| final completer = Completer(); |
| ReceivePort rpExits = ReceivePort() |
| ..listen((e) { |
| exitCounter++; |
| print('exitCounter: $exitCounter, exit: $e'); |
| if (exitCounter == nWorkers) { |
| completer.complete(true); |
| } |
| }); |
| int errorCounter = 0; |
| ReceivePort rpErrors = ReceivePort() |
| ..listen((e) { |
| errorCounter++; |
| Expect.equals("165", e[0]); |
| print('errorCounter: $errorCounter, error: $e'); |
| }); |
| for (int i = 0; i < nWorkers; i++) { |
| Isolate.spawn( |
| (sendPort) { |
| IsolateGroup.runSync(() { |
| try { |
| sendPort.send(shared_late_final_throw); |
| } catch (e) { |
| Expect.equals("165", e); |
| rethrow; |
| } |
| }); |
| }, |
| rp.sendPort, |
| onExit: rpExits.sendPort, |
| onError: rpErrors.sendPort, |
| ); |
| print("spawned isolate #$i"); |
| } |
| await completer.future; |
| Expect.equals(nWorkers, errorCounter); |
| rpErrors.close(); |
| rpExits.close(); |
| rp.close(); |
| } |
| |
| @pragma('vm:shared') |
| late final String foo_bar = () { |
| return "${int.parse('123') + 42} $foo"; |
| }(); |
| |
| testNestedInitCall() { |
| Expect.equals("165 165", foo_bar); |
| } |
| |
| main() async { |
| asyncStart(); |
| await testInitStrings(); |
| await testInitThrows(); |
| testNestedInitCall(); |
| asyncEnd(); |
| } |