1#ifndef Py_BUILD_CORE_BUILTIN
2#  define Py_BUILD_CORE_MODULE 1
3#endif
4#define NEEDS_PY_IDENTIFIER
5
6#include "Python.h"
7#include "pycore_pyerrors.h"      // _PyErr_ClearExcState()
8#include "pycore_pystate.h"       // _PyThreadState_GET()
9#include <stddef.h>               // offsetof()
10
11
12/*[clinic input]
13module _asyncio
14[clinic start generated code]*/
15/*[clinic end generated code: output=da39a3ee5e6b4b0d input=8fd17862aa989c69]*/
16
17
18/* identifiers used from some functions */
19_Py_IDENTIFIER(__asyncio_running_event_loop__);
20_Py_IDENTIFIER(_asyncio_future_blocking);
21_Py_IDENTIFIER(add_done_callback);
22_Py_IDENTIFIER(call_soon);
23_Py_IDENTIFIER(cancel);
24_Py_IDENTIFIER(get_event_loop);
25_Py_IDENTIFIER(throw);
26
27
28/* State of the _asyncio module */
29static PyObject *asyncio_mod;
30static PyObject *traceback_extract_stack;
31static PyObject *asyncio_get_event_loop_policy;
32static PyObject *asyncio_future_repr_func;
33static PyObject *asyncio_iscoroutine_func;
34static PyObject *asyncio_task_get_stack_func;
35static PyObject *asyncio_task_print_stack_func;
36static PyObject *asyncio_task_repr_func;
37static PyObject *asyncio_InvalidStateError;
38static PyObject *asyncio_CancelledError;
39static PyObject *context_kwname;
40static int module_initialized;
41
42static PyObject *cached_running_holder;
43static volatile uint64_t cached_running_holder_tsid;
44
45/* Counter for autogenerated Task names */
46static uint64_t task_name_counter = 0;
47
48/* WeakSet containing all alive tasks. */
49static PyObject *all_tasks;
50
51/* Dictionary containing tasks that are currently active in
52   all running event loops.  {EventLoop: Task} */
53static PyObject *current_tasks;
54
55/* An isinstance type cache for the 'is_coroutine()' function. */
56static PyObject *iscoroutine_typecache;
57
58
59typedef enum {
60    STATE_PENDING,
61    STATE_CANCELLED,
62    STATE_FINISHED
63} fut_state;
64
65#define FutureObj_HEAD(prefix)                                              \
66    PyObject_HEAD                                                           \
67    PyObject *prefix##_loop;                                                \
68    PyObject *prefix##_callback0;                                           \
69    PyObject *prefix##_context0;                                            \
70    PyObject *prefix##_callbacks;                                           \
71    PyObject *prefix##_exception;                                           \
72    PyObject *prefix##_exception_tb;                                        \
73    PyObject *prefix##_result;                                              \
74    PyObject *prefix##_source_tb;                                           \
75    PyObject *prefix##_cancel_msg;                                          \
76    fut_state prefix##_state;                                               \
77    int prefix##_log_tb;                                                    \
78    int prefix##_blocking;                                                  \
79    PyObject *dict;                                                         \
80    PyObject *prefix##_weakreflist;                                         \
81    PyObject *prefix##_cancelled_exc;
82
83typedef struct {
84    FutureObj_HEAD(fut)
85} FutureObj;
86
87typedef struct {
88    FutureObj_HEAD(task)
89    PyObject *task_fut_waiter;
90    PyObject *task_coro;
91    PyObject *task_name;
92    PyObject *task_context;
93    int task_must_cancel;
94    int task_log_destroy_pending;
95    int task_num_cancels_requested;
96} TaskObj;
97
98typedef struct {
99    PyObject_HEAD
100    TaskObj *sw_task;
101    PyObject *sw_arg;
102} TaskStepMethWrapper;
103
104typedef struct {
105    PyObject_HEAD
106    PyObject *rl_loop;
107#if defined(HAVE_GETPID) && !defined(MS_WINDOWS)
108    pid_t rl_pid;
109#endif
110} PyRunningLoopHolder;
111
112
113static PyTypeObject FutureType;
114static PyTypeObject TaskType;
115static PyTypeObject PyRunningLoopHolder_Type;
116
117
118#define Future_CheckExact(obj) Py_IS_TYPE(obj, &FutureType)
119#define Task_CheckExact(obj) Py_IS_TYPE(obj, &TaskType)
120
121#define Future_Check(obj) PyObject_TypeCheck(obj, &FutureType)
122#define Task_Check(obj) PyObject_TypeCheck(obj, &TaskType)
123
124#include "clinic/_asynciomodule.c.h"
125
126
127/*[clinic input]
128class _asyncio.Future "FutureObj *" "&Future_Type"
129[clinic start generated code]*/
130/*[clinic end generated code: output=da39a3ee5e6b4b0d input=00d3e4abca711e0f]*/
131
132
133/* Get FutureIter from Future */
134static PyObject * future_new_iter(PyObject *);
135
136static PyRunningLoopHolder * new_running_loop_holder(PyObject *);
137
138
139static int
140_is_coroutine(PyObject *coro)
141{
142    /* 'coro' is not a native coroutine, call asyncio.iscoroutine()
143       to check if it's another coroutine flavour.
144
145       Do this check after 'future_init()'; in case we need to raise
146       an error, __del__ needs a properly initialized object.
147    */
148    PyObject *res = PyObject_CallOneArg(asyncio_iscoroutine_func, coro);
149    if (res == NULL) {
150        return -1;
151    }
152
153    int is_res_true = PyObject_IsTrue(res);
154    Py_DECREF(res);
155    if (is_res_true <= 0) {
156        return is_res_true;
157    }
158
159    if (PySet_GET_SIZE(iscoroutine_typecache) < 100) {
160        /* Just in case we don't want to cache more than 100
161           positive types.  That shouldn't ever happen, unless
162           someone stressing the system on purpose.
163        */
164        if (PySet_Add(iscoroutine_typecache, (PyObject*) Py_TYPE(coro))) {
165            return -1;
166        }
167    }
168
169    return 1;
170}
171
172
173static inline int
174is_coroutine(PyObject *coro)
175{
176    if (PyCoro_CheckExact(coro)) {
177        return 1;
178    }
179
180    /* Check if `type(coro)` is in the cache.
181       Caching makes is_coroutine() function almost as fast as
182       PyCoro_CheckExact() for non-native coroutine-like objects
183       (like coroutines compiled with Cython).
184
185       asyncio.iscoroutine() has its own type caching mechanism.
186       This cache allows us to avoid the cost of even calling
187       a pure-Python function in 99.9% cases.
188    */
189    int has_it = PySet_Contains(
190        iscoroutine_typecache, (PyObject*) Py_TYPE(coro));
191    if (has_it == 0) {
192        /* type(coro) is not in iscoroutine_typecache */
193        return _is_coroutine(coro);
194    }
195
196    /* either an error has occurred or
197       type(coro) is in iscoroutine_typecache
198    */
199    return has_it;
200}
201
202
203static PyObject *
204get_future_loop(PyObject *fut)
205{
206    /* Implementation of `asyncio.futures._get_loop` */
207
208    _Py_IDENTIFIER(get_loop);
209    _Py_IDENTIFIER(_loop);
210    PyObject *getloop;
211
212    if (Future_CheckExact(fut) || Task_CheckExact(fut)) {
213        PyObject *loop = ((FutureObj *)fut)->fut_loop;
214        Py_INCREF(loop);
215        return loop;
216    }
217
218    if (_PyObject_LookupAttrId(fut, &PyId_get_loop, &getloop) < 0) {
219        return NULL;
220    }
221    if (getloop != NULL) {
222        PyObject *res = PyObject_CallNoArgs(getloop);
223        Py_DECREF(getloop);
224        return res;
225    }
226
227    return _PyObject_GetAttrId(fut, &PyId__loop);
228}
229
230
231static int
232get_running_loop(PyObject **loop)
233{
234    PyObject *rl;
235
236    PyThreadState *ts = _PyThreadState_GET();
237    uint64_t ts_id = PyThreadState_GetID(ts);
238    if (ts_id == cached_running_holder_tsid && cached_running_holder != NULL) {
239        // Fast path, check the cache.
240        rl = cached_running_holder;  // borrowed
241    }
242    else {
243        PyObject *ts_dict = _PyThreadState_GetDict(ts);  // borrowed
244        if (ts_dict == NULL) {
245            goto not_found;
246        }
247
248        rl = _PyDict_GetItemIdWithError(
249            ts_dict, &PyId___asyncio_running_event_loop__);  // borrowed
250        if (rl == NULL) {
251            if (PyErr_Occurred()) {
252                goto error;
253            }
254            else {
255                goto not_found;
256            }
257        }
258
259        cached_running_holder = rl;  // borrowed
260        cached_running_holder_tsid = ts_id;
261    }
262
263    assert(Py_IS_TYPE(rl, &PyRunningLoopHolder_Type));
264    PyObject *running_loop = ((PyRunningLoopHolder *)rl)->rl_loop;
265
266    if (running_loop == Py_None) {
267        goto not_found;
268    }
269
270#if defined(HAVE_GETPID) && !defined(MS_WINDOWS)
271    /* On Windows there is no getpid, but there is also no os.fork(),
272       so there is no need for this check.
273    */
274    if (getpid() != ((PyRunningLoopHolder *)rl)->rl_pid) {
275        goto not_found;
276    }
277#endif
278
279    Py_INCREF(running_loop);
280    *loop = running_loop;
281    return 0;
282
283not_found:
284    *loop = NULL;
285    return 0;
286
287error:
288    *loop = NULL;
289    return -1;
290}
291
292
293static int
294set_running_loop(PyObject *loop)
295{
296    PyObject *ts_dict = NULL;
297
298    PyThreadState *tstate = _PyThreadState_GET();
299    if (tstate != NULL) {
300        ts_dict = _PyThreadState_GetDict(tstate);  // borrowed
301    }
302
303    if (ts_dict == NULL) {
304        PyErr_SetString(
305            PyExc_RuntimeError, "thread-local storage is not available");
306        return -1;
307    }
308
309    PyRunningLoopHolder *rl = new_running_loop_holder(loop);
310    if (rl == NULL) {
311        return -1;
312    }
313
314    if (_PyDict_SetItemId(
315            ts_dict, &PyId___asyncio_running_event_loop__, (PyObject *)rl) < 0)
316    {
317        Py_DECREF(rl);  // will cleanup loop & current_pid
318        return -1;
319    }
320    Py_DECREF(rl);
321
322    cached_running_holder = (PyObject *)rl;
323    cached_running_holder_tsid = PyThreadState_GetID(tstate);
324
325    return 0;
326}
327
328
329static PyObject *
330get_event_loop(int stacklevel)
331{
332    PyObject *loop;
333    PyObject *policy;
334
335    if (get_running_loop(&loop)) {
336        return NULL;
337    }
338    if (loop != NULL) {
339        return loop;
340    }
341
342    policy = PyObject_CallNoArgs(asyncio_get_event_loop_policy);
343    if (policy == NULL) {
344        return NULL;
345    }
346
347    loop = _PyObject_CallMethodIdNoArgs(policy, &PyId_get_event_loop);
348    Py_DECREF(policy);
349    return loop;
350}
351
352
353static int
354call_soon(PyObject *loop, PyObject *func, PyObject *arg, PyObject *ctx)
355{
356    PyObject *handle;
357    PyObject *stack[3];
358    Py_ssize_t nargs;
359
360    if (ctx == NULL) {
361        handle = _PyObject_CallMethodIdObjArgs(
362            loop, &PyId_call_soon, func, arg, NULL);
363    }
364    else {
365        /* Use FASTCALL to pass a keyword-only argument to call_soon */
366
367        PyObject *callable = _PyObject_GetAttrId(loop, &PyId_call_soon);
368        if (callable == NULL) {
369            return -1;
370        }
371
372        /* All refs in 'stack' are borrowed. */
373        nargs = 1;
374        stack[0] = func;
375        if (arg != NULL) {
376            stack[1] = arg;
377            nargs++;
378        }
379        stack[nargs] = (PyObject *)ctx;
380
381        handle = PyObject_Vectorcall(callable, stack, nargs, context_kwname);
382        Py_DECREF(callable);
383    }
384
385    if (handle == NULL) {
386        return -1;
387    }
388    Py_DECREF(handle);
389    return 0;
390}
391
392
393static inline int
394future_is_alive(FutureObj *fut)
395{
396    return fut->fut_loop != NULL;
397}
398
399
400static inline int
401future_ensure_alive(FutureObj *fut)
402{
403    if (!future_is_alive(fut)) {
404        PyErr_SetString(PyExc_RuntimeError,
405                        "Future object is not initialized.");
406        return -1;
407    }
408    return 0;
409}
410
411
412#define ENSURE_FUTURE_ALIVE(fut)                                \
413    do {                                                        \
414        assert(Future_Check(fut) || Task_Check(fut));           \
415        if (future_ensure_alive((FutureObj*)fut)) {             \
416            return NULL;                                        \
417        }                                                       \
418    } while(0);
419
420
421static int
422future_schedule_callbacks(FutureObj *fut)
423{
424    Py_ssize_t len;
425    Py_ssize_t i;
426
427    if (fut->fut_callback0 != NULL) {
428        /* There's a 1st callback */
429
430        int ret = call_soon(
431            fut->fut_loop, fut->fut_callback0,
432            (PyObject *)fut, fut->fut_context0);
433
434        Py_CLEAR(fut->fut_callback0);
435        Py_CLEAR(fut->fut_context0);
436        if (ret) {
437            /* If an error occurs in pure-Python implementation,
438               all callbacks are cleared. */
439            Py_CLEAR(fut->fut_callbacks);
440            return ret;
441        }
442
443        /* we called the first callback, now try calling
444           callbacks from the 'fut_callbacks' list. */
445    }
446
447    if (fut->fut_callbacks == NULL) {
448        /* No more callbacks, return. */
449        return 0;
450    }
451
452    len = PyList_GET_SIZE(fut->fut_callbacks);
453    if (len == 0) {
454        /* The list of callbacks was empty; clear it and return. */
455        Py_CLEAR(fut->fut_callbacks);
456        return 0;
457    }
458
459    for (i = 0; i < len; i++) {
460        PyObject *cb_tup = PyList_GET_ITEM(fut->fut_callbacks, i);
461        PyObject *cb = PyTuple_GET_ITEM(cb_tup, 0);
462        PyObject *ctx = PyTuple_GET_ITEM(cb_tup, 1);
463
464        if (call_soon(fut->fut_loop, cb, (PyObject *)fut, ctx)) {
465            /* If an error occurs in pure-Python implementation,
466               all callbacks are cleared. */
467            Py_CLEAR(fut->fut_callbacks);
468            return -1;
469        }
470    }
471
472    Py_CLEAR(fut->fut_callbacks);
473    return 0;
474}
475
476
477static int
478future_init(FutureObj *fut, PyObject *loop)
479{
480    PyObject *res;
481    int is_true;
482    _Py_IDENTIFIER(get_debug);
483
484    // Same to FutureObj_clear() but not clearing fut->dict
485    Py_CLEAR(fut->fut_loop);
486    Py_CLEAR(fut->fut_callback0);
487    Py_CLEAR(fut->fut_context0);
488    Py_CLEAR(fut->fut_callbacks);
489    Py_CLEAR(fut->fut_result);
490    Py_CLEAR(fut->fut_exception);
491    Py_CLEAR(fut->fut_exception_tb);
492    Py_CLEAR(fut->fut_source_tb);
493    Py_CLEAR(fut->fut_cancel_msg);
494    Py_CLEAR(fut->fut_cancelled_exc);
495
496    fut->fut_state = STATE_PENDING;
497    fut->fut_log_tb = 0;
498    fut->fut_blocking = 0;
499
500    if (loop == Py_None) {
501        loop = get_event_loop(1);
502        if (loop == NULL) {
503            return -1;
504        }
505    }
506    else {
507        Py_INCREF(loop);
508    }
509    fut->fut_loop = loop;
510
511    res = _PyObject_CallMethodIdNoArgs(fut->fut_loop, &PyId_get_debug);
512    if (res == NULL) {
513        return -1;
514    }
515    is_true = PyObject_IsTrue(res);
516    Py_DECREF(res);
517    if (is_true < 0) {
518        return -1;
519    }
520    if (is_true && !_Py_IsFinalizing()) {
521        /* Only try to capture the traceback if the interpreter is not being
522           finalized.  The original motivation to add a `_Py_IsFinalizing()`
523           call was to prevent SIGSEGV when a Future is created in a __del__
524           method, which is called during the interpreter shutdown and the
525           traceback module is already unloaded.
526        */
527        fut->fut_source_tb = PyObject_CallNoArgs(traceback_extract_stack);
528        if (fut->fut_source_tb == NULL) {
529            return -1;
530        }
531    }
532
533    return 0;
534}
535
536static PyObject *
537future_set_result(FutureObj *fut, PyObject *res)
538{
539    if (future_ensure_alive(fut)) {
540        return NULL;
541    }
542
543    if (fut->fut_state != STATE_PENDING) {
544        PyErr_SetString(asyncio_InvalidStateError, "invalid state");
545        return NULL;
546    }
547
548    assert(!fut->fut_result);
549    Py_INCREF(res);
550    fut->fut_result = res;
551    fut->fut_state = STATE_FINISHED;
552
553    if (future_schedule_callbacks(fut) == -1) {
554        return NULL;
555    }
556    Py_RETURN_NONE;
557}
558
559static PyObject *
560future_set_exception(FutureObj *fut, PyObject *exc)
561{
562    PyObject *exc_val = NULL;
563
564    if (fut->fut_state != STATE_PENDING) {
565        PyErr_SetString(asyncio_InvalidStateError, "invalid state");
566        return NULL;
567    }
568
569    if (PyExceptionClass_Check(exc)) {
570        exc_val = PyObject_CallNoArgs(exc);
571        if (exc_val == NULL) {
572            return NULL;
573        }
574        if (fut->fut_state != STATE_PENDING) {
575            Py_DECREF(exc_val);
576            PyErr_SetString(asyncio_InvalidStateError, "invalid state");
577            return NULL;
578        }
579    }
580    else {
581        exc_val = exc;
582        Py_INCREF(exc_val);
583    }
584    if (!PyExceptionInstance_Check(exc_val)) {
585        Py_DECREF(exc_val);
586        PyErr_SetString(PyExc_TypeError, "invalid exception object");
587        return NULL;
588    }
589    if (Py_IS_TYPE(exc_val, (PyTypeObject *)PyExc_StopIteration)) {
590        Py_DECREF(exc_val);
591        PyErr_SetString(PyExc_TypeError,
592                        "StopIteration interacts badly with generators "
593                        "and cannot be raised into a Future");
594        return NULL;
595    }
596
597    assert(!fut->fut_exception);
598    assert(!fut->fut_exception_tb);
599    fut->fut_exception = exc_val;
600    fut->fut_exception_tb = PyException_GetTraceback(exc_val);
601    fut->fut_state = STATE_FINISHED;
602
603    if (future_schedule_callbacks(fut) == -1) {
604        return NULL;
605    }
606
607    fut->fut_log_tb = 1;
608    Py_RETURN_NONE;
609}
610
611static PyObject *
612create_cancelled_error(FutureObj *fut)
613{
614    PyObject *exc;
615    if (fut->fut_cancelled_exc != NULL) {
616        /* transfer ownership */
617        exc = fut->fut_cancelled_exc;
618        fut->fut_cancelled_exc = NULL;
619        return exc;
620    }
621    PyObject *msg = fut->fut_cancel_msg;
622    if (msg == NULL || msg == Py_None) {
623        exc = PyObject_CallNoArgs(asyncio_CancelledError);
624    } else {
625        exc = PyObject_CallOneArg(asyncio_CancelledError, msg);
626    }
627    return exc;
628}
629
630static void
631future_set_cancelled_error(FutureObj *fut)
632{
633    PyObject *exc = create_cancelled_error(fut);
634    if (exc == NULL) {
635        return;
636    }
637    PyErr_SetObject(asyncio_CancelledError, exc);
638    Py_DECREF(exc);
639}
640
641static int
642future_get_result(FutureObj *fut, PyObject **result)
643{
644    if (fut->fut_state == STATE_CANCELLED) {
645        future_set_cancelled_error(fut);
646        return -1;
647    }
648
649    if (fut->fut_state != STATE_FINISHED) {
650        PyErr_SetString(asyncio_InvalidStateError, "Result is not set.");
651        return -1;
652    }
653
654    fut->fut_log_tb = 0;
655    if (fut->fut_exception != NULL) {
656        PyObject *tb = fut->fut_exception_tb;
657        if (tb == NULL) {
658            tb = Py_None;
659        }
660        if (PyException_SetTraceback(fut->fut_exception, tb) < 0) {
661            return -1;
662        }
663        Py_INCREF(fut->fut_exception);
664        *result = fut->fut_exception;
665        Py_CLEAR(fut->fut_exception_tb);
666        return 1;
667    }
668
669    Py_INCREF(fut->fut_result);
670    *result = fut->fut_result;
671    return 0;
672}
673
674static PyObject *
675future_add_done_callback(FutureObj *fut, PyObject *arg, PyObject *ctx)
676{
677    if (!future_is_alive(fut)) {
678        PyErr_SetString(PyExc_RuntimeError, "uninitialized Future object");
679        return NULL;
680    }
681
682    if (fut->fut_state != STATE_PENDING) {
683        /* The future is done/cancelled, so schedule the callback
684           right away. */
685        if (call_soon(fut->fut_loop, arg, (PyObject*) fut, ctx)) {
686            return NULL;
687        }
688    }
689    else {
690        /* The future is pending, add a callback.
691
692           Callbacks in the future object are stored as follows:
693
694              callback0 -- a pointer to the first callback
695              callbacks -- a list of 2nd, 3rd, ... callbacks
696
697           Invariants:
698
699            * callbacks != NULL:
700                There are some callbacks in in the list.  Just
701                add the new callback to it.
702
703            * callbacks == NULL and callback0 == NULL:
704                This is the first callback.  Set it to callback0.
705
706            * callbacks == NULL and callback0 != NULL:
707                This is a second callback.  Initialize callbacks
708                with a new list and add the new callback to it.
709        */
710
711        if (fut->fut_callbacks == NULL && fut->fut_callback0 == NULL) {
712            Py_INCREF(arg);
713            fut->fut_callback0 = arg;
714            Py_INCREF(ctx);
715            fut->fut_context0 = ctx;
716        }
717        else {
718            PyObject *tup = PyTuple_New(2);
719            if (tup == NULL) {
720                return NULL;
721            }
722            Py_INCREF(arg);
723            PyTuple_SET_ITEM(tup, 0, arg);
724            Py_INCREF(ctx);
725            PyTuple_SET_ITEM(tup, 1, (PyObject *)ctx);
726
727            if (fut->fut_callbacks != NULL) {
728                int err = PyList_Append(fut->fut_callbacks, tup);
729                if (err) {
730                    Py_DECREF(tup);
731                    return NULL;
732                }
733                Py_DECREF(tup);
734            }
735            else {
736                fut->fut_callbacks = PyList_New(1);
737                if (fut->fut_callbacks == NULL) {
738                    Py_DECREF(tup);
739                    return NULL;
740                }
741
742                PyList_SET_ITEM(fut->fut_callbacks, 0, tup);  /* borrow */
743            }
744        }
745    }
746
747    Py_RETURN_NONE;
748}
749
750static PyObject *
751future_cancel(FutureObj *fut, PyObject *msg)
752{
753    fut->fut_log_tb = 0;
754
755    if (fut->fut_state != STATE_PENDING) {
756        Py_RETURN_FALSE;
757    }
758    fut->fut_state = STATE_CANCELLED;
759
760    Py_XINCREF(msg);
761    Py_XSETREF(fut->fut_cancel_msg, msg);
762
763    if (future_schedule_callbacks(fut) == -1) {
764        return NULL;
765    }
766
767    Py_RETURN_TRUE;
768}
769
770/*[clinic input]
771_asyncio.Future.__init__
772
773    *
774    loop: object = None
775
776This class is *almost* compatible with concurrent.futures.Future.
777
778    Differences:
779
780    - result() and exception() do not take a timeout argument and
781      raise an exception when the future isn't done yet.
782
783    - Callbacks registered with add_done_callback() are always called
784      via the event loop's call_soon_threadsafe().
785
786    - This class is not compatible with the wait() and as_completed()
787      methods in the concurrent.futures package.
788[clinic start generated code]*/
789
790static int
791_asyncio_Future___init___impl(FutureObj *self, PyObject *loop)
792/*[clinic end generated code: output=9ed75799eaccb5d6 input=89af317082bc0bf8]*/
793
794{
795    return future_init(self, loop);
796}
797
798static int
799FutureObj_clear(FutureObj *fut)
800{
801    Py_CLEAR(fut->fut_loop);
802    Py_CLEAR(fut->fut_callback0);
803    Py_CLEAR(fut->fut_context0);
804    Py_CLEAR(fut->fut_callbacks);
805    Py_CLEAR(fut->fut_result);
806    Py_CLEAR(fut->fut_exception);
807    Py_CLEAR(fut->fut_exception_tb);
808    Py_CLEAR(fut->fut_source_tb);
809    Py_CLEAR(fut->fut_cancel_msg);
810    Py_CLEAR(fut->fut_cancelled_exc);
811    Py_CLEAR(fut->dict);
812    return 0;
813}
814
815static int
816FutureObj_traverse(FutureObj *fut, visitproc visit, void *arg)
817{
818    Py_VISIT(fut->fut_loop);
819    Py_VISIT(fut->fut_callback0);
820    Py_VISIT(fut->fut_context0);
821    Py_VISIT(fut->fut_callbacks);
822    Py_VISIT(fut->fut_result);
823    Py_VISIT(fut->fut_exception);
824    Py_VISIT(fut->fut_exception_tb);
825    Py_VISIT(fut->fut_source_tb);
826    Py_VISIT(fut->fut_cancel_msg);
827    Py_VISIT(fut->fut_cancelled_exc);
828    Py_VISIT(fut->dict);
829    return 0;
830}
831
832/*[clinic input]
833_asyncio.Future.result
834
835Return the result this future represents.
836
837If the future has been cancelled, raises CancelledError.  If the
838future's result isn't yet available, raises InvalidStateError.  If
839the future is done and has an exception set, this exception is raised.
840[clinic start generated code]*/
841
842static PyObject *
843_asyncio_Future_result_impl(FutureObj *self)
844/*[clinic end generated code: output=f35f940936a4b1e5 input=49ecf9cf5ec50dc5]*/
845{
846    PyObject *result;
847
848    if (!future_is_alive(self)) {
849        PyErr_SetString(asyncio_InvalidStateError,
850                        "Future object is not initialized.");
851        return NULL;
852    }
853
854    int res = future_get_result(self, &result);
855
856    if (res == -1) {
857        return NULL;
858    }
859
860    if (res == 0) {
861        return result;
862    }
863
864    assert(res == 1);
865
866    PyErr_SetObject(PyExceptionInstance_Class(result), result);
867    Py_DECREF(result);
868    return NULL;
869}
870
871/*[clinic input]
872_asyncio.Future.exception
873
874Return the exception that was set on this future.
875
876The exception (or None if no exception was set) is returned only if
877the future is done.  If the future has been cancelled, raises
878CancelledError.  If the future isn't done yet, raises
879InvalidStateError.
880[clinic start generated code]*/
881
882static PyObject *
883_asyncio_Future_exception_impl(FutureObj *self)
884/*[clinic end generated code: output=88b20d4f855e0710 input=733547a70c841c68]*/
885{
886    if (!future_is_alive(self)) {
887        PyErr_SetString(asyncio_InvalidStateError,
888                        "Future object is not initialized.");
889        return NULL;
890    }
891
892    if (self->fut_state == STATE_CANCELLED) {
893        future_set_cancelled_error(self);
894        return NULL;
895    }
896
897    if (self->fut_state != STATE_FINISHED) {
898        PyErr_SetString(asyncio_InvalidStateError, "Exception is not set.");
899        return NULL;
900    }
901
902    if (self->fut_exception != NULL) {
903        self->fut_log_tb = 0;
904        Py_INCREF(self->fut_exception);
905        return self->fut_exception;
906    }
907
908    Py_RETURN_NONE;
909}
910
911/*[clinic input]
912_asyncio.Future.set_result
913
914    result: object
915    /
916
917Mark the future done and set its result.
918
919If the future is already done when this method is called, raises
920InvalidStateError.
921[clinic start generated code]*/
922
923static PyObject *
924_asyncio_Future_set_result(FutureObj *self, PyObject *result)
925/*[clinic end generated code: output=1ec2e6bcccd6f2ce input=8b75172c2a7b05f1]*/
926{
927    ENSURE_FUTURE_ALIVE(self)
928    return future_set_result(self, result);
929}
930
931/*[clinic input]
932_asyncio.Future.set_exception
933
934    exception: object
935    /
936
937Mark the future done and set an exception.
938
939If the future is already done when this method is called, raises
940InvalidStateError.
941[clinic start generated code]*/
942
943static PyObject *
944_asyncio_Future_set_exception(FutureObj *self, PyObject *exception)
945/*[clinic end generated code: output=f1c1b0cd321be360 input=e45b7d7aa71cc66d]*/
946{
947    ENSURE_FUTURE_ALIVE(self)
948    return future_set_exception(self, exception);
949}
950
951/*[clinic input]
952_asyncio.Future.add_done_callback
953
954    fn: object
955    /
956    *
957    context: object = NULL
958
959Add a callback to be run when the future becomes done.
960
961The callback is called with a single argument - the future object. If
962the future is already done when this is called, the callback is
963scheduled with call_soon.
964[clinic start generated code]*/
965
966static PyObject *
967_asyncio_Future_add_done_callback_impl(FutureObj *self, PyObject *fn,
968                                       PyObject *context)
969/*[clinic end generated code: output=7ce635bbc9554c1e input=15ab0693a96e9533]*/
970{
971    if (context == NULL) {
972        context = PyContext_CopyCurrent();
973        if (context == NULL) {
974            return NULL;
975        }
976        PyObject *res = future_add_done_callback(self, fn, context);
977        Py_DECREF(context);
978        return res;
979    }
980    return future_add_done_callback(self, fn, context);
981}
982
983/*[clinic input]
984_asyncio.Future.remove_done_callback
985
986    fn: object
987    /
988
989Remove all instances of a callback from the "call when done" list.
990
991Returns the number of callbacks removed.
992[clinic start generated code]*/
993
994static PyObject *
995_asyncio_Future_remove_done_callback(FutureObj *self, PyObject *fn)
996/*[clinic end generated code: output=5ab1fb52b24ef31f input=0a43280a149d505b]*/
997{
998    PyObject *newlist;
999    Py_ssize_t len, i, j=0;
1000    Py_ssize_t cleared_callback0 = 0;
1001
1002    ENSURE_FUTURE_ALIVE(self)
1003
1004    if (self->fut_callback0 != NULL) {
1005        int cmp = PyObject_RichCompareBool(self->fut_callback0, fn, Py_EQ);
1006        if (cmp == -1) {
1007            return NULL;
1008        }
1009        if (cmp == 1) {
1010            /* callback0 == fn */
1011            Py_CLEAR(self->fut_callback0);
1012            Py_CLEAR(self->fut_context0);
1013            cleared_callback0 = 1;
1014        }
1015    }
1016
1017    if (self->fut_callbacks == NULL) {
1018        return PyLong_FromSsize_t(cleared_callback0);
1019    }
1020
1021    len = PyList_GET_SIZE(self->fut_callbacks);
1022    if (len == 0) {
1023        Py_CLEAR(self->fut_callbacks);
1024        return PyLong_FromSsize_t(cleared_callback0);
1025    }
1026
1027    if (len == 1) {
1028        PyObject *cb_tup = PyList_GET_ITEM(self->fut_callbacks, 0);
1029        int cmp = PyObject_RichCompareBool(
1030            PyTuple_GET_ITEM(cb_tup, 0), fn, Py_EQ);
1031        if (cmp == -1) {
1032            return NULL;
1033        }
1034        if (cmp == 1) {
1035            /* callbacks[0] == fn */
1036            Py_CLEAR(self->fut_callbacks);
1037            return PyLong_FromSsize_t(1 + cleared_callback0);
1038        }
1039        /* callbacks[0] != fn and len(callbacks) == 1 */
1040        return PyLong_FromSsize_t(cleared_callback0);
1041    }
1042
1043    newlist = PyList_New(len);
1044    if (newlist == NULL) {
1045        return NULL;
1046    }
1047
1048    // Beware: PyObject_RichCompareBool below may change fut_callbacks.
1049    // See GH-97592.
1050    for (i = 0;
1051         self->fut_callbacks != NULL && i < PyList_GET_SIZE(self->fut_callbacks);
1052         i++) {
1053        int ret;
1054        PyObject *item = PyList_GET_ITEM(self->fut_callbacks, i);
1055        Py_INCREF(item);
1056        ret = PyObject_RichCompareBool(PyTuple_GET_ITEM(item, 0), fn, Py_EQ);
1057        if (ret == 0) {
1058            if (j < len) {
1059                PyList_SET_ITEM(newlist, j, item);
1060                j++;
1061                continue;
1062            }
1063            ret = PyList_Append(newlist, item);
1064        }
1065        Py_DECREF(item);
1066        if (ret < 0) {
1067            goto fail;
1068        }
1069    }
1070
1071    // Note: fut_callbacks may have been cleared.
1072    if (j == 0 || self->fut_callbacks == NULL) {
1073        Py_CLEAR(self->fut_callbacks);
1074        Py_DECREF(newlist);
1075        return PyLong_FromSsize_t(len + cleared_callback0);
1076    }
1077
1078    if (j < len) {
1079        Py_SET_SIZE(newlist, j);
1080    }
1081    j = PyList_GET_SIZE(newlist);
1082    len = PyList_GET_SIZE(self->fut_callbacks);
1083    if (j != len) {
1084        if (PyList_SetSlice(self->fut_callbacks, 0, len, newlist) < 0) {
1085            goto fail;
1086        }
1087    }
1088    Py_DECREF(newlist);
1089    return PyLong_FromSsize_t(len - j + cleared_callback0);
1090
1091fail:
1092    Py_DECREF(newlist);
1093    return NULL;
1094}
1095
1096/*[clinic input]
1097_asyncio.Future.cancel
1098
1099    msg: object = None
1100
1101Cancel the future and schedule callbacks.
1102
1103If the future is already done or cancelled, return False.  Otherwise,
1104change the future's state to cancelled, schedule the callbacks and
1105return True.
1106[clinic start generated code]*/
1107
1108static PyObject *
1109_asyncio_Future_cancel_impl(FutureObj *self, PyObject *msg)
1110/*[clinic end generated code: output=3edebbc668e5aba3 input=925eb545251f2c5a]*/
1111{
1112    ENSURE_FUTURE_ALIVE(self)
1113    return future_cancel(self, msg);
1114}
1115
1116/*[clinic input]
1117_asyncio.Future.cancelled
1118
1119Return True if the future was cancelled.
1120[clinic start generated code]*/
1121
1122static PyObject *
1123_asyncio_Future_cancelled_impl(FutureObj *self)
1124/*[clinic end generated code: output=145197ced586357d input=943ab8b7b7b17e45]*/
1125{
1126    if (future_is_alive(self) && self->fut_state == STATE_CANCELLED) {
1127        Py_RETURN_TRUE;
1128    }
1129    else {
1130        Py_RETURN_FALSE;
1131    }
1132}
1133
1134/*[clinic input]
1135_asyncio.Future.done
1136
1137Return True if the future is done.
1138
1139Done means either that a result / exception are available, or that the
1140future was cancelled.
1141[clinic start generated code]*/
1142
1143static PyObject *
1144_asyncio_Future_done_impl(FutureObj *self)
1145/*[clinic end generated code: output=244c5ac351145096 input=28d7b23fdb65d2ac]*/
1146{
1147    if (!future_is_alive(self) || self->fut_state == STATE_PENDING) {
1148        Py_RETURN_FALSE;
1149    }
1150    else {
1151        Py_RETURN_TRUE;
1152    }
1153}
1154
1155/*[clinic input]
1156_asyncio.Future.get_loop
1157
1158Return the event loop the Future is bound to.
1159[clinic start generated code]*/
1160
1161static PyObject *
1162_asyncio_Future_get_loop_impl(FutureObj *self)
1163/*[clinic end generated code: output=119b6ea0c9816c3f input=cba48c2136c79d1f]*/
1164{
1165    ENSURE_FUTURE_ALIVE(self)
1166    Py_INCREF(self->fut_loop);
1167    return self->fut_loop;
1168}
1169
1170static PyObject *
1171FutureObj_get_blocking(FutureObj *fut, void *Py_UNUSED(ignored))
1172{
1173    if (future_is_alive(fut) && fut->fut_blocking) {
1174        Py_RETURN_TRUE;
1175    }
1176    else {
1177        Py_RETURN_FALSE;
1178    }
1179}
1180
1181static int
1182FutureObj_set_blocking(FutureObj *fut, PyObject *val, void *Py_UNUSED(ignored))
1183{
1184    if (future_ensure_alive(fut)) {
1185        return -1;
1186    }
1187    if (val == NULL) {
1188        PyErr_SetString(PyExc_AttributeError, "cannot delete attribute");
1189        return -1;
1190    }
1191
1192    int is_true = PyObject_IsTrue(val);
1193    if (is_true < 0) {
1194        return -1;
1195    }
1196    fut->fut_blocking = is_true;
1197    return 0;
1198}
1199
1200static PyObject *
1201FutureObj_get_log_traceback(FutureObj *fut, void *Py_UNUSED(ignored))
1202{
1203    ENSURE_FUTURE_ALIVE(fut)
1204    if (fut->fut_log_tb) {
1205        Py_RETURN_TRUE;
1206    }
1207    else {
1208        Py_RETURN_FALSE;
1209    }
1210}
1211
1212static int
1213FutureObj_set_log_traceback(FutureObj *fut, PyObject *val, void *Py_UNUSED(ignored))
1214{
1215    if (val == NULL) {
1216        PyErr_SetString(PyExc_AttributeError, "cannot delete attribute");
1217        return -1;
1218    }
1219    int is_true = PyObject_IsTrue(val);
1220    if (is_true < 0) {
1221        return -1;
1222    }
1223    if (is_true) {
1224        PyErr_SetString(PyExc_ValueError,
1225                        "_log_traceback can only be set to False");
1226        return -1;
1227    }
1228    fut->fut_log_tb = is_true;
1229    return 0;
1230}
1231
1232static PyObject *
1233FutureObj_get_loop(FutureObj *fut, void *Py_UNUSED(ignored))
1234{
1235    if (!future_is_alive(fut)) {
1236        Py_RETURN_NONE;
1237    }
1238    Py_INCREF(fut->fut_loop);
1239    return fut->fut_loop;
1240}
1241
1242static PyObject *
1243FutureObj_get_callbacks(FutureObj *fut, void *Py_UNUSED(ignored))
1244{
1245    Py_ssize_t i;
1246
1247    ENSURE_FUTURE_ALIVE(fut)
1248
1249    if (fut->fut_callback0 == NULL) {
1250        if (fut->fut_callbacks == NULL) {
1251            Py_RETURN_NONE;
1252        }
1253
1254        Py_INCREF(fut->fut_callbacks);
1255        return fut->fut_callbacks;
1256    }
1257
1258    Py_ssize_t len = 1;
1259    if (fut->fut_callbacks != NULL) {
1260        len += PyList_GET_SIZE(fut->fut_callbacks);
1261    }
1262
1263
1264    PyObject *new_list = PyList_New(len);
1265    if (new_list == NULL) {
1266        return NULL;
1267    }
1268
1269    PyObject *tup0 = PyTuple_New(2);
1270    if (tup0 == NULL) {
1271        Py_DECREF(new_list);
1272        return NULL;
1273    }
1274
1275    Py_INCREF(fut->fut_callback0);
1276    PyTuple_SET_ITEM(tup0, 0, fut->fut_callback0);
1277    assert(fut->fut_context0 != NULL);
1278    Py_INCREF(fut->fut_context0);
1279    PyTuple_SET_ITEM(tup0, 1, (PyObject *)fut->fut_context0);
1280
1281    PyList_SET_ITEM(new_list, 0, tup0);
1282
1283    if (fut->fut_callbacks != NULL) {
1284        for (i = 0; i < PyList_GET_SIZE(fut->fut_callbacks); i++) {
1285            PyObject *cb = PyList_GET_ITEM(fut->fut_callbacks, i);
1286            Py_INCREF(cb);
1287            PyList_SET_ITEM(new_list, i + 1, cb);
1288        }
1289    }
1290
1291    return new_list;
1292}
1293
1294static PyObject *
1295FutureObj_get_result(FutureObj *fut, void *Py_UNUSED(ignored))
1296{
1297    ENSURE_FUTURE_ALIVE(fut)
1298    if (fut->fut_result == NULL) {
1299        Py_RETURN_NONE;
1300    }
1301    Py_INCREF(fut->fut_result);
1302    return fut->fut_result;
1303}
1304
1305static PyObject *
1306FutureObj_get_exception(FutureObj *fut, void *Py_UNUSED(ignored))
1307{
1308    ENSURE_FUTURE_ALIVE(fut)
1309    if (fut->fut_exception == NULL) {
1310        Py_RETURN_NONE;
1311    }
1312    Py_INCREF(fut->fut_exception);
1313    return fut->fut_exception;
1314}
1315
1316static PyObject *
1317FutureObj_get_source_traceback(FutureObj *fut, void *Py_UNUSED(ignored))
1318{
1319    if (!future_is_alive(fut) || fut->fut_source_tb == NULL) {
1320        Py_RETURN_NONE;
1321    }
1322    Py_INCREF(fut->fut_source_tb);
1323    return fut->fut_source_tb;
1324}
1325
1326static PyObject *
1327FutureObj_get_cancel_message(FutureObj *fut, void *Py_UNUSED(ignored))
1328{
1329    if (fut->fut_cancel_msg == NULL) {
1330        Py_RETURN_NONE;
1331    }
1332    Py_INCREF(fut->fut_cancel_msg);
1333    return fut->fut_cancel_msg;
1334}
1335
1336static int
1337FutureObj_set_cancel_message(FutureObj *fut, PyObject *msg,
1338                             void *Py_UNUSED(ignored))
1339{
1340    if (msg == NULL) {
1341        PyErr_SetString(PyExc_AttributeError, "cannot delete attribute");
1342        return -1;
1343    }
1344    Py_INCREF(msg);
1345    Py_XSETREF(fut->fut_cancel_msg, msg);
1346    return 0;
1347}
1348
1349static PyObject *
1350FutureObj_get_state(FutureObj *fut, void *Py_UNUSED(ignored))
1351{
1352    _Py_IDENTIFIER(PENDING);
1353    _Py_IDENTIFIER(CANCELLED);
1354    _Py_IDENTIFIER(FINISHED);
1355    PyObject *ret = NULL;
1356
1357    ENSURE_FUTURE_ALIVE(fut)
1358
1359    switch (fut->fut_state) {
1360    case STATE_PENDING:
1361        ret = _PyUnicode_FromId(&PyId_PENDING);
1362        break;
1363    case STATE_CANCELLED:
1364        ret = _PyUnicode_FromId(&PyId_CANCELLED);
1365        break;
1366    case STATE_FINISHED:
1367        ret = _PyUnicode_FromId(&PyId_FINISHED);
1368        break;
1369    default:
1370        assert (0);
1371    }
1372    Py_XINCREF(ret);
1373    return ret;
1374}
1375
1376static PyObject *
1377FutureObj_repr(FutureObj *fut)
1378{
1379    ENSURE_FUTURE_ALIVE(fut)
1380    return PyObject_CallOneArg(asyncio_future_repr_func, (PyObject *)fut);
1381}
1382
1383/*[clinic input]
1384_asyncio.Future._make_cancelled_error
1385
1386Create the CancelledError to raise if the Future is cancelled.
1387
1388This should only be called once when handling a cancellation since
1389it erases the context exception value.
1390[clinic start generated code]*/
1391
1392static PyObject *
1393_asyncio_Future__make_cancelled_error_impl(FutureObj *self)
1394/*[clinic end generated code: output=a5df276f6c1213de input=ac6effe4ba795ecc]*/
1395{
1396    return create_cancelled_error(self);
1397}
1398
1399static void
1400FutureObj_finalize(FutureObj *fut)
1401{
1402    _Py_IDENTIFIER(call_exception_handler);
1403    _Py_IDENTIFIER(message);
1404    _Py_IDENTIFIER(exception);
1405    _Py_IDENTIFIER(future);
1406    _Py_IDENTIFIER(source_traceback);
1407
1408    PyObject *error_type, *error_value, *error_traceback;
1409    PyObject *context;
1410    PyObject *message = NULL;
1411    PyObject *func;
1412
1413    if (!fut->fut_log_tb) {
1414        return;
1415    }
1416    assert(fut->fut_exception != NULL);
1417    fut->fut_log_tb = 0;
1418
1419    /* Save the current exception, if any. */
1420    PyErr_Fetch(&error_type, &error_value, &error_traceback);
1421
1422    context = PyDict_New();
1423    if (context == NULL) {
1424        goto finally;
1425    }
1426
1427    message = PyUnicode_FromFormat(
1428        "%s exception was never retrieved", _PyType_Name(Py_TYPE(fut)));
1429    if (message == NULL) {
1430        goto finally;
1431    }
1432
1433    if (_PyDict_SetItemId(context, &PyId_message, message) < 0 ||
1434        _PyDict_SetItemId(context, &PyId_exception, fut->fut_exception) < 0 ||
1435        _PyDict_SetItemId(context, &PyId_future, (PyObject*)fut) < 0) {
1436        goto finally;
1437    }
1438    if (fut->fut_source_tb != NULL) {
1439        if (_PyDict_SetItemId(context, &PyId_source_traceback,
1440                              fut->fut_source_tb) < 0) {
1441            goto finally;
1442        }
1443    }
1444
1445    func = _PyObject_GetAttrId(fut->fut_loop, &PyId_call_exception_handler);
1446    if (func != NULL) {
1447        PyObject *res = PyObject_CallOneArg(func, context);
1448        if (res == NULL) {
1449            PyErr_WriteUnraisable(func);
1450        }
1451        else {
1452            Py_DECREF(res);
1453        }
1454        Py_DECREF(func);
1455    }
1456
1457finally:
1458    Py_XDECREF(context);
1459    Py_XDECREF(message);
1460
1461    /* Restore the saved exception. */
1462    PyErr_Restore(error_type, error_value, error_traceback);
1463}
1464
1465static PyAsyncMethods FutureType_as_async = {
1466    (unaryfunc)future_new_iter,         /* am_await */
1467    0,                                  /* am_aiter */
1468    0,                                  /* am_anext */
1469    0,                                  /* am_send  */
1470};
1471
1472static PyMethodDef FutureType_methods[] = {
1473    _ASYNCIO_FUTURE_RESULT_METHODDEF
1474    _ASYNCIO_FUTURE_EXCEPTION_METHODDEF
1475    _ASYNCIO_FUTURE_SET_RESULT_METHODDEF
1476    _ASYNCIO_FUTURE_SET_EXCEPTION_METHODDEF
1477    _ASYNCIO_FUTURE_ADD_DONE_CALLBACK_METHODDEF
1478    _ASYNCIO_FUTURE_REMOVE_DONE_CALLBACK_METHODDEF
1479    _ASYNCIO_FUTURE_CANCEL_METHODDEF
1480    _ASYNCIO_FUTURE_CANCELLED_METHODDEF
1481    _ASYNCIO_FUTURE_DONE_METHODDEF
1482    _ASYNCIO_FUTURE_GET_LOOP_METHODDEF
1483    _ASYNCIO_FUTURE__MAKE_CANCELLED_ERROR_METHODDEF
1484    {"__class_getitem__", Py_GenericAlias, METH_O|METH_CLASS, PyDoc_STR("See PEP 585")},
1485    {NULL, NULL}        /* Sentinel */
1486};
1487
1488#define FUTURE_COMMON_GETSETLIST                                              \
1489    {"_state", (getter)FutureObj_get_state, NULL, NULL},                      \
1490    {"_asyncio_future_blocking", (getter)FutureObj_get_blocking,              \
1491                                 (setter)FutureObj_set_blocking, NULL},       \
1492    {"_loop", (getter)FutureObj_get_loop, NULL, NULL},                        \
1493    {"_callbacks", (getter)FutureObj_get_callbacks, NULL, NULL},              \
1494    {"_result", (getter)FutureObj_get_result, NULL, NULL},                    \
1495    {"_exception", (getter)FutureObj_get_exception, NULL, NULL},              \
1496    {"_log_traceback", (getter)FutureObj_get_log_traceback,                   \
1497                       (setter)FutureObj_set_log_traceback, NULL},            \
1498    {"_source_traceback", (getter)FutureObj_get_source_traceback,             \
1499                          NULL, NULL},                                        \
1500    {"_cancel_message", (getter)FutureObj_get_cancel_message,                 \
1501                        (setter)FutureObj_set_cancel_message, NULL},
1502
1503static PyGetSetDef FutureType_getsetlist[] = {
1504    FUTURE_COMMON_GETSETLIST
1505    {NULL} /* Sentinel */
1506};
1507
1508static void FutureObj_dealloc(PyObject *self);
1509
1510static PyTypeObject FutureType = {
1511    PyVarObject_HEAD_INIT(NULL, 0)
1512    "_asyncio.Future",
1513    sizeof(FutureObj),                       /* tp_basicsize */
1514    .tp_dealloc = FutureObj_dealloc,
1515    .tp_as_async = &FutureType_as_async,
1516    .tp_repr = (reprfunc)FutureObj_repr,
1517    .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE,
1518    .tp_doc = _asyncio_Future___init____doc__,
1519    .tp_traverse = (traverseproc)FutureObj_traverse,
1520    .tp_clear = (inquiry)FutureObj_clear,
1521    .tp_weaklistoffset = offsetof(FutureObj, fut_weakreflist),
1522    .tp_iter = (getiterfunc)future_new_iter,
1523    .tp_methods = FutureType_methods,
1524    .tp_getset = FutureType_getsetlist,
1525    .tp_dictoffset = offsetof(FutureObj, dict),
1526    .tp_init = (initproc)_asyncio_Future___init__,
1527    .tp_new = PyType_GenericNew,
1528    .tp_finalize = (destructor)FutureObj_finalize,
1529};
1530
1531static void
1532FutureObj_dealloc(PyObject *self)
1533{
1534    FutureObj *fut = (FutureObj *)self;
1535
1536    if (Future_CheckExact(fut)) {
1537        /* When fut is subclass of Future, finalizer is called from
1538         * subtype_dealloc.
1539         */
1540        if (PyObject_CallFinalizerFromDealloc(self) < 0) {
1541            // resurrected.
1542            return;
1543        }
1544    }
1545
1546    PyObject_GC_UnTrack(self);
1547
1548    if (fut->fut_weakreflist != NULL) {
1549        PyObject_ClearWeakRefs(self);
1550    }
1551
1552    (void)FutureObj_clear(fut);
1553    Py_TYPE(fut)->tp_free(fut);
1554}
1555
1556
1557/*********************** Future Iterator **************************/
1558
1559typedef struct {
1560    PyObject_HEAD
1561    FutureObj *future;
1562} futureiterobject;
1563
1564
1565#define FI_FREELIST_MAXLEN 255
1566static futureiterobject *fi_freelist = NULL;
1567static Py_ssize_t fi_freelist_len = 0;
1568
1569
1570static void
1571FutureIter_dealloc(futureiterobject *it)
1572{
1573    PyObject_GC_UnTrack(it);
1574    Py_CLEAR(it->future);
1575
1576    if (fi_freelist_len < FI_FREELIST_MAXLEN) {
1577        fi_freelist_len++;
1578        it->future = (FutureObj*) fi_freelist;
1579        fi_freelist = it;
1580    }
1581    else {
1582        PyObject_GC_Del(it);
1583    }
1584}
1585
1586static PySendResult
1587FutureIter_am_send(futureiterobject *it,
1588                   PyObject *Py_UNUSED(arg),
1589                   PyObject **result)
1590{
1591    /* arg is unused, see the comment on FutureIter_send for clarification */
1592
1593    PyObject *res;
1594    FutureObj *fut = it->future;
1595
1596    *result = NULL;
1597    if (fut == NULL) {
1598        return PYGEN_ERROR;
1599    }
1600
1601    if (fut->fut_state == STATE_PENDING) {
1602        if (!fut->fut_blocking) {
1603            fut->fut_blocking = 1;
1604            Py_INCREF(fut);
1605            *result = (PyObject *)fut;
1606            return PYGEN_NEXT;
1607        }
1608        PyErr_SetString(PyExc_RuntimeError,
1609                        "await wasn't used with future");
1610        return PYGEN_ERROR;
1611    }
1612
1613    it->future = NULL;
1614    res = _asyncio_Future_result_impl(fut);
1615    if (res != NULL) {
1616        Py_DECREF(fut);
1617        *result = res;
1618        return PYGEN_RETURN;
1619    }
1620
1621    Py_DECREF(fut);
1622    return PYGEN_ERROR;
1623}
1624
1625static PyObject *
1626FutureIter_iternext(futureiterobject *it)
1627{
1628    PyObject *result;
1629    switch (FutureIter_am_send(it, Py_None, &result)) {
1630        case PYGEN_RETURN:
1631            (void)_PyGen_SetStopIterationValue(result);
1632            Py_DECREF(result);
1633            return NULL;
1634        case PYGEN_NEXT:
1635            return result;
1636        case PYGEN_ERROR:
1637            return NULL;
1638        default:
1639            Py_UNREACHABLE();
1640    }
1641}
1642
1643static PyObject *
1644FutureIter_send(futureiterobject *self, PyObject *unused)
1645{
1646    /* Future.__iter__ doesn't care about values that are pushed to the
1647     * generator, it just returns self.result().
1648     */
1649    return FutureIter_iternext(self);
1650}
1651
1652static PyObject *
1653FutureIter_throw(futureiterobject *self, PyObject *const *args, Py_ssize_t nargs)
1654{
1655    PyObject *type, *val = NULL, *tb = NULL;
1656    if (!_PyArg_CheckPositional("throw", nargs, 1, 3)) {
1657        return NULL;
1658    }
1659
1660    type = args[0];
1661    if (nargs == 3) {
1662        val = args[1];
1663        tb = args[2];
1664    }
1665    else if (nargs == 2) {
1666        val = args[1];
1667    }
1668
1669    if (val == Py_None) {
1670        val = NULL;
1671    }
1672    if (tb == Py_None ) {
1673        tb = NULL;
1674    } else if (tb != NULL && !PyTraceBack_Check(tb)) {
1675        PyErr_SetString(PyExc_TypeError, "throw() third argument must be a traceback");
1676        return NULL;
1677    }
1678
1679    Py_INCREF(type);
1680    Py_XINCREF(val);
1681    Py_XINCREF(tb);
1682
1683    if (PyExceptionClass_Check(type)) {
1684        PyErr_NormalizeException(&type, &val, &tb);
1685        /* No need to call PyException_SetTraceback since we'll be calling
1686           PyErr_Restore for `type`, `val`, and `tb`. */
1687    } else if (PyExceptionInstance_Check(type)) {
1688        if (val) {
1689            PyErr_SetString(PyExc_TypeError,
1690                            "instance exception may not have a separate value");
1691            goto fail;
1692        }
1693        val = type;
1694        type = PyExceptionInstance_Class(type);
1695        Py_INCREF(type);
1696        if (tb == NULL)
1697            tb = PyException_GetTraceback(val);
1698    } else {
1699        PyErr_SetString(PyExc_TypeError,
1700                        "exceptions must be classes deriving BaseException or "
1701                        "instances of such a class");
1702        goto fail;
1703    }
1704
1705    Py_CLEAR(self->future);
1706
1707    PyErr_Restore(type, val, tb);
1708
1709    return NULL;
1710
1711  fail:
1712    Py_DECREF(type);
1713    Py_XDECREF(val);
1714    Py_XDECREF(tb);
1715    return NULL;
1716}
1717
1718static PyObject *
1719FutureIter_close(futureiterobject *self, PyObject *arg)
1720{
1721    Py_CLEAR(self->future);
1722    Py_RETURN_NONE;
1723}
1724
1725static int
1726FutureIter_traverse(futureiterobject *it, visitproc visit, void *arg)
1727{
1728    Py_VISIT(it->future);
1729    return 0;
1730}
1731
1732static PyMethodDef FutureIter_methods[] = {
1733    {"send",  (PyCFunction)FutureIter_send, METH_O, NULL},
1734    {"throw", _PyCFunction_CAST(FutureIter_throw), METH_FASTCALL, NULL},
1735    {"close", (PyCFunction)FutureIter_close, METH_NOARGS, NULL},
1736    {NULL, NULL}        /* Sentinel */
1737};
1738
1739static PyAsyncMethods FutureIterType_as_async = {
1740    0,                                  /* am_await */
1741    0,                                  /* am_aiter */
1742    0,                                  /* am_anext */
1743    (sendfunc)FutureIter_am_send,       /* am_send  */
1744};
1745
1746
1747static PyTypeObject FutureIterType = {
1748    PyVarObject_HEAD_INIT(NULL, 0)
1749    "_asyncio.FutureIter",
1750    .tp_basicsize = sizeof(futureiterobject),
1751    .tp_itemsize = 0,
1752    .tp_dealloc = (destructor)FutureIter_dealloc,
1753    .tp_as_async = &FutureIterType_as_async,
1754    .tp_getattro = PyObject_GenericGetAttr,
1755    .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
1756    .tp_traverse = (traverseproc)FutureIter_traverse,
1757    .tp_iter = PyObject_SelfIter,
1758    .tp_iternext = (iternextfunc)FutureIter_iternext,
1759    .tp_methods = FutureIter_methods,
1760};
1761
1762static PyObject *
1763future_new_iter(PyObject *fut)
1764{
1765    futureiterobject *it;
1766
1767    if (!PyObject_TypeCheck(fut, &FutureType)) {
1768        PyErr_BadInternalCall();
1769        return NULL;
1770    }
1771
1772    ENSURE_FUTURE_ALIVE(fut)
1773
1774    if (fi_freelist_len) {
1775        fi_freelist_len--;
1776        it = fi_freelist;
1777        fi_freelist = (futureiterobject*) it->future;
1778        it->future = NULL;
1779        _Py_NewReference((PyObject*) it);
1780    }
1781    else {
1782        it = PyObject_GC_New(futureiterobject, &FutureIterType);
1783        if (it == NULL) {
1784            return NULL;
1785        }
1786    }
1787
1788    Py_INCREF(fut);
1789    it->future = (FutureObj*)fut;
1790    PyObject_GC_Track(it);
1791    return (PyObject*)it;
1792}
1793
1794
1795/*********************** Task **************************/
1796
1797
1798/*[clinic input]
1799class _asyncio.Task "TaskObj *" "&Task_Type"
1800[clinic start generated code]*/
1801/*[clinic end generated code: output=da39a3ee5e6b4b0d input=719dcef0fcc03b37]*/
1802
1803static int task_call_step_soon(TaskObj *, PyObject *);
1804static PyObject * task_wakeup(TaskObj *, PyObject *);
1805static PyObject * task_step(TaskObj *, PyObject *);
1806
1807/* ----- Task._step wrapper */
1808
1809static int
1810TaskStepMethWrapper_clear(TaskStepMethWrapper *o)
1811{
1812    Py_CLEAR(o->sw_task);
1813    Py_CLEAR(o->sw_arg);
1814    return 0;
1815}
1816
1817static void
1818TaskStepMethWrapper_dealloc(TaskStepMethWrapper *o)
1819{
1820    PyObject_GC_UnTrack(o);
1821    (void)TaskStepMethWrapper_clear(o);
1822    Py_TYPE(o)->tp_free(o);
1823}
1824
1825static PyObject *
1826TaskStepMethWrapper_call(TaskStepMethWrapper *o,
1827                         PyObject *args, PyObject *kwds)
1828{
1829    if (kwds != NULL && PyDict_GET_SIZE(kwds) != 0) {
1830        PyErr_SetString(PyExc_TypeError, "function takes no keyword arguments");
1831        return NULL;
1832    }
1833    if (args != NULL && PyTuple_GET_SIZE(args) != 0) {
1834        PyErr_SetString(PyExc_TypeError, "function takes no positional arguments");
1835        return NULL;
1836    }
1837    return task_step(o->sw_task, o->sw_arg);
1838}
1839
1840static int
1841TaskStepMethWrapper_traverse(TaskStepMethWrapper *o,
1842                             visitproc visit, void *arg)
1843{
1844    Py_VISIT(o->sw_task);
1845    Py_VISIT(o->sw_arg);
1846    return 0;
1847}
1848
1849static PyObject *
1850TaskStepMethWrapper_get___self__(TaskStepMethWrapper *o, void *Py_UNUSED(ignored))
1851{
1852    if (o->sw_task) {
1853        Py_INCREF(o->sw_task);
1854        return (PyObject*)o->sw_task;
1855    }
1856    Py_RETURN_NONE;
1857}
1858
1859static PyGetSetDef TaskStepMethWrapper_getsetlist[] = {
1860    {"__self__", (getter)TaskStepMethWrapper_get___self__, NULL, NULL},
1861    {NULL} /* Sentinel */
1862};
1863
1864static PyTypeObject TaskStepMethWrapper_Type = {
1865    PyVarObject_HEAD_INIT(NULL, 0)
1866    "TaskStepMethWrapper",
1867    .tp_basicsize = sizeof(TaskStepMethWrapper),
1868    .tp_itemsize = 0,
1869    .tp_getset = TaskStepMethWrapper_getsetlist,
1870    .tp_dealloc = (destructor)TaskStepMethWrapper_dealloc,
1871    .tp_call = (ternaryfunc)TaskStepMethWrapper_call,
1872    .tp_getattro = PyObject_GenericGetAttr,
1873    .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
1874    .tp_traverse = (traverseproc)TaskStepMethWrapper_traverse,
1875    .tp_clear = (inquiry)TaskStepMethWrapper_clear,
1876};
1877
1878static PyObject *
1879TaskStepMethWrapper_new(TaskObj *task, PyObject *arg)
1880{
1881    TaskStepMethWrapper *o;
1882    o = PyObject_GC_New(TaskStepMethWrapper, &TaskStepMethWrapper_Type);
1883    if (o == NULL) {
1884        return NULL;
1885    }
1886
1887    Py_INCREF(task);
1888    o->sw_task = task;
1889
1890    Py_XINCREF(arg);
1891    o->sw_arg = arg;
1892
1893    PyObject_GC_Track(o);
1894    return (PyObject*) o;
1895}
1896
1897/* ----- Task._wakeup implementation */
1898
1899static  PyMethodDef TaskWakeupDef = {
1900    "task_wakeup",
1901    (PyCFunction)task_wakeup,
1902    METH_O,
1903    NULL
1904};
1905
1906/* ----- Task introspection helpers */
1907
1908static int
1909register_task(PyObject *task)
1910{
1911    _Py_IDENTIFIER(add);
1912
1913    PyObject *res = _PyObject_CallMethodIdOneArg(all_tasks,
1914                                                 &PyId_add, task);
1915    if (res == NULL) {
1916        return -1;
1917    }
1918    Py_DECREF(res);
1919    return 0;
1920}
1921
1922
1923static int
1924unregister_task(PyObject *task)
1925{
1926    _Py_IDENTIFIER(discard);
1927
1928    PyObject *res = _PyObject_CallMethodIdOneArg(all_tasks,
1929                                                 &PyId_discard, task);
1930    if (res == NULL) {
1931        return -1;
1932    }
1933    Py_DECREF(res);
1934    return 0;
1935}
1936
1937
1938static int
1939enter_task(PyObject *loop, PyObject *task)
1940{
1941    PyObject *item;
1942    Py_hash_t hash;
1943    hash = PyObject_Hash(loop);
1944    if (hash == -1) {
1945        return -1;
1946    }
1947    item = _PyDict_GetItem_KnownHash(current_tasks, loop, hash);
1948    if (item != NULL) {
1949        Py_INCREF(item);
1950        PyErr_Format(
1951            PyExc_RuntimeError,
1952            "Cannot enter into task %R while another " \
1953            "task %R is being executed.",
1954            task, item, NULL);
1955        Py_DECREF(item);
1956        return -1;
1957    }
1958    if (PyErr_Occurred()) {
1959        return -1;
1960    }
1961    return _PyDict_SetItem_KnownHash(current_tasks, loop, task, hash);
1962}
1963
1964
1965static int
1966leave_task(PyObject *loop, PyObject *task)
1967/*[clinic end generated code: output=0ebf6db4b858fb41 input=51296a46313d1ad8]*/
1968{
1969    PyObject *item;
1970    Py_hash_t hash;
1971    hash = PyObject_Hash(loop);
1972    if (hash == -1) {
1973        return -1;
1974    }
1975    item = _PyDict_GetItem_KnownHash(current_tasks, loop, hash);
1976    if (item != task) {
1977        if (item == NULL) {
1978            /* Not entered, replace with None */
1979            item = Py_None;
1980        }
1981        PyErr_Format(
1982            PyExc_RuntimeError,
1983            "Leaving task %R does not match the current task %R.",
1984            task, item, NULL);
1985        return -1;
1986    }
1987    return _PyDict_DelItem_KnownHash(current_tasks, loop, hash);
1988}
1989
1990/* ----- Task */
1991
1992/*[clinic input]
1993_asyncio.Task.__init__
1994
1995    coro: object
1996    *
1997    loop: object = None
1998    name: object = None
1999    context: object = None
2000
2001A coroutine wrapped in a Future.
2002[clinic start generated code]*/
2003
2004static int
2005_asyncio_Task___init___impl(TaskObj *self, PyObject *coro, PyObject *loop,
2006                            PyObject *name, PyObject *context)
2007/*[clinic end generated code: output=49ac96fe33d0e5c7 input=924522490c8ce825]*/
2008
2009{
2010    if (future_init((FutureObj*)self, loop)) {
2011        return -1;
2012    }
2013
2014    int is_coro = is_coroutine(coro);
2015    if (is_coro == -1) {
2016        return -1;
2017    }
2018    if (is_coro == 0) {
2019        self->task_log_destroy_pending = 0;
2020        PyErr_Format(PyExc_TypeError,
2021                     "a coroutine was expected, got %R",
2022                     coro, NULL);
2023        return -1;
2024    }
2025
2026    if (context == Py_None) {
2027        Py_XSETREF(self->task_context, PyContext_CopyCurrent());
2028        if (self->task_context == NULL) {
2029            return -1;
2030        }
2031    } else {
2032        self->task_context = Py_NewRef(context);
2033    }
2034
2035    Py_CLEAR(self->task_fut_waiter);
2036    self->task_must_cancel = 0;
2037    self->task_log_destroy_pending = 1;
2038    self->task_num_cancels_requested = 0;
2039    Py_INCREF(coro);
2040    Py_XSETREF(self->task_coro, coro);
2041
2042    if (name == Py_None) {
2043        name = PyUnicode_FromFormat("Task-%" PRIu64, ++task_name_counter);
2044    } else if (!PyUnicode_CheckExact(name)) {
2045        name = PyObject_Str(name);
2046    } else {
2047        Py_INCREF(name);
2048    }
2049    Py_XSETREF(self->task_name, name);
2050    if (self->task_name == NULL) {
2051        return -1;
2052    }
2053
2054    if (task_call_step_soon(self, NULL)) {
2055        return -1;
2056    }
2057    return register_task((PyObject*)self);
2058}
2059
2060static int
2061TaskObj_clear(TaskObj *task)
2062{
2063    (void)FutureObj_clear((FutureObj*) task);
2064    Py_CLEAR(task->task_context);
2065    Py_CLEAR(task->task_coro);
2066    Py_CLEAR(task->task_name);
2067    Py_CLEAR(task->task_fut_waiter);
2068    return 0;
2069}
2070
2071static int
2072TaskObj_traverse(TaskObj *task, visitproc visit, void *arg)
2073{
2074    Py_VISIT(task->task_context);
2075    Py_VISIT(task->task_coro);
2076    Py_VISIT(task->task_name);
2077    Py_VISIT(task->task_fut_waiter);
2078    (void)FutureObj_traverse((FutureObj*) task, visit, arg);
2079    return 0;
2080}
2081
2082static PyObject *
2083TaskObj_get_log_destroy_pending(TaskObj *task, void *Py_UNUSED(ignored))
2084{
2085    if (task->task_log_destroy_pending) {
2086        Py_RETURN_TRUE;
2087    }
2088    else {
2089        Py_RETURN_FALSE;
2090    }
2091}
2092
2093static int
2094TaskObj_set_log_destroy_pending(TaskObj *task, PyObject *val, void *Py_UNUSED(ignored))
2095{
2096    if (val == NULL) {
2097        PyErr_SetString(PyExc_AttributeError, "cannot delete attribute");
2098        return -1;
2099    }
2100    int is_true = PyObject_IsTrue(val);
2101    if (is_true < 0) {
2102        return -1;
2103    }
2104    task->task_log_destroy_pending = is_true;
2105    return 0;
2106}
2107
2108static PyObject *
2109TaskObj_get_must_cancel(TaskObj *task, void *Py_UNUSED(ignored))
2110{
2111    if (task->task_must_cancel) {
2112        Py_RETURN_TRUE;
2113    }
2114    else {
2115        Py_RETURN_FALSE;
2116    }
2117}
2118
2119static PyObject *
2120TaskObj_get_coro(TaskObj *task, void *Py_UNUSED(ignored))
2121{
2122    if (task->task_coro) {
2123        Py_INCREF(task->task_coro);
2124        return task->task_coro;
2125    }
2126
2127    Py_RETURN_NONE;
2128}
2129
2130static PyObject *
2131TaskObj_get_fut_waiter(TaskObj *task, void *Py_UNUSED(ignored))
2132{
2133    if (task->task_fut_waiter) {
2134        Py_INCREF(task->task_fut_waiter);
2135        return task->task_fut_waiter;
2136    }
2137
2138    Py_RETURN_NONE;
2139}
2140
2141static PyObject *
2142TaskObj_repr(TaskObj *task)
2143{
2144    return PyObject_CallOneArg(asyncio_task_repr_func, (PyObject *)task);
2145}
2146
2147
2148/*[clinic input]
2149_asyncio.Task._make_cancelled_error
2150
2151Create the CancelledError to raise if the Task is cancelled.
2152
2153This should only be called once when handling a cancellation since
2154it erases the context exception value.
2155[clinic start generated code]*/
2156
2157static PyObject *
2158_asyncio_Task__make_cancelled_error_impl(TaskObj *self)
2159/*[clinic end generated code: output=55a819e8b4276fab input=52c0e32de8e2f840]*/
2160{
2161    FutureObj *fut = (FutureObj*)self;
2162    return _asyncio_Future__make_cancelled_error_impl(fut);
2163}
2164
2165
2166/*[clinic input]
2167_asyncio.Task.cancel
2168
2169    msg: object = None
2170
2171Request that this task cancel itself.
2172
2173This arranges for a CancelledError to be thrown into the
2174wrapped coroutine on the next cycle through the event loop.
2175The coroutine then has a chance to clean up or even deny
2176the request using try/except/finally.
2177
2178Unlike Future.cancel, this does not guarantee that the
2179task will be cancelled: the exception might be caught and
2180acted upon, delaying cancellation of the task or preventing
2181cancellation completely.  The task may also return a value or
2182raise a different exception.
2183
2184Immediately after this method is called, Task.cancelled() will
2185not return True (unless the task was already cancelled).  A
2186task will be marked as cancelled when the wrapped coroutine
2187terminates with a CancelledError exception (even if cancel()
2188was not called).
2189
2190This also increases the task's count of cancellation requests.
2191[clinic start generated code]*/
2192
2193static PyObject *
2194_asyncio_Task_cancel_impl(TaskObj *self, PyObject *msg)
2195/*[clinic end generated code: output=c66b60d41c74f9f1 input=7bb51bf25974c783]*/
2196{
2197    self->task_log_tb = 0;
2198
2199    if (self->task_state != STATE_PENDING) {
2200        Py_RETURN_FALSE;
2201    }
2202
2203    self->task_num_cancels_requested += 1;
2204
2205    // These three lines are controversial.  See discussion starting at
2206    // https://github.com/python/cpython/pull/31394#issuecomment-1053545331
2207    // and corresponding code in tasks.py.
2208    // if (self->task_num_cancels_requested > 1) {
2209    //     Py_RETURN_FALSE;
2210    // }
2211
2212    if (self->task_fut_waiter) {
2213        PyObject *res;
2214        int is_true;
2215
2216        res = _PyObject_CallMethodIdOneArg(self->task_fut_waiter,
2217                                           &PyId_cancel, msg);
2218        if (res == NULL) {
2219            return NULL;
2220        }
2221
2222        is_true = PyObject_IsTrue(res);
2223        Py_DECREF(res);
2224        if (is_true < 0) {
2225            return NULL;
2226        }
2227
2228        if (is_true) {
2229            Py_RETURN_TRUE;
2230        }
2231    }
2232
2233    self->task_must_cancel = 1;
2234    Py_XINCREF(msg);
2235    Py_XSETREF(self->task_cancel_msg, msg);
2236    Py_RETURN_TRUE;
2237}
2238
2239/*[clinic input]
2240_asyncio.Task.cancelling
2241
2242Return the count of the task's cancellation requests.
2243
2244This count is incremented when .cancel() is called
2245and may be decremented using .uncancel().
2246[clinic start generated code]*/
2247
2248static PyObject *
2249_asyncio_Task_cancelling_impl(TaskObj *self)
2250/*[clinic end generated code: output=803b3af96f917d7e input=b625224d310cbb17]*/
2251/*[clinic end generated code]*/
2252{
2253    return PyLong_FromLong(self->task_num_cancels_requested);
2254}
2255
2256/*[clinic input]
2257_asyncio.Task.uncancel
2258
2259Decrement the task's count of cancellation requests.
2260
2261This should be used by tasks that catch CancelledError
2262and wish to continue indefinitely until they are cancelled again.
2263
2264Returns the remaining number of cancellation requests.
2265[clinic start generated code]*/
2266
2267static PyObject *
2268_asyncio_Task_uncancel_impl(TaskObj *self)
2269/*[clinic end generated code: output=58184d236a817d3c input=68f81a4b90b46be2]*/
2270/*[clinic end generated code]*/
2271{
2272    if (self->task_num_cancels_requested > 0) {
2273        self->task_num_cancels_requested -= 1;
2274    }
2275    return PyLong_FromLong(self->task_num_cancels_requested);
2276}
2277
2278/*[clinic input]
2279_asyncio.Task.get_stack
2280
2281    *
2282    limit: object = None
2283
2284Return the list of stack frames for this task's coroutine.
2285
2286If the coroutine is not done, this returns the stack where it is
2287suspended.  If the coroutine has completed successfully or was
2288cancelled, this returns an empty list.  If the coroutine was
2289terminated by an exception, this returns the list of traceback
2290frames.
2291
2292The frames are always ordered from oldest to newest.
2293
2294The optional limit gives the maximum number of frames to
2295return; by default all available frames are returned.  Its
2296meaning differs depending on whether a stack or a traceback is
2297returned: the newest frames of a stack are returned, but the
2298oldest frames of a traceback are returned.  (This matches the
2299behavior of the traceback module.)
2300
2301For reasons beyond our control, only one stack frame is
2302returned for a suspended coroutine.
2303[clinic start generated code]*/
2304
2305static PyObject *
2306_asyncio_Task_get_stack_impl(TaskObj *self, PyObject *limit)
2307/*[clinic end generated code: output=c9aeeeebd1e18118 input=05b323d42b809b90]*/
2308{
2309    return PyObject_CallFunctionObjArgs(
2310        asyncio_task_get_stack_func, self, limit, NULL);
2311}
2312
2313/*[clinic input]
2314_asyncio.Task.print_stack
2315
2316    *
2317    limit: object = None
2318    file: object = None
2319
2320Print the stack or traceback for this task's coroutine.
2321
2322This produces output similar to that of the traceback module,
2323for the frames retrieved by get_stack().  The limit argument
2324is passed to get_stack().  The file argument is an I/O stream
2325to which the output is written; by default output is written
2326to sys.stderr.
2327[clinic start generated code]*/
2328
2329static PyObject *
2330_asyncio_Task_print_stack_impl(TaskObj *self, PyObject *limit,
2331                               PyObject *file)
2332/*[clinic end generated code: output=7339e10314cd3f4d input=1a0352913b7fcd92]*/
2333{
2334    return PyObject_CallFunctionObjArgs(
2335        asyncio_task_print_stack_func, self, limit, file, NULL);
2336}
2337
2338/*[clinic input]
2339_asyncio.Task.set_result
2340
2341    result: object
2342    /
2343[clinic start generated code]*/
2344
2345static PyObject *
2346_asyncio_Task_set_result(TaskObj *self, PyObject *result)
2347/*[clinic end generated code: output=1dcae308bfcba318 input=9d1a00c07be41bab]*/
2348{
2349    PyErr_SetString(PyExc_RuntimeError,
2350                    "Task does not support set_result operation");
2351    return NULL;
2352}
2353
2354/*[clinic input]
2355_asyncio.Task.set_exception
2356
2357    exception: object
2358    /
2359[clinic start generated code]*/
2360
2361static PyObject *
2362_asyncio_Task_set_exception(TaskObj *self, PyObject *exception)
2363/*[clinic end generated code: output=bc377fc28067303d input=9a8f65c83dcf893a]*/
2364{
2365    PyErr_SetString(PyExc_RuntimeError,
2366                    "Task does not support set_exception operation");
2367    return NULL;
2368}
2369
2370/*[clinic input]
2371_asyncio.Task.get_coro
2372[clinic start generated code]*/
2373
2374static PyObject *
2375_asyncio_Task_get_coro_impl(TaskObj *self)
2376/*[clinic end generated code: output=bcac27c8cc6c8073 input=d2e8606c42a7b403]*/
2377{
2378    Py_INCREF(self->task_coro);
2379    return self->task_coro;
2380}
2381
2382/*[clinic input]
2383_asyncio.Task.get_name
2384[clinic start generated code]*/
2385
2386static PyObject *
2387_asyncio_Task_get_name_impl(TaskObj *self)
2388/*[clinic end generated code: output=0ecf1570c3b37a8f input=a4a6595d12f4f0f8]*/
2389{
2390    if (self->task_name) {
2391        Py_INCREF(self->task_name);
2392        return self->task_name;
2393    }
2394
2395    Py_RETURN_NONE;
2396}
2397
2398/*[clinic input]
2399_asyncio.Task.set_name
2400
2401    value: object
2402    /
2403[clinic start generated code]*/
2404
2405static PyObject *
2406_asyncio_Task_set_name(TaskObj *self, PyObject *value)
2407/*[clinic end generated code: output=138a8d51e32057d6 input=a8359b6e65f8fd31]*/
2408{
2409    if (!PyUnicode_CheckExact(value)) {
2410        value = PyObject_Str(value);
2411        if (value == NULL) {
2412            return NULL;
2413        }
2414    } else {
2415        Py_INCREF(value);
2416    }
2417
2418    Py_XSETREF(self->task_name, value);
2419    Py_RETURN_NONE;
2420}
2421
2422static void
2423TaskObj_finalize(TaskObj *task)
2424{
2425    _Py_IDENTIFIER(call_exception_handler);
2426    _Py_IDENTIFIER(task);
2427    _Py_IDENTIFIER(message);
2428    _Py_IDENTIFIER(source_traceback);
2429
2430    PyObject *context;
2431    PyObject *message = NULL;
2432    PyObject *func;
2433    PyObject *error_type, *error_value, *error_traceback;
2434
2435    if (task->task_state != STATE_PENDING || !task->task_log_destroy_pending) {
2436        goto done;
2437    }
2438
2439    /* Save the current exception, if any. */
2440    PyErr_Fetch(&error_type, &error_value, &error_traceback);
2441
2442    context = PyDict_New();
2443    if (context == NULL) {
2444        goto finally;
2445    }
2446
2447    message = PyUnicode_FromString("Task was destroyed but it is pending!");
2448    if (message == NULL) {
2449        goto finally;
2450    }
2451
2452    if (_PyDict_SetItemId(context, &PyId_message, message) < 0 ||
2453        _PyDict_SetItemId(context, &PyId_task, (PyObject*)task) < 0)
2454    {
2455        goto finally;
2456    }
2457
2458    if (task->task_source_tb != NULL) {
2459        if (_PyDict_SetItemId(context, &PyId_source_traceback,
2460                              task->task_source_tb) < 0)
2461        {
2462            goto finally;
2463        }
2464    }
2465
2466    func = _PyObject_GetAttrId(task->task_loop, &PyId_call_exception_handler);
2467    if (func != NULL) {
2468        PyObject *res = PyObject_CallOneArg(func, context);
2469        if (res == NULL) {
2470            PyErr_WriteUnraisable(func);
2471        }
2472        else {
2473            Py_DECREF(res);
2474        }
2475        Py_DECREF(func);
2476    }
2477
2478finally:
2479    Py_XDECREF(context);
2480    Py_XDECREF(message);
2481
2482    /* Restore the saved exception. */
2483    PyErr_Restore(error_type, error_value, error_traceback);
2484
2485done:
2486    FutureObj_finalize((FutureObj*)task);
2487}
2488
2489static void TaskObj_dealloc(PyObject *);  /* Needs Task_CheckExact */
2490
2491static PyMethodDef TaskType_methods[] = {
2492    _ASYNCIO_FUTURE_RESULT_METHODDEF
2493    _ASYNCIO_FUTURE_EXCEPTION_METHODDEF
2494    _ASYNCIO_FUTURE_ADD_DONE_CALLBACK_METHODDEF
2495    _ASYNCIO_FUTURE_REMOVE_DONE_CALLBACK_METHODDEF
2496    _ASYNCIO_FUTURE_CANCELLED_METHODDEF
2497    _ASYNCIO_FUTURE_DONE_METHODDEF
2498    _ASYNCIO_TASK_SET_RESULT_METHODDEF
2499    _ASYNCIO_TASK_SET_EXCEPTION_METHODDEF
2500    _ASYNCIO_TASK_CANCEL_METHODDEF
2501    _ASYNCIO_TASK_CANCELLING_METHODDEF
2502    _ASYNCIO_TASK_UNCANCEL_METHODDEF
2503    _ASYNCIO_TASK_GET_STACK_METHODDEF
2504    _ASYNCIO_TASK_PRINT_STACK_METHODDEF
2505    _ASYNCIO_TASK__MAKE_CANCELLED_ERROR_METHODDEF
2506    _ASYNCIO_TASK_GET_NAME_METHODDEF
2507    _ASYNCIO_TASK_SET_NAME_METHODDEF
2508    _ASYNCIO_TASK_GET_CORO_METHODDEF
2509    {"__class_getitem__", Py_GenericAlias, METH_O|METH_CLASS, PyDoc_STR("See PEP 585")},
2510    {NULL, NULL}        /* Sentinel */
2511};
2512
2513static PyGetSetDef TaskType_getsetlist[] = {
2514    FUTURE_COMMON_GETSETLIST
2515    {"_log_destroy_pending", (getter)TaskObj_get_log_destroy_pending,
2516                             (setter)TaskObj_set_log_destroy_pending, NULL},
2517    {"_must_cancel", (getter)TaskObj_get_must_cancel, NULL, NULL},
2518    {"_coro", (getter)TaskObj_get_coro, NULL, NULL},
2519    {"_fut_waiter", (getter)TaskObj_get_fut_waiter, NULL, NULL},
2520    {NULL} /* Sentinel */
2521};
2522
2523static PyTypeObject TaskType = {
2524    PyVarObject_HEAD_INIT(NULL, 0)
2525    "_asyncio.Task",
2526    sizeof(TaskObj),                       /* tp_basicsize */
2527    .tp_base = &FutureType,
2528    .tp_dealloc = TaskObj_dealloc,
2529    .tp_as_async = &FutureType_as_async,
2530    .tp_repr = (reprfunc)TaskObj_repr,
2531    .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE,
2532    .tp_doc = _asyncio_Task___init____doc__,
2533    .tp_traverse = (traverseproc)TaskObj_traverse,
2534    .tp_clear = (inquiry)TaskObj_clear,
2535    .tp_weaklistoffset = offsetof(TaskObj, task_weakreflist),
2536    .tp_iter = (getiterfunc)future_new_iter,
2537    .tp_methods = TaskType_methods,
2538    .tp_getset = TaskType_getsetlist,
2539    .tp_dictoffset = offsetof(TaskObj, dict),
2540    .tp_init = (initproc)_asyncio_Task___init__,
2541    .tp_new = PyType_GenericNew,
2542    .tp_finalize = (destructor)TaskObj_finalize,
2543};
2544
2545static void
2546TaskObj_dealloc(PyObject *self)
2547{
2548    TaskObj *task = (TaskObj *)self;
2549
2550    if (Task_CheckExact(self)) {
2551        /* When fut is subclass of Task, finalizer is called from
2552         * subtype_dealloc.
2553         */
2554        if (PyObject_CallFinalizerFromDealloc(self) < 0) {
2555            // resurrected.
2556            return;
2557        }
2558    }
2559
2560    PyObject_GC_UnTrack(self);
2561
2562    if (task->task_weakreflist != NULL) {
2563        PyObject_ClearWeakRefs(self);
2564    }
2565
2566    (void)TaskObj_clear(task);
2567    Py_TYPE(task)->tp_free(task);
2568}
2569
2570static int
2571task_call_step_soon(TaskObj *task, PyObject *arg)
2572{
2573    PyObject *cb = TaskStepMethWrapper_new(task, arg);
2574    if (cb == NULL) {
2575        return -1;
2576    }
2577
2578    int ret = call_soon(task->task_loop, cb, NULL, task->task_context);
2579    Py_DECREF(cb);
2580    return ret;
2581}
2582
2583static PyObject *
2584task_set_error_soon(TaskObj *task, PyObject *et, const char *format, ...)
2585{
2586    PyObject* msg;
2587
2588    va_list vargs;
2589#ifdef HAVE_STDARG_PROTOTYPES
2590    va_start(vargs, format);
2591#else
2592    va_start(vargs);
2593#endif
2594    msg = PyUnicode_FromFormatV(format, vargs);
2595    va_end(vargs);
2596
2597    if (msg == NULL) {
2598        return NULL;
2599    }
2600
2601    PyObject *e = PyObject_CallOneArg(et, msg);
2602    Py_DECREF(msg);
2603    if (e == NULL) {
2604        return NULL;
2605    }
2606
2607    if (task_call_step_soon(task, e) == -1) {
2608        Py_DECREF(e);
2609        return NULL;
2610    }
2611
2612    Py_DECREF(e);
2613    Py_RETURN_NONE;
2614}
2615
2616static inline int
2617gen_status_from_result(PyObject **result)
2618{
2619    if (*result != NULL) {
2620        return PYGEN_NEXT;
2621    }
2622    if (_PyGen_FetchStopIterationValue(result) == 0) {
2623        return PYGEN_RETURN;
2624    }
2625
2626    assert(PyErr_Occurred());
2627    return PYGEN_ERROR;
2628}
2629
2630static PyObject *
2631task_step_impl(TaskObj *task, PyObject *exc)
2632{
2633    int res;
2634    int clear_exc = 0;
2635    PyObject *result = NULL;
2636    PyObject *coro;
2637    PyObject *o;
2638
2639    if (task->task_state != STATE_PENDING) {
2640        PyErr_Format(asyncio_InvalidStateError,
2641                     "_step(): already done: %R %R",
2642                     task,
2643                     exc ? exc : Py_None);
2644        goto fail;
2645    }
2646
2647    if (task->task_must_cancel) {
2648        assert(exc != Py_None);
2649
2650        if (exc) {
2651            /* Check if exc is a CancelledError */
2652            res = PyObject_IsInstance(exc, asyncio_CancelledError);
2653            if (res == -1) {
2654                /* An error occurred, abort */
2655                goto fail;
2656            }
2657            if (res == 0) {
2658                /* exc is not CancelledError; reset it to NULL */
2659                exc = NULL;
2660            }
2661        }
2662
2663        if (!exc) {
2664            /* exc was not a CancelledError */
2665            exc = create_cancelled_error((FutureObj*)task);
2666
2667            if (!exc) {
2668                goto fail;
2669            }
2670            clear_exc = 1;
2671        }
2672
2673        task->task_must_cancel = 0;
2674    }
2675
2676    Py_CLEAR(task->task_fut_waiter);
2677
2678    coro = task->task_coro;
2679    if (coro == NULL) {
2680        PyErr_SetString(PyExc_RuntimeError, "uninitialized Task object");
2681        if (clear_exc) {
2682            /* We created 'exc' during this call */
2683            Py_DECREF(exc);
2684        }
2685        return NULL;
2686    }
2687
2688    int gen_status = PYGEN_ERROR;
2689    if (exc == NULL) {
2690        gen_status = PyIter_Send(coro, Py_None, &result);
2691    }
2692    else {
2693        result = _PyObject_CallMethodIdOneArg(coro, &PyId_throw, exc);
2694        gen_status = gen_status_from_result(&result);
2695        if (clear_exc) {
2696            /* We created 'exc' during this call */
2697            Py_DECREF(exc);
2698        }
2699    }
2700
2701    if (gen_status == PYGEN_RETURN || gen_status == PYGEN_ERROR) {
2702        PyObject *et, *ev, *tb;
2703
2704        if (result != NULL) {
2705            /* The error is StopIteration and that means that
2706               the underlying coroutine has resolved */
2707
2708            PyObject *tmp;
2709            if (task->task_must_cancel) {
2710                // Task is cancelled right before coro stops.
2711                task->task_must_cancel = 0;
2712                tmp = future_cancel((FutureObj*)task, task->task_cancel_msg);
2713            }
2714            else {
2715                tmp = future_set_result((FutureObj*)task, result);
2716            }
2717
2718            Py_DECREF(result);
2719
2720            if (tmp == NULL) {
2721                return NULL;
2722            }
2723            Py_DECREF(tmp);
2724            Py_RETURN_NONE;
2725        }
2726
2727        if (PyErr_ExceptionMatches(asyncio_CancelledError)) {
2728            /* CancelledError */
2729            PyErr_Fetch(&et, &ev, &tb);
2730            assert(et);
2731            PyErr_NormalizeException(&et, &ev, &tb);
2732            if (tb != NULL) {
2733                PyException_SetTraceback(ev, tb);
2734                Py_DECREF(tb);
2735            }
2736            Py_XDECREF(et);
2737
2738            FutureObj *fut = (FutureObj*)task;
2739            /* transfer ownership */
2740            fut->fut_cancelled_exc = ev;
2741
2742            return future_cancel(fut, NULL);
2743        }
2744
2745        /* Some other exception; pop it and call Task.set_exception() */
2746        PyErr_Fetch(&et, &ev, &tb);
2747        assert(et);
2748        PyErr_NormalizeException(&et, &ev, &tb);
2749        if (tb != NULL) {
2750            PyException_SetTraceback(ev, tb);
2751        }
2752
2753        o = future_set_exception((FutureObj*)task, ev);
2754        if (!o) {
2755            /* An exception in Task.set_exception() */
2756            Py_DECREF(et);
2757            Py_XDECREF(tb);
2758            Py_XDECREF(ev);
2759            goto fail;
2760        }
2761        assert(o == Py_None);
2762        Py_DECREF(o);
2763
2764        if (PyErr_GivenExceptionMatches(et, PyExc_KeyboardInterrupt) ||
2765            PyErr_GivenExceptionMatches(et, PyExc_SystemExit))
2766        {
2767            /* We've got a KeyboardInterrupt or a SystemError; re-raise it */
2768            PyErr_Restore(et, ev, tb);
2769            goto fail;
2770        }
2771
2772        Py_DECREF(et);
2773        Py_XDECREF(tb);
2774        Py_XDECREF(ev);
2775
2776        Py_RETURN_NONE;
2777    }
2778
2779    if (result == (PyObject*)task) {
2780        /* We have a task that wants to await on itself */
2781        goto self_await;
2782    }
2783
2784    /* Check if `result` is FutureObj or TaskObj (and not a subclass) */
2785    if (Future_CheckExact(result) || Task_CheckExact(result)) {
2786        PyObject *wrapper;
2787        PyObject *tmp;
2788        FutureObj *fut = (FutureObj*)result;
2789
2790        /* Check if `result` future is attached to a different loop */
2791        if (fut->fut_loop != task->task_loop) {
2792            goto different_loop;
2793        }
2794
2795        if (!fut->fut_blocking) {
2796            goto yield_insteadof_yf;
2797        }
2798
2799        fut->fut_blocking = 0;
2800
2801        /* result.add_done_callback(task._wakeup) */
2802        wrapper = PyCFunction_New(&TaskWakeupDef, (PyObject *)task);
2803        if (wrapper == NULL) {
2804            goto fail;
2805        }
2806        tmp = future_add_done_callback(
2807            (FutureObj*)result, wrapper, task->task_context);
2808        Py_DECREF(wrapper);
2809        if (tmp == NULL) {
2810            goto fail;
2811        }
2812        Py_DECREF(tmp);
2813
2814        /* task._fut_waiter = result */
2815        task->task_fut_waiter = result;  /* no incref is necessary */
2816
2817        if (task->task_must_cancel) {
2818            PyObject *r;
2819            int is_true;
2820            r = _PyObject_CallMethodIdOneArg(result, &PyId_cancel,
2821                                             task->task_cancel_msg);
2822            if (r == NULL) {
2823                return NULL;
2824            }
2825            is_true = PyObject_IsTrue(r);
2826            Py_DECREF(r);
2827            if (is_true < 0) {
2828                return NULL;
2829            }
2830            else if (is_true) {
2831                task->task_must_cancel = 0;
2832            }
2833        }
2834
2835        Py_RETURN_NONE;
2836    }
2837
2838    /* Check if `result` is None */
2839    if (result == Py_None) {
2840        /* Bare yield relinquishes control for one event loop iteration. */
2841        if (task_call_step_soon(task, NULL)) {
2842            goto fail;
2843        }
2844        return result;
2845    }
2846
2847    /* Check if `result` is a Future-compatible object */
2848    if (_PyObject_LookupAttrId(result, &PyId__asyncio_future_blocking, &o) < 0) {
2849        goto fail;
2850    }
2851    if (o != NULL && o != Py_None) {
2852        /* `result` is a Future-compatible object */
2853        PyObject *wrapper;
2854        PyObject *tmp;
2855
2856        int blocking = PyObject_IsTrue(o);
2857        Py_DECREF(o);
2858        if (blocking < 0) {
2859            goto fail;
2860        }
2861
2862        /* Check if `result` future is attached to a different loop */
2863        PyObject *oloop = get_future_loop(result);
2864        if (oloop == NULL) {
2865            goto fail;
2866        }
2867        if (oloop != task->task_loop) {
2868            Py_DECREF(oloop);
2869            goto different_loop;
2870        }
2871        Py_DECREF(oloop);
2872
2873        if (!blocking) {
2874            goto yield_insteadof_yf;
2875        }
2876
2877        /* result._asyncio_future_blocking = False */
2878        if (_PyObject_SetAttrId(
2879                result, &PyId__asyncio_future_blocking, Py_False) == -1) {
2880            goto fail;
2881        }
2882
2883        wrapper = PyCFunction_New(&TaskWakeupDef, (PyObject *)task);
2884        if (wrapper == NULL) {
2885            goto fail;
2886        }
2887
2888        /* result.add_done_callback(task._wakeup) */
2889        PyObject *add_cb = _PyObject_GetAttrId(
2890            result, &PyId_add_done_callback);
2891        if (add_cb == NULL) {
2892            Py_DECREF(wrapper);
2893            goto fail;
2894        }
2895        PyObject *stack[2];
2896        stack[0] = wrapper;
2897        stack[1] = (PyObject *)task->task_context;
2898        tmp = PyObject_Vectorcall(add_cb, stack, 1, context_kwname);
2899        Py_DECREF(add_cb);
2900        Py_DECREF(wrapper);
2901        if (tmp == NULL) {
2902            goto fail;
2903        }
2904        Py_DECREF(tmp);
2905
2906        /* task._fut_waiter = result */
2907        task->task_fut_waiter = result;  /* no incref is necessary */
2908
2909        if (task->task_must_cancel) {
2910            PyObject *r;
2911            int is_true;
2912            r = _PyObject_CallMethodIdOneArg(result, &PyId_cancel,
2913                                             task->task_cancel_msg);
2914            if (r == NULL) {
2915                return NULL;
2916            }
2917            is_true = PyObject_IsTrue(r);
2918            Py_DECREF(r);
2919            if (is_true < 0) {
2920                return NULL;
2921            }
2922            else if (is_true) {
2923                task->task_must_cancel = 0;
2924            }
2925        }
2926
2927        Py_RETURN_NONE;
2928    }
2929
2930    Py_XDECREF(o);
2931    /* Check if `result` is a generator */
2932    res = PyObject_IsInstance(result, (PyObject*)&PyGen_Type);
2933    if (res < 0) {
2934        goto fail;
2935    }
2936    if (res) {
2937        /* `result` is a generator */
2938        o = task_set_error_soon(
2939            task, PyExc_RuntimeError,
2940            "yield was used instead of yield from for "
2941            "generator in task %R with %R", task, result);
2942        Py_DECREF(result);
2943        return o;
2944    }
2945
2946    /* The `result` is none of the above */
2947    o = task_set_error_soon(
2948        task, PyExc_RuntimeError, "Task got bad yield: %R", result);
2949    Py_DECREF(result);
2950    return o;
2951
2952self_await:
2953    o = task_set_error_soon(
2954        task, PyExc_RuntimeError,
2955        "Task cannot await on itself: %R", task);
2956    Py_DECREF(result);
2957    return o;
2958
2959yield_insteadof_yf:
2960    o = task_set_error_soon(
2961        task, PyExc_RuntimeError,
2962        "yield was used instead of yield from "
2963        "in task %R with %R",
2964        task, result);
2965    Py_DECREF(result);
2966    return o;
2967
2968different_loop:
2969    o = task_set_error_soon(
2970        task, PyExc_RuntimeError,
2971        "Task %R got Future %R attached to a different loop",
2972        task, result);
2973    Py_DECREF(result);
2974    return o;
2975
2976fail:
2977    Py_XDECREF(result);
2978    return NULL;
2979}
2980
2981static PyObject *
2982task_step(TaskObj *task, PyObject *exc)
2983{
2984    PyObject *res;
2985
2986    if (enter_task(task->task_loop, (PyObject*)task) < 0) {
2987        return NULL;
2988    }
2989
2990    res = task_step_impl(task, exc);
2991
2992    if (res == NULL) {
2993        PyObject *et, *ev, *tb;
2994        PyErr_Fetch(&et, &ev, &tb);
2995        leave_task(task->task_loop, (PyObject*)task);
2996        _PyErr_ChainExceptions(et, ev, tb); /* Normalizes (et, ev, tb) */
2997        return NULL;
2998    }
2999    else {
3000        if (leave_task(task->task_loop, (PyObject*)task) < 0) {
3001            Py_DECREF(res);
3002            return NULL;
3003        }
3004        else {
3005            return res;
3006        }
3007    }
3008}
3009
3010static PyObject *
3011task_wakeup(TaskObj *task, PyObject *o)
3012{
3013    PyObject *et, *ev, *tb;
3014    PyObject *result;
3015    assert(o);
3016
3017    if (Future_CheckExact(o) || Task_CheckExact(o)) {
3018        PyObject *fut_result = NULL;
3019        int res = future_get_result((FutureObj*)o, &fut_result);
3020
3021        switch(res) {
3022        case -1:
3023            assert(fut_result == NULL);
3024            break; /* exception raised */
3025        case 0:
3026            Py_DECREF(fut_result);
3027            return task_step(task, NULL);
3028        default:
3029            assert(res == 1);
3030            result = task_step(task, fut_result);
3031            Py_DECREF(fut_result);
3032            return result;
3033        }
3034    }
3035    else {
3036        PyObject *fut_result = PyObject_CallMethod(o, "result", NULL);
3037        if (fut_result != NULL) {
3038            Py_DECREF(fut_result);
3039            return task_step(task, NULL);
3040        }
3041        /* exception raised */
3042    }
3043
3044    PyErr_Fetch(&et, &ev, &tb);
3045    assert(et);
3046    PyErr_NormalizeException(&et, &ev, &tb);
3047    if (tb != NULL) {
3048        PyException_SetTraceback(ev, tb);
3049    }
3050
3051    result = task_step(task, ev);
3052
3053    Py_DECREF(et);
3054    Py_XDECREF(tb);
3055    Py_XDECREF(ev);
3056
3057    return result;
3058}
3059
3060
3061/*********************** Functions **************************/
3062
3063
3064/*[clinic input]
3065_asyncio._get_running_loop
3066
3067Return the running event loop or None.
3068
3069This is a low-level function intended to be used by event loops.
3070This function is thread-specific.
3071
3072[clinic start generated code]*/
3073
3074static PyObject *
3075_asyncio__get_running_loop_impl(PyObject *module)
3076/*[clinic end generated code: output=b4390af721411a0a input=0a21627e25a4bd43]*/
3077{
3078    PyObject *loop;
3079    if (get_running_loop(&loop)) {
3080        return NULL;
3081    }
3082    if (loop == NULL) {
3083        /* There's no currently running event loop */
3084        Py_RETURN_NONE;
3085    }
3086    return loop;
3087}
3088
3089/*[clinic input]
3090_asyncio._set_running_loop
3091    loop: 'O'
3092    /
3093
3094Set the running event loop.
3095
3096This is a low-level function intended to be used by event loops.
3097This function is thread-specific.
3098[clinic start generated code]*/
3099
3100static PyObject *
3101_asyncio__set_running_loop(PyObject *module, PyObject *loop)
3102/*[clinic end generated code: output=ae56bf7a28ca189a input=4c9720233d606604]*/
3103{
3104    if (set_running_loop(loop)) {
3105        return NULL;
3106    }
3107    Py_RETURN_NONE;
3108}
3109
3110/*[clinic input]
3111_asyncio.get_event_loop
3112
3113Return an asyncio event loop.
3114
3115When called from a coroutine or a callback (e.g. scheduled with
3116call_soon or similar API), this function will always return the
3117running event loop.
3118
3119If there is no running event loop set, the function will return
3120the result of `get_event_loop_policy().get_event_loop()` call.
3121[clinic start generated code]*/
3122
3123static PyObject *
3124_asyncio_get_event_loop_impl(PyObject *module)
3125/*[clinic end generated code: output=2a2d8b2f824c648b input=9364bf2916c8655d]*/
3126{
3127    return get_event_loop(1);
3128}
3129
3130// This internal method is going away in Python 3.12, left here only for
3131// backwards compatibility with 3.10.0 - 3.10.8 and 3.11.0.
3132// Similarly, this method's Python equivalent in asyncio.events is going
3133// away as well.
3134// See GH-99949 for more details.
3135/*[clinic input]
3136_asyncio._get_event_loop
3137    stacklevel: int = 3
3138[clinic start generated code]*/
3139
3140static PyObject *
3141_asyncio__get_event_loop_impl(PyObject *module, int stacklevel)
3142/*[clinic end generated code: output=9c1d6d3c802e67c9 input=d17aebbd686f711d]*/
3143{
3144    return get_event_loop(stacklevel-1);
3145}
3146
3147/*[clinic input]
3148_asyncio.get_running_loop
3149
3150Return the running event loop.  Raise a RuntimeError if there is none.
3151
3152This function is thread-specific.
3153[clinic start generated code]*/
3154
3155static PyObject *
3156_asyncio_get_running_loop_impl(PyObject *module)
3157/*[clinic end generated code: output=c247b5f9e529530e input=2a3bf02ba39f173d]*/
3158{
3159    PyObject *loop;
3160    if (get_running_loop(&loop)) {
3161        return NULL;
3162    }
3163    if (loop == NULL) {
3164        /* There's no currently running event loop */
3165        PyErr_SetString(
3166            PyExc_RuntimeError, "no running event loop");
3167    }
3168    return loop;
3169}
3170
3171/*[clinic input]
3172_asyncio._register_task
3173
3174    task: object
3175
3176Register a new task in asyncio as executed by loop.
3177
3178Returns None.
3179[clinic start generated code]*/
3180
3181static PyObject *
3182_asyncio__register_task_impl(PyObject *module, PyObject *task)
3183/*[clinic end generated code: output=8672dadd69a7d4e2 input=21075aaea14dfbad]*/
3184{
3185    if (register_task(task) < 0) {
3186        return NULL;
3187    }
3188    Py_RETURN_NONE;
3189}
3190
3191
3192/*[clinic input]
3193_asyncio._unregister_task
3194
3195    task: object
3196
3197Unregister a task.
3198
3199Returns None.
3200[clinic start generated code]*/
3201
3202static PyObject *
3203_asyncio__unregister_task_impl(PyObject *module, PyObject *task)
3204/*[clinic end generated code: output=6e5585706d568a46 input=28fb98c3975f7bdc]*/
3205{
3206    if (unregister_task(task) < 0) {
3207        return NULL;
3208    }
3209    Py_RETURN_NONE;
3210}
3211
3212
3213/*[clinic input]
3214_asyncio._enter_task
3215
3216    loop: object
3217    task: object
3218
3219Enter into task execution or resume suspended task.
3220
3221Task belongs to loop.
3222
3223Returns None.
3224[clinic start generated code]*/
3225
3226static PyObject *
3227_asyncio__enter_task_impl(PyObject *module, PyObject *loop, PyObject *task)
3228/*[clinic end generated code: output=a22611c858035b73 input=de1b06dca70d8737]*/
3229{
3230    if (enter_task(loop, task) < 0) {
3231        return NULL;
3232    }
3233    Py_RETURN_NONE;
3234}
3235
3236
3237/*[clinic input]
3238_asyncio._leave_task
3239
3240    loop: object
3241    task: object
3242
3243Leave task execution or suspend a task.
3244
3245Task belongs to loop.
3246
3247Returns None.
3248[clinic start generated code]*/
3249
3250static PyObject *
3251_asyncio__leave_task_impl(PyObject *module, PyObject *loop, PyObject *task)
3252/*[clinic end generated code: output=0ebf6db4b858fb41 input=51296a46313d1ad8]*/
3253{
3254    if (leave_task(loop, task) < 0) {
3255        return NULL;
3256    }
3257    Py_RETURN_NONE;
3258}
3259
3260
3261/*********************** PyRunningLoopHolder ********************/
3262
3263
3264static PyRunningLoopHolder *
3265new_running_loop_holder(PyObject *loop)
3266{
3267    PyRunningLoopHolder *rl = PyObject_New(
3268        PyRunningLoopHolder, &PyRunningLoopHolder_Type);
3269    if (rl == NULL) {
3270        return NULL;
3271    }
3272
3273#if defined(HAVE_GETPID) && !defined(MS_WINDOWS)
3274    rl->rl_pid = getpid();
3275#endif
3276
3277    Py_INCREF(loop);
3278    rl->rl_loop = loop;
3279
3280    return rl;
3281}
3282
3283
3284static void
3285PyRunningLoopHolder_tp_dealloc(PyRunningLoopHolder *rl)
3286{
3287    if (cached_running_holder == (PyObject *)rl) {
3288        cached_running_holder = NULL;
3289    }
3290    Py_CLEAR(rl->rl_loop);
3291    PyObject_Free(rl);
3292}
3293
3294
3295static PyTypeObject PyRunningLoopHolder_Type = {
3296    PyVarObject_HEAD_INIT(NULL, 0)
3297    "_RunningLoopHolder",
3298    sizeof(PyRunningLoopHolder),
3299    .tp_getattro = PyObject_GenericGetAttr,
3300    .tp_flags = Py_TPFLAGS_DEFAULT,
3301    .tp_dealloc = (destructor)PyRunningLoopHolder_tp_dealloc,
3302};
3303
3304
3305/*********************** Module **************************/
3306
3307
3308static void
3309module_free_freelists(void)
3310{
3311    PyObject *next;
3312    PyObject *current;
3313
3314    next = (PyObject*) fi_freelist;
3315    while (next != NULL) {
3316        assert(fi_freelist_len > 0);
3317        fi_freelist_len--;
3318
3319        current = next;
3320        next = (PyObject*) ((futureiterobject*) current)->future;
3321        PyObject_GC_Del(current);
3322    }
3323    assert(fi_freelist_len == 0);
3324    fi_freelist = NULL;
3325}
3326
3327
3328static void
3329module_free(void *m)
3330{
3331    Py_CLEAR(asyncio_mod);
3332    Py_CLEAR(traceback_extract_stack);
3333    Py_CLEAR(asyncio_future_repr_func);
3334    Py_CLEAR(asyncio_get_event_loop_policy);
3335    Py_CLEAR(asyncio_iscoroutine_func);
3336    Py_CLEAR(asyncio_task_get_stack_func);
3337    Py_CLEAR(asyncio_task_print_stack_func);
3338    Py_CLEAR(asyncio_task_repr_func);
3339    Py_CLEAR(asyncio_InvalidStateError);
3340    Py_CLEAR(asyncio_CancelledError);
3341
3342    Py_CLEAR(all_tasks);
3343    Py_CLEAR(current_tasks);
3344    Py_CLEAR(iscoroutine_typecache);
3345
3346    Py_CLEAR(context_kwname);
3347
3348    module_free_freelists();
3349
3350    module_initialized = 0;
3351}
3352
3353static int
3354module_init(void)
3355{
3356    PyObject *module = NULL;
3357    if (module_initialized) {
3358        return 0;
3359    }
3360
3361    asyncio_mod = PyImport_ImportModule("asyncio");
3362    if (asyncio_mod == NULL) {
3363        goto fail;
3364    }
3365
3366    current_tasks = PyDict_New();
3367    if (current_tasks == NULL) {
3368        goto fail;
3369    }
3370
3371    iscoroutine_typecache = PySet_New(NULL);
3372    if (iscoroutine_typecache == NULL) {
3373        goto fail;
3374    }
3375
3376
3377    context_kwname = Py_BuildValue("(s)", "context");
3378    if (context_kwname == NULL) {
3379        goto fail;
3380    }
3381
3382#define WITH_MOD(NAME) \
3383    Py_CLEAR(module); \
3384    module = PyImport_ImportModule(NAME); \
3385    if (module == NULL) { \
3386        goto fail; \
3387    }
3388
3389#define GET_MOD_ATTR(VAR, NAME) \
3390    VAR = PyObject_GetAttrString(module, NAME); \
3391    if (VAR == NULL) { \
3392        goto fail; \
3393    }
3394
3395    WITH_MOD("asyncio.events")
3396    GET_MOD_ATTR(asyncio_get_event_loop_policy, "get_event_loop_policy")
3397
3398    WITH_MOD("asyncio.base_futures")
3399    GET_MOD_ATTR(asyncio_future_repr_func, "_future_repr")
3400
3401    WITH_MOD("asyncio.exceptions")
3402    GET_MOD_ATTR(asyncio_InvalidStateError, "InvalidStateError")
3403    GET_MOD_ATTR(asyncio_CancelledError, "CancelledError")
3404
3405    WITH_MOD("asyncio.base_tasks")
3406    GET_MOD_ATTR(asyncio_task_repr_func, "_task_repr")
3407    GET_MOD_ATTR(asyncio_task_get_stack_func, "_task_get_stack")
3408    GET_MOD_ATTR(asyncio_task_print_stack_func, "_task_print_stack")
3409
3410    WITH_MOD("asyncio.coroutines")
3411    GET_MOD_ATTR(asyncio_iscoroutine_func, "iscoroutine")
3412
3413    WITH_MOD("traceback")
3414    GET_MOD_ATTR(traceback_extract_stack, "extract_stack")
3415
3416    PyObject *weak_set;
3417    WITH_MOD("weakref")
3418    GET_MOD_ATTR(weak_set, "WeakSet");
3419    all_tasks = PyObject_CallNoArgs(weak_set);
3420    Py_CLEAR(weak_set);
3421    if (all_tasks == NULL) {
3422        goto fail;
3423    }
3424
3425    module_initialized = 1;
3426    Py_DECREF(module);
3427    return 0;
3428
3429fail:
3430    Py_CLEAR(module);
3431    module_free(NULL);
3432    return -1;
3433
3434#undef WITH_MOD
3435#undef GET_MOD_ATTR
3436}
3437
3438PyDoc_STRVAR(module_doc, "Accelerator module for asyncio");
3439
3440static PyMethodDef asyncio_methods[] = {
3441    _ASYNCIO_GET_EVENT_LOOP_METHODDEF
3442    _ASYNCIO__GET_EVENT_LOOP_METHODDEF
3443    _ASYNCIO_GET_RUNNING_LOOP_METHODDEF
3444    _ASYNCIO__GET_RUNNING_LOOP_METHODDEF
3445    _ASYNCIO__SET_RUNNING_LOOP_METHODDEF
3446    _ASYNCIO__REGISTER_TASK_METHODDEF
3447    _ASYNCIO__UNREGISTER_TASK_METHODDEF
3448    _ASYNCIO__ENTER_TASK_METHODDEF
3449    _ASYNCIO__LEAVE_TASK_METHODDEF
3450    {NULL, NULL}
3451};
3452
3453static struct PyModuleDef _asynciomodule = {
3454    PyModuleDef_HEAD_INIT,      /* m_base */
3455    "_asyncio",                 /* m_name */
3456    module_doc,                 /* m_doc */
3457    -1,                         /* m_size */
3458    asyncio_methods,            /* m_methods */
3459    NULL,                       /* m_slots */
3460    NULL,                       /* m_traverse */
3461    NULL,                       /* m_clear */
3462    (freefunc)module_free       /* m_free */
3463};
3464
3465
3466PyMODINIT_FUNC
3467PyInit__asyncio(void)
3468{
3469    if (module_init() < 0) {
3470        return NULL;
3471    }
3472    if (PyType_Ready(&FutureIterType) < 0) {
3473        return NULL;
3474    }
3475    if (PyType_Ready(&TaskStepMethWrapper_Type) < 0) {
3476        return NULL;
3477    }
3478    if (PyType_Ready(&PyRunningLoopHolder_Type) < 0) {
3479        return NULL;
3480    }
3481
3482    PyObject *m = PyModule_Create(&_asynciomodule);
3483    if (m == NULL) {
3484        return NULL;
3485    }
3486
3487    /* FutureType and TaskType are made ready by PyModule_AddType() calls below. */
3488    if (PyModule_AddType(m, &FutureType) < 0) {
3489        Py_DECREF(m);
3490        return NULL;
3491    }
3492
3493    if (PyModule_AddType(m, &TaskType) < 0) {
3494        Py_DECREF(m);
3495        return NULL;
3496    }
3497
3498    Py_INCREF(all_tasks);
3499    if (PyModule_AddObject(m, "_all_tasks", all_tasks) < 0) {
3500        Py_DECREF(all_tasks);
3501        Py_DECREF(m);
3502        return NULL;
3503    }
3504
3505    Py_INCREF(current_tasks);
3506    if (PyModule_AddObject(m, "_current_tasks", current_tasks) < 0) {
3507        Py_DECREF(current_tasks);
3508        Py_DECREF(m);
3509        return NULL;
3510    }
3511
3512    return m;
3513}
3514