@@ -1969,15 +1969,13 @@ unregister_task(asyncio_state *state, PyObject *task)
19691969static int
19701970enter_task (asyncio_state * state , PyObject * loop , PyObject * task )
19711971{
1972- PyObject * item ;
1973- Py_hash_t hash ;
1974- hash = PyObject_Hash ( loop );
1975- if (hash == -1 ) {
1972+ int is_insert ;
1973+ PyObject * item = _PyDict_SetDefault ( state -> current_tasks , loop , task , 1 ,
1974+ & is_insert );
1975+ if (item == NULL ) {
19761976 return -1 ;
19771977 }
1978- item = _PyDict_GetItem_KnownHash (state -> current_tasks , loop , hash );
1979- if (item != NULL ) {
1980- Py_INCREF (item );
1978+ if (!is_insert ) {
19811979 PyErr_Format (
19821980 PyExc_RuntimeError ,
19831981 "Cannot enter into task %R while another " \
@@ -1986,36 +1984,51 @@ enter_task(asyncio_state *state, PyObject *loop, PyObject *task)
19861984 Py_DECREF (item );
19871985 return -1 ;
19881986 }
1989- if (PyErr_Occurred ()) {
1990- return -1 ;
1991- }
1992- return _PyDict_SetItem_KnownHash (state -> current_tasks , loop , task , hash );
1987+ assert (item == task );
1988+ Py_DECREF (item );
1989+ return 0 ;
19931990}
19941991
1992+ struct task_matches_arg {
1993+ PyObject * task ;
1994+ PyObject * item ;
1995+ };
1996+
1997+ static int
1998+ task_matches (PyObject * item , void * data )
1999+ {
2000+ struct task_matches_arg * arg = (struct task_matches_arg * )data ;
2001+ arg -> item = Py_NewRef (item );
2002+ return arg -> task == item ;
2003+ }
19952004
19962005static int
19972006leave_task (asyncio_state * state , PyObject * loop , PyObject * task )
19982007/*[clinic end generated code: output=0ebf6db4b858fb41 input=51296a46313d1ad8]*/
19992008{
2000- PyObject * item ;
2001- Py_hash_t hash ;
2002- hash = PyObject_Hash (loop );
2003- if (hash == -1 ) {
2004- return -1 ;
2005- }
2006- item = _PyDict_GetItem_KnownHash (state -> current_tasks , loop , hash );
2007- if (item != task ) {
2008- if (item == NULL ) {
2009- /* Not entered, replace with None */
2010- item = Py_None ;
2009+ struct task_matches_arg arg ;
2010+ arg .task = task ;
2011+ arg .item = Py_None ;
2012+ int res = _PyDict_DelItemIf (state -> current_tasks , loop , & task_matches , & arg );
2013+ if (res != 0 ) {
2014+ if (PyErr_ExceptionMatches (PyExc_KeyError )) {
2015+ // use custom error message if loop is not present
2016+ goto fail ;
20112017 }
2012- PyErr_Format (
2013- PyExc_RuntimeError ,
2014- "Leaving task %R does not match the current task %R." ,
2015- task , item , NULL );
20162018 return -1 ;
20172019 }
2018- return _PyDict_DelItem_KnownHash (state -> current_tasks , loop , hash );
2020+ if (arg .item == task ) {
2021+ Py_XDECREF (arg .item );
2022+ return 0 ;
2023+ }
2024+
2025+ fail :
2026+ PyErr_Format (
2027+ PyExc_RuntimeError ,
2028+ "Leaving task %R does not match the current task %R." ,
2029+ task , arg .item , NULL );
2030+ Py_XDECREF (arg .item );
2031+ return -1 ;
20192032}
20202033
20212034/* ----- Task */
0 commit comments