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