disown method

  1. @override
bool disown(
  1. Object value
)
override

Drops the cleanup registered for value by abandonable, join or run.

Returns whether anything was dropped. The lookup is by identity, so pass the very object the body was handed. What an equal one finds depends on the value and the platform: identical answers by value for numbers of one type and for bools, and on some platforms for strings and records, so an equal value of that kind may drop a registration somebody else made. A resource such a value stands for is registered with onDispose or onDiscard instead. Registrations made by those two carry no value and are invisible here — they are dropped by the function those members return; an unknown value is not an error. With two registrations for one value the top one goes, one per call.

Stands next to the hand-over: before it, when the hand-over is synchronous and may throw after its own work (emit of solo, for example), and inside the same uncancellable section, when it is asynchronous.

Implementation

@override
bool disown(Object value) {
  if (_owner.isFinished) {
    throw StateError('$_owner has already finished, cannot disown');
  }
  // Both stores, and the newest wins: the unwinding moves the
  // registrations it puts off out of the stack, and a late value can be
  // registered while they are aside, so neither list alone holds the
  // order. One waiting for an outcome that has not happened yet is still
  // a registration, and handing the value on must still take it back.
  List<_Cleanup>? found;
  var at = -1;
  void look(List<_Cleanup> list) {
    for (var i = list.length - 1; i >= 0; i--) {
      if (identical(list[i].value, value) &&
          (found == null || list[i].order > found![at].order)) {
        found = list;
        at = i;
      }
    }
  }

  look(_owner._cleanups);
  look(_owner._skipped);
  if (found case final list?) {
    list.removeAt(at).release();
    return true;
  }
  return false;
}