Description
For NativeFinalizer
s it would be really useful if they could live in an isolate group rather than in an isolate. #55050 (comment) (TL;DR: Migrating NativeFinalizer
s to the longest living isolate, or doing refcounting can both not be encapsulated. Artificially keeping all NativeFinalizer
objects alive until the isolate group dies leads to a memory leak.)
In order to achieve NativeFinalizer
s living in an isolate group instead of an isolated, we'd like to be able to mark static fields as shared across an isolate group.
We introduce two pragmas:
pragma('vm:sharable')
Marks a type as being sharable, cannot be used by users, only by Dart SDK code. Dart SDK developers would need to make sure that all code reachable from such type is concurrency safe.pragma('vm:shared')
Marks a static field as shared across isolates in an isolate groups. Can be used by users. The type of the field must be markedpragma('vm:sharable')
, all its subtypes must be shareable too, and the class must be final or sealed.
Users would then be able to write
@pragma('vm:deeply-immutable')
final class MyFinalizable implements Finalizable {
@pragma('vm:shared')
static final NativeFinalizer _finalizer = ...;
MyFinalizable(...) {
_finalizer.attach(this, ...);
}
}
void foo(SendPort sendPort) {
sendPort.send(MyFinalizable(...));
}
Whichever isolate lives the longest would keep the NativeFinalizer
alive. No need to migrate the NativeFinalizer
to the longest living isolate with Isolate.exit
#55050 (comment).
We might need to introduce a NativeFinalizer.shared(...)
constructor to signify that this finalizer is shared across isolates. Or NativeFinalizer.concurrent(...)
.
@mraleph This is implementing a subset of dart-lang/language#3531. But not as a general language feature but for a single type in the VM for which this enables some use cases.