Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GH-107803: double linked list implementation for asyncio tasks #107804

Merged
merged 35 commits into from
Jun 22, 2024
Merged
Show file tree
Hide file tree
Changes from 26 commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
cc66eeb
linked list
kumaraditya303 May 24, 2023
d5a3d87
add tail optmiization to linked list
kumaraditya303 May 26, 2023
a0c5fcf
wip
kumaraditya303 May 26, 2023
77d012f
wip
kumaraditya303 May 28, 2023
5d9653d
wip
kumaraditya303 May 28, 2023
5a00198
Merge branch 'main' of https://github.com/python/cpython into linked-…
kumaraditya303 Jun 16, 2023
4cdc834
Merge branch 'main' of https://github.com/python/cpython into linked-…
kumaraditya303 Aug 2, 2023
35a00f1
more fixes
kumaraditya303 Aug 2, 2023
fddb9d6
Merge branch 'main' of https://github.com/python/cpython into linked-…
kumaraditya303 Aug 5, 2023
1d32835
finally it works
kumaraditya303 Aug 5, 2023
b46bcfe
Merge branch 'main' of https://github.com/python/cpython into linked-…
kumaraditya303 Aug 8, 2023
ee7ead2
Merge branch 'main' of https://github.com/python/cpython into linked-…
kumaraditya303 Aug 9, 2023
af0280a
add tests
kumaraditya303 Aug 9, 2023
999fff7
remove weakreflist
kumaraditya303 Aug 10, 2023
87a2231
add some comments
kumaraditya303 Aug 10, 2023
1812408
Merge branch 'main' of https://github.com/python/cpython into linked-…
kumaraditya303 Aug 12, 2023
3cb5673
Merge branch 'main' of https://github.com/python/cpython into linked-…
kumaraditya303 Aug 15, 2023
9552636
reduce code duplication in _asynciomodule.c
kumaraditya303 Aug 15, 2023
5c5b559
address some review comments
kumaraditya303 Aug 17, 2023
82cf69b
add invariants about the state of the linked list
kumaraditya303 Aug 17, 2023
8998f6a
add better explanation
kumaraditya303 Aug 17, 2023
d93c4e1
clinic regen
kumaraditya303 Aug 17, 2023
35726d9
reorder branches for better branch prediction
kumaraditya303 Aug 17, 2023
8dd0492
Update Modules/_asynciomodule.c
kumaraditya303 Aug 18, 2023
8325302
Apply suggestions from code review
kumaraditya303 Aug 19, 2023
80b65e0
fix capturing of eager tasks
kumaraditya303 Aug 19, 2023
b67649e
add comment to task finalization
kumaraditya303 Aug 20, 2023
1252b2f
Merge branch 'main' of https://github.com/python/cpython into linked-…
kumaraditya303 Aug 20, 2023
457739a
Merge branch 'main' into linked-list
kumaraditya303 Aug 20, 2023
4670731
Merge branch 'main' of https://github.com/python/cpython into linked-…
kumaraditya303 Aug 24, 2023
e061081
fix tests and couple c implmentation to c task
kumaraditya303 Aug 24, 2023
836d254
Merge branch 'main' of https://github.com/python/cpython into linked-…
kumaraditya303 Aug 30, 2023
efce4b3
fix test
kumaraditya303 Aug 30, 2023
c7b604c
Merge branch 'main' of https://github.com/python/cpython into linked-…
kumaraditya303 Jun 21, 2024
56beb04
Merge branch 'main' of https://github.com/python/cpython into linked-…
kumaraditya303 Jun 22, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Include/internal/pycore_global_objects_fini_generated.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Include/internal/pycore_global_strings.h
Original file line number Diff line number Diff line change
Expand Up @@ -385,6 +385,7 @@ struct _Py_global_strings {
STRUCT_FOR_ID(displayhook)
STRUCT_FOR_ID(dklen)
STRUCT_FOR_ID(doc)
STRUCT_FOR_ID(done)
STRUCT_FOR_ID(dont_inherit)
STRUCT_FOR_ID(dst)
STRUCT_FOR_ID(dst_dir_fd)
Expand Down
1 change: 1 addition & 0 deletions Include/internal/pycore_runtime_init_generated.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions Include/internal/pycore_unicodeobject_generated.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 3 additions & 2 deletions Lib/asyncio/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -1025,14 +1025,14 @@ def _unregister_eager_task(task):
_py_enter_task = _enter_task
_py_leave_task = _leave_task
_py_swap_current_task = _swap_current_task

_py_all_tasks = all_tasks

try:
from _asyncio import (_register_task, _register_eager_task,
_unregister_task, _unregister_eager_task,
_enter_task, _leave_task, _swap_current_task,
_scheduled_tasks, _eager_tasks, _current_tasks,
current_task)
current_task, all_tasks)
except ImportError:
pass
else:
Expand All @@ -1044,3 +1044,4 @@ def _unregister_eager_task(task):
_c_enter_task = _enter_task
_c_leave_task = _leave_task
_c_swap_current_task = _swap_current_task
_c_all_tasks = all_tasks
34 changes: 23 additions & 11 deletions Lib/test/test_asyncio/test_tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ class BaseTaskTests:

Task = None
Future = None
all_tasks = None

def new_task(self, loop, coro, name='TestTask', context=None):
return self.__class__.Task(coro, loop=loop, name=name, context=context)
Expand Down Expand Up @@ -2087,7 +2088,7 @@ async def kill_me(loop):
coro = kill_me(self.loop)
task = asyncio.ensure_future(coro, loop=self.loop)

self.assertEqual(asyncio.all_tasks(loop=self.loop), {task})
self.assertEqual(self.all_tasks(loop=self.loop), {task})

asyncio.set_event_loop(None)

Expand All @@ -2102,7 +2103,7 @@ async def kill_me(loop):
# no more reference to kill_me() task: the task is destroyed by the GC
support.gc_collect()

self.assertEqual(asyncio.all_tasks(loop=self.loop), set())
self.assertEqual(self.all_tasks(loop=self.loop), set())

mock_handler.assert_called_with(self.loop, {
'message': 'Task was destroyed but it is pending!',
Expand Down Expand Up @@ -2251,7 +2252,7 @@ async def coro():
message = m_log.error.call_args[0][0]
self.assertIn('Task was destroyed but it is pending', message)

self.assertEqual(asyncio.all_tasks(self.loop), set())
self.assertEqual(self.all_tasks(self.loop), set())

def test_create_task_with_noncoroutine(self):
with self.assertRaisesRegex(TypeError,
Expand Down Expand Up @@ -2551,6 +2552,7 @@ async def func():
# Add patched Task & Future back to the test case
cls.Task = Task
cls.Future = Future
cls.all_tasks = tasks.all_tasks

# Add an extra unit-test
cls.test_subclasses_ctask_cfuture = test_subclasses_ctask_cfuture
Expand Down Expand Up @@ -2624,6 +2626,7 @@ class CTask_CFuture_Tests(BaseTaskTests, SetMethodsTest,

Task = getattr(tasks, '_CTask', None)
Future = getattr(futures, '_CFuture', None)
all_tasks = getattr(tasks, '_c_all_tasks', None)
kumaraditya303 marked this conversation as resolved.
Show resolved Hide resolved

@support.refcount_test
def test_refleaks_in_task___init__(self):
Expand Down Expand Up @@ -2655,6 +2658,7 @@ class CTask_CFuture_SubclassTests(BaseTaskTests, test_utils.TestCase):

Task = getattr(tasks, '_CTask', None)
Future = getattr(futures, '_CFuture', None)
all_tasks = getattr(tasks, '_c_all_tasks', None)


@unittest.skipUnless(hasattr(tasks, '_CTask'),
Expand All @@ -2664,6 +2668,7 @@ class CTaskSubclass_PyFuture_Tests(BaseTaskTests, test_utils.TestCase):

Task = getattr(tasks, '_CTask', None)
Future = futures._PyFuture
all_tasks = getattr(tasks, '_py_all_tasks', None)
kumaraditya303 marked this conversation as resolved.
Show resolved Hide resolved


@unittest.skipUnless(hasattr(futures, '_CFuture'),
Expand All @@ -2673,6 +2678,7 @@ class PyTask_CFutureSubclass_Tests(BaseTaskTests, test_utils.TestCase):

Future = getattr(futures, '_CFuture', None)
Task = tasks._PyTask
all_tasks = getattr(tasks, '_py_all_tasks', None)


@unittest.skipUnless(hasattr(tasks, '_CTask'),
Expand All @@ -2681,6 +2687,7 @@ class CTask_PyFuture_Tests(BaseTaskTests, test_utils.TestCase):

Task = getattr(tasks, '_CTask', None)
Future = futures._PyFuture
all_tasks = getattr(tasks, '_c_all_tasks', None)


@unittest.skipUnless(hasattr(futures, '_CFuture'),
Expand All @@ -2689,13 +2696,15 @@ class PyTask_CFuture_Tests(BaseTaskTests, test_utils.TestCase):

Task = tasks._PyTask
Future = getattr(futures, '_CFuture', None)
all_tasks = getattr(tasks, '_c_all_tasks', None)


class PyTask_PyFuture_Tests(BaseTaskTests, SetMethodsTest,
kumaraditya303 marked this conversation as resolved.
Show resolved Hide resolved
test_utils.TestCase):

Task = tasks._PyTask
Future = futures._PyFuture
all_tasks = asyncio.all_tasks


@add_subclass_tests
Expand Down Expand Up @@ -2735,6 +2744,7 @@ class BaseTaskIntrospectionTests:
_unregister_task = None
_enter_task = None
_leave_task = None
all_tasks = None

def test__register_task_1(self):
class TaskLike:
Expand All @@ -2748,9 +2758,9 @@ def done(self):
task = TaskLike()
loop = mock.Mock()

self.assertEqual(asyncio.all_tasks(loop), set())
self.assertEqual(self.all_tasks(loop), set())
self._register_task(task)
self.assertEqual(asyncio.all_tasks(loop), {task})
self.assertEqual(self.all_tasks(loop), {task})
self._unregister_task(task)

def test__register_task_2(self):
Expand All @@ -2764,9 +2774,9 @@ def done(self):
task = TaskLike()
loop = mock.Mock()

self.assertEqual(asyncio.all_tasks(loop), set())
self.assertEqual(self.all_tasks(loop), set())
self._register_task(task)
self.assertEqual(asyncio.all_tasks(loop), {task})
self.assertEqual(self.all_tasks(loop), {task})
self._unregister_task(task)

def test__register_task_3(self):
Expand All @@ -2780,9 +2790,9 @@ def done(self):
task = TaskLike()
loop = mock.Mock()

self.assertEqual(asyncio.all_tasks(loop), set())
self.assertEqual(self.all_tasks(loop), set())
self._register_task(task)
self.assertEqual(asyncio.all_tasks(loop), set())
self.assertEqual(self.all_tasks(loop), set())
self._unregister_task(task)

def test__enter_task(self):
Expand Down Expand Up @@ -2833,20 +2843,21 @@ def test__unregister_task(self):
task.get_loop = lambda: loop
self._register_task(task)
self._unregister_task(task)
self.assertEqual(asyncio.all_tasks(loop), set())
self.assertEqual(self.all_tasks(loop), set())

def test__unregister_task_not_registered(self):
task = mock.Mock()
loop = mock.Mock()
self._unregister_task(task)
self.assertEqual(asyncio.all_tasks(loop), set())
self.assertEqual(self.all_tasks(loop), set())


class PyIntrospectionTests(test_utils.TestCase, BaseTaskIntrospectionTests):
_register_task = staticmethod(tasks._py_register_task)
_unregister_task = staticmethod(tasks._py_unregister_task)
_enter_task = staticmethod(tasks._py_enter_task)
_leave_task = staticmethod(tasks._py_leave_task)
all_tasks = staticmethod(tasks._py_all_tasks)


@unittest.skipUnless(hasattr(tasks, '_c_register_task'),
Expand All @@ -2857,6 +2868,7 @@ class CIntrospectionTests(test_utils.TestCase, BaseTaskIntrospectionTests):
_unregister_task = staticmethod(tasks._c_unregister_task)
_enter_task = staticmethod(tasks._c_enter_task)
_leave_task = staticmethod(tasks._c_leave_task)
all_tasks = staticmethod(tasks._c_all_tasks)
else:
_register_task = _unregister_task = _enter_task = _leave_task = None

Expand Down
Loading