Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

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

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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Merged
willingc merged 35 commits intopython:mainfromkumaraditya303:linked-list
Jun 22, 2024
Merged
Show file tree
Hide file tree
Changes from1 commit
Commits
Show all changes
35 commits
Select commitHold shift + click to select a range
cc66eeb
linked list
kumaraditya303May 24, 2023
d5a3d87
add tail optmiization to linked list
kumaraditya303May 26, 2023
a0c5fcf
wip
kumaraditya303May 26, 2023
77d012f
wip
kumaraditya303May 28, 2023
5d9653d
wip
kumaraditya303May 28, 2023
5a00198
Merge branch 'main' of https://github.com/python/cpython into linked-…
kumaraditya303Jun 16, 2023
4cdc834
Merge branch 'main' of https://github.com/python/cpython into linked-…
kumaraditya303Aug 2, 2023
35a00f1
more fixes
kumaraditya303Aug 2, 2023
fddb9d6
Merge branch 'main' of https://github.com/python/cpython into linked-…
kumaraditya303Aug 5, 2023
1d32835
finally it works
kumaraditya303Aug 5, 2023
b46bcfe
Merge branch 'main' of https://github.com/python/cpython into linked-…
kumaraditya303Aug 8, 2023
ee7ead2
Merge branch 'main' of https://github.com/python/cpython into linked-…
kumaraditya303Aug 9, 2023
af0280a
add tests
kumaraditya303Aug 9, 2023
999fff7
remove weakreflist
kumaraditya303Aug 10, 2023
87a2231
add some comments
kumaraditya303Aug 10, 2023
1812408
Merge branch 'main' of https://github.com/python/cpython into linked-…
kumaraditya303Aug 12, 2023
3cb5673
Merge branch 'main' of https://github.com/python/cpython into linked-…
kumaraditya303Aug 15, 2023
9552636
reduce code duplication in _asynciomodule.c
kumaraditya303Aug 15, 2023
5c5b559
address some review comments
kumaraditya303Aug 17, 2023
82cf69b
add invariants about the state of the linked list
kumaraditya303Aug 17, 2023
8998f6a
add better explanation
kumaraditya303Aug 17, 2023
d93c4e1
clinic regen
kumaraditya303Aug 17, 2023
35726d9
reorder branches for better branch prediction
kumaraditya303Aug 17, 2023
8dd0492
Update Modules/_asynciomodule.c
kumaraditya303Aug 18, 2023
8325302
Apply suggestions from code review
kumaraditya303Aug 19, 2023
80b65e0
fix capturing of eager tasks
kumaraditya303Aug 19, 2023
b67649e
add comment to task finalization
kumaraditya303Aug 20, 2023
1252b2f
Merge branch 'main' of https://github.com/python/cpython into linked-…
kumaraditya303Aug 20, 2023
457739a
Merge branch 'main' into linked-list
kumaraditya303Aug 20, 2023
4670731
Merge branch 'main' of https://github.com/python/cpython into linked-…
kumaraditya303Aug 24, 2023
e061081
fix tests and couple c implmentation to c task
kumaraditya303Aug 24, 2023
836d254
Merge branch 'main' of https://github.com/python/cpython into linked-…
kumaraditya303Aug 30, 2023
efce4b3
fix test
kumaraditya303Aug 30, 2023
c7b604c
Merge branch 'main' of https://github.com/python/cpython into linked-…
kumaraditya303Jun 21, 2024
56beb04
Merge branch 'main' of https://github.com/python/cpython into linked-…
kumaraditya303Jun 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
NextNext commit
linked list
  • Loading branch information
@kumaraditya303
kumaraditya303 committedMay 26, 2023
commitcc66eeb5575af1303f997a7955d50998a03cba6e
2 changes: 1 addition & 1 deletionLib/asyncio/tasks.py
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -1041,7 +1041,7 @@ def _unregister_eager_task(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 Down
212 changes: 138 additions & 74 deletionsModules/_asynciomodule.c
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -16,6 +16,59 @@ module _asyncio
[clinic start generated code]*/
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=8fd17862aa989c69]*/

typedef enum {
STATE_PENDING,
STATE_CANCELLED,
STATE_FINISHED
} fut_state;

#define FutureObj_HEAD(prefix) \
PyObject_HEAD \
PyObject *prefix##_loop; \
PyObject *prefix##_callback0; \
PyObject *prefix##_context0; \
PyObject *prefix##_callbacks; \
PyObject *prefix##_exception; \
PyObject *prefix##_exception_tb; \
PyObject *prefix##_result; \
PyObject *prefix##_source_tb; \
PyObject *prefix##_cancel_msg; \
fut_state prefix##_state; \
int prefix##_log_tb; \
int prefix##_blocking; \
PyObject *dict; \
PyObject *prefix##_weakreflist; \
PyObject *prefix##_cancelled_exc;

typedef struct {
FutureObj_HEAD(fut)
} FutureObj;

typedef struct TaskObj {
FutureObj_HEAD(task)
PyObject *task_fut_waiter;
PyObject *task_coro;
PyObject *task_name;
PyObject *task_context;
int task_must_cancel;
int task_log_destroy_pending;
int task_num_cancels_requested;
struct TaskObj *next;
struct TaskObj *prev;
} TaskObj;

typedef struct {
PyObject_HEAD
TaskObj *sw_task;
PyObject *sw_arg;
} TaskStepMethWrapper;


#define Future_CheckExact(state, obj) Py_IS_TYPE(obj, state->FutureType)
#define Task_CheckExact(state, obj) Py_IS_TYPE(obj, state->TaskType)

#define Future_Check(state, obj) PyObject_TypeCheck(obj, state->FutureType)
#define Task_Check(state, obj) PyObject_TypeCheck(obj, state->TaskType)

#define FI_FREELIST_MAXLEN 255

Expand DownExpand Up@@ -73,6 +126,11 @@ typedef struct {

futureiterobject *fi_freelist;
Py_ssize_t fi_freelist_len;

struct {
TaskObj *head;
} asyncio_tasks;

} asyncio_state;

static inline asyncio_state *
Expand DownExpand Up@@ -102,56 +160,6 @@ get_asyncio_state_by_def(PyObject *self)
return get_asyncio_state(mod);
}

typedef enum {
STATE_PENDING,
STATE_CANCELLED,
STATE_FINISHED
} fut_state;

#define FutureObj_HEAD(prefix) \
PyObject_HEAD \
PyObject *prefix##_loop; \
PyObject *prefix##_callback0; \
PyObject *prefix##_context0; \
PyObject *prefix##_callbacks; \
PyObject *prefix##_exception; \
PyObject *prefix##_exception_tb; \
PyObject *prefix##_result; \
PyObject *prefix##_source_tb; \
PyObject *prefix##_cancel_msg; \
fut_state prefix##_state; \
int prefix##_log_tb; \
int prefix##_blocking; \
PyObject *prefix##_weakreflist; \
PyObject *prefix##_cancelled_exc;

typedef struct {
FutureObj_HEAD(fut)
} FutureObj;

typedef struct {
FutureObj_HEAD(task)
PyObject *task_fut_waiter;
PyObject *task_coro;
PyObject *task_name;
PyObject *task_context;
int task_must_cancel;
int task_log_destroy_pending;
int task_num_cancels_requested;
} TaskObj;

typedef struct {
PyObject_HEAD
TaskObj *sw_task;
PyObject *sw_arg;
} TaskStepMethWrapper;


#define Future_CheckExact(state, obj) Py_IS_TYPE(obj, state->FutureType)
#define Task_CheckExact(state, obj) Py_IS_TYPE(obj, state->TaskType)

#define Future_Check(state, obj) PyObject_TypeCheck(obj, state->FutureType)
#define Task_Check(state, obj) PyObject_TypeCheck(obj, state->TaskType)

#include "clinic/_asynciomodule.c.h"

Expand DownExpand Up@@ -1939,16 +1947,17 @@ static PyMethodDef TaskWakeupDef = {

/* ----- Task introspection helpers */

staticint
register_task(asyncio_state *state,PyObject *task)
staticvoid
register_task(asyncio_state *state,TaskObj *task)
{
PyObject *res = PyObject_CallMethodOneArg(state->scheduled_tasks,
&_Py_ID(add), task);
if (res == NULL) {
return -1;
assert(Task_Check(state, task));
assert(task->prev == NULL);
assert(task->next == NULL);
task->prev = state->asyncio_tasks.head;
if (state->asyncio_tasks.head != NULL) {
state->asyncio_tasks.head->next = task;
}
Py_DECREF(res);
return 0;
state->asyncio_tasks.head = task;
}

static int
Expand All@@ -1957,16 +1966,22 @@ register_eager_task(asyncio_state *state, PyObject *task)
return PySet_Add(state->eager_tasks, task);
}

staticint
unregister_task(asyncio_state *state,PyObject *task)
staticvoid
unregister_task(asyncio_state *state,TaskObj *task)
{
PyObject *res = PyObject_CallMethodOneArg(state->scheduled_tasks,
&_Py_ID(discard), task);
if (res == NULL) {
return -1;
assert(Task_Check(state, task));
if (task->prev != NULL) {
task->prev->next = task->next;
}
Py_DECREF(res);
return 0;
if (task->next != NULL) {
task->next->prev = task->prev;
}
if (state->asyncio_tasks.head == task) {
assert(task->next == NULL);
state->asyncio_tasks.head = task->prev;
}
task->next = NULL;
task->prev = NULL;
}

static int
Expand DownExpand Up@@ -2147,7 +2162,8 @@ _asyncio_Task___init___impl(TaskObj *self, PyObject *coro, PyObject *loop,
if (task_call_step_soon(state, self, NULL)) {
return -1;
}
return register_task(state, (PyObject*)self);
register_task(state, self);
return 0;
}

static int
Expand DownExpand Up@@ -2552,6 +2568,9 @@ _asyncio_Task_set_name(TaskObj *self, PyObject *value)
static void
TaskObj_finalize(TaskObj *task)
{
asyncio_state *state = get_asyncio_state_by_def((PyObject *)task);
unregister_task(state, task);

PyObject *context;
PyObject *message = NULL;
PyObject *func;
Expand DownExpand Up@@ -3184,9 +3203,7 @@ task_eager_start(asyncio_state *state, TaskObj *task)
}

if (task->task_state == STATE_PENDING) {
if (register_task(state, (PyObject *)task) == -1) {
retval = -1;
}
register_task(state, task);
} else {
// This seems to really help performance on pyperformance benchmarks
Py_CLEAR(task->task_coro);
Expand DownExpand Up@@ -3352,9 +3369,16 @@ _asyncio__register_task_impl(PyObject *module, PyObject *task)
/*[clinic end generated code: output=8672dadd69a7d4e2 input=21075aaea14dfbad]*/
{
asyncio_state *state = get_asyncio_state(module);
if (register_task(state, task) < 0) {
return NULL;
if (!Task_Check(state, task)) {
PyObject *res = PyObject_CallMethodOneArg(state->scheduled_tasks,
&_Py_ID(add), task);
if (res == NULL) {
return NULL;
}
Py_DECREF(res);
Py_RETURN_NONE;
}
register_task(state, (TaskObj *)task);
Py_RETURN_NONE;
}

Expand DownExpand Up@@ -3395,9 +3419,16 @@ _asyncio__unregister_task_impl(PyObject *module, PyObject *task)
/*[clinic end generated code: output=6e5585706d568a46 input=28fb98c3975f7bdc]*/
{
asyncio_state *state = get_asyncio_state(module);
if (unregister_task(state, task) < 0) {
return NULL;
if (!Task_Check(state, task)) {
PyObject *res = PyObject_CallMethodOneArg(state->scheduled_tasks,
&_Py_ID(discard), task);
if (res == NULL) {
return NULL;
}
Py_DECREF(res);
Py_RETURN_NONE;
}
unregister_task(state, (TaskObj *)task);
Py_RETURN_NONE;
}

Expand DownExpand Up@@ -3534,6 +3565,37 @@ _asyncio_current_task_impl(PyObject *module, PyObject *loop)

/*********************** Module **************************/

/*[clinic input]
_asyncio.all_tasks

loop: object = None

Return set of tasks associated for loop.

[clinic start generated code]*/

static PyObject *
_asyncio_all_tasks_impl(PyObject *module, PyObject *loop)
/*[clinic end generated code: output=0e107cbb7f72aa7b input=02fab144171b1879]*/
{
PyObject *tasks = PySet_New(NULL);
if (tasks == NULL) {
return NULL;
}
asyncio_state *state = get_asyncio_state(module);
TaskObj *head = state->asyncio_tasks.head;
while (head)
{
if (loop == Py_None || head->task_loop == loop) {
if (PySet_Add(tasks, (PyObject *)head) < 0) {
Py_DECREF(tasks);
return NULL;
}
}
head = head->prev;
}
return tasks;
}

static void
module_free_freelists(asyncio_state *state)
Expand DownExpand Up@@ -3731,13 +3793,15 @@ static PyMethodDef asyncio_methods[] = {
_ASYNCIO__ENTER_TASK_METHODDEF
_ASYNCIO__LEAVE_TASK_METHODDEF
_ASYNCIO__SWAP_CURRENT_TASK_METHODDEF
_ASYNCIO_ALL_TASKS_METHODDEF
{NULL, NULL}
};

static int
module_exec(PyObject *mod)
{
asyncio_state *state = get_asyncio_state(mod);
state->asyncio_tasks.head = NULL;

#define CREATE_TYPE(m, tp, spec, base) \
do { \
Expand Down
62 changes: 61 additions & 1 deletionModules/clinic/_asynciomodule.c.h
View file
Open in desktop

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

11 changes: 11 additions & 0 deletionsmain.py
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
import asyncio
import gc
async def foo():pass

async def main():
await asyncio.create_task(foo())
gc.collect(0)
print(asyncio.all_tasks())


asyncio.run(main())

[8]ページ先頭

©2009-2025 Movatter.jp