@@ -567,14 +567,14 @@ in-progress:
567
567
return not self .inst.backpressure and not self .inst.calling_sync_import
568
568
```
569
569
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:
573
573
* 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
576
576
` 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
578
578
` None ` ) and thus there is no ` async ` -lowered caller to switch to and so we
579
579
let Python's ` asyncio ` scheduler non-deterministically pick some other task
580
580
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]
598
598
proposal, removing the need for ` on_block ` and the subtle calling contract
599
599
between ` Task.suspend ` and ` canon_lift ` .
600
600
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
- ```
636
601
While a task is running, it may call ` wait ` (via ` canon task.wait ` or, when a
637
602
` callback ` is present, by returning to the event loop) to block until there is
638
603
progress 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)`).
683
648
await self .suspend(asyncio.sleep(0 ))
684
649
```
685
650
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
+
686
685
Lastly, when a task exits, the runtime enforces the guard conditions mentioned
687
686
above and allows other tasks to start or make progress.
688
687
``` python
0 commit comments