6
6
#include "pycore_critical_section.h" // Py_BEGIN_CRITICAL_SECTION_MUT()
7
7
#include "pycore_dict.h" // _PyDict_GetItem_KnownHash()
8
8
#include "pycore_freelist.h" // _Py_FREELIST_POP()
9
+ #include "pycore_llist.h" // struct llist_node
9
10
#include "pycore_modsupport.h" // _PyArg_CheckPositional()
10
11
#include "pycore_moduleobject.h" // _PyModule_GetState()
11
- #include "pycore_object.h" // _Py_SetImmortalUntracked()
12
12
#include "pycore_pyerrors.h" // _PyErr_ClearExcState()
13
13
#include "pycore_pylifecycle.h" // _Py_IsInterpreterFinalizing()
14
14
#include "pycore_pystate.h" // _PyThreadState_GET()
@@ -60,8 +60,7 @@ typedef struct TaskObj {
60
60
PyObject * task_coro ;
61
61
PyObject * task_name ;
62
62
PyObject * task_context ;
63
- struct TaskObj * next ;
64
- struct TaskObj * prev ;
63
+ struct llist_node task_node ;
65
64
} TaskObj ;
66
65
67
66
typedef struct {
@@ -136,21 +135,11 @@ typedef struct {
136
135
/* Counter for autogenerated Task names */
137
136
uint64_t task_name_counter ;
138
137
139
- /* Circular linked-list of all tasks which are instances of asyncio.Task or subclasses
140
- of it. Third party tasks implementations which don't inherit from
141
- asyncio.Task are tracked separately using the 'non_asyncio_tasks' WeakSet.
142
- `first` is used as a sentinel to mark the end of the linked-list. It avoids one
143
- branch in checking for empty list when adding a new task, the list is
144
- initialized with `head`, `head->next` and `head->prev` pointing to `first`
145
- to mark an empty list.
146
-
138
+ /* Head of circular linked-list of all tasks which are instances of `asyncio.Task`
139
+ or subclasses of it. Third party tasks implementations which don't inherit from
140
+ `asyncio.Task` are tracked separately using the `non_asyncio_tasks` WeakSet.
147
141
*/
148
-
149
- struct {
150
- TaskObj first ;
151
- TaskObj * head ;
152
- } asyncio_tasks ;
153
-
142
+ struct llist_node asyncio_tasks_head ;
154
143
} asyncio_state ;
155
144
156
145
static inline asyncio_state *
@@ -1896,19 +1885,12 @@ register_task(asyncio_state *state, TaskObj *task)
1896
1885
{
1897
1886
ASYNCIO_STATE_LOCK (state );
1898
1887
assert (Task_Check (state , task ));
1899
- assert (task != & state -> asyncio_tasks .first );
1900
- if (task -> next != NULL ) {
1888
+ if (task -> task_node .next != NULL ) {
1901
1889
// already registered
1890
+ assert (task -> task_node .prev != NULL );
1902
1891
goto exit ;
1903
1892
}
1904
- assert (task -> prev == NULL );
1905
- assert (state -> asyncio_tasks .head != NULL );
1906
-
1907
- task -> next = state -> asyncio_tasks .head ;
1908
- task -> prev = state -> asyncio_tasks .head -> prev ;
1909
- state -> asyncio_tasks .head -> prev -> next = task ;
1910
- state -> asyncio_tasks .head -> prev = task ;
1911
-
1893
+ llist_insert_tail (& state -> asyncio_tasks_head , & task -> task_node );
1912
1894
exit :
1913
1895
ASYNCIO_STATE_UNLOCK (state );
1914
1896
}
@@ -1924,18 +1906,12 @@ unregister_task(asyncio_state *state, TaskObj *task)
1924
1906
{
1925
1907
ASYNCIO_STATE_LOCK (state );
1926
1908
assert (Task_Check (state , task ));
1927
- assert (task != & state -> asyncio_tasks .first );
1928
- if (task -> next == NULL ) {
1909
+ if (task -> task_node .next == NULL ) {
1929
1910
// not registered
1930
- assert (task -> prev == NULL );
1931
- assert (state -> asyncio_tasks .head != task );
1911
+ assert (task -> task_node .prev == NULL );
1932
1912
goto exit ;
1933
1913
}
1934
- task -> next -> prev = task -> prev ;
1935
- task -> prev -> next = task -> next ;
1936
- task -> next = NULL ;
1937
- task -> prev = NULL ;
1938
- assert (state -> asyncio_tasks .head != task );
1914
+ llist_remove (& task -> task_node );
1939
1915
exit :
1940
1916
ASYNCIO_STATE_UNLOCK (state );
1941
1917
}
@@ -3625,20 +3601,18 @@ _asyncio_all_tasks_impl(PyObject *module, PyObject *loop)
3625
3601
Py_DECREF (eager_iter );
3626
3602
int err = 0 ;
3627
3603
ASYNCIO_STATE_LOCK (state );
3628
- TaskObj * first = & state -> asyncio_tasks . first ;
3629
- TaskObj * head = state -> asyncio_tasks . head -> next ;
3630
- Py_INCREF ( head );
3631
- while ( head != first )
3632
- {
3633
- if ( add_one_task ( state , tasks , ( PyObject * ) head , loop ) < 0 ) {
3604
+ struct llist_node * node ;
3605
+ llist_for_each_safe ( node , & state -> asyncio_tasks_head ) {
3606
+ TaskObj * task = llist_data ( node , TaskObj , task_node );
3607
+ Py_INCREF ( task );
3608
+ if ( add_one_task ( state , tasks , ( PyObject * ) task , loop ) < 0 ) {
3609
+ Py_DECREF ( task );
3634
3610
Py_DECREF (tasks );
3635
3611
Py_DECREF (loop );
3636
- Py_DECREF (head );
3637
3612
err = 1 ;
3638
3613
break ;
3639
3614
}
3640
- Py_INCREF (head -> next );
3641
- Py_SETREF (head , head -> next );
3615
+ Py_DECREF (task );
3642
3616
}
3643
3617
ASYNCIO_STATE_UNLOCK (state );
3644
3618
if (err ) {
@@ -3847,11 +3821,7 @@ module_exec(PyObject *mod)
3847
3821
{
3848
3822
asyncio_state * state = get_asyncio_state (mod );
3849
3823
3850
- Py_SET_TYPE (& state -> asyncio_tasks .first , state -> TaskType );
3851
- _Py_SetImmortalUntracked ((PyObject * )& state -> asyncio_tasks .first );
3852
- state -> asyncio_tasks .head = & state -> asyncio_tasks .first ;
3853
- state -> asyncio_tasks .head -> next = & state -> asyncio_tasks .first ;
3854
- state -> asyncio_tasks .head -> prev = & state -> asyncio_tasks .first ;
3824
+ llist_init (& state -> asyncio_tasks_head );
3855
3825
3856
3826
#define CREATE_TYPE (m , tp , spec , base ) \
3857
3827
do { \
0 commit comments