@@ -567,14 +567,14 @@ in-progress:
567567 return not self .inst.backpressure and not self .inst.calling_sync_import
568568```
569569
570- The key method of ` Task ` , used by ` enter ` , ` wait ` and ` yield_ ` , is ` suspend ` .
571- ` Task.suspend ` takes an ` asyncio.Future ` and waits on it, while allowing other
572- tasks make progress. When suspending, there are two cases to consider:
570+ The key method of ` Task ` , used by ` enter ` , ` wait ` and ` yield_ ` , is ` suspend ` ,
571+ which takes an ` asyncio.Future ` to ` await ` on. When suspending, there are two
572+ cases to consider:
573573* This is the first time the current ` Task ` has blocked and thus there may be
574- an ` async ` -lowered caller waiting to find out that its call blocked (which we
575- signal by calling the ` on_block ` handler that the caller passed to
574+ an ` async ` -lowered caller waiting to find out that the callee blocked (which
575+ is signalled by calling the ` on_block ` handler that the caller passed to
576576 ` canon_lift ` ).
577- * This task has already blocked in the past (signaled by ` on_block ` being
577+ * This task has already blocked in the past (signalled by ` on_block ` being
578578 ` None ` ) and thus there is no ` async ` -lowered caller to switch to and so we
579579 let Python's ` asyncio ` scheduler non-deterministically pick some other task
580580 that is ready to go, waiting to ` acquire ` the ` current_task ` lock.
@@ -598,41 +598,6 @@ reimplemented using the [`suspend`] instruction of the [typed continuations]
598598proposal, removing the need for ` on_block ` and the subtle calling contract
599599between ` Task.suspend ` and ` canon_lift ` .
600600
601- The ` borrow_count ` field is used by the following methods to track the number
602- of borrowed handles that were passed as parameters to the export that have not
603- yet been dropped (and thus might dangle if the caller destroys the resource
604- after this export call finishes):
605- ``` python
606- def create_borrow (self ):
607- self .borrow_count += 1
608-
609- def drop_borrow (self ):
610- assert (self .borrow_count > 0 )
611- self .borrow_count -= 1
612- ```
613- The ` exit ` defined below traps if ` borrow_count ` is not zero when the lifted
614- call completes.
615-
616- All ` Task ` s (whether lifted ` async ` or not) are allowed to call ` async ` -lowered
617- imports. Calling an ` async ` -lowered import creates an ` AsyncSubtask ` (defined
618- below) which is stored in the current component instance's ` async_subtasks `
619- table and tracked by the current task's ` num_async_subtasks ` counter, which is
620- guarded to be ` 0 ` in ` Task.exit ` (below) to ensure [ structured concurrency] .
621- ``` python
622- def add_async_subtask (self , subtask ):
623- assert (subtask.supertask is None and subtask.index is None )
624- subtask.supertask = self
625- subtask.index = self .inst.async_subtasks.add(subtask)
626- self .num_async_subtasks += 1
627- return subtask.index
628-
629- def async_subtask_made_progress (self , subtask ):
630- assert (subtask.supertask is self )
631- if subtask.enqueued:
632- return
633- subtask.enqueued = True
634- self .events.put_nowait(subtask)
635- ```
636601While a task is running, it may call ` wait ` (via ` canon task.wait ` or, when a
637602` callback ` is present, by returning to the event loop) to block until there is
638603progress on one of the task's async subtasks. Although the Python code uses an
@@ -683,6 +648,40 @@ emulated in the Python code here by awaiting a `sleep(0)`).
683648 await self .suspend(asyncio.sleep(0 ))
684649```
685650
651+ All ` Task ` s (whether lifted ` async ` or not) are allowed to call ` async ` -lowered
652+ imports. Calling an ` async ` -lowered import creates an ` AsyncSubtask ` (defined
653+ below) which is stored in the current component instance's ` async_subtasks `
654+ table and tracked by the current task's ` num_async_subtasks ` counter, which is
655+ guarded to be ` 0 ` in ` Task.exit ` (below) to ensure [ structured concurrency] .
656+ ``` python
657+ def add_async_subtask (self , subtask ):
658+ assert (subtask.supertask is None and subtask.index is None )
659+ subtask.supertask = self
660+ subtask.index = self .inst.async_subtasks.add(subtask)
661+ self .num_async_subtasks += 1
662+ return subtask.index
663+
664+ def async_subtask_made_progress (self , subtask ):
665+ assert (subtask.supertask is self )
666+ if subtask.enqueued:
667+ return
668+ subtask.enqueued = True
669+ self .events.put_nowait(subtask)
670+ ```
671+
672+ The ` borrow_count ` field is used by the following methods to track the number
673+ of borrowed handles that were passed as parameters to the export that have not
674+ yet been dropped (and thus might dangle if the caller destroys the resource
675+ after this export call finishes):
676+ ``` python
677+ def create_borrow (self ):
678+ self .borrow_count += 1
679+
680+ def drop_borrow (self ):
681+ assert (self .borrow_count > 0 )
682+ self .borrow_count -= 1
683+ ```
684+
686685Lastly, when a task exits, the runtime enforces the guard conditions mentioned
687686above and allows other tasks to start or make progress.
688687``` python
0 commit comments