Record that `fut` is awaited on by `waiter`.
(fut, waiter, /)
| 427 | |
| 428 | |
| 429 | def future_add_to_awaited_by(fut, waiter, /): |
| 430 | """Record that `fut` is awaited on by `waiter`.""" |
| 431 | # For the sake of keeping the implementation minimal and assuming |
| 432 | # that most of asyncio users use the built-in Futures and Tasks |
| 433 | # (or their subclasses), we only support native Future objects |
| 434 | # and their subclasses. |
| 435 | # |
| 436 | # Longer version: tracking requires storing the caller-callee |
| 437 | # dependency somewhere. One obvious choice is to store that |
| 438 | # information right in the future itself in a dedicated attribute. |
| 439 | # This means that we'd have to require all duck-type compatible |
| 440 | # futures to implement a specific attribute used by asyncio for |
| 441 | # the book keeping. Another solution would be to store that in |
| 442 | # a global dictionary. The downside here is that that would create |
| 443 | # strong references and any scenario where the "add" call isn't |
| 444 | # followed by a "discard" call would lead to a memory leak. |
| 445 | # Using WeakDict would resolve that issue, but would complicate |
| 446 | # the C code (_asynciomodule.c). The bottom line here is that |
| 447 | # it's not clear that all this work would be worth the effort. |
| 448 | # |
| 449 | # Note that there's an accelerated version of this function |
| 450 | # shadowing this implementation later in this file. |
| 451 | if isinstance(fut, _PyFuture) and isinstance(waiter, _PyFuture): |
| 452 | if fut._Future__asyncio_awaited_by is None: |
| 453 | fut._Future__asyncio_awaited_by = set() |
| 454 | fut._Future__asyncio_awaited_by.add(waiter) |
| 455 | |
| 456 | |
| 457 | def future_discard_from_awaited_by(fut, waiter, /): |