Spec-Zone.ru › Dart 2

dart:ffi

Класс Finalizable

Маркерный интерфейс для объектов, которые не должны завершать работу слишком рано.

Любая локальная переменная со статическим типом, который включает Finalizable, гарантированно будет существовать до тех пор, пока выполнение не завершит блок кода, в котором переменная находится в области видимости.

Тип включает Finalizable, если:

  • тип является не-Never подтипом Finalizable, или
  • тип является T? или FutureOr<T>, где T включает Finalizable.

Другими словами, пока объект ссылается через такую переменную, он гарантированно не считается недоступным, и сама переменная считается активной на протяжении всего срока её видимости, даже после последней ссылки на неё.

Без этого маркерного интерфейса для типа переменной, значение переменной может быть собрано сборщиком мусора до полного выполнения окружающего блока кода, до тех пор, пока переменная определённо не будет использована снова. Это, в свою очередь, может вызвать NativeFinalizer для выполнения обратного вызова. Когда тип переменной включает Finalizable, обратный вызов NativeFinalizer предотвращается до завершения текущего кода, использующего эту переменную.

Например, finalizable сохраняется живым во время выполнения 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);
}

Методы класса, реализующего Finalizable, поддерживают объект this живым на протяжении всего выполнения метода. Значение this обрабатывается как локальная переменная.

Например, this сохраняется живым во время выполнения someNativeCall в myFunction.

class MyFinalizable implements Finalizable {
  final Pointer nativeResource;

  MyFinalizable(this.nativeResource);

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

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

Рекомендуется реализовывать логику, связанную с finalizable, как методы в классе, который реализует Finalizable.

Если замыкание создаётся внутри области видимости объявления переменной, и это замыкание содержит ссылку на переменную, переменная остаётся живой, пока существует объект замыкания или пока выполняется тело такого замыкания.

Например, finalizable сохраняется живым объектом замыкания и до конца тела замыкания:

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);
}

Только захваченные переменные поддерживаются живыми замыканиями, а не все переменные.

Например, finalizable не поддерживается живой возвращённым объектом замыкания:

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);
}

Вероятно, это ошибка, если ресурс, извлечённый из объекта finalizable, выходит за пределы области видимости переменной finalizable, из которой он был взят.

Поведение переменных Finalizable относится и к асинхронным функциям. Такие переменные поддерживаются живыми, пока код может выполняться внутри области видимости, в которой была объявлена переменная, или в замыкании, захватывающем переменную, даже если во время этого выполнения есть асинхронные задержки.

Например, finalizable сохраняется живым во время await someAsyncCall().

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

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

class MyFinalizable implements Finalizable {
  // ..
}

Также в асинхронном коде вероятно ошибка, если ресурс, извлечённый из объекта finalizable, выходит за пределы области видимости переменной finalizable, из которой он был взят. Если вам необходимо извлечь ресурс из Finalizable, необходимо убедиться, что область видимости, в которой определён Finalizable, переживёт ресурс, await любой асинхронный код, использующий ресурс.

Например, this сохраняется живым, пока resource больше не используется в useAsync1, но не в useAsync2 и 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;
}

Возможна ситуация, когда асинхронная функция «зависнет» на await, так что система выполнения может определить, что нет возможности для завершения await. В этом случае код после await никогда не будет выполнен, включая блоки finally, и переменная может считаться мёртвой вместе со всем остальным.

Если вы не собираетесь поддерживать переменную живой самостоятельно, передайте объект finalizable другим функциям вместо просто его ресурса.

Например, finalizable не поддерживается живым myFunction после завершения его области видимости, в то время как someAsyncCall может продолжить выполнение. Однако finalizable поддерживается живым самим someAsyncCall.

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

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

class MyFinalizable implements Finalizable {
  // ..
}
Аннотации
  • @Since('2.17')

Свойства

hashCode → int
только для чтения, унаследованное
Код хэширования этого объекта.
runtimeType → Type
только для чтения, унаследованное
Представление типа объекта в ходе выполнения.

Методы

noSuchMethod(Invocation invocation) → dynamic
унаследованное
Вызывается при доступе к несуществующему методу или свойству.
toString() → String
унаследованное
Строковое представление этого объекта.

Операторы

operator ==(Object other) → bool
унаследованное
Оператор равенства.

© 2012 the Dart project authors
Licensed under the BSD 3-Clause "New" or "Revised" License.
https://api.dart.dev/stable/2.18.5/dart-ffi/Finalizable-class.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API