| // Copyright (c) 2020, 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. | |
| // SharedObjects=ffi_test_functions | |
| // VMOptions=--disable_heap_verification --no_check_function_fingerprints | |
| import 'dart:async'; | |
| import 'dart:ffi'; | |
| import 'package:expect/expect.dart'; | |
| import 'test_utils.dart'; | |
| import '../../../../../tests/ffi/dylib_utils.dart'; | |
| // This should be larger than max-new-space-size/tlab-size. | |
| const int threadCount = 200; | |
| final class Isolate extends Opaque {} | |
| typedef Dart_CurrentIsolateFT = Pointer<Isolate> Function(); | |
| typedef Dart_CurrentIsolateNFT = Pointer<Isolate> Function(); | |
| typedef Dart_EnterIsolateFT = void Function(Pointer<Isolate>); | |
| typedef Dart_EnterIsolateNFT = Void Function(Pointer<Isolate>); | |
| typedef Dart_ExitIsolateFT = void Function(); | |
| typedef Dart_ExitIsolateNFT = Void Function(); | |
| final ffiTestFunctions = dlopenPlatformSpecific("ffi_test_functions"); | |
| final threadPoolBarrierSync = ffiTestFunctions | |
| .lookupFunction< | |
| Void Function( | |
| Pointer<NativeFunction<Dart_CurrentIsolateNFT>>, | |
| Pointer<NativeFunction<Dart_EnterIsolateNFT>>, | |
| Pointer<NativeFunction<Dart_ExitIsolateNFT>>, | |
| IntPtr, | |
| Bool, | |
| ), | |
| void Function( | |
| Pointer<NativeFunction<Dart_CurrentIsolateNFT>>, | |
| Pointer<NativeFunction<Dart_EnterIsolateNFT>>, | |
| Pointer<NativeFunction<Dart_ExitIsolateNFT>>, | |
| int, | |
| bool, | |
| ) | |
| >('ThreadPoolTest_BarrierSync'); | |
| final Pointer<NativeFunction<Dart_CurrentIsolateNFT>> dartCurrentIsolate = | |
| DynamicLibrary.executable().lookup("Dart_CurrentIsolate").cast(); | |
| final Pointer<NativeFunction<Dart_EnterIsolateNFT>> dartEnterIsolate = | |
| DynamicLibrary.executable().lookup("Dart_EnterIsolate").cast(); | |
| final Pointer<NativeFunction<Dart_ExitIsolateNFT>> dartExitIsolate = | |
| DynamicLibrary.executable().lookup("Dart_ExitIsolate").cast(); | |
| class Worker extends RingElement { | |
| final int id; | |
| Worker(this.id); | |
| Future run(dynamic _, dynamic _2) async { | |
| const bool exitAndReenterIsolate = true; | |
| threadPoolBarrierSync( | |
| dartCurrentIsolate, | |
| dartEnterIsolate, | |
| dartExitIsolate, | |
| threadCount, | |
| exitAndReenterIsolate, | |
| ); | |
| return id; | |
| } | |
| } | |
| main(args) async { | |
| final ring = await Ring.create(threadCount); | |
| // Let each worker: | |
| // - call into C | |
| // - exit the isolate | |
| // - wait until notified | |
| // - continue & exit | |
| final results = await ring.run((int id) => Worker(id)); | |
| Expect.equals(threadCount, results.length); | |
| for (int i = 0; i < threadCount; ++i) { | |
| Expect.equals(i, results[i]); | |
| } | |
| await ring.close(); | |
| } |