From 3b9b4cfc110fe6a3727d8d7d9c148218df2ce300 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristj=C3=A1n=20Valur=20J=C3=B3nsson?= Date: Tue, 26 Sep 2023 16:11:13 +0000 Subject: [PATCH 1/4] Update state transition comment for Task --- Lib/asyncio/tasks.py | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/Lib/asyncio/tasks.py b/Lib/asyncio/tasks.py index 21a1b24194bcd8..9bb36d7ec4a286 100644 --- a/Lib/asyncio/tasks.py +++ b/Lib/asyncio/tasks.py @@ -73,15 +73,23 @@ class Task(futures._PyFuture): # Inherit Python Task implementation """A coroutine wrapped in a Future.""" # An important invariant maintained while a Task not done: + # _fut_waiter is either None or a Future. The task can be + # in any of 3 states: # - # - Either _fut_waiter is None, and _step() is scheduled; - # - or _fut_waiter is some Future, and _step() is *not* scheduled. + # - 1 (_fut_waiter is not None and not _fut_waiter.done()); + # __step() is *not* scheduled and the Task is waiting for _fut_waiter. + # - 2 (_fut_waiter is None or _fut_waiter.done()), and __step() is scheduled; + # the Task is waiting for __step() to be executed. + # - 3 _fut_waiter is None and __step() is *not* scheduled; + # the Task is currently executing (in __step()). # - # The only transition from the latter to the former is through - # _wakeup(). When _fut_waiter is not None, one of its callbacks - # must be _wakeup(). + # The only transition from 1 to 2 is through __wakeup(). __wakeup() + # leaves _fut_waiter in place. + # In state 1, one of the callbacks of __fut_waiter must be __wakeup(). + # It transitions from 2 to 3 when __step() is executed, and it clears + # _fut_waiter to None. - # If False, don't log a message if the task is destroyed whereas its + # If False, don't log a message if the task is destroyed while its # status is still pending _log_destroy_pending = True From 3cc8ca9f4be1b7039aaa4919240ce816408e7c3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristj=C3=A1n=20Valur=20J=C3=B3nsson?= Date: Tue, 26 Sep 2023 17:37:00 +0000 Subject: [PATCH 2/4] update comment with states 2a and 2b --- Lib/asyncio/tasks.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/Lib/asyncio/tasks.py b/Lib/asyncio/tasks.py index 9bb36d7ec4a286..71c28197b82889 100644 --- a/Lib/asyncio/tasks.py +++ b/Lib/asyncio/tasks.py @@ -78,15 +78,19 @@ class Task(futures._PyFuture): # Inherit Python Task implementation # # - 1 (_fut_waiter is not None and not _fut_waiter.done()); # __step() is *not* scheduled and the Task is waiting for _fut_waiter. - # - 2 (_fut_waiter is None or _fut_waiter.done()), and __step() is scheduled; + # - 2a (_fut_waiter is None or _fut_waiter.done()), and __wakeup() is scheduled; + # the Task is waiting for __wakeup() to be executed. + # - 2b (_fut_waiter is None or _fut_waiter.done()), and __step() is scheduled; # the Task is waiting for __step() to be executed. # - 3 _fut_waiter is None and __step() is *not* scheduled; # the Task is currently executing (in __step()). # - # The only transition from 1 to 2 is through __wakeup(). __wakeup() - # leaves _fut_waiter in place. + # The transition from 1 to 2a happens when _fut_waiter becomes done(), + # as it schedules __wakeup() to be called. + # The transition from 2a to 2b happens when __wakeup() is executed, + # scheduling __step() to be called, leaving _fut_waiter in place. # In state 1, one of the callbacks of __fut_waiter must be __wakeup(). - # It transitions from 2 to 3 when __step() is executed, and it clears + # It transitions from 2b to 3 when __step() is executed, and it clears # _fut_waiter to None. # If False, don't log a message if the task is destroyed while its From e3f07bbf3f720a9921f1082ae03339f89b420e37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristj=C3=A1n=20Valur=20J=C3=B3nsson?= Date: Wed, 27 Sep 2023 21:17:12 +0000 Subject: [PATCH 3/4] Update Lib/asyncio/tasks.py Co-authored-by: Adam Turner <9087854+AA-Turner@users.noreply.github.com> --- Lib/asyncio/tasks.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Lib/asyncio/tasks.py b/Lib/asyncio/tasks.py index 71c28197b82889..7fbcff769afe21 100644 --- a/Lib/asyncio/tasks.py +++ b/Lib/asyncio/tasks.py @@ -76,14 +76,14 @@ class Task(futures._PyFuture): # Inherit Python Task implementation # _fut_waiter is either None or a Future. The task can be # in any of 3 states: # - # - 1 (_fut_waiter is not None and not _fut_waiter.done()); - # __step() is *not* scheduled and the Task is waiting for _fut_waiter. - # - 2a (_fut_waiter is None or _fut_waiter.done()), and __wakeup() is scheduled; - # the Task is waiting for __wakeup() to be executed. - # - 2b (_fut_waiter is None or _fut_waiter.done()), and __step() is scheduled; - # the Task is waiting for __step() to be executed. - # - 3 _fut_waiter is None and __step() is *not* scheduled; - # the Task is currently executing (in __step()). + # - 1: _fut_waiter is not None and not _fut_waiter.done()): + # __step() is *not* scheduled and the Task is waiting for _fut_waiter. + # - 2a: _fut_waiter is None or _fut_waiter.done()) and __wakeup() is scheduled: + # the Task is waiting for __wakeup() to be executed. + # - 2b: _fut_waiter is None or _fut_waiter.done()) and __step() is scheduled + # the Task is waiting for __step() to be executed. + # - 3: _fut_waiter is None and __step() is *not* scheduled: + # the Task is currently executing (in __step()). # # The transition from 1 to 2a happens when _fut_waiter becomes done(), # as it schedules __wakeup() to be called. From 729a291813442bcd86d168b22ea5c7c7dfd90b15 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristj=C3=A1n=20Valur=20J=C3=B3nsson?= Date: Wed, 27 Sep 2023 21:33:36 +0000 Subject: [PATCH 4/4] Fix incorrect detail. __wakeup() calls __step() directly --- Lib/asyncio/tasks.py | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/Lib/asyncio/tasks.py b/Lib/asyncio/tasks.py index 7fbcff769afe21..72f4cc07173f0a 100644 --- a/Lib/asyncio/tasks.py +++ b/Lib/asyncio/tasks.py @@ -73,25 +73,23 @@ class Task(futures._PyFuture): # Inherit Python Task implementation """A coroutine wrapped in a Future.""" # An important invariant maintained while a Task not done: - # _fut_waiter is either None or a Future. The task can be - # in any of 3 states: + # _fut_waiter is either None or a Future. The Future + # can be either done() or not done(). + # The task can be in any of 3 states: # - # - 1: _fut_waiter is not None and not _fut_waiter.done()): - # __step() is *not* scheduled and the Task is waiting for _fut_waiter. - # - 2a: _fut_waiter is None or _fut_waiter.done()) and __wakeup() is scheduled: - # the Task is waiting for __wakeup() to be executed. - # - 2b: _fut_waiter is None or _fut_waiter.done()) and __step() is scheduled + # - 1: _fut_waiter is not None and not _fut_waiter.done(): + # __step() is *not* scheduled and the Task is waiting for _fut_waiter. + # - 2: (_fut_waiter is None or _fut_waiter.done()) and __step() is scheduled: # the Task is waiting for __step() to be executed. # - 3: _fut_waiter is None and __step() is *not* scheduled: # the Task is currently executing (in __step()). # - # The transition from 1 to 2a happens when _fut_waiter becomes done(), - # as it schedules __wakeup() to be called. - # The transition from 2a to 2b happens when __wakeup() is executed, - # scheduling __step() to be called, leaving _fut_waiter in place. - # In state 1, one of the callbacks of __fut_waiter must be __wakeup(). - # It transitions from 2b to 3 when __step() is executed, and it clears - # _fut_waiter to None. + # * In state 1, one of the callbacks of __fut_waiter must be __wakeup(). + # * The transition from 1 to 2 happens when _fut_waiter becomes done(), + # as it schedules __wakeup() to be called (which calls __step() so + # we way that __step() is scheduled). + # * It transitions from 2 to 3 when __step() is executed, and it clears + # _fut_waiter to None. # If False, don't log a message if the task is destroyed while its # status is still pending