description

# Finalizable class abstract interface

Marker interface for objects which should not be finalized too soon.

Any local variable with a static type that includes `Finalizable` is guaranteed to be alive until execution exits the code block where the variable is in scope.

A type includes `Finalizable` if either

- the type is a non-`Never` subtype of `Finalizable`, or
- the type is `T?` or `FutureOr<T>` where `T` includes `Finalizable`.

In other words, while an object is referenced by such a variable, it is guaranteed to not be considered unreachable, and the variable itself is considered alive for the entire duration of its scope, even after it is last referenced.

Without this marker interface on the variable's type, a variable's value might be garbage collected before the surrounding scope has been completely executed, as long as the variable is definitely not referenced again. That can, in turn, trigger a `NativeFinalizer` to perform a callback. When the variable's type includes Finalizable, The `NativeFinalizer` callback is prevented from running until the current code using that variable is complete.

For example, `finalizable` is kept alive during the execution of `someNativeCall`:

    void myFunction() {
      final finalizable = MyFinalizable(Pointer.fromAddress(0));
      someNativeCall(finalizable.nativeResource);
    }

    void someNativeCall(Pointer nativeResource) {
      // ..
    }

    class MyFinalizable implements Finalizable {
      final Pointer nativeResource;

      MyFinalizable(this.nativeResource);
    }

Methods on a class implementing `Finalizable` keep the `this` object alive for the duration of the method execution. The `this` value is treated like a local variable.

For example, `this` is kept alive during the execution of `someNativeCall` in `myFunction`:

    class MyFinalizable implements Finalizable {
      final Pointer nativeResource;

      MyFinalizable(this.nativeResource);

      void myFunction() {
        someNativeCall(nativeResource);
      }
    }

    void someNativeCall(Pointer nativeResource) {
      // ..
    }

It is good practise to implement logic involving finalizables as methods on the class that implements Finalizable.

If a closure is created inside the block scope declaring the variable, and that closure contains any reference to the variable, the variable stays alive as long as the closure object does, or as long as the body of such a closure is executing.

For example, `finalizable` is kept alive by the closure object and until the end of the closure body:

    void doSomething() {
      final resourceAction = myFunction();
      resourceAction(); // `finalizable` is alive until this call returns.
    }

    void Function() myFunction() {
      final finalizable = MyFinalizable(Pointer.fromAddress(0));
      return () {
        someNativeCall(finalizable.nativeResource);
      };
    }

    void someNativeCall(Pointer nativeResource) {
      // ..
    }

    class MyFinalizable implements Finalizable {
      final Pointer nativeResource;

      MyFinalizable(this.nativeResource);
    }

Only captured variables are kept alive by closures, not all variables.

For example, `finalizable` is not kept alive by the returned closure object:

    void Function() myFunction() {
      final finalizable = MyFinalizable(Pointer.fromAddress(0));
      final nativeResource = finalizable.nativeResource;
      return () {
        someNativeCall(nativeResource);
      };
    }

    void someNativeCall(Pointer nativeResource) {
      // ..
    }

    class MyFinalizable implements Finalizable {
      final Pointer nativeResource;

      MyFinalizable(this.nativeResource);
    }

It's likely an error if a resource extracted from a finalizable object escapes the scope of the finalizable variable it's taken from.

The behavior of `Finalizable` variables applies to asynchronous functions too. Such variables are kept alive as long as any code may still execute inside the scope that declared the variable, or in a closure capturing the variable, even if there are asynchronous delays during that execution.

For example, `finalizable` is kept alive during the `await someAsyncCall()`:

    Future<void> myFunction() async {
      final finalizable = MyFinalizable();
      await someAsyncCall();
    }

    Future<void> someAsyncCall() async {
      // ..
    }

    class MyFinalizable implements Finalizable {
      // ..
    }

Also in asynchronous code it's likely an error if a resource extracted from a finalizable object escapes the scope of the finalizable variable it's taken from. If you have to extract a resource from a `Finalizable`, you should ensure the scope in which Finalizable is defined outlives the resource by `await`ing any asynchronous code that uses the resource.

For example, `this` is kept alive until `resource` is not used anymore in `useAsync1`, but not in `useAsync2` and `useAsync3`:

    class MyFinalizable {
      final Pointer<Int8> resource;

      MyFinalizable(this.resource);

      Future<int> useAsync1() async {
        return await useResource(resource);
      }

      Future<int> useAsync2() async {
        return useResource(resource);
      }

      Future<int> useAsync3() {
        return useResource(resource);
      }
    }

    /// Does not use [resource] after the returned future completes.
    Future<int> useResource(Pointer<Int8> resource) async {
      return resource.value;
    }

It is possible for an asynchronous function to stall at an `await`, such that the runtime system can see that there is no possible way for that `await` to complete. In that case, no code after the `await` will ever execute, including `finally` blocks, and the variable may be considered dead along with everything else.

If you're not going to keep a variable alive yourself, make sure to pass the finalizable object to other functions instead of just its resource.

For example, `finalizable` is not kept alive by `myFunction` after it has run to the end of its scope, while `someAsyncCall` could still continue execution. However, `finalizable` is kept alive by `someAsyncCall` itself:

    void myFunction() {
      final finalizable = MyFinalizable();
      someAsyncCall(finalizable);
    }

    Future<void> someAsyncCall(MyFinalizable finalizable) async {
      // ..
    }

    class MyFinalizable implements Finalizable {
      // ..
    }

Annotations
  - @Since.new('2.17')

## Properties

hashCode → int
  The hash code for this object.
  no setterinherited
runtimeType → Type
  A representation of the runtime type of the object.
  no setterinherited

## Methods

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