Skip to content

Commit 988ec53

Browse files
committed
Tidy CABI: use IntEnum instead of raw bool for cancellation
1 parent 11f8269 commit 988ec53

File tree

2 files changed

+28
-20
lines changed

2 files changed

+28
-20
lines changed

design/mvp/CanonicalABI.md

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -642,9 +642,13 @@ threaded through all core function calls as the "[current task]".
642642

643643
Tasks are parameterized by the caller with 3 callbacks of the following types:
644644
```python
645+
class Cancelled(IntEnum):
646+
FALSE = 0
647+
TRUE = 1
648+
645649
OnStart = Callable[[], list[any]]
646650
OnResolve = Callable[[Optional[list[any]]], None]
647-
OnBlock = Callable[[Awaitable], Awaitable[bool]]
651+
OnBlock = Callable[[Awaitable], Awaitable[Cancelled]]
648652
```
649653
and with the following meanings:
650654
* The `OnStart` callback is called by the task when the task is ready to start
@@ -660,8 +664,8 @@ and with the following meanings:
660664
on a Python [awaitable]. `OnBlock` allows a transitive (async) supertask to
661665
take control flow while its subtask is blocked. During a call to `OnBlock`,
662666
any other `asyncio.Task`s can be scheduled or new `asyncio.Task`s can be
663-
started in response to new export calls. `OnBlock` may return `True` at most
664-
once before a task is resolved to signal that the caller is requesting
667+
started in response to new export calls. `OnBlock` may return `Cancelled.TRUE`
668+
at most once before a task is resolved to signal that the caller is requesting
665669
cancellation; in this case, the given awaitable may not be resolved, and the
666670
cancelled task should call `OnResolve` ASAP (potentially passing `None`).
667671

@@ -711,11 +715,11 @@ called:
711715
if not self.may_enter(self) or self.inst.pending_tasks:
712716
f = asyncio.Future()
713717
self.inst.pending_tasks.append((self, f))
714-
if await self.on_block(f):
718+
if await self.on_block(f) == Cancelled.TRUE:
715719
[i] = [i for i,(t,_) in enumerate(self.inst.pending_tasks) if t == self]
716720
self.inst.pending_tasks.pop(i)
717721
self.on_resolve(None)
718-
return False
722+
return Cancelled.FALSE
719723
assert(self.may_enter(self) and self.inst.starting_pending_task)
720724
self.inst.starting_pending_task = False
721725
if self.opts.sync:
@@ -830,7 +834,7 @@ Python [awaitable] using the `OnBlock` callback described above:
830834

831835
awaitable = asyncio.ensure_future(awaitable)
832836
if awaitable.done() and not DETERMINISTIC_PROFILE and random.randint(0,1):
833-
cancelled = False
837+
cancelled = Cancelled.FALSE
834838
else:
835839
cancelled = await self.on_block(awaitable)
836840
if cancelled and not cancellable:
@@ -878,11 +882,11 @@ the calls in the stack actually block on external I/O.
878882
```python
879883
async def call_sync(self, callee, on_start, on_return):
880884
async def sync_on_block(awaitable):
881-
if await self.on_block(awaitable):
885+
if await self.on_block(awaitable) == Cancelled.TRUE:
882886
assert(self.state == Task.State.INITIAL)
883887
self.state = Task.State.PENDING_CANCEL
884-
assert(not await self.on_block(awaitable))
885-
return False
888+
assert(await self.on_block(awaitable) == Cancelled.FALSE)
889+
return Cancelled.FALSE
886890

887891
assert(not self.inst.calling_sync_import)
888892
self.inst.calling_sync_import = True
@@ -1132,12 +1136,12 @@ cancellation:
11321136
await asyncio.wait([awaitable, self.request_cancel_begin],
11331137
return_when = asyncio.FIRST_COMPLETED)
11341138
if self.request_cancel_begin.done():
1135-
return True
1139+
return Cancelled.TRUE
11361140
else:
11371141
await awaitable
11381142
assert(awaitable.done())
11391143
await scheduler.acquire()
1140-
return False
1144+
return Cancelled.FALSE
11411145

11421146
def relinquish_control():
11431147
if not ret.done():

design/mvp/canonical-abi/definitions.py

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -458,9 +458,13 @@ def drop(self):
458458

459459
#### Task State
460460

461+
class Cancelled(IntEnum):
462+
FALSE = 0
463+
TRUE = 1
464+
461465
OnStart = Callable[[], list[any]]
462466
OnResolve = Callable[[Optional[list[any]]], None]
463-
OnBlock = Callable[[Awaitable], Awaitable[bool]]
467+
OnBlock = Callable[[Awaitable], Awaitable[Cancelled]]
464468

465469
class Task:
466470
class State(Enum):
@@ -496,11 +500,11 @@ async def enter(self):
496500
if not self.may_enter(self) or self.inst.pending_tasks:
497501
f = asyncio.Future()
498502
self.inst.pending_tasks.append((self, f))
499-
if await self.on_block(f):
503+
if await self.on_block(f) == Cancelled.TRUE:
500504
[i] = [i for i,(t,_) in enumerate(self.inst.pending_tasks) if t == self]
501505
self.inst.pending_tasks.pop(i)
502506
self.on_resolve(None)
503-
return False
507+
return Cancelled.FALSE
504508
assert(self.may_enter(self) and self.inst.starting_pending_task)
505509
self.inst.starting_pending_task = False
506510
if self.opts.sync:
@@ -537,7 +541,7 @@ async def wait_on(self, awaitable, sync, cancellable = False) -> bool:
537541

538542
awaitable = asyncio.ensure_future(awaitable)
539543
if awaitable.done() and not DETERMINISTIC_PROFILE and random.randint(0,1):
540-
cancelled = False
544+
cancelled = Cancelled.FALSE
541545
else:
542546
cancelled = await self.on_block(awaitable)
543547
if cancelled and not cancellable:
@@ -557,11 +561,11 @@ async def wait_on(self, awaitable, sync, cancellable = False) -> bool:
557561

558562
async def call_sync(self, callee, on_start, on_return):
559563
async def sync_on_block(awaitable):
560-
if await self.on_block(awaitable):
564+
if await self.on_block(awaitable) == Cancelled.TRUE:
561565
assert(self.state == Task.State.INITIAL)
562566
self.state = Task.State.PENDING_CANCEL
563-
assert(not await self.on_block(awaitable))
564-
return False
567+
assert(await self.on_block(awaitable) == Cancelled.FALSE)
568+
return Cancelled.FALSE
565569

566570
assert(not self.inst.calling_sync_import)
567571
self.inst.calling_sync_import = True
@@ -712,12 +716,12 @@ async def async_on_block(awaitable):
712716
await asyncio.wait([awaitable, self.request_cancel_begin],
713717
return_when = asyncio.FIRST_COMPLETED)
714718
if self.request_cancel_begin.done():
715-
return True
719+
return Cancelled.TRUE
716720
else:
717721
await awaitable
718722
assert(awaitable.done())
719723
await scheduler.acquire()
720-
return False
724+
return Cancelled.FALSE
721725

722726
def relinquish_control():
723727
if not ret.done():

0 commit comments

Comments
 (0)