// 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

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;

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),
    void Function(
        Pointer<NativeFunction<Dart_CurrentIsolateNFT>>,
        Pointer<NativeFunction<Dart_EnterIsolateNFT>>,
        Pointer<NativeFunction<Dart_ExitIsolateNFT>>,
        int)>('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 {
    threadPoolBarrierSync(
        dartCurrentIsolate, dartEnterIsolate, dartExitIsolate, threadCount);
    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();
}
