A native finalizer which can be attached to Dart objects.
When attached to a Dart object, this finalizer's native callback is called after the Dart object is garbage collected or becomes inaccessible for other reasons.
Callbacks will happen as early as possible, when the object becomes inaccessible to the program, and may happen at any moment during execution of the program. At the latest, when an isolate group shuts down, this callback is guaranteed to be called for each object in that isolate group that the finalizer is still attached to.
Compared to the Finalizer from dart:core
, which makes no promises to
ever call an attached callback, this native finalizer promises that all
attached finalizers are definitely called at least once before the program
ends, and the callbacks are called as soon as possible after an object
is recognized as inaccessible.
When the callback is a Dart function rather than a native function, use Finalizer instead.
A native finalizer can be used to close native resources. See the following example.
/// [Database] enables interacting with the native database.
///
/// After [close] is called, cannot be used to [query].
///
/// If a [Database] is garbage collected, it is automatically closed by
/// means of a native finalizer. Prefer closing manually for timely
/// release of native resources.
///
/// Note this class is incomplete and for illustration purposes only.
class Database implements Finalizable {
/// The native finalizer runs [_closeDatabasePointer] on [_nativeDatabase]
/// if the object is garbage collected.
///
/// Keeps the finalizer itself reachable, otherwise it might be disposed
/// before the finalizer callback gets a chance to run.
static final _finalizer =
NativeFinalizer(_nativeDatabaseBindings.closeDatabaseAddress.cast());
/// The native resource.
///
/// Should be closed exactly once with [_closeDatabase] or
/// [_closeDatabasePointer].
Pointer<_NativeDatabase> _nativeDatabase;
/// Used to prevent double close and usage after close.
bool _closed = false;
Database._(this._nativeDatabase);
/// Open a database.
factory Database.open() {
final nativeDatabase = _nativeDatabaseBindings.openDatabase();
final database = Database._(nativeDatabase);
_finalizer.attach(database, nativeDatabase.cast(), detach: database);
return database;
}
/// Closes this database.
///
/// This database cannot be used anymore after it is closed.
void close() {
if (_closed) {
return;
}
_closed = true;
_finalizer.detach(this);
_nativeDatabaseBindings.closeDatabase(_nativeDatabase);
}
/// Query the database.
///
/// The database should not have been closed.
void query() {
if (_closed) {
throw StateError('The database has been closed.');
}
// Query the database.
}
}
final _nativeDatabaseBindings = _NativeDatabaseLib(DynamicLibrary.process());
// The following classes are typically generated with `package:ffigen`.
// Use `symbol-address` to expose the address of the close function.
class _NativeDatabaseLib {
final DynamicLibrary _library;
_NativeDatabaseLib(this._library);
late final openDatabase = _library.lookupFunction<
Pointer<_NativeDatabase> Function(),
Pointer<_NativeDatabase> Function()>('OpenDatabase');
late final closeDatabaseAddress =
_library.lookup<NativeFunction<Void Function(Pointer<_NativeDatabase>)>>(
'CloseDatabase');
late final closeDatabase = closeDatabaseAddress
.asFunction<void Function(Pointer<_NativeDatabase>)>();
}
final class _NativeDatabase extends Opaque {}
- Annotations
-
- @Since('2.17')
Constructors
-
NativeFinalizer(Pointer<
NativeFinalizerFunction> callback) -
Creates a finalizer with the given finalization callback.
factory
Properties
- hashCode → int
-
The hash code for this object.
read-onlyinherited
- runtimeType → Type
-
A representation of the runtime type of the object.
read-onlyinherited
Methods
-
attach(
Finalizable value, Pointer< Void> token, {Object? detach, int? externalSize}) → void -
Attaches this finalizer to
value
. -
detach(
Object detach) → void - Detaches this finalizer from values attached with detach.
-
noSuchMethod(
Invocation invocation) → dynamic -
Invoked when a nonexistent method or property is accessed.
inherited
-
toString(
) → String -
A string representation of this object.
inherited
Operators
-
operator ==(
Object other) → bool -
The equality operator.
inherited