Avoid leaking unreachable listeners on `CancelableOperation`. (#206)

* Make `CancelableOperation` not hold onto unnecessary callbacks.

The existing `CancelableOperation` contains two completers,
where at most one will ever complete. Listeners added to
the other completer's future will never be released as
long as the operation is alive, even after the operation
has otherwise completed.

This change drops reference to the other completer when
one completer is chosen for completion.
That can allow the completer, its future, and that future's listeners
to be GC'ed when it's known that they'll never be relevant again.

The change has one visible effect: If asking for the `value`
future after the operation has been cancelled and the value
completer has been released, you'll get a new future,
which also never completes, which is not identical to
other futures returned by the same getter.
THis only matters if someone checks the future for identity,
their behavior is exactly the same (no behavior, whatsoever).

Since the same class returns a completely new future on each
call read of `valueOrCancellation`, I think that's a reasonable
change, and unlikely to affect anyone.
(Users are not usually expecting asynchronous functions to
return the same future every time since `async` functions
don't.)

Fixes #200.

1 file changed
tree: dca347684fda00e043037aed1bc155123fce6a83
  1. .github/
  2. lib/
  3. test/
  4. .gitignore
  5. analysis_options.yaml
  6. AUTHORS
  7. CHANGELOG.md
  8. CONTRIBUTING.md
  9. LICENSE
  10. pubspec.yaml
  11. README.md
README.md

Contains utility classes in the style of dart:async to work with asynchronous computations.