blob: a3b7a9187080a1b44a2c8c38c62b0c97bfe25c59 [file] [edit]
// Copyright (c) 2026, 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 Isolate threading API.
//
// VMOptions=--experimental-shared-data
import 'dart:async';
import 'dart:concurrent';
import 'dart:ffi';
import 'dart:io';
import 'dart:isolate';
import "package:expect/async_helper.dart";
import 'package:expect/expect.dart';
import 'package:ffi/ffi.dart';
import 'threading_utils.dart';
@pragma('vm:shared')
late Mutex mutexCondvar;
@pragma('vm:shared')
late ConditionVariable condVar;
@pragma('vm:shared')
bool greetingsReceived = false;
int threadMain(Pointer<Void> data) {
final new_isolate = Isolate.create(debugName: "helper");
Expect.isNotNull(new_isolate);
final SendPort sp = new_isolate.runSync(() {
Expect.isFalse(Isolate.current.isPinnedToCurrentThread);
Expect.isTrue(Isolate.pinToCurrentThread());
Expect.isTrue(Isolate.current.isPinnedToCurrentThread);
late RawReceivePort rp;
rp = RawReceivePort((e) {
print('running RawReceivePort handler $e');
Expect.isTrue(Isolate.current.isPinnedToCurrentThread);
Expect.equals("greetings!", e);
mutexCondvar.runLocked(() {
greetingsReceived = true;
condVar.notify();
});
rp.close();
});
return rp.sendPort;
});
Expect.isNotNull(sp);
sp.send('greetings!');
// No response is expected until we start running event loop.
mutexCondvar.runLocked(() => condVar.wait(mutexCondvar, /*timeout_ms=*/ 100));
Expect.isFalse(greetingsReceived);
print('=== running event loop for $new_isolate');
new_isolate.runEventLoopSync();
mutexCondvar.runLocked(() {
while (!greetingsReceived) {
condVar.wait(mutexCondvar);
}
});
Expect.isTrue(greetingsReceived);
Expect.isTrue(new_isolate.isPinnedToCurrentThread);
print('=== shutting down');
new_isolate.shutdownSync();
return 0;
}
main(List<String> args, SendPort? message) async {
if (Platform.isWindows) {
// pthread library loading doesn't work on Windows.
return;
}
asyncStart();
mutexCondvar = Mutex();
condVar = ConditionVariable();
final threadInfo = ThreadInfo();
Expect.equals(0, pthreadAttrInit(threadInfo.ptr_attr));
threadInfo.ptr_data.cast<Uint8>()[0] = 0;
final callback =
NativeCallable<IntPtr Function(Pointer<Void>)>.isolateGroupBound(
threadMain,
exceptionalReturn: -1,
);
callback.keepIsolateAlive = false;
pthreadCreate(
threadInfo.ptr_tid,
threadInfo.ptr_attr,
callback.nativeFunction,
threadInfo.ptr_data.cast<Void>(),
);
threadInfo.join();
asyncEnd();
}