blob: 5ba2bc4975709895a0bdb5660be3dd808d486043 [file] [log] [blame]
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001#include "Python.h"
2#include "structmember.h"
3
4
Yury Selivanova0c1ba62016-10-28 12:52:37 -04005/*[clinic input]
6module _asyncio
7[clinic start generated code]*/
8/*[clinic end generated code: output=da39a3ee5e6b4b0d input=8fd17862aa989c69]*/
9
10
INADA Naoki9e4e38e2016-10-09 14:44:47 +090011/* identifiers used from some functions */
Yury Selivanova70232f2017-12-13 14:49:42 -050012_Py_IDENTIFIER(__asyncio_running_event_loop__);
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +030013_Py_IDENTIFIER(_asyncio_future_blocking);
Yury Selivanova0c1ba62016-10-28 12:52:37 -040014_Py_IDENTIFIER(add_done_callback);
Yury Selivanov416c1eb2018-05-28 17:54:02 -040015_Py_IDENTIFIER(_all_tasks_compat);
INADA Naoki9e4e38e2016-10-09 14:44:47 +090016_Py_IDENTIFIER(call_soon);
Yury Selivanova0c1ba62016-10-28 12:52:37 -040017_Py_IDENTIFIER(cancel);
Andrew Svetlov44d1a592017-12-16 21:58:38 +020018_Py_IDENTIFIER(current_task);
Yury Selivanova70232f2017-12-13 14:49:42 -050019_Py_IDENTIFIER(get_event_loop);
Yury Selivanova0c1ba62016-10-28 12:52:37 -040020_Py_IDENTIFIER(send);
21_Py_IDENTIFIER(throw);
INADA Naoki9e4e38e2016-10-09 14:44:47 +090022
23
INADA Naoki9f2ce252016-10-15 15:39:19 +090024/* State of the _asyncio module */
Andrew Svetlov44d1a592017-12-16 21:58:38 +020025static PyObject *asyncio_mod;
Andrew Svetlov44d1a592017-12-16 21:58:38 +020026static PyObject *traceback_extract_stack;
27static PyObject *asyncio_get_event_loop_policy;
28static PyObject *asyncio_future_repr_info_func;
29static PyObject *asyncio_iscoroutine_func;
30static PyObject *asyncio_task_get_stack_func;
31static PyObject *asyncio_task_print_stack_func;
32static PyObject *asyncio_task_repr_info_func;
33static PyObject *asyncio_InvalidStateError;
34static PyObject *asyncio_CancelledError;
Yury Selivanovf23746a2018-01-22 19:11:18 -050035static PyObject *context_kwname;
Miss Islington (bot)13915a32019-10-07 09:38:00 -070036static int module_initialized;
Andrew Svetlov44d1a592017-12-16 21:58:38 +020037
Yury Selivanov9d411c12018-01-23 15:10:03 -050038static PyObject *cached_running_holder;
39static volatile uint64_t cached_running_holder_tsid;
40
Alex Grönholmcca4eec2018-08-09 00:06:47 +030041/* Counter for autogenerated Task names */
42static uint64_t task_name_counter = 0;
Andrew Svetlov44d1a592017-12-16 21:58:38 +020043
Yury Selivanovca9b36c2017-12-23 15:04:15 -050044/* WeakSet containing all alive tasks. */
45static PyObject *all_tasks;
Andrew Svetlov44d1a592017-12-16 21:58:38 +020046
47/* Dictionary containing tasks that are currently active in
48 all running event loops. {EventLoop: Task} */
Yury Selivanovca9b36c2017-12-23 15:04:15 -050049static PyObject *current_tasks;
INADA Naoki9e4e38e2016-10-09 14:44:47 +090050
Yury Selivanova9d7e552017-12-19 07:18:45 -050051/* An isinstance type cache for the 'is_coroutine()' function. */
52static PyObject *iscoroutine_typecache;
53
INADA Naoki9e4e38e2016-10-09 14:44:47 +090054
INADA Naoki9e4e38e2016-10-09 14:44:47 +090055typedef enum {
56 STATE_PENDING,
57 STATE_CANCELLED,
58 STATE_FINISHED
59} fut_state;
60
Yury Selivanova0c1ba62016-10-28 12:52:37 -040061#define FutureObj_HEAD(prefix) \
62 PyObject_HEAD \
63 PyObject *prefix##_loop; \
Yury Selivanov1b7c11f2017-12-17 20:19:47 -050064 PyObject *prefix##_callback0; \
Yury Selivanov994269c2018-09-27 14:55:55 -040065 PyObject *prefix##_context0; \
Yury Selivanova0c1ba62016-10-28 12:52:37 -040066 PyObject *prefix##_callbacks; \
67 PyObject *prefix##_exception; \
68 PyObject *prefix##_result; \
69 PyObject *prefix##_source_tb; \
70 fut_state prefix##_state; \
71 int prefix##_log_tb; \
72 int prefix##_blocking; \
73 PyObject *dict; \
74 PyObject *prefix##_weakreflist;
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;
Alex Grönholmcca4eec2018-08-09 00:06:47 +030084 PyObject *task_name;
Yury Selivanov994269c2018-09-27 14:55:55 -040085 PyObject *task_context;
Yury Selivanova0c1ba62016-10-28 12:52:37 -040086 int task_must_cancel;
87 int task_log_destroy_pending;
88} TaskObj;
INADA Naoki9e4e38e2016-10-09 14:44:47 +090089
90typedef struct {
91 PyObject_HEAD
Yury Selivanova0c1ba62016-10-28 12:52:37 -040092 TaskObj *sw_task;
93 PyObject *sw_arg;
Serhiy Storchakabca49392017-09-03 08:10:14 +030094} TaskStepMethWrapper;
INADA Naoki9e4e38e2016-10-09 14:44:47 +090095
Yury Selivanova0c1ba62016-10-28 12:52:37 -040096typedef struct {
97 PyObject_HEAD
98 TaskObj *ww_task;
99} TaskWakeupMethWrapper;
100
Yury Selivanov9d411c12018-01-23 15:10:03 -0500101typedef struct {
102 PyObject_HEAD
103 PyObject *rl_loop;
104#if defined(HAVE_GETPID) && !defined(MS_WINDOWS)
105 pid_t rl_pid;
106#endif
107} PyRunningLoopHolder;
108
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400109
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500110static PyTypeObject FutureType;
111static PyTypeObject TaskType;
Yury Selivanov9d411c12018-01-23 15:10:03 -0500112static PyTypeObject PyRunningLoopHolder_Type;
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500113
114
115#define Future_CheckExact(obj) (Py_TYPE(obj) == &FutureType)
116#define Task_CheckExact(obj) (Py_TYPE(obj) == &TaskType)
117
118#define Future_Check(obj) PyObject_TypeCheck(obj, &FutureType)
119#define Task_Check(obj) PyObject_TypeCheck(obj, &TaskType)
120
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400121#include "clinic/_asynciomodule.c.h"
122
123
124/*[clinic input]
125class _asyncio.Future "FutureObj *" "&Future_Type"
126[clinic start generated code]*/
127/*[clinic end generated code: output=da39a3ee5e6b4b0d input=00d3e4abca711e0f]*/
128
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500129
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400130/* Get FutureIter from Future */
Yury Selivanov9d411c12018-01-23 15:10:03 -0500131static PyObject * future_new_iter(PyObject *);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900132
Yury Selivanov9d411c12018-01-23 15:10:03 -0500133static PyRunningLoopHolder * new_running_loop_holder(PyObject *);
134
Yury Selivanova70232f2017-12-13 14:49:42 -0500135
136static int
Yury Selivanova9d7e552017-12-19 07:18:45 -0500137_is_coroutine(PyObject *coro)
138{
139 /* 'coro' is not a native coroutine, call asyncio.iscoroutine()
140 to check if it's another coroutine flavour.
141
142 Do this check after 'future_init()'; in case we need to raise
143 an error, __del__ needs a properly initialized object.
144 */
145 PyObject *res = PyObject_CallFunctionObjArgs(
146 asyncio_iscoroutine_func, coro, NULL);
147 if (res == NULL) {
148 return -1;
149 }
150
151 int is_res_true = PyObject_IsTrue(res);
152 Py_DECREF(res);
153 if (is_res_true <= 0) {
154 return is_res_true;
155 }
156
Andrew Svetlov0f47fa22017-12-23 22:06:46 +0200157 if (PySet_GET_SIZE(iscoroutine_typecache) < 100) {
Yury Selivanova9d7e552017-12-19 07:18:45 -0500158 /* Just in case we don't want to cache more than 100
159 positive types. That shouldn't ever happen, unless
160 someone stressing the system on purpose.
161 */
162 if (PySet_Add(iscoroutine_typecache, (PyObject*) Py_TYPE(coro))) {
163 return -1;
164 }
165 }
166
167 return 1;
168}
169
170
171static inline int
172is_coroutine(PyObject *coro)
173{
174 if (PyCoro_CheckExact(coro)) {
175 return 1;
176 }
177
178 /* Check if `type(coro)` is in the cache.
179 Caching makes is_coroutine() function almost as fast as
180 PyCoro_CheckExact() for non-native coroutine-like objects
181 (like coroutines compiled with Cython).
182
183 asyncio.iscoroutine() has its own type caching mechanism.
184 This cache allows us to avoid the cost of even calling
185 a pure-Python function in 99.9% cases.
186 */
187 int has_it = PySet_Contains(
188 iscoroutine_typecache, (PyObject*) Py_TYPE(coro));
189 if (has_it == 0) {
190 /* type(coro) is not in iscoroutine_typecache */
191 return _is_coroutine(coro);
192 }
193
Leo Ariasc3d95082018-02-03 18:36:10 -0600194 /* either an error has occurred or
Yury Selivanova9d7e552017-12-19 07:18:45 -0500195 type(coro) is in iscoroutine_typecache
196 */
197 return has_it;
198}
199
200
Yury Selivanovca9b36c2017-12-23 15:04:15 -0500201static PyObject *
202get_future_loop(PyObject *fut)
203{
204 /* Implementation of `asyncio.futures._get_loop` */
205
206 _Py_IDENTIFIER(get_loop);
207 _Py_IDENTIFIER(_loop);
Serhiy Storchaka66553542018-05-20 16:30:31 +0300208 PyObject *getloop;
Yury Selivanovca9b36c2017-12-23 15:04:15 -0500209
210 if (Future_CheckExact(fut) || Task_CheckExact(fut)) {
211 PyObject *loop = ((FutureObj *)fut)->fut_loop;
212 Py_INCREF(loop);
213 return loop;
214 }
215
Serhiy Storchaka66553542018-05-20 16:30:31 +0300216 if (_PyObject_LookupAttrId(fut, &PyId_get_loop, &getloop) < 0) {
217 return NULL;
218 }
Yury Selivanovca9b36c2017-12-23 15:04:15 -0500219 if (getloop != NULL) {
220 PyObject *res = _PyObject_CallNoArg(getloop);
221 Py_DECREF(getloop);
222 return res;
223 }
224
225 return _PyObject_GetAttrId(fut, &PyId__loop);
226}
227
228
Yury Selivanova9d7e552017-12-19 07:18:45 -0500229static int
Yury Selivanova70232f2017-12-13 14:49:42 -0500230get_running_loop(PyObject **loop)
231{
Yury Selivanov9d411c12018-01-23 15:10:03 -0500232 PyObject *rl;
Yury Selivanova70232f2017-12-13 14:49:42 -0500233
Yury Selivanov9d411c12018-01-23 15:10:03 -0500234 PyThreadState *ts = PyThreadState_Get();
235 if (ts->id == cached_running_holder_tsid && cached_running_holder != NULL) {
236 // Fast path, check the cache.
237 rl = cached_running_holder; // borrowed
238 }
239 else {
240 if (ts->dict == NULL) {
241 goto not_found;
242 }
243
244 rl = _PyDict_GetItemIdWithError(
245 ts->dict, &PyId___asyncio_running_event_loop__); // borrowed
246 if (rl == NULL) {
247 if (PyErr_Occurred()) {
248 goto error;
249 }
250 else {
251 goto not_found;
252 }
253 }
254
255 cached_running_holder = rl; // borrowed
256 cached_running_holder_tsid = ts->id;
Yury Selivanova70232f2017-12-13 14:49:42 -0500257 }
258
Yury Selivanov9d411c12018-01-23 15:10:03 -0500259 assert(Py_TYPE(rl) == &PyRunningLoopHolder_Type);
260 PyObject *running_loop = ((PyRunningLoopHolder *)rl)->rl_loop;
Yury Selivanova70232f2017-12-13 14:49:42 -0500261
262 if (running_loop == Py_None) {
263 goto not_found;
264 }
265
Yury Selivanov9d411c12018-01-23 15:10:03 -0500266#if defined(HAVE_GETPID) && !defined(MS_WINDOWS)
267 /* On Windows there is no getpid, but there is also no os.fork(),
268 so there is no need for this check.
269 */
270 if (getpid() != ((PyRunningLoopHolder *)rl)->rl_pid) {
271 goto not_found;
Yury Selivanova70232f2017-12-13 14:49:42 -0500272 }
Yury Selivanov9d411c12018-01-23 15:10:03 -0500273#endif
Yury Selivanova70232f2017-12-13 14:49:42 -0500274
Yury Selivanov9d411c12018-01-23 15:10:03 -0500275 Py_INCREF(running_loop);
276 *loop = running_loop;
277 return 0;
Yury Selivanova70232f2017-12-13 14:49:42 -0500278
279not_found:
280 *loop = NULL;
281 return 0;
282
Yury Selivanova70232f2017-12-13 14:49:42 -0500283error:
284 *loop = NULL;
285 return -1;
286}
287
288
289static int
290set_running_loop(PyObject *loop)
291{
Yury Selivanov9d411c12018-01-23 15:10:03 -0500292 cached_running_holder = NULL;
293 cached_running_holder_tsid = 0;
Yury Selivanova70232f2017-12-13 14:49:42 -0500294
Yury Selivanov9d411c12018-01-23 15:10:03 -0500295 PyObject *ts_dict = PyThreadState_GetDict(); // borrowed
Yury Selivanova70232f2017-12-13 14:49:42 -0500296 if (ts_dict == NULL) {
297 PyErr_SetString(
298 PyExc_RuntimeError, "thread-local storage is not available");
299 return -1;
300 }
301
Yury Selivanov9d411c12018-01-23 15:10:03 -0500302 PyRunningLoopHolder *rl = new_running_loop_holder(loop);
303 if (rl == NULL) {
Yury Selivanova70232f2017-12-13 14:49:42 -0500304 return -1;
305 }
306
Yury Selivanova70232f2017-12-13 14:49:42 -0500307 if (_PyDict_SetItemId(
Yury Selivanov9d411c12018-01-23 15:10:03 -0500308 ts_dict, &PyId___asyncio_running_event_loop__, (PyObject *)rl) < 0)
309 {
310 Py_DECREF(rl); // will cleanup loop & current_pid
Yury Selivanova70232f2017-12-13 14:49:42 -0500311 return -1;
312 }
Yury Selivanov9d411c12018-01-23 15:10:03 -0500313 Py_DECREF(rl);
Yury Selivanova70232f2017-12-13 14:49:42 -0500314
315 return 0;
316}
317
318
319static PyObject *
320get_event_loop(void)
321{
322 PyObject *loop;
323 PyObject *policy;
324
325 if (get_running_loop(&loop)) {
326 return NULL;
327 }
328 if (loop != NULL) {
329 return loop;
330 }
331
332 policy = _PyObject_CallNoArg(asyncio_get_event_loop_policy);
333 if (policy == NULL) {
334 return NULL;
335 }
336
337 loop = _PyObject_CallMethodId(policy, &PyId_get_event_loop, NULL);
338 Py_DECREF(policy);
339 return loop;
340}
341
342
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900343static int
Yury Selivanov994269c2018-09-27 14:55:55 -0400344call_soon(PyObject *loop, PyObject *func, PyObject *arg, PyObject *ctx)
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500345{
346 PyObject *handle;
Yury Selivanovf23746a2018-01-22 19:11:18 -0500347 PyObject *stack[3];
348 Py_ssize_t nargs;
349
350 if (ctx == NULL) {
351 handle = _PyObject_CallMethodIdObjArgs(
352 loop, &PyId_call_soon, func, arg, NULL);
353 }
354 else {
355 /* Use FASTCALL to pass a keyword-only argument to call_soon */
356
357 PyObject *callable = _PyObject_GetAttrId(loop, &PyId_call_soon);
358 if (callable == NULL) {
359 return -1;
360 }
361
362 /* All refs in 'stack' are borrowed. */
363 nargs = 1;
364 stack[0] = func;
365 if (arg != NULL) {
366 stack[1] = arg;
367 nargs++;
368 }
369 stack[nargs] = (PyObject *)ctx;
370
Jeroen Demeyeraacc77f2019-05-29 20:31:52 +0200371 handle = _PyObject_Vectorcall(callable, stack, nargs, context_kwname);
Yury Selivanovf23746a2018-01-22 19:11:18 -0500372 Py_DECREF(callable);
373 }
374
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500375 if (handle == NULL) {
376 return -1;
377 }
378 Py_DECREF(handle);
379 return 0;
380}
381
382
383static inline int
384future_is_alive(FutureObj *fut)
385{
386 return fut->fut_loop != NULL;
387}
388
389
390static inline int
391future_ensure_alive(FutureObj *fut)
392{
393 if (!future_is_alive(fut)) {
394 PyErr_SetString(PyExc_RuntimeError,
395 "Future object is not initialized.");
396 return -1;
397 }
398 return 0;
399}
400
401
402#define ENSURE_FUTURE_ALIVE(fut) \
403 do { \
404 assert(Future_Check(fut) || Task_Check(fut)); \
405 if (future_ensure_alive((FutureObj*)fut)) { \
406 return NULL; \
407 } \
408 } while(0);
409
410
411static int
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400412future_schedule_callbacks(FutureObj *fut)
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900413{
414 Py_ssize_t len;
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500415 Py_ssize_t i;
416
417 if (fut->fut_callback0 != NULL) {
418 /* There's a 1st callback */
419
420 int ret = call_soon(
Yury Selivanovf23746a2018-01-22 19:11:18 -0500421 fut->fut_loop, fut->fut_callback0,
422 (PyObject *)fut, fut->fut_context0);
423
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500424 Py_CLEAR(fut->fut_callback0);
Yury Selivanovf23746a2018-01-22 19:11:18 -0500425 Py_CLEAR(fut->fut_context0);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500426 if (ret) {
427 /* If an error occurs in pure-Python implementation,
428 all callbacks are cleared. */
429 Py_CLEAR(fut->fut_callbacks);
430 return ret;
431 }
432
433 /* we called the first callback, now try calling
434 callbacks from the 'fut_callbacks' list. */
435 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900436
437 if (fut->fut_callbacks == NULL) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500438 /* No more callbacks, return. */
439 return 0;
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900440 }
441
442 len = PyList_GET_SIZE(fut->fut_callbacks);
443 if (len == 0) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500444 /* The list of callbacks was empty; clear it and return. */
445 Py_CLEAR(fut->fut_callbacks);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900446 return 0;
447 }
448
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900449 for (i = 0; i < len; i++) {
Yury Selivanovf23746a2018-01-22 19:11:18 -0500450 PyObject *cb_tup = PyList_GET_ITEM(fut->fut_callbacks, i);
451 PyObject *cb = PyTuple_GET_ITEM(cb_tup, 0);
452 PyObject *ctx = PyTuple_GET_ITEM(cb_tup, 1);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900453
Yury Selivanov994269c2018-09-27 14:55:55 -0400454 if (call_soon(fut->fut_loop, cb, (PyObject *)fut, ctx)) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500455 /* If an error occurs in pure-Python implementation,
456 all callbacks are cleared. */
457 Py_CLEAR(fut->fut_callbacks);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900458 return -1;
459 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900460 }
461
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500462 Py_CLEAR(fut->fut_callbacks);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900463 return 0;
464}
465
Oren Milmand019bc82018-02-13 12:28:33 +0200466
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900467static int
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400468future_init(FutureObj *fut, PyObject *loop)
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900469{
Serhiy Storchakabca49392017-09-03 08:10:14 +0300470 PyObject *res;
471 int is_true;
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900472 _Py_IDENTIFIER(get_debug);
473
Oren Milmand019bc82018-02-13 12:28:33 +0200474 // Same to FutureObj_clear() but not clearing fut->dict
475 Py_CLEAR(fut->fut_loop);
476 Py_CLEAR(fut->fut_callback0);
477 Py_CLEAR(fut->fut_context0);
478 Py_CLEAR(fut->fut_callbacks);
479 Py_CLEAR(fut->fut_result);
480 Py_CLEAR(fut->fut_exception);
481 Py_CLEAR(fut->fut_source_tb);
482
483 fut->fut_state = STATE_PENDING;
484 fut->fut_log_tb = 0;
485 fut->fut_blocking = 0;
486
Serhiy Storchakabca49392017-09-03 08:10:14 +0300487 if (loop == Py_None) {
Yury Selivanova70232f2017-12-13 14:49:42 -0500488 loop = get_event_loop();
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900489 if (loop == NULL) {
490 return -1;
491 }
492 }
493 else {
494 Py_INCREF(loop);
495 }
Oren Milmand019bc82018-02-13 12:28:33 +0200496 fut->fut_loop = loop;
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900497
Victor Stinnerf94d1ee2016-10-29 09:05:39 +0200498 res = _PyObject_CallMethodId(fut->fut_loop, &PyId_get_debug, NULL);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900499 if (res == NULL) {
500 return -1;
501 }
Serhiy Storchakabca49392017-09-03 08:10:14 +0300502 is_true = PyObject_IsTrue(res);
503 Py_DECREF(res);
504 if (is_true < 0) {
505 return -1;
506 }
Yury Selivanov35230d02018-05-28 11:11:31 -0400507 if (is_true && !_Py_IsFinalizing()) {
508 /* Only try to capture the traceback if the interpreter is not being
509 finalized. The original motivation to add a `_Py_IsFinalizing()`
510 call was to prevent SIGSEGV when a Future is created in a __del__
511 method, which is called during the interpreter shutdown and the
512 traceback module is already unloaded.
513 */
Oren Milmand019bc82018-02-13 12:28:33 +0200514 fut->fut_source_tb = _PyObject_CallNoArg(traceback_extract_stack);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900515 if (fut->fut_source_tb == NULL) {
516 return -1;
517 }
518 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900519
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900520 return 0;
521}
522
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900523static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400524future_set_result(FutureObj *fut, PyObject *res)
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900525{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500526 if (future_ensure_alive(fut)) {
527 return NULL;
528 }
529
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900530 if (fut->fut_state != STATE_PENDING) {
531 PyErr_SetString(asyncio_InvalidStateError, "invalid state");
532 return NULL;
533 }
534
Serhiy Storchakabca49392017-09-03 08:10:14 +0300535 assert(!fut->fut_result);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900536 Py_INCREF(res);
537 fut->fut_result = res;
538 fut->fut_state = STATE_FINISHED;
539
Yury Selivanov22feeb82018-01-24 11:31:01 -0500540 if (future_schedule_callbacks(fut) == -1) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900541 return NULL;
542 }
543 Py_RETURN_NONE;
544}
545
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900546static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400547future_set_exception(FutureObj *fut, PyObject *exc)
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900548{
549 PyObject *exc_val = NULL;
550
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900551 if (fut->fut_state != STATE_PENDING) {
552 PyErr_SetString(asyncio_InvalidStateError, "invalid state");
553 return NULL;
554 }
555
556 if (PyExceptionClass_Check(exc)) {
Victor Stinnera5ed5f02016-12-06 18:45:50 +0100557 exc_val = _PyObject_CallNoArg(exc);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900558 if (exc_val == NULL) {
559 return NULL;
560 }
Serhiy Storchakabca49392017-09-03 08:10:14 +0300561 if (fut->fut_state != STATE_PENDING) {
562 Py_DECREF(exc_val);
563 PyErr_SetString(asyncio_InvalidStateError, "invalid state");
564 return NULL;
565 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900566 }
567 else {
568 exc_val = exc;
569 Py_INCREF(exc_val);
570 }
571 if (!PyExceptionInstance_Check(exc_val)) {
572 Py_DECREF(exc_val);
573 PyErr_SetString(PyExc_TypeError, "invalid exception object");
574 return NULL;
575 }
576 if ((PyObject*)Py_TYPE(exc_val) == PyExc_StopIteration) {
577 Py_DECREF(exc_val);
578 PyErr_SetString(PyExc_TypeError,
579 "StopIteration interacts badly with generators "
580 "and cannot be raised into a Future");
581 return NULL;
582 }
583
Serhiy Storchakabca49392017-09-03 08:10:14 +0300584 assert(!fut->fut_exception);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900585 fut->fut_exception = exc_val;
586 fut->fut_state = STATE_FINISHED;
587
Yury Selivanov22feeb82018-01-24 11:31:01 -0500588 if (future_schedule_callbacks(fut) == -1) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900589 return NULL;
590 }
591
592 fut->fut_log_tb = 1;
593 Py_RETURN_NONE;
594}
595
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400596static int
597future_get_result(FutureObj *fut, PyObject **result)
598{
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400599 if (fut->fut_state == STATE_CANCELLED) {
Serhiy Storchakabca49392017-09-03 08:10:14 +0300600 PyErr_SetNone(asyncio_CancelledError);
601 return -1;
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400602 }
603
604 if (fut->fut_state != STATE_FINISHED) {
Serhiy Storchakabca49392017-09-03 08:10:14 +0300605 PyErr_SetString(asyncio_InvalidStateError, "Result is not set.");
606 return -1;
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400607 }
608
609 fut->fut_log_tb = 0;
610 if (fut->fut_exception != NULL) {
611 Py_INCREF(fut->fut_exception);
612 *result = fut->fut_exception;
613 return 1;
614 }
615
616 Py_INCREF(fut->fut_result);
617 *result = fut->fut_result;
618 return 0;
619}
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900620
621static PyObject *
Yury Selivanov994269c2018-09-27 14:55:55 -0400622future_add_done_callback(FutureObj *fut, PyObject *arg, PyObject *ctx)
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900623{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500624 if (!future_is_alive(fut)) {
625 PyErr_SetString(PyExc_RuntimeError, "uninitialized Future object");
626 return NULL;
627 }
628
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900629 if (fut->fut_state != STATE_PENDING) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500630 /* The future is done/cancelled, so schedule the callback
631 right away. */
Yury Selivanovf23746a2018-01-22 19:11:18 -0500632 if (call_soon(fut->fut_loop, arg, (PyObject*) fut, ctx)) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900633 return NULL;
634 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900635 }
636 else {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500637 /* The future is pending, add a callback.
638
639 Callbacks in the future object are stored as follows:
640
641 callback0 -- a pointer to the first callback
642 callbacks -- a list of 2nd, 3rd, ... callbacks
643
644 Invariants:
645
646 * callbacks != NULL:
647 There are some callbacks in in the list. Just
648 add the new callback to it.
649
650 * callbacks == NULL and callback0 == NULL:
651 This is the first callback. Set it to callback0.
652
653 * callbacks == NULL and callback0 != NULL:
654 This is a second callback. Initialize callbacks
655 with a new list and add the new callback to it.
656 */
657
Yury Selivanovf23746a2018-01-22 19:11:18 -0500658 if (fut->fut_callbacks == NULL && fut->fut_callback0 == NULL) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500659 Py_INCREF(arg);
660 fut->fut_callback0 = arg;
Yury Selivanovf23746a2018-01-22 19:11:18 -0500661 Py_INCREF(ctx);
662 fut->fut_context0 = ctx;
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500663 }
664 else {
Yury Selivanovf23746a2018-01-22 19:11:18 -0500665 PyObject *tup = PyTuple_New(2);
666 if (tup == NULL) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500667 return NULL;
668 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500669 Py_INCREF(arg);
Yury Selivanovf23746a2018-01-22 19:11:18 -0500670 PyTuple_SET_ITEM(tup, 0, arg);
671 Py_INCREF(ctx);
672 PyTuple_SET_ITEM(tup, 1, (PyObject *)ctx);
673
674 if (fut->fut_callbacks != NULL) {
675 int err = PyList_Append(fut->fut_callbacks, tup);
676 if (err) {
677 Py_DECREF(tup);
678 return NULL;
679 }
680 Py_DECREF(tup);
681 }
682 else {
683 fut->fut_callbacks = PyList_New(1);
684 if (fut->fut_callbacks == NULL) {
685 return NULL;
686 }
687
688 PyList_SET_ITEM(fut->fut_callbacks, 0, tup); /* borrow */
689 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900690 }
691 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500692
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900693 Py_RETURN_NONE;
694}
695
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400696static PyObject *
697future_cancel(FutureObj *fut)
698{
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +0000699 fut->fut_log_tb = 0;
700
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400701 if (fut->fut_state != STATE_PENDING) {
702 Py_RETURN_FALSE;
703 }
704 fut->fut_state = STATE_CANCELLED;
705
Yury Selivanov22feeb82018-01-24 11:31:01 -0500706 if (future_schedule_callbacks(fut) == -1) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400707 return NULL;
708 }
709
710 Py_RETURN_TRUE;
711}
712
713/*[clinic input]
714_asyncio.Future.__init__
715
716 *
Serhiy Storchakabca49392017-09-03 08:10:14 +0300717 loop: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400718
719This class is *almost* compatible with concurrent.futures.Future.
720
721 Differences:
722
723 - result() and exception() do not take a timeout argument and
724 raise an exception when the future isn't done yet.
725
726 - Callbacks registered with add_done_callback() are always called
727 via the event loop's call_soon_threadsafe().
728
729 - This class is not compatible with the wait() and as_completed()
730 methods in the concurrent.futures package.
731[clinic start generated code]*/
732
733static int
734_asyncio_Future___init___impl(FutureObj *self, PyObject *loop)
Serhiy Storchakabca49392017-09-03 08:10:14 +0300735/*[clinic end generated code: output=9ed75799eaccb5d6 input=89af317082bc0bf8]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400736
737{
738 return future_init(self, loop);
739}
740
741static int
742FutureObj_clear(FutureObj *fut)
743{
744 Py_CLEAR(fut->fut_loop);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500745 Py_CLEAR(fut->fut_callback0);
Yury Selivanovf23746a2018-01-22 19:11:18 -0500746 Py_CLEAR(fut->fut_context0);
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400747 Py_CLEAR(fut->fut_callbacks);
748 Py_CLEAR(fut->fut_result);
749 Py_CLEAR(fut->fut_exception);
750 Py_CLEAR(fut->fut_source_tb);
751 Py_CLEAR(fut->dict);
752 return 0;
753}
754
755static int
756FutureObj_traverse(FutureObj *fut, visitproc visit, void *arg)
757{
758 Py_VISIT(fut->fut_loop);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500759 Py_VISIT(fut->fut_callback0);
Yury Selivanovf23746a2018-01-22 19:11:18 -0500760 Py_VISIT(fut->fut_context0);
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400761 Py_VISIT(fut->fut_callbacks);
762 Py_VISIT(fut->fut_result);
763 Py_VISIT(fut->fut_exception);
764 Py_VISIT(fut->fut_source_tb);
765 Py_VISIT(fut->dict);
766 return 0;
767}
768
769/*[clinic input]
770_asyncio.Future.result
771
772Return the result this future represents.
773
774If the future has been cancelled, raises CancelledError. If the
775future's result isn't yet available, raises InvalidStateError. If
776the future is done and has an exception set, this exception is raised.
777[clinic start generated code]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900778
779static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400780_asyncio_Future_result_impl(FutureObj *self)
781/*[clinic end generated code: output=f35f940936a4b1e5 input=49ecf9cf5ec50dc5]*/
782{
783 PyObject *result;
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500784
785 if (!future_is_alive(self)) {
786 PyErr_SetString(asyncio_InvalidStateError,
787 "Future object is not initialized.");
788 return NULL;
789 }
790
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400791 int res = future_get_result(self, &result);
792
793 if (res == -1) {
794 return NULL;
795 }
796
797 if (res == 0) {
798 return result;
799 }
800
801 assert(res == 1);
802
803 PyErr_SetObject(PyExceptionInstance_Class(result), result);
804 Py_DECREF(result);
805 return NULL;
806}
807
808/*[clinic input]
809_asyncio.Future.exception
810
811Return the exception that was set on this future.
812
813The exception (or None if no exception was set) is returned only if
814the future is done. If the future has been cancelled, raises
815CancelledError. If the future isn't done yet, raises
816InvalidStateError.
817[clinic start generated code]*/
818
819static PyObject *
820_asyncio_Future_exception_impl(FutureObj *self)
821/*[clinic end generated code: output=88b20d4f855e0710 input=733547a70c841c68]*/
822{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500823 if (!future_is_alive(self)) {
824 PyErr_SetString(asyncio_InvalidStateError,
825 "Future object is not initialized.");
826 return NULL;
827 }
828
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400829 if (self->fut_state == STATE_CANCELLED) {
Serhiy Storchakabca49392017-09-03 08:10:14 +0300830 PyErr_SetNone(asyncio_CancelledError);
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400831 return NULL;
832 }
833
834 if (self->fut_state != STATE_FINISHED) {
Serhiy Storchakabca49392017-09-03 08:10:14 +0300835 PyErr_SetString(asyncio_InvalidStateError, "Exception is not set.");
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400836 return NULL;
837 }
838
839 if (self->fut_exception != NULL) {
840 self->fut_log_tb = 0;
841 Py_INCREF(self->fut_exception);
842 return self->fut_exception;
843 }
844
845 Py_RETURN_NONE;
846}
847
848/*[clinic input]
849_asyncio.Future.set_result
850
Yury Selivanov0cf16f92017-12-25 10:48:15 -0500851 result: object
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400852 /
853
854Mark the future done and set its result.
855
856If the future is already done when this method is called, raises
857InvalidStateError.
858[clinic start generated code]*/
859
860static PyObject *
Yury Selivanov0cf16f92017-12-25 10:48:15 -0500861_asyncio_Future_set_result(FutureObj *self, PyObject *result)
862/*[clinic end generated code: output=1ec2e6bcccd6f2ce input=8b75172c2a7b05f1]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400863{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500864 ENSURE_FUTURE_ALIVE(self)
Yury Selivanov0cf16f92017-12-25 10:48:15 -0500865 return future_set_result(self, result);
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400866}
867
868/*[clinic input]
869_asyncio.Future.set_exception
870
Serhiy Storchakabca49392017-09-03 08:10:14 +0300871 exception: object
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400872 /
873
874Mark the future done and set an exception.
875
876If the future is already done when this method is called, raises
877InvalidStateError.
878[clinic start generated code]*/
879
880static PyObject *
881_asyncio_Future_set_exception(FutureObj *self, PyObject *exception)
Serhiy Storchakabca49392017-09-03 08:10:14 +0300882/*[clinic end generated code: output=f1c1b0cd321be360 input=e45b7d7aa71cc66d]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400883{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500884 ENSURE_FUTURE_ALIVE(self)
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400885 return future_set_exception(self, exception);
886}
887
888/*[clinic input]
889_asyncio.Future.add_done_callback
890
Serhiy Storchakabca49392017-09-03 08:10:14 +0300891 fn: object
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400892 /
Yury Selivanovf23746a2018-01-22 19:11:18 -0500893 *
894 context: object = NULL
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400895
896Add a callback to be run when the future becomes done.
897
898The callback is called with a single argument - the future object. If
899the future is already done when this is called, the callback is
900scheduled with call_soon.
901[clinic start generated code]*/
902
903static PyObject *
Yury Selivanovf23746a2018-01-22 19:11:18 -0500904_asyncio_Future_add_done_callback_impl(FutureObj *self, PyObject *fn,
905 PyObject *context)
906/*[clinic end generated code: output=7ce635bbc9554c1e input=15ab0693a96e9533]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400907{
Yury Selivanovf23746a2018-01-22 19:11:18 -0500908 if (context == NULL) {
Yury Selivanov994269c2018-09-27 14:55:55 -0400909 context = PyContext_CopyCurrent();
Yury Selivanovf23746a2018-01-22 19:11:18 -0500910 if (context == NULL) {
911 return NULL;
912 }
Yury Selivanov994269c2018-09-27 14:55:55 -0400913 PyObject *res = future_add_done_callback(self, fn, context);
Yury Selivanovf23746a2018-01-22 19:11:18 -0500914 Py_DECREF(context);
915 return res;
916 }
Yury Selivanov994269c2018-09-27 14:55:55 -0400917 return future_add_done_callback(self, fn, context);
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400918}
919
920/*[clinic input]
921_asyncio.Future.remove_done_callback
922
Serhiy Storchakabca49392017-09-03 08:10:14 +0300923 fn: object
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400924 /
925
926Remove all instances of a callback from the "call when done" list.
927
928Returns the number of callbacks removed.
929[clinic start generated code]*/
930
931static PyObject *
932_asyncio_Future_remove_done_callback(FutureObj *self, PyObject *fn)
Serhiy Storchakabca49392017-09-03 08:10:14 +0300933/*[clinic end generated code: output=5ab1fb52b24ef31f input=0a43280a149d505b]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900934{
935 PyObject *newlist;
936 Py_ssize_t len, i, j=0;
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500937 Py_ssize_t cleared_callback0 = 0;
938
939 ENSURE_FUTURE_ALIVE(self)
940
941 if (self->fut_callback0 != NULL) {
942 int cmp = PyObject_RichCompareBool(fn, self->fut_callback0, Py_EQ);
943 if (cmp == -1) {
944 return NULL;
945 }
946 if (cmp == 1) {
947 /* callback0 == fn */
948 Py_CLEAR(self->fut_callback0);
Yury Selivanovf23746a2018-01-22 19:11:18 -0500949 Py_CLEAR(self->fut_context0);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500950 cleared_callback0 = 1;
951 }
952 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900953
Serhiy Storchakabca49392017-09-03 08:10:14 +0300954 if (self->fut_callbacks == NULL) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500955 return PyLong_FromSsize_t(cleared_callback0);
Serhiy Storchakabca49392017-09-03 08:10:14 +0300956 }
957
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400958 len = PyList_GET_SIZE(self->fut_callbacks);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900959 if (len == 0) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500960 Py_CLEAR(self->fut_callbacks);
961 return PyLong_FromSsize_t(cleared_callback0);
962 }
963
964 if (len == 1) {
Yury Selivanovf23746a2018-01-22 19:11:18 -0500965 PyObject *cb_tup = PyList_GET_ITEM(self->fut_callbacks, 0);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500966 int cmp = PyObject_RichCompareBool(
Yury Selivanovf23746a2018-01-22 19:11:18 -0500967 fn, PyTuple_GET_ITEM(cb_tup, 0), Py_EQ);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500968 if (cmp == -1) {
969 return NULL;
970 }
971 if (cmp == 1) {
972 /* callbacks[0] == fn */
973 Py_CLEAR(self->fut_callbacks);
974 return PyLong_FromSsize_t(1 + cleared_callback0);
975 }
976 /* callbacks[0] != fn and len(callbacks) == 1 */
977 return PyLong_FromSsize_t(cleared_callback0);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900978 }
979
980 newlist = PyList_New(len);
981 if (newlist == NULL) {
982 return NULL;
983 }
984
Yury Selivanov84af9032017-03-02 23:46:56 -0500985 for (i = 0; i < PyList_GET_SIZE(self->fut_callbacks); i++) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900986 int ret;
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400987 PyObject *item = PyList_GET_ITEM(self->fut_callbacks, i);
Serhiy Storchakabca49392017-09-03 08:10:14 +0300988 Py_INCREF(item);
Yury Selivanovf23746a2018-01-22 19:11:18 -0500989 ret = PyObject_RichCompareBool(fn, PyTuple_GET_ITEM(item, 0), Py_EQ);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900990 if (ret == 0) {
Yury Selivanov833a3b02017-07-05 13:32:03 -0400991 if (j < len) {
Yury Selivanov833a3b02017-07-05 13:32:03 -0400992 PyList_SET_ITEM(newlist, j, item);
993 j++;
Serhiy Storchakabca49392017-09-03 08:10:14 +0300994 continue;
Yury Selivanov833a3b02017-07-05 13:32:03 -0400995 }
Serhiy Storchakabca49392017-09-03 08:10:14 +0300996 ret = PyList_Append(newlist, item);
997 }
998 Py_DECREF(item);
999 if (ret < 0) {
1000 goto fail;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001001 }
1002 }
1003
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001004 if (j == 0) {
1005 Py_CLEAR(self->fut_callbacks);
1006 Py_DECREF(newlist);
1007 return PyLong_FromSsize_t(len + cleared_callback0);
1008 }
1009
Serhiy Storchakabca49392017-09-03 08:10:14 +03001010 if (j < len) {
1011 Py_SIZE(newlist) = j;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001012 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03001013 j = PyList_GET_SIZE(newlist);
1014 len = PyList_GET_SIZE(self->fut_callbacks);
1015 if (j != len) {
1016 if (PyList_SetSlice(self->fut_callbacks, 0, len, newlist) < 0) {
1017 goto fail;
1018 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001019 }
1020 Py_DECREF(newlist);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001021 return PyLong_FromSsize_t(len - j + cleared_callback0);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001022
1023fail:
1024 Py_DECREF(newlist);
1025 return NULL;
1026}
1027
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001028/*[clinic input]
1029_asyncio.Future.cancel
1030
1031Cancel the future and schedule callbacks.
1032
1033If the future is already done or cancelled, return False. Otherwise,
1034change the future's state to cancelled, schedule the callbacks and
1035return True.
1036[clinic start generated code]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001037
1038static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001039_asyncio_Future_cancel_impl(FutureObj *self)
1040/*[clinic end generated code: output=e45b932ba8bd68a1 input=515709a127995109]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001041{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001042 ENSURE_FUTURE_ALIVE(self)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001043 return future_cancel(self);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001044}
1045
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001046/*[clinic input]
1047_asyncio.Future.cancelled
1048
1049Return True if the future was cancelled.
1050[clinic start generated code]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001051
1052static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001053_asyncio_Future_cancelled_impl(FutureObj *self)
1054/*[clinic end generated code: output=145197ced586357d input=943ab8b7b7b17e45]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001055{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001056 if (future_is_alive(self) && self->fut_state == STATE_CANCELLED) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001057 Py_RETURN_TRUE;
1058 }
1059 else {
1060 Py_RETURN_FALSE;
1061 }
1062}
1063
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001064/*[clinic input]
1065_asyncio.Future.done
1066
1067Return True if the future is done.
1068
1069Done means either that a result / exception are available, or that the
1070future was cancelled.
1071[clinic start generated code]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001072
1073static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001074_asyncio_Future_done_impl(FutureObj *self)
1075/*[clinic end generated code: output=244c5ac351145096 input=28d7b23fdb65d2ac]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001076{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001077 if (!future_is_alive(self) || self->fut_state == STATE_PENDING) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001078 Py_RETURN_FALSE;
1079 }
1080 else {
1081 Py_RETURN_TRUE;
1082 }
1083}
1084
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001085/*[clinic input]
1086_asyncio.Future.get_loop
1087
1088Return the event loop the Future is bound to.
1089[clinic start generated code]*/
1090
1091static PyObject *
1092_asyncio_Future_get_loop_impl(FutureObj *self)
1093/*[clinic end generated code: output=119b6ea0c9816c3f input=cba48c2136c79d1f]*/
1094{
Miss Islington (bot)694c03f2019-11-13 13:54:56 -08001095 ENSURE_FUTURE_ALIVE(self)
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001096 Py_INCREF(self->fut_loop);
1097 return self->fut_loop;
1098}
1099
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001100static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001101FutureObj_get_blocking(FutureObj *fut, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001102{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001103 if (future_is_alive(fut) && fut->fut_blocking) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001104 Py_RETURN_TRUE;
1105 }
1106 else {
1107 Py_RETURN_FALSE;
1108 }
1109}
1110
1111static int
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001112FutureObj_set_blocking(FutureObj *fut, PyObject *val, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001113{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001114 if (future_ensure_alive(fut)) {
1115 return -1;
1116 }
Zackery Spytz842acaa2018-12-17 07:52:45 -07001117 if (val == NULL) {
1118 PyErr_SetString(PyExc_AttributeError, "cannot delete attribute");
1119 return -1;
1120 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001121
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001122 int is_true = PyObject_IsTrue(val);
1123 if (is_true < 0) {
1124 return -1;
1125 }
1126 fut->fut_blocking = is_true;
1127 return 0;
1128}
1129
1130static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001131FutureObj_get_log_traceback(FutureObj *fut, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001132{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001133 ENSURE_FUTURE_ALIVE(fut)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001134 if (fut->fut_log_tb) {
1135 Py_RETURN_TRUE;
1136 }
1137 else {
1138 Py_RETURN_FALSE;
1139 }
1140}
1141
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +00001142static int
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001143FutureObj_set_log_traceback(FutureObj *fut, PyObject *val, void *Py_UNUSED(ignored))
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +00001144{
Zackery Spytz842acaa2018-12-17 07:52:45 -07001145 if (val == NULL) {
1146 PyErr_SetString(PyExc_AttributeError, "cannot delete attribute");
1147 return -1;
1148 }
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +00001149 int is_true = PyObject_IsTrue(val);
1150 if (is_true < 0) {
1151 return -1;
1152 }
Yury Selivanove0aef4f2017-12-25 16:16:10 -05001153 if (is_true) {
1154 PyErr_SetString(PyExc_ValueError,
1155 "_log_traceback can only be set to False");
1156 return -1;
1157 }
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +00001158 fut->fut_log_tb = is_true;
1159 return 0;
1160}
1161
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001162static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001163FutureObj_get_loop(FutureObj *fut, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001164{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001165 if (!future_is_alive(fut)) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001166 Py_RETURN_NONE;
1167 }
1168 Py_INCREF(fut->fut_loop);
1169 return fut->fut_loop;
1170}
1171
1172static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001173FutureObj_get_callbacks(FutureObj *fut, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001174{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001175 Py_ssize_t i;
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001176
1177 ENSURE_FUTURE_ALIVE(fut)
1178
Yury Selivanovf23746a2018-01-22 19:11:18 -05001179 if (fut->fut_callback0 == NULL) {
1180 if (fut->fut_callbacks == NULL) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001181 Py_RETURN_NONE;
1182 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001183
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001184 Py_INCREF(fut->fut_callbacks);
1185 return fut->fut_callbacks;
1186 }
1187
Yury Selivanovf23746a2018-01-22 19:11:18 -05001188 Py_ssize_t len = 1;
1189 if (fut->fut_callbacks != NULL) {
1190 len += PyList_GET_SIZE(fut->fut_callbacks);
1191 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001192
Yury Selivanovf23746a2018-01-22 19:11:18 -05001193
1194 PyObject *new_list = PyList_New(len);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001195 if (new_list == NULL) {
1196 return NULL;
1197 }
1198
Yury Selivanovf23746a2018-01-22 19:11:18 -05001199 PyObject *tup0 = PyTuple_New(2);
1200 if (tup0 == NULL) {
1201 Py_DECREF(new_list);
1202 return NULL;
1203 }
1204
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001205 Py_INCREF(fut->fut_callback0);
Yury Selivanovf23746a2018-01-22 19:11:18 -05001206 PyTuple_SET_ITEM(tup0, 0, fut->fut_callback0);
1207 assert(fut->fut_context0 != NULL);
1208 Py_INCREF(fut->fut_context0);
1209 PyTuple_SET_ITEM(tup0, 1, (PyObject *)fut->fut_context0);
1210
1211 PyList_SET_ITEM(new_list, 0, tup0);
1212
1213 if (fut->fut_callbacks != NULL) {
1214 for (i = 0; i < PyList_GET_SIZE(fut->fut_callbacks); i++) {
1215 PyObject *cb = PyList_GET_ITEM(fut->fut_callbacks, i);
1216 Py_INCREF(cb);
1217 PyList_SET_ITEM(new_list, i + 1, cb);
1218 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001219 }
1220
1221 return new_list;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001222}
1223
1224static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001225FutureObj_get_result(FutureObj *fut, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001226{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001227 ENSURE_FUTURE_ALIVE(fut)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001228 if (fut->fut_result == NULL) {
1229 Py_RETURN_NONE;
1230 }
1231 Py_INCREF(fut->fut_result);
1232 return fut->fut_result;
1233}
1234
1235static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001236FutureObj_get_exception(FutureObj *fut, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001237{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001238 ENSURE_FUTURE_ALIVE(fut)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001239 if (fut->fut_exception == NULL) {
1240 Py_RETURN_NONE;
1241 }
1242 Py_INCREF(fut->fut_exception);
1243 return fut->fut_exception;
1244}
1245
1246static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001247FutureObj_get_source_traceback(FutureObj *fut, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001248{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001249 if (!future_is_alive(fut) || fut->fut_source_tb == NULL) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001250 Py_RETURN_NONE;
1251 }
1252 Py_INCREF(fut->fut_source_tb);
1253 return fut->fut_source_tb;
1254}
1255
1256static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001257FutureObj_get_state(FutureObj *fut, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001258{
1259 _Py_IDENTIFIER(PENDING);
1260 _Py_IDENTIFIER(CANCELLED);
1261 _Py_IDENTIFIER(FINISHED);
1262 PyObject *ret = NULL;
1263
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001264 ENSURE_FUTURE_ALIVE(fut)
1265
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001266 switch (fut->fut_state) {
1267 case STATE_PENDING:
1268 ret = _PyUnicode_FromId(&PyId_PENDING);
1269 break;
1270 case STATE_CANCELLED:
1271 ret = _PyUnicode_FromId(&PyId_CANCELLED);
1272 break;
1273 case STATE_FINISHED:
1274 ret = _PyUnicode_FromId(&PyId_FINISHED);
1275 break;
1276 default:
1277 assert (0);
1278 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03001279 Py_XINCREF(ret);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001280 return ret;
1281}
1282
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001283/*[clinic input]
1284_asyncio.Future._repr_info
1285[clinic start generated code]*/
1286
1287static PyObject *
1288_asyncio_Future__repr_info_impl(FutureObj *self)
1289/*[clinic end generated code: output=fa69e901bd176cfb input=f21504d8e2ae1ca2]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001290{
Victor Stinnerde4ae3d2016-12-04 22:59:09 +01001291 return PyObject_CallFunctionObjArgs(
1292 asyncio_future_repr_info_func, self, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001293}
1294
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001295static PyObject *
1296FutureObj_repr(FutureObj *fut)
1297{
1298 _Py_IDENTIFIER(_repr_info);
1299
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001300 ENSURE_FUTURE_ALIVE(fut)
1301
Serhiy Storchakabca49392017-09-03 08:10:14 +03001302 PyObject *rinfo = _PyObject_CallMethodIdObjArgs((PyObject*)fut,
1303 &PyId__repr_info,
1304 NULL);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001305 if (rinfo == NULL) {
1306 return NULL;
1307 }
1308
Serhiy Storchakabca49392017-09-03 08:10:14 +03001309 PyObject *rinfo_s = PyUnicode_Join(NULL, rinfo);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001310 Py_DECREF(rinfo);
1311 if (rinfo_s == NULL) {
1312 return NULL;
1313 }
1314
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03001315 PyObject *rstr = PyUnicode_FromFormat("<%s %U>",
1316 _PyType_Name(Py_TYPE(fut)), rinfo_s);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001317 Py_DECREF(rinfo_s);
1318 return rstr;
1319}
1320
1321static void
1322FutureObj_finalize(FutureObj *fut)
1323{
1324 _Py_IDENTIFIER(call_exception_handler);
1325 _Py_IDENTIFIER(message);
1326 _Py_IDENTIFIER(exception);
1327 _Py_IDENTIFIER(future);
1328 _Py_IDENTIFIER(source_traceback);
1329
Serhiy Storchakabca49392017-09-03 08:10:14 +03001330 PyObject *error_type, *error_value, *error_traceback;
1331 PyObject *context;
Serhiy Storchakabca49392017-09-03 08:10:14 +03001332 PyObject *message = NULL;
1333 PyObject *func;
1334
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001335 if (!fut->fut_log_tb) {
1336 return;
1337 }
1338 assert(fut->fut_exception != NULL);
Serhiy Storchakabca49392017-09-03 08:10:14 +03001339 fut->fut_log_tb = 0;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001340
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001341 /* Save the current exception, if any. */
1342 PyErr_Fetch(&error_type, &error_value, &error_traceback);
1343
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001344 context = PyDict_New();
1345 if (context == NULL) {
1346 goto finally;
1347 }
1348
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001349 message = PyUnicode_FromFormat(
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03001350 "%s exception was never retrieved", _PyType_Name(Py_TYPE(fut)));
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001351 if (message == NULL) {
1352 goto finally;
1353 }
1354
1355 if (_PyDict_SetItemId(context, &PyId_message, message) < 0 ||
1356 _PyDict_SetItemId(context, &PyId_exception, fut->fut_exception) < 0 ||
1357 _PyDict_SetItemId(context, &PyId_future, (PyObject*)fut) < 0) {
1358 goto finally;
1359 }
1360 if (fut->fut_source_tb != NULL) {
1361 if (_PyDict_SetItemId(context, &PyId_source_traceback,
1362 fut->fut_source_tb) < 0) {
1363 goto finally;
1364 }
1365 }
1366
1367 func = _PyObject_GetAttrId(fut->fut_loop, &PyId_call_exception_handler);
1368 if (func != NULL) {
Serhiy Storchakabca49392017-09-03 08:10:14 +03001369 PyObject *res = PyObject_CallFunctionObjArgs(func, context, NULL);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001370 if (res == NULL) {
1371 PyErr_WriteUnraisable(func);
1372 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03001373 else {
1374 Py_DECREF(res);
1375 }
1376 Py_DECREF(func);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001377 }
1378
1379finally:
Serhiy Storchakabca49392017-09-03 08:10:14 +03001380 Py_XDECREF(context);
1381 Py_XDECREF(message);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001382
1383 /* Restore the saved exception. */
1384 PyErr_Restore(error_type, error_value, error_traceback);
1385}
1386
1387
1388static PyAsyncMethods FutureType_as_async = {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001389 (unaryfunc)future_new_iter, /* am_await */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001390 0, /* am_aiter */
1391 0 /* am_anext */
1392};
1393
1394static PyMethodDef FutureType_methods[] = {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001395 _ASYNCIO_FUTURE_RESULT_METHODDEF
1396 _ASYNCIO_FUTURE_EXCEPTION_METHODDEF
1397 _ASYNCIO_FUTURE_SET_RESULT_METHODDEF
1398 _ASYNCIO_FUTURE_SET_EXCEPTION_METHODDEF
1399 _ASYNCIO_FUTURE_ADD_DONE_CALLBACK_METHODDEF
1400 _ASYNCIO_FUTURE_REMOVE_DONE_CALLBACK_METHODDEF
1401 _ASYNCIO_FUTURE_CANCEL_METHODDEF
1402 _ASYNCIO_FUTURE_CANCELLED_METHODDEF
1403 _ASYNCIO_FUTURE_DONE_METHODDEF
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001404 _ASYNCIO_FUTURE_GET_LOOP_METHODDEF
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001405 _ASYNCIO_FUTURE__REPR_INFO_METHODDEF
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001406 {NULL, NULL} /* Sentinel */
1407};
1408
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001409#define FUTURE_COMMON_GETSETLIST \
1410 {"_state", (getter)FutureObj_get_state, NULL, NULL}, \
1411 {"_asyncio_future_blocking", (getter)FutureObj_get_blocking, \
1412 (setter)FutureObj_set_blocking, NULL}, \
1413 {"_loop", (getter)FutureObj_get_loop, NULL, NULL}, \
1414 {"_callbacks", (getter)FutureObj_get_callbacks, NULL, NULL}, \
1415 {"_result", (getter)FutureObj_get_result, NULL, NULL}, \
1416 {"_exception", (getter)FutureObj_get_exception, NULL, NULL}, \
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +00001417 {"_log_traceback", (getter)FutureObj_get_log_traceback, \
1418 (setter)FutureObj_set_log_traceback, NULL}, \
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001419 {"_source_traceback", (getter)FutureObj_get_source_traceback, NULL, NULL},
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001420
1421static PyGetSetDef FutureType_getsetlist[] = {
1422 FUTURE_COMMON_GETSETLIST
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001423 {NULL} /* Sentinel */
1424};
1425
1426static void FutureObj_dealloc(PyObject *self);
1427
1428static PyTypeObject FutureType = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02001429 PyVarObject_HEAD_INIT(NULL, 0)
INADA Naoki9f2ce252016-10-15 15:39:19 +09001430 "_asyncio.Future",
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001431 sizeof(FutureObj), /* tp_basicsize */
1432 .tp_dealloc = FutureObj_dealloc,
1433 .tp_as_async = &FutureType_as_async,
1434 .tp_repr = (reprfunc)FutureObj_repr,
Antoine Pitrouada319b2019-05-29 22:12:38 +02001435 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001436 .tp_doc = _asyncio_Future___init____doc__,
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001437 .tp_traverse = (traverseproc)FutureObj_traverse,
1438 .tp_clear = (inquiry)FutureObj_clear,
1439 .tp_weaklistoffset = offsetof(FutureObj, fut_weakreflist),
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001440 .tp_iter = (getiterfunc)future_new_iter,
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001441 .tp_methods = FutureType_methods,
1442 .tp_getset = FutureType_getsetlist,
1443 .tp_dictoffset = offsetof(FutureObj, dict),
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001444 .tp_init = (initproc)_asyncio_Future___init__,
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001445 .tp_new = PyType_GenericNew,
1446 .tp_finalize = (destructor)FutureObj_finalize,
1447};
1448
1449static void
1450FutureObj_dealloc(PyObject *self)
1451{
1452 FutureObj *fut = (FutureObj *)self;
1453
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001454 if (Future_CheckExact(fut)) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001455 /* When fut is subclass of Future, finalizer is called from
1456 * subtype_dealloc.
1457 */
1458 if (PyObject_CallFinalizerFromDealloc(self) < 0) {
1459 // resurrected.
1460 return;
1461 }
1462 }
1463
Alexander Mohrde34cbe2017-08-01 23:31:07 -07001464 PyObject_GC_UnTrack(self);
1465
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001466 if (fut->fut_weakreflist != NULL) {
1467 PyObject_ClearWeakRefs(self);
1468 }
1469
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001470 (void)FutureObj_clear(fut);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001471 Py_TYPE(fut)->tp_free(fut);
1472}
1473
1474
1475/*********************** Future Iterator **************************/
1476
1477typedef struct {
1478 PyObject_HEAD
1479 FutureObj *future;
1480} futureiterobject;
1481
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001482
1483#define FI_FREELIST_MAXLEN 255
1484static futureiterobject *fi_freelist = NULL;
1485static Py_ssize_t fi_freelist_len = 0;
1486
1487
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001488static void
1489FutureIter_dealloc(futureiterobject *it)
1490{
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001491 PyObject_GC_UnTrack(it);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001492 Py_CLEAR(it->future);
1493
1494 if (fi_freelist_len < FI_FREELIST_MAXLEN) {
1495 fi_freelist_len++;
1496 it->future = (FutureObj*) fi_freelist;
1497 fi_freelist = it;
1498 }
1499 else {
1500 PyObject_GC_Del(it);
1501 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001502}
1503
1504static PyObject *
1505FutureIter_iternext(futureiterobject *it)
1506{
1507 PyObject *res;
1508 FutureObj *fut = it->future;
1509
1510 if (fut == NULL) {
1511 return NULL;
1512 }
1513
1514 if (fut->fut_state == STATE_PENDING) {
1515 if (!fut->fut_blocking) {
1516 fut->fut_blocking = 1;
1517 Py_INCREF(fut);
1518 return (PyObject *)fut;
1519 }
Yury Selivanov0cf16f92017-12-25 10:48:15 -05001520 PyErr_SetString(PyExc_RuntimeError,
1521 "await wasn't used with future");
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001522 return NULL;
1523 }
1524
Serhiy Storchakabca49392017-09-03 08:10:14 +03001525 it->future = NULL;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001526 res = _asyncio_Future_result_impl(fut);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001527 if (res != NULL) {
Serhiy Storchaka60e49aa2016-11-06 18:47:03 +02001528 /* The result of the Future is not an exception. */
Serhiy Storchakabca49392017-09-03 08:10:14 +03001529 (void)_PyGen_SetStopIterationValue(res);
Serhiy Storchaka60e49aa2016-11-06 18:47:03 +02001530 Py_DECREF(res);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001531 }
1532
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001533 Py_DECREF(fut);
1534 return NULL;
1535}
1536
1537static PyObject *
INADA Naoki74c17532016-10-25 19:00:45 +09001538FutureIter_send(futureiterobject *self, PyObject *unused)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001539{
INADA Naoki74c17532016-10-25 19:00:45 +09001540 /* Future.__iter__ doesn't care about values that are pushed to the
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03001541 * generator, it just returns self.result().
INADA Naoki74c17532016-10-25 19:00:45 +09001542 */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001543 return FutureIter_iternext(self);
1544}
1545
1546static PyObject *
1547FutureIter_throw(futureiterobject *self, PyObject *args)
1548{
Serhiy Storchakabca49392017-09-03 08:10:14 +03001549 PyObject *type, *val = NULL, *tb = NULL;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001550 if (!PyArg_ParseTuple(args, "O|OO", &type, &val, &tb))
1551 return NULL;
1552
1553 if (val == Py_None) {
1554 val = NULL;
1555 }
1556 if (tb == Py_None) {
1557 tb = NULL;
Benjamin Peterson996fc1f2016-11-14 00:15:44 -08001558 } else if (tb != NULL && !PyTraceBack_Check(tb)) {
1559 PyErr_SetString(PyExc_TypeError, "throw() third argument must be a traceback");
1560 return NULL;
1561 }
1562
1563 Py_INCREF(type);
1564 Py_XINCREF(val);
1565 Py_XINCREF(tb);
1566
1567 if (PyExceptionClass_Check(type)) {
1568 PyErr_NormalizeException(&type, &val, &tb);
Yury Selivanovedfe8862016-12-01 11:37:47 -05001569 /* No need to call PyException_SetTraceback since we'll be calling
1570 PyErr_Restore for `type`, `val`, and `tb`. */
Benjamin Peterson996fc1f2016-11-14 00:15:44 -08001571 } else if (PyExceptionInstance_Check(type)) {
1572 if (val) {
1573 PyErr_SetString(PyExc_TypeError,
1574 "instance exception may not have a separate value");
1575 goto fail;
1576 }
1577 val = type;
1578 type = PyExceptionInstance_Class(type);
1579 Py_INCREF(type);
1580 if (tb == NULL)
1581 tb = PyException_GetTraceback(val);
1582 } else {
1583 PyErr_SetString(PyExc_TypeError,
1584 "exceptions must be classes deriving BaseException or "
1585 "instances of such a class");
1586 goto fail;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001587 }
1588
1589 Py_CLEAR(self->future);
1590
Benjamin Peterson996fc1f2016-11-14 00:15:44 -08001591 PyErr_Restore(type, val, tb);
1592
Serhiy Storchakabca49392017-09-03 08:10:14 +03001593 return NULL;
Benjamin Peterson996fc1f2016-11-14 00:15:44 -08001594
1595 fail:
1596 Py_DECREF(type);
1597 Py_XDECREF(val);
1598 Py_XDECREF(tb);
1599 return NULL;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001600}
1601
1602static PyObject *
1603FutureIter_close(futureiterobject *self, PyObject *arg)
1604{
1605 Py_CLEAR(self->future);
1606 Py_RETURN_NONE;
1607}
1608
1609static int
1610FutureIter_traverse(futureiterobject *it, visitproc visit, void *arg)
1611{
1612 Py_VISIT(it->future);
1613 return 0;
1614}
1615
1616static PyMethodDef FutureIter_methods[] = {
1617 {"send", (PyCFunction)FutureIter_send, METH_O, NULL},
1618 {"throw", (PyCFunction)FutureIter_throw, METH_VARARGS, NULL},
1619 {"close", (PyCFunction)FutureIter_close, METH_NOARGS, NULL},
1620 {NULL, NULL} /* Sentinel */
1621};
1622
1623static PyTypeObject FutureIterType = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02001624 PyVarObject_HEAD_INIT(NULL, 0)
INADA Naoki9f2ce252016-10-15 15:39:19 +09001625 "_asyncio.FutureIter",
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001626 .tp_basicsize = sizeof(futureiterobject),
1627 .tp_itemsize = 0,
1628 .tp_dealloc = (destructor)FutureIter_dealloc,
1629 .tp_getattro = PyObject_GenericGetAttr,
1630 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
1631 .tp_traverse = (traverseproc)FutureIter_traverse,
1632 .tp_iter = PyObject_SelfIter,
1633 .tp_iternext = (iternextfunc)FutureIter_iternext,
1634 .tp_methods = FutureIter_methods,
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001635};
1636
1637static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001638future_new_iter(PyObject *fut)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001639{
1640 futureiterobject *it;
1641
1642 if (!PyObject_TypeCheck(fut, &FutureType)) {
1643 PyErr_BadInternalCall();
1644 return NULL;
1645 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001646
1647 ENSURE_FUTURE_ALIVE(fut)
1648
1649 if (fi_freelist_len) {
1650 fi_freelist_len--;
1651 it = fi_freelist;
1652 fi_freelist = (futureiterobject*) it->future;
1653 it->future = NULL;
1654 _Py_NewReference((PyObject*) it);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001655 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001656 else {
1657 it = PyObject_GC_New(futureiterobject, &FutureIterType);
1658 if (it == NULL) {
1659 return NULL;
1660 }
1661 }
1662
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001663 Py_INCREF(fut);
1664 it->future = (FutureObj*)fut;
INADA Naoki1be427b2016-10-11 02:12:34 +09001665 PyObject_GC_Track(it);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001666 return (PyObject*)it;
1667}
1668
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001669
1670/*********************** Task **************************/
1671
1672
1673/*[clinic input]
1674class _asyncio.Task "TaskObj *" "&Task_Type"
1675[clinic start generated code]*/
1676/*[clinic end generated code: output=da39a3ee5e6b4b0d input=719dcef0fcc03b37]*/
1677
1678static int task_call_step_soon(TaskObj *, PyObject *);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001679static PyObject * task_wakeup(TaskObj *, PyObject *);
1680static PyObject * task_step(TaskObj *, PyObject *);
1681
1682/* ----- Task._step wrapper */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001683
INADA Naokic411a7d2016-10-18 11:48:14 +09001684static int
Serhiy Storchakabca49392017-09-03 08:10:14 +03001685TaskStepMethWrapper_clear(TaskStepMethWrapper *o)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001686{
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001687 Py_CLEAR(o->sw_task);
1688 Py_CLEAR(o->sw_arg);
1689 return 0;
1690}
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001691
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001692static void
Serhiy Storchakabca49392017-09-03 08:10:14 +03001693TaskStepMethWrapper_dealloc(TaskStepMethWrapper *o)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001694{
1695 PyObject_GC_UnTrack(o);
Serhiy Storchakabca49392017-09-03 08:10:14 +03001696 (void)TaskStepMethWrapper_clear(o);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001697 Py_TYPE(o)->tp_free(o);
1698}
1699
1700static PyObject *
Serhiy Storchakabca49392017-09-03 08:10:14 +03001701TaskStepMethWrapper_call(TaskStepMethWrapper *o,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001702 PyObject *args, PyObject *kwds)
1703{
Serhiy Storchakabca49392017-09-03 08:10:14 +03001704 if (kwds != NULL && PyDict_GET_SIZE(kwds) != 0) {
1705 PyErr_SetString(PyExc_TypeError, "function takes no keyword arguments");
1706 return NULL;
1707 }
1708 if (args != NULL && PyTuple_GET_SIZE(args) != 0) {
1709 PyErr_SetString(PyExc_TypeError, "function takes no positional arguments");
1710 return NULL;
1711 }
Yury Selivanov22feeb82018-01-24 11:31:01 -05001712 return task_step(o->sw_task, o->sw_arg);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001713}
1714
1715static int
Serhiy Storchakabca49392017-09-03 08:10:14 +03001716TaskStepMethWrapper_traverse(TaskStepMethWrapper *o,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001717 visitproc visit, void *arg)
1718{
1719 Py_VISIT(o->sw_task);
1720 Py_VISIT(o->sw_arg);
1721 return 0;
1722}
1723
1724static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001725TaskStepMethWrapper_get___self__(TaskStepMethWrapper *o, void *Py_UNUSED(ignored))
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001726{
1727 if (o->sw_task) {
1728 Py_INCREF(o->sw_task);
1729 return (PyObject*)o->sw_task;
1730 }
1731 Py_RETURN_NONE;
1732}
1733
Serhiy Storchakabca49392017-09-03 08:10:14 +03001734static PyGetSetDef TaskStepMethWrapper_getsetlist[] = {
1735 {"__self__", (getter)TaskStepMethWrapper_get___self__, NULL, NULL},
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001736 {NULL} /* Sentinel */
1737};
1738
Benjamin Peterson3c8aae92018-07-05 22:39:34 -07001739static PyTypeObject TaskStepMethWrapper_Type = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02001740 PyVarObject_HEAD_INIT(NULL, 0)
Serhiy Storchakabca49392017-09-03 08:10:14 +03001741 "TaskStepMethWrapper",
1742 .tp_basicsize = sizeof(TaskStepMethWrapper),
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001743 .tp_itemsize = 0,
Serhiy Storchakabca49392017-09-03 08:10:14 +03001744 .tp_getset = TaskStepMethWrapper_getsetlist,
1745 .tp_dealloc = (destructor)TaskStepMethWrapper_dealloc,
1746 .tp_call = (ternaryfunc)TaskStepMethWrapper_call,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001747 .tp_getattro = PyObject_GenericGetAttr,
1748 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
Serhiy Storchakabca49392017-09-03 08:10:14 +03001749 .tp_traverse = (traverseproc)TaskStepMethWrapper_traverse,
1750 .tp_clear = (inquiry)TaskStepMethWrapper_clear,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001751};
1752
1753static PyObject *
Serhiy Storchakabca49392017-09-03 08:10:14 +03001754TaskStepMethWrapper_new(TaskObj *task, PyObject *arg)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001755{
Serhiy Storchakabca49392017-09-03 08:10:14 +03001756 TaskStepMethWrapper *o;
1757 o = PyObject_GC_New(TaskStepMethWrapper, &TaskStepMethWrapper_Type);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001758 if (o == NULL) {
1759 return NULL;
1760 }
1761
1762 Py_INCREF(task);
1763 o->sw_task = task;
1764
1765 Py_XINCREF(arg);
1766 o->sw_arg = arg;
1767
1768 PyObject_GC_Track(o);
1769 return (PyObject*) o;
1770}
1771
1772/* ----- Task._wakeup wrapper */
1773
1774static PyObject *
1775TaskWakeupMethWrapper_call(TaskWakeupMethWrapper *o,
1776 PyObject *args, PyObject *kwds)
1777{
1778 PyObject *fut;
1779
Serhiy Storchakabca49392017-09-03 08:10:14 +03001780 if (kwds != NULL && PyDict_GET_SIZE(kwds) != 0) {
1781 PyErr_SetString(PyExc_TypeError, "function takes no keyword arguments");
1782 return NULL;
1783 }
1784 if (!PyArg_ParseTuple(args, "O", &fut)) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001785 return NULL;
1786 }
1787
Yury Selivanov22feeb82018-01-24 11:31:01 -05001788 return task_wakeup(o->ww_task, fut);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001789}
1790
1791static int
1792TaskWakeupMethWrapper_clear(TaskWakeupMethWrapper *o)
1793{
1794 Py_CLEAR(o->ww_task);
1795 return 0;
1796}
1797
1798static int
1799TaskWakeupMethWrapper_traverse(TaskWakeupMethWrapper *o,
1800 visitproc visit, void *arg)
1801{
1802 Py_VISIT(o->ww_task);
1803 return 0;
1804}
1805
1806static void
1807TaskWakeupMethWrapper_dealloc(TaskWakeupMethWrapper *o)
1808{
1809 PyObject_GC_UnTrack(o);
1810 (void)TaskWakeupMethWrapper_clear(o);
1811 Py_TYPE(o)->tp_free(o);
1812}
1813
Miss Islington (bot)ce0a2a82019-12-07 03:41:41 -08001814static PyObject *
1815TaskWakeupMethWrapper_get___self__(TaskWakeupMethWrapper *o, void *Py_UNUSED(ignored))
1816{
1817 if (o->ww_task) {
1818 Py_INCREF(o->ww_task);
1819 return (PyObject*)o->ww_task;
1820 }
1821 Py_RETURN_NONE;
1822}
1823
1824static PyGetSetDef TaskWakeupMethWrapper_getsetlist[] = {
1825 {"__self__", (getter)TaskWakeupMethWrapper_get___self__, NULL, NULL},
1826 {NULL} /* Sentinel */
1827};
1828
Benjamin Peterson3c8aae92018-07-05 22:39:34 -07001829static PyTypeObject TaskWakeupMethWrapper_Type = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02001830 PyVarObject_HEAD_INIT(NULL, 0)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001831 "TaskWakeupMethWrapper",
1832 .tp_basicsize = sizeof(TaskWakeupMethWrapper),
1833 .tp_itemsize = 0,
1834 .tp_dealloc = (destructor)TaskWakeupMethWrapper_dealloc,
1835 .tp_call = (ternaryfunc)TaskWakeupMethWrapper_call,
1836 .tp_getattro = PyObject_GenericGetAttr,
1837 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
1838 .tp_traverse = (traverseproc)TaskWakeupMethWrapper_traverse,
1839 .tp_clear = (inquiry)TaskWakeupMethWrapper_clear,
Miss Islington (bot)ce0a2a82019-12-07 03:41:41 -08001840 .tp_getset = TaskWakeupMethWrapper_getsetlist,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001841};
1842
1843static PyObject *
1844TaskWakeupMethWrapper_new(TaskObj *task)
1845{
1846 TaskWakeupMethWrapper *o;
1847 o = PyObject_GC_New(TaskWakeupMethWrapper, &TaskWakeupMethWrapper_Type);
1848 if (o == NULL) {
1849 return NULL;
1850 }
1851
1852 Py_INCREF(task);
1853 o->ww_task = task;
1854
1855 PyObject_GC_Track(o);
1856 return (PyObject*) o;
1857}
1858
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001859/* ----- Task introspection helpers */
1860
1861static int
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001862register_task(PyObject *task)
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001863{
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001864 _Py_IDENTIFIER(add);
1865
1866 PyObject *res = _PyObject_CallMethodIdObjArgs(
1867 all_tasks, &PyId_add, task, NULL);
1868 if (res == NULL) {
1869 return -1;
1870 }
1871 Py_DECREF(res);
1872 return 0;
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001873}
1874
1875
1876static int
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001877unregister_task(PyObject *task)
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001878{
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001879 _Py_IDENTIFIER(discard);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001880
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001881 PyObject *res = _PyObject_CallMethodIdObjArgs(
1882 all_tasks, &PyId_discard, task, NULL);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001883 if (res == NULL) {
1884 return -1;
1885 }
1886 Py_DECREF(res);
1887 return 0;
1888}
1889
1890
1891static int
1892enter_task(PyObject *loop, PyObject *task)
1893{
1894 PyObject *item;
1895 Py_hash_t hash;
1896 hash = PyObject_Hash(loop);
1897 if (hash == -1) {
1898 return -1;
1899 }
1900 item = _PyDict_GetItem_KnownHash(current_tasks, loop, hash);
1901 if (item != NULL) {
Serhiy Storchaka66553542018-05-20 16:30:31 +03001902 Py_INCREF(item);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001903 PyErr_Format(
1904 PyExc_RuntimeError,
1905 "Cannot enter into task %R while another " \
1906 "task %R is being executed.",
1907 task, item, NULL);
Serhiy Storchaka66553542018-05-20 16:30:31 +03001908 Py_DECREF(item);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001909 return -1;
1910 }
Serhiy Storchaka66553542018-05-20 16:30:31 +03001911 if (PyErr_Occurred()) {
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001912 return -1;
1913 }
Serhiy Storchaka66553542018-05-20 16:30:31 +03001914 return _PyDict_SetItem_KnownHash(current_tasks, loop, task, hash);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001915}
1916
1917
1918static int
1919leave_task(PyObject *loop, PyObject *task)
1920/*[clinic end generated code: output=0ebf6db4b858fb41 input=51296a46313d1ad8]*/
1921{
1922 PyObject *item;
1923 Py_hash_t hash;
1924 hash = PyObject_Hash(loop);
1925 if (hash == -1) {
1926 return -1;
1927 }
1928 item = _PyDict_GetItem_KnownHash(current_tasks, loop, hash);
1929 if (item != task) {
1930 if (item == NULL) {
1931 /* Not entered, replace with None */
1932 item = Py_None;
1933 }
1934 PyErr_Format(
1935 PyExc_RuntimeError,
1936 "Leaving task %R does not match the current task %R.",
1937 task, item, NULL);
1938 return -1;
1939 }
1940 return _PyDict_DelItem_KnownHash(current_tasks, loop, hash);
1941}
1942
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001943/* ----- Task */
1944
1945/*[clinic input]
1946_asyncio.Task.__init__
1947
Serhiy Storchakabca49392017-09-03 08:10:14 +03001948 coro: object
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001949 *
Serhiy Storchakabca49392017-09-03 08:10:14 +03001950 loop: object = None
Alex Grönholmcca4eec2018-08-09 00:06:47 +03001951 name: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001952
1953A coroutine wrapped in a Future.
1954[clinic start generated code]*/
1955
1956static int
Alex Grönholmcca4eec2018-08-09 00:06:47 +03001957_asyncio_Task___init___impl(TaskObj *self, PyObject *coro, PyObject *loop,
1958 PyObject *name)
1959/*[clinic end generated code: output=88b12b83d570df50 input=352a3137fe60091d]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001960{
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001961 if (future_init((FutureObj*)self, loop)) {
INADA Naokic411a7d2016-10-18 11:48:14 +09001962 return -1;
1963 }
INADA Naokic411a7d2016-10-18 11:48:14 +09001964
Yury Selivanova9d7e552017-12-19 07:18:45 -05001965 int is_coro = is_coroutine(coro);
1966 if (is_coro == -1) {
1967 return -1;
1968 }
1969 if (is_coro == 0) {
1970 self->task_log_destroy_pending = 0;
1971 PyErr_Format(PyExc_TypeError,
1972 "a coroutine was expected, got %R",
1973 coro, NULL);
1974 return -1;
Andrew Svetlovf74ef452017-12-15 07:04:38 +02001975 }
1976
Oren Milmand019bc82018-02-13 12:28:33 +02001977 Py_XSETREF(self->task_context, PyContext_CopyCurrent());
Yury Selivanovf23746a2018-01-22 19:11:18 -05001978 if (self->task_context == NULL) {
1979 return -1;
1980 }
1981
Oren Milmand019bc82018-02-13 12:28:33 +02001982 Py_CLEAR(self->task_fut_waiter);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001983 self->task_must_cancel = 0;
1984 self->task_log_destroy_pending = 1;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001985 Py_INCREF(coro);
Oren Milmand019bc82018-02-13 12:28:33 +02001986 Py_XSETREF(self->task_coro, coro);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001987
Alex Grönholmcca4eec2018-08-09 00:06:47 +03001988 if (name == Py_None) {
1989 name = PyUnicode_FromFormat("Task-%" PRIu64, ++task_name_counter);
Alex Grönholma7548232018-08-09 23:49:49 +03001990 } else if (!PyUnicode_CheckExact(name)) {
Alex Grönholmcca4eec2018-08-09 00:06:47 +03001991 name = PyObject_Str(name);
1992 } else {
1993 Py_INCREF(name);
1994 }
1995 Py_XSETREF(self->task_name, name);
1996 if (self->task_name == NULL) {
1997 return -1;
1998 }
1999
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002000 if (task_call_step_soon(self, NULL)) {
2001 return -1;
INADA Naokic411a7d2016-10-18 11:48:14 +09002002 }
Yury Selivanovca9b36c2017-12-23 15:04:15 -05002003 return register_task((PyObject*)self);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002004}
2005
2006static int
2007TaskObj_clear(TaskObj *task)
2008{
2009 (void)FutureObj_clear((FutureObj*) task);
Yury Selivanovf23746a2018-01-22 19:11:18 -05002010 Py_CLEAR(task->task_context);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002011 Py_CLEAR(task->task_coro);
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002012 Py_CLEAR(task->task_name);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002013 Py_CLEAR(task->task_fut_waiter);
2014 return 0;
2015}
2016
2017static int
2018TaskObj_traverse(TaskObj *task, visitproc visit, void *arg)
2019{
Yury Selivanovf23746a2018-01-22 19:11:18 -05002020 Py_VISIT(task->task_context);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002021 Py_VISIT(task->task_coro);
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002022 Py_VISIT(task->task_name);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002023 Py_VISIT(task->task_fut_waiter);
2024 (void)FutureObj_traverse((FutureObj*) task, visit, arg);
2025 return 0;
2026}
2027
2028static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02002029TaskObj_get_log_destroy_pending(TaskObj *task, void *Py_UNUSED(ignored))
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002030{
2031 if (task->task_log_destroy_pending) {
2032 Py_RETURN_TRUE;
2033 }
2034 else {
2035 Py_RETURN_FALSE;
2036 }
2037}
2038
2039static int
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02002040TaskObj_set_log_destroy_pending(TaskObj *task, PyObject *val, void *Py_UNUSED(ignored))
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002041{
Zackery Spytz842acaa2018-12-17 07:52:45 -07002042 if (val == NULL) {
2043 PyErr_SetString(PyExc_AttributeError, "cannot delete attribute");
2044 return -1;
2045 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002046 int is_true = PyObject_IsTrue(val);
2047 if (is_true < 0) {
2048 return -1;
2049 }
2050 task->task_log_destroy_pending = is_true;
2051 return 0;
2052}
2053
2054static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02002055TaskObj_get_must_cancel(TaskObj *task, void *Py_UNUSED(ignored))
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002056{
2057 if (task->task_must_cancel) {
2058 Py_RETURN_TRUE;
2059 }
2060 else {
2061 Py_RETURN_FALSE;
2062 }
2063}
2064
2065static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02002066TaskObj_get_coro(TaskObj *task, void *Py_UNUSED(ignored))
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002067{
2068 if (task->task_coro) {
2069 Py_INCREF(task->task_coro);
2070 return task->task_coro;
2071 }
2072
2073 Py_RETURN_NONE;
2074}
2075
2076static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02002077TaskObj_get_fut_waiter(TaskObj *task, void *Py_UNUSED(ignored))
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002078{
2079 if (task->task_fut_waiter) {
2080 Py_INCREF(task->task_fut_waiter);
2081 return task->task_fut_waiter;
2082 }
2083
2084 Py_RETURN_NONE;
2085}
2086
2087/*[clinic input]
2088@classmethod
2089_asyncio.Task.current_task
2090
Serhiy Storchakabca49392017-09-03 08:10:14 +03002091 loop: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002092
2093Return the currently running task in an event loop or None.
2094
2095By default the current task for the current event loop is returned.
2096
2097None is returned when called not in the context of a Task.
2098[clinic start generated code]*/
2099
2100static PyObject *
2101_asyncio_Task_current_task_impl(PyTypeObject *type, PyObject *loop)
Serhiy Storchakabca49392017-09-03 08:10:14 +03002102/*[clinic end generated code: output=99fbe7332c516e03 input=cd14770c5b79c7eb]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002103{
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002104 PyObject *ret;
2105 PyObject *current_task_func;
2106
Inada Naokic5c6cda2019-03-22 20:07:32 +09002107 if (PyErr_WarnEx(PyExc_DeprecationWarning,
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002108 "Task.current_task() is deprecated, " \
2109 "use asyncio.current_task() instead",
2110 1) < 0) {
2111 return NULL;
2112 }
2113
2114 current_task_func = _PyObject_GetAttrId(asyncio_mod, &PyId_current_task);
2115 if (current_task_func == NULL) {
2116 return NULL;
2117 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002118
Yury Selivanov8d26aa92017-03-02 22:16:33 -05002119 if (loop == Py_None) {
Yury Selivanova70232f2017-12-13 14:49:42 -05002120 loop = get_event_loop();
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002121 if (loop == NULL) {
Serhiy Storchaka66553542018-05-20 16:30:31 +03002122 Py_DECREF(current_task_func);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002123 return NULL;
2124 }
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002125 ret = PyObject_CallFunctionObjArgs(current_task_func, loop, NULL);
2126 Py_DECREF(current_task_func);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002127 Py_DECREF(loop);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002128 return ret;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002129 }
2130 else {
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002131 ret = PyObject_CallFunctionObjArgs(current_task_func, loop, NULL);
2132 Py_DECREF(current_task_func);
2133 return ret;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002134 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002135}
2136
2137/*[clinic input]
2138@classmethod
2139_asyncio.Task.all_tasks
2140
Serhiy Storchakabca49392017-09-03 08:10:14 +03002141 loop: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002142
2143Return a set of all tasks for an event loop.
2144
2145By default all tasks for the current event loop are returned.
2146[clinic start generated code]*/
2147
2148static PyObject *
2149_asyncio_Task_all_tasks_impl(PyTypeObject *type, PyObject *loop)
Serhiy Storchakabca49392017-09-03 08:10:14 +03002150/*[clinic end generated code: output=11f9b20749ccca5d input=497f80bc9ce726b5]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002151{
2152 PyObject *res;
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002153 PyObject *all_tasks_func;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002154
Inada Naokic5c6cda2019-03-22 20:07:32 +09002155 if (PyErr_WarnEx(PyExc_DeprecationWarning,
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002156 "Task.all_tasks() is deprecated, " \
2157 "use asyncio.all_tasks() instead",
2158 1) < 0) {
2159 return NULL;
2160 }
2161
Yury Selivanov416c1eb2018-05-28 17:54:02 -04002162 all_tasks_func = _PyObject_GetAttrId(asyncio_mod, &PyId__all_tasks_compat);
Serhiy Storchaka66553542018-05-20 16:30:31 +03002163 if (all_tasks_func == NULL) {
2164 return NULL;
2165 }
2166
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002167 res = PyObject_CallFunctionObjArgs(all_tasks_func, loop, NULL);
2168 Py_DECREF(all_tasks_func);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002169 return res;
2170}
2171
2172/*[clinic input]
2173_asyncio.Task._repr_info
2174[clinic start generated code]*/
2175
2176static PyObject *
2177_asyncio_Task__repr_info_impl(TaskObj *self)
2178/*[clinic end generated code: output=6a490eb66d5ba34b input=3c6d051ed3ddec8b]*/
2179{
Victor Stinnerde4ae3d2016-12-04 22:59:09 +01002180 return PyObject_CallFunctionObjArgs(
2181 asyncio_task_repr_info_func, self, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002182}
2183
2184/*[clinic input]
2185_asyncio.Task.cancel
2186
2187Request that this task cancel itself.
2188
2189This arranges for a CancelledError to be thrown into the
2190wrapped coroutine on the next cycle through the event loop.
2191The coroutine then has a chance to clean up or even deny
2192the request using try/except/finally.
2193
2194Unlike Future.cancel, this does not guarantee that the
2195task will be cancelled: the exception might be caught and
2196acted upon, delaying cancellation of the task or preventing
2197cancellation completely. The task may also return a value or
2198raise a different exception.
2199
2200Immediately after this method is called, Task.cancelled() will
2201not return True (unless the task was already cancelled). A
2202task will be marked as cancelled when the wrapped coroutine
2203terminates with a CancelledError exception (even if cancel()
2204was not called).
2205[clinic start generated code]*/
2206
2207static PyObject *
2208_asyncio_Task_cancel_impl(TaskObj *self)
2209/*[clinic end generated code: output=6bfc0479da9d5757 input=13f9bf496695cb52]*/
2210{
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +00002211 self->task_log_tb = 0;
2212
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002213 if (self->task_state != STATE_PENDING) {
2214 Py_RETURN_FALSE;
2215 }
2216
2217 if (self->task_fut_waiter) {
2218 PyObject *res;
2219 int is_true;
2220
2221 res = _PyObject_CallMethodId(
2222 self->task_fut_waiter, &PyId_cancel, NULL);
2223 if (res == NULL) {
2224 return NULL;
2225 }
2226
2227 is_true = PyObject_IsTrue(res);
2228 Py_DECREF(res);
2229 if (is_true < 0) {
2230 return NULL;
2231 }
2232
2233 if (is_true) {
2234 Py_RETURN_TRUE;
2235 }
2236 }
2237
2238 self->task_must_cancel = 1;
2239 Py_RETURN_TRUE;
2240}
2241
2242/*[clinic input]
2243_asyncio.Task.get_stack
2244
2245 *
Serhiy Storchakabca49392017-09-03 08:10:14 +03002246 limit: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002247
2248Return the list of stack frames for this task's coroutine.
2249
2250If the coroutine is not done, this returns the stack where it is
2251suspended. If the coroutine has completed successfully or was
2252cancelled, this returns an empty list. If the coroutine was
2253terminated by an exception, this returns the list of traceback
2254frames.
2255
2256The frames are always ordered from oldest to newest.
2257
2258The optional limit gives the maximum number of frames to
2259return; by default all available frames are returned. Its
2260meaning differs depending on whether a stack or a traceback is
2261returned: the newest frames of a stack are returned, but the
2262oldest frames of a traceback are returned. (This matches the
2263behavior of the traceback module.)
2264
2265For reasons beyond our control, only one stack frame is
2266returned for a suspended coroutine.
2267[clinic start generated code]*/
2268
2269static PyObject *
2270_asyncio_Task_get_stack_impl(TaskObj *self, PyObject *limit)
Serhiy Storchakabca49392017-09-03 08:10:14 +03002271/*[clinic end generated code: output=c9aeeeebd1e18118 input=05b323d42b809b90]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002272{
2273 return PyObject_CallFunctionObjArgs(
2274 asyncio_task_get_stack_func, self, limit, NULL);
2275}
2276
2277/*[clinic input]
2278_asyncio.Task.print_stack
2279
2280 *
Serhiy Storchakabca49392017-09-03 08:10:14 +03002281 limit: object = None
2282 file: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002283
2284Print the stack or traceback for this task's coroutine.
2285
2286This produces output similar to that of the traceback module,
2287for the frames retrieved by get_stack(). The limit argument
2288is passed to get_stack(). The file argument is an I/O stream
2289to which the output is written; by default output is written
2290to sys.stderr.
2291[clinic start generated code]*/
2292
2293static PyObject *
2294_asyncio_Task_print_stack_impl(TaskObj *self, PyObject *limit,
2295 PyObject *file)
Serhiy Storchakabca49392017-09-03 08:10:14 +03002296/*[clinic end generated code: output=7339e10314cd3f4d input=1a0352913b7fcd92]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002297{
2298 return PyObject_CallFunctionObjArgs(
2299 asyncio_task_print_stack_func, self, limit, file, NULL);
2300}
2301
2302/*[clinic input]
Yury Selivanov0cf16f92017-12-25 10:48:15 -05002303_asyncio.Task.set_result
2304
2305 result: object
2306 /
2307[clinic start generated code]*/
2308
2309static PyObject *
2310_asyncio_Task_set_result(TaskObj *self, PyObject *result)
2311/*[clinic end generated code: output=1dcae308bfcba318 input=9d1a00c07be41bab]*/
2312{
2313 PyErr_SetString(PyExc_RuntimeError,
2314 "Task does not support set_result operation");
2315 return NULL;
2316}
2317
2318/*[clinic input]
2319_asyncio.Task.set_exception
2320
2321 exception: object
2322 /
2323[clinic start generated code]*/
2324
2325static PyObject *
2326_asyncio_Task_set_exception(TaskObj *self, PyObject *exception)
2327/*[clinic end generated code: output=bc377fc28067303d input=9a8f65c83dcf893a]*/
2328{
2329 PyErr_SetString(PyExc_RuntimeError,
Andrew Svetlovfc359322017-12-30 15:40:27 +02002330 "Task does not support set_exception operation");
Yury Selivanov0cf16f92017-12-25 10:48:15 -05002331 return NULL;
2332}
2333
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002334/*[clinic input]
Alex Grönholm98ef9202019-05-30 18:30:09 +03002335_asyncio.Task.get_coro
2336[clinic start generated code]*/
2337
2338static PyObject *
2339_asyncio_Task_get_coro_impl(TaskObj *self)
2340/*[clinic end generated code: output=bcac27c8cc6c8073 input=d2e8606c42a7b403]*/
2341{
2342 Py_INCREF(self->task_coro);
2343 return self->task_coro;
2344}
2345
2346/*[clinic input]
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002347_asyncio.Task.get_name
2348[clinic start generated code]*/
2349
2350static PyObject *
2351_asyncio_Task_get_name_impl(TaskObj *self)
2352/*[clinic end generated code: output=0ecf1570c3b37a8f input=a4a6595d12f4f0f8]*/
2353{
2354 if (self->task_name) {
2355 Py_INCREF(self->task_name);
2356 return self->task_name;
2357 }
2358
2359 Py_RETURN_NONE;
2360}
2361
2362/*[clinic input]
2363_asyncio.Task.set_name
2364
2365 value: object
2366 /
2367[clinic start generated code]*/
2368
2369static PyObject *
2370_asyncio_Task_set_name(TaskObj *self, PyObject *value)
2371/*[clinic end generated code: output=138a8d51e32057d6 input=a8359b6e65f8fd31]*/
2372{
Alex Grönholma7548232018-08-09 23:49:49 +03002373 if (!PyUnicode_CheckExact(value)) {
2374 value = PyObject_Str(value);
2375 if (value == NULL) {
2376 return NULL;
2377 }
2378 } else {
2379 Py_INCREF(value);
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002380 }
2381
Alex Grönholma7548232018-08-09 23:49:49 +03002382 Py_XSETREF(self->task_name, value);
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002383 Py_RETURN_NONE;
2384}
Yury Selivanov0cf16f92017-12-25 10:48:15 -05002385
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002386static void
2387TaskObj_finalize(TaskObj *task)
2388{
2389 _Py_IDENTIFIER(call_exception_handler);
2390 _Py_IDENTIFIER(task);
2391 _Py_IDENTIFIER(message);
2392 _Py_IDENTIFIER(source_traceback);
2393
Serhiy Storchakabca49392017-09-03 08:10:14 +03002394 PyObject *context;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002395 PyObject *message = NULL;
Serhiy Storchakabca49392017-09-03 08:10:14 +03002396 PyObject *func;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002397 PyObject *error_type, *error_value, *error_traceback;
2398
2399 if (task->task_state != STATE_PENDING || !task->task_log_destroy_pending) {
2400 goto done;
2401 }
2402
2403 /* Save the current exception, if any. */
2404 PyErr_Fetch(&error_type, &error_value, &error_traceback);
2405
2406 context = PyDict_New();
2407 if (context == NULL) {
2408 goto finally;
2409 }
2410
2411 message = PyUnicode_FromString("Task was destroyed but it is pending!");
2412 if (message == NULL) {
2413 goto finally;
2414 }
2415
2416 if (_PyDict_SetItemId(context, &PyId_message, message) < 0 ||
2417 _PyDict_SetItemId(context, &PyId_task, (PyObject*)task) < 0)
2418 {
2419 goto finally;
2420 }
2421
2422 if (task->task_source_tb != NULL) {
2423 if (_PyDict_SetItemId(context, &PyId_source_traceback,
2424 task->task_source_tb) < 0)
2425 {
2426 goto finally;
2427 }
2428 }
2429
2430 func = _PyObject_GetAttrId(task->task_loop, &PyId_call_exception_handler);
2431 if (func != NULL) {
Serhiy Storchakabca49392017-09-03 08:10:14 +03002432 PyObject *res = PyObject_CallFunctionObjArgs(func, context, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002433 if (res == NULL) {
2434 PyErr_WriteUnraisable(func);
2435 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03002436 else {
2437 Py_DECREF(res);
2438 }
2439 Py_DECREF(func);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002440 }
2441
2442finally:
Serhiy Storchakabca49392017-09-03 08:10:14 +03002443 Py_XDECREF(context);
2444 Py_XDECREF(message);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002445
2446 /* Restore the saved exception. */
2447 PyErr_Restore(error_type, error_value, error_traceback);
2448
2449done:
2450 FutureObj_finalize((FutureObj*)task);
2451}
2452
2453static void TaskObj_dealloc(PyObject *); /* Needs Task_CheckExact */
2454
2455static PyMethodDef TaskType_methods[] = {
2456 _ASYNCIO_FUTURE_RESULT_METHODDEF
2457 _ASYNCIO_FUTURE_EXCEPTION_METHODDEF
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002458 _ASYNCIO_FUTURE_ADD_DONE_CALLBACK_METHODDEF
2459 _ASYNCIO_FUTURE_REMOVE_DONE_CALLBACK_METHODDEF
2460 _ASYNCIO_FUTURE_CANCELLED_METHODDEF
2461 _ASYNCIO_FUTURE_DONE_METHODDEF
Yury Selivanov0cf16f92017-12-25 10:48:15 -05002462 _ASYNCIO_TASK_SET_RESULT_METHODDEF
2463 _ASYNCIO_TASK_SET_EXCEPTION_METHODDEF
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002464 _ASYNCIO_TASK_CURRENT_TASK_METHODDEF
2465 _ASYNCIO_TASK_ALL_TASKS_METHODDEF
2466 _ASYNCIO_TASK_CANCEL_METHODDEF
2467 _ASYNCIO_TASK_GET_STACK_METHODDEF
2468 _ASYNCIO_TASK_PRINT_STACK_METHODDEF
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002469 _ASYNCIO_TASK__REPR_INFO_METHODDEF
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002470 _ASYNCIO_TASK_GET_NAME_METHODDEF
2471 _ASYNCIO_TASK_SET_NAME_METHODDEF
Alex Grönholm98ef9202019-05-30 18:30:09 +03002472 _ASYNCIO_TASK_GET_CORO_METHODDEF
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002473 {NULL, NULL} /* Sentinel */
2474};
2475
2476static PyGetSetDef TaskType_getsetlist[] = {
2477 FUTURE_COMMON_GETSETLIST
2478 {"_log_destroy_pending", (getter)TaskObj_get_log_destroy_pending,
2479 (setter)TaskObj_set_log_destroy_pending, NULL},
2480 {"_must_cancel", (getter)TaskObj_get_must_cancel, NULL, NULL},
2481 {"_coro", (getter)TaskObj_get_coro, NULL, NULL},
2482 {"_fut_waiter", (getter)TaskObj_get_fut_waiter, NULL, NULL},
2483 {NULL} /* Sentinel */
2484};
2485
2486static PyTypeObject TaskType = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02002487 PyVarObject_HEAD_INIT(NULL, 0)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002488 "_asyncio.Task",
2489 sizeof(TaskObj), /* tp_basicsize */
2490 .tp_base = &FutureType,
2491 .tp_dealloc = TaskObj_dealloc,
2492 .tp_as_async = &FutureType_as_async,
2493 .tp_repr = (reprfunc)FutureObj_repr,
Antoine Pitrouada319b2019-05-29 22:12:38 +02002494 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002495 .tp_doc = _asyncio_Task___init____doc__,
2496 .tp_traverse = (traverseproc)TaskObj_traverse,
2497 .tp_clear = (inquiry)TaskObj_clear,
2498 .tp_weaklistoffset = offsetof(TaskObj, task_weakreflist),
2499 .tp_iter = (getiterfunc)future_new_iter,
2500 .tp_methods = TaskType_methods,
2501 .tp_getset = TaskType_getsetlist,
2502 .tp_dictoffset = offsetof(TaskObj, dict),
2503 .tp_init = (initproc)_asyncio_Task___init__,
2504 .tp_new = PyType_GenericNew,
2505 .tp_finalize = (destructor)TaskObj_finalize,
2506};
2507
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002508static void
2509TaskObj_dealloc(PyObject *self)
2510{
2511 TaskObj *task = (TaskObj *)self;
2512
2513 if (Task_CheckExact(self)) {
2514 /* When fut is subclass of Task, finalizer is called from
2515 * subtype_dealloc.
2516 */
2517 if (PyObject_CallFinalizerFromDealloc(self) < 0) {
2518 // resurrected.
2519 return;
2520 }
2521 }
2522
Alexander Mohrde34cbe2017-08-01 23:31:07 -07002523 PyObject_GC_UnTrack(self);
2524
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002525 if (task->task_weakreflist != NULL) {
2526 PyObject_ClearWeakRefs(self);
2527 }
2528
2529 (void)TaskObj_clear(task);
2530 Py_TYPE(task)->tp_free(task);
2531}
2532
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002533static int
2534task_call_step_soon(TaskObj *task, PyObject *arg)
2535{
Serhiy Storchakabca49392017-09-03 08:10:14 +03002536 PyObject *cb = TaskStepMethWrapper_new(task, arg);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002537 if (cb == NULL) {
2538 return -1;
2539 }
2540
Yury Selivanovf23746a2018-01-22 19:11:18 -05002541 int ret = call_soon(task->task_loop, cb, NULL, task->task_context);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002542 Py_DECREF(cb);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05002543 return ret;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002544}
2545
2546static PyObject *
2547task_set_error_soon(TaskObj *task, PyObject *et, const char *format, ...)
2548{
2549 PyObject* msg;
2550
2551 va_list vargs;
2552#ifdef HAVE_STDARG_PROTOTYPES
2553 va_start(vargs, format);
2554#else
2555 va_start(vargs);
2556#endif
2557 msg = PyUnicode_FromFormatV(format, vargs);
2558 va_end(vargs);
2559
2560 if (msg == NULL) {
2561 return NULL;
2562 }
2563
Victor Stinnerde4ae3d2016-12-04 22:59:09 +01002564 PyObject *e = PyObject_CallFunctionObjArgs(et, msg, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002565 Py_DECREF(msg);
2566 if (e == NULL) {
2567 return NULL;
2568 }
2569
2570 if (task_call_step_soon(task, e) == -1) {
2571 Py_DECREF(e);
2572 return NULL;
2573 }
2574
2575 Py_DECREF(e);
2576 Py_RETURN_NONE;
2577}
2578
2579static PyObject *
2580task_step_impl(TaskObj *task, PyObject *exc)
2581{
2582 int res;
2583 int clear_exc = 0;
2584 PyObject *result = NULL;
Serhiy Storchakabca49392017-09-03 08:10:14 +03002585 PyObject *coro;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002586 PyObject *o;
2587
2588 if (task->task_state != STATE_PENDING) {
Yury Selivanov0cf16f92017-12-25 10:48:15 -05002589 PyErr_Format(asyncio_InvalidStateError,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002590 "_step(): already done: %R %R",
2591 task,
2592 exc ? exc : Py_None);
INADA Naokic411a7d2016-10-18 11:48:14 +09002593 goto fail;
2594 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09002595
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002596 if (task->task_must_cancel) {
2597 assert(exc != Py_None);
2598
2599 if (exc) {
2600 /* Check if exc is a CancelledError */
2601 res = PyObject_IsInstance(exc, asyncio_CancelledError);
2602 if (res == -1) {
2603 /* An error occurred, abort */
2604 goto fail;
2605 }
2606 if (res == 0) {
2607 /* exc is not CancelledError; reset it to NULL */
2608 exc = NULL;
2609 }
2610 }
2611
2612 if (!exc) {
2613 /* exc was not a CancelledError */
Victor Stinnerf17c3de2016-12-06 18:46:19 +01002614 exc = _PyObject_CallNoArg(asyncio_CancelledError);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002615 if (!exc) {
2616 goto fail;
2617 }
2618 clear_exc = 1;
2619 }
2620
2621 task->task_must_cancel = 0;
2622 }
2623
2624 Py_CLEAR(task->task_fut_waiter);
2625
Serhiy Storchakabca49392017-09-03 08:10:14 +03002626 coro = task->task_coro;
2627 if (coro == NULL) {
2628 PyErr_SetString(PyExc_RuntimeError, "uninitialized Task object");
2629 return NULL;
2630 }
2631
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002632 if (exc == NULL) {
2633 if (PyGen_CheckExact(coro) || PyCoro_CheckExact(coro)) {
2634 result = _PyGen_Send((PyGenObject*)coro, Py_None);
2635 }
2636 else {
Victor Stinnerb6ed57d2016-12-09 14:24:02 +01002637 result = _PyObject_CallMethodIdObjArgs(coro, &PyId_send,
2638 Py_None, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002639 }
2640 }
2641 else {
Victor Stinnerb6ed57d2016-12-09 14:24:02 +01002642 result = _PyObject_CallMethodIdObjArgs(coro, &PyId_throw,
2643 exc, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002644 if (clear_exc) {
2645 /* We created 'exc' during this call */
Serhiy Storchakabca49392017-09-03 08:10:14 +03002646 Py_DECREF(exc);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002647 }
2648 }
2649
2650 if (result == NULL) {
2651 PyObject *et, *ev, *tb;
2652
2653 if (_PyGen_FetchStopIterationValue(&o) == 0) {
2654 /* The error is StopIteration and that means that
2655 the underlying coroutine has resolved */
Miss Islington (bot)16cec132019-09-25 04:48:52 -07002656
2657 PyObject *res;
INADA Naoki991adca2017-05-11 21:18:38 +09002658 if (task->task_must_cancel) {
2659 // Task is cancelled right before coro stops.
INADA Naoki991adca2017-05-11 21:18:38 +09002660 task->task_must_cancel = 0;
Miss Islington (bot)16cec132019-09-25 04:48:52 -07002661 res = future_cancel((FutureObj*)task);
INADA Naoki991adca2017-05-11 21:18:38 +09002662 }
Miss Islington (bot)16cec132019-09-25 04:48:52 -07002663 else {
2664 res = future_set_result((FutureObj*)task, o);
2665 }
2666
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002667 Py_DECREF(o);
Miss Islington (bot)16cec132019-09-25 04:48:52 -07002668
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002669 if (res == NULL) {
2670 return NULL;
2671 }
2672 Py_DECREF(res);
2673 Py_RETURN_NONE;
2674 }
2675
2676 if (PyErr_ExceptionMatches(asyncio_CancelledError)) {
2677 /* CancelledError */
2678 PyErr_Clear();
2679 return future_cancel((FutureObj*)task);
2680 }
2681
2682 /* Some other exception; pop it and call Task.set_exception() */
2683 PyErr_Fetch(&et, &ev, &tb);
INADA Naoki991adca2017-05-11 21:18:38 +09002684
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002685 assert(et);
2686 if (!ev || !PyObject_TypeCheck(ev, (PyTypeObject *) et)) {
2687 PyErr_NormalizeException(&et, &ev, &tb);
2688 }
Yury Selivanovedfe8862016-12-01 11:37:47 -05002689 if (tb != NULL) {
2690 PyException_SetTraceback(ev, tb);
2691 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002692 o = future_set_exception((FutureObj*)task, ev);
2693 if (!o) {
2694 /* An exception in Task.set_exception() */
Serhiy Storchakabca49392017-09-03 08:10:14 +03002695 Py_DECREF(et);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002696 Py_XDECREF(tb);
2697 Py_XDECREF(ev);
2698 goto fail;
2699 }
2700 assert(o == Py_None);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002701 Py_DECREF(o);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002702
Yury Selivanov431b5402019-05-27 14:45:12 +02002703 if (PyErr_GivenExceptionMatches(et, PyExc_KeyboardInterrupt) ||
2704 PyErr_GivenExceptionMatches(et, PyExc_SystemExit))
2705 {
2706 /* We've got a KeyboardInterrupt or a SystemError; re-raise it */
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002707 PyErr_Restore(et, ev, tb);
2708 goto fail;
2709 }
2710
Serhiy Storchakabca49392017-09-03 08:10:14 +03002711 Py_DECREF(et);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002712 Py_XDECREF(tb);
2713 Py_XDECREF(ev);
2714
2715 Py_RETURN_NONE;
2716 }
2717
2718 if (result == (PyObject*)task) {
2719 /* We have a task that wants to await on itself */
2720 goto self_await;
2721 }
2722
2723 /* Check if `result` is FutureObj or TaskObj (and not a subclass) */
2724 if (Future_CheckExact(result) || Task_CheckExact(result)) {
2725 PyObject *wrapper;
2726 PyObject *res;
2727 FutureObj *fut = (FutureObj*)result;
2728
2729 /* Check if `result` future is attached to a different loop */
2730 if (fut->fut_loop != task->task_loop) {
2731 goto different_loop;
2732 }
2733
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002734 if (!fut->fut_blocking) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002735 goto yield_insteadof_yf;
2736 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002737
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002738 fut->fut_blocking = 0;
2739
2740 /* result.add_done_callback(task._wakeup) */
2741 wrapper = TaskWakeupMethWrapper_new(task);
2742 if (wrapper == NULL) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002743 goto fail;
2744 }
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002745 res = future_add_done_callback(
2746 (FutureObj*)result, wrapper, task->task_context);
2747 Py_DECREF(wrapper);
2748 if (res == NULL) {
2749 goto fail;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002750 }
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002751 Py_DECREF(res);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002752
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002753 /* task._fut_waiter = result */
2754 task->task_fut_waiter = result; /* no incref is necessary */
2755
2756 if (task->task_must_cancel) {
2757 PyObject *r;
Elvis Pranskevichus0c797a62018-10-03 10:30:31 -04002758 int is_true;
Serhiy Storchakaaddf8af2018-10-05 21:20:02 +03002759 r = _PyObject_CallMethodId(result, &PyId_cancel, NULL);
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002760 if (r == NULL) {
2761 return NULL;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002762 }
Elvis Pranskevichus0c797a62018-10-03 10:30:31 -04002763 is_true = PyObject_IsTrue(r);
2764 Py_DECREF(r);
2765 if (is_true < 0) {
2766 return NULL;
2767 }
2768 else if (is_true) {
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002769 task->task_must_cancel = 0;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002770 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002771 }
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002772
2773 Py_RETURN_NONE;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002774 }
2775
2776 /* Check if `result` is None */
2777 if (result == Py_None) {
2778 /* Bare yield relinquishes control for one event loop iteration. */
2779 if (task_call_step_soon(task, NULL)) {
2780 goto fail;
2781 }
2782 return result;
2783 }
2784
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002785 /* Check if `result` is a Future-compatible object */
2786 if (_PyObject_LookupAttrId(result, &PyId__asyncio_future_blocking, &o) < 0) {
2787 goto fail;
2788 }
2789 if (o != NULL && o != Py_None) {
2790 /* `result` is a Future-compatible object */
2791 PyObject *wrapper;
2792 PyObject *res;
2793
2794 int blocking = PyObject_IsTrue(o);
2795 Py_DECREF(o);
2796 if (blocking < 0) {
2797 goto fail;
2798 }
2799
2800 /* Check if `result` future is attached to a different loop */
2801 PyObject *oloop = get_future_loop(result);
2802 if (oloop == NULL) {
2803 goto fail;
2804 }
2805 if (oloop != task->task_loop) {
2806 Py_DECREF(oloop);
2807 goto different_loop;
2808 }
2809 Py_DECREF(oloop);
2810
2811 if (!blocking) {
2812 goto yield_insteadof_yf;
2813 }
2814
2815 /* result._asyncio_future_blocking = False */
2816 if (_PyObject_SetAttrId(
2817 result, &PyId__asyncio_future_blocking, Py_False) == -1) {
2818 goto fail;
2819 }
2820
2821 wrapper = TaskWakeupMethWrapper_new(task);
2822 if (wrapper == NULL) {
2823 goto fail;
2824 }
2825
2826 /* result.add_done_callback(task._wakeup) */
2827 PyObject *add_cb = _PyObject_GetAttrId(
2828 result, &PyId_add_done_callback);
2829 if (add_cb == NULL) {
2830 Py_DECREF(wrapper);
2831 goto fail;
2832 }
2833 PyObject *stack[2];
2834 stack[0] = wrapper;
2835 stack[1] = (PyObject *)task->task_context;
Jeroen Demeyeraacc77f2019-05-29 20:31:52 +02002836 res = _PyObject_Vectorcall(add_cb, stack, 1, context_kwname);
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002837 Py_DECREF(add_cb);
2838 Py_DECREF(wrapper);
2839 if (res == NULL) {
2840 goto fail;
2841 }
2842 Py_DECREF(res);
2843
2844 /* task._fut_waiter = result */
2845 task->task_fut_waiter = result; /* no incref is necessary */
2846
2847 if (task->task_must_cancel) {
2848 PyObject *r;
2849 int is_true;
2850 r = _PyObject_CallMethodId(result, &PyId_cancel, NULL);
2851 if (r == NULL) {
2852 return NULL;
2853 }
2854 is_true = PyObject_IsTrue(r);
2855 Py_DECREF(r);
2856 if (is_true < 0) {
2857 return NULL;
2858 }
2859 else if (is_true) {
2860 task->task_must_cancel = 0;
2861 }
2862 }
2863
2864 Py_RETURN_NONE;
2865 }
2866
2867 Py_XDECREF(o);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002868 /* Check if `result` is a generator */
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002869 res = PyObject_IsInstance(result, (PyObject*)&PyGen_Type);
2870 if (res < 0) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002871 goto fail;
2872 }
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002873 if (res) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002874 /* `result` is a generator */
Serhiy Storchaka66553542018-05-20 16:30:31 +03002875 o = task_set_error_soon(
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002876 task, PyExc_RuntimeError,
2877 "yield was used instead of yield from for "
Serhiy Storchaka66553542018-05-20 16:30:31 +03002878 "generator in task %R with %R", task, result);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002879 Py_DECREF(result);
Serhiy Storchaka66553542018-05-20 16:30:31 +03002880 return o;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002881 }
2882
2883 /* The `result` is none of the above */
Serhiy Storchaka66553542018-05-20 16:30:31 +03002884 o = task_set_error_soon(
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002885 task, PyExc_RuntimeError, "Task got bad yield: %R", result);
Serhiy Storchaka66553542018-05-20 16:30:31 +03002886 Py_DECREF(result);
2887 return o;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002888
2889self_await:
2890 o = task_set_error_soon(
2891 task, PyExc_RuntimeError,
2892 "Task cannot await on itself: %R", task);
2893 Py_DECREF(result);
2894 return o;
2895
2896yield_insteadof_yf:
2897 o = task_set_error_soon(
2898 task, PyExc_RuntimeError,
2899 "yield was used instead of yield from "
2900 "in task %R with %R",
2901 task, result);
2902 Py_DECREF(result);
2903 return o;
2904
2905different_loop:
2906 o = task_set_error_soon(
2907 task, PyExc_RuntimeError,
2908 "Task %R got Future %R attached to a different loop",
2909 task, result);
2910 Py_DECREF(result);
2911 return o;
2912
2913fail:
2914 Py_XDECREF(result);
2915 return NULL;
2916}
2917
2918static PyObject *
2919task_step(TaskObj *task, PyObject *exc)
2920{
2921 PyObject *res;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002922
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002923 if (enter_task(task->task_loop, (PyObject*)task) < 0) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002924 return NULL;
2925 }
2926
2927 res = task_step_impl(task, exc);
2928
2929 if (res == NULL) {
2930 PyObject *et, *ev, *tb;
2931 PyErr_Fetch(&et, &ev, &tb);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002932 leave_task(task->task_loop, (PyObject*)task);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002933 _PyErr_ChainExceptions(et, ev, tb);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002934 return NULL;
2935 }
2936 else {
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002937 if (leave_task(task->task_loop, (PyObject*)task) < 0) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002938 Py_DECREF(res);
2939 return NULL;
2940 }
2941 else {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002942 return res;
2943 }
2944 }
2945}
2946
2947static PyObject *
2948task_wakeup(TaskObj *task, PyObject *o)
2949{
Serhiy Storchakabca49392017-09-03 08:10:14 +03002950 PyObject *et, *ev, *tb;
2951 PyObject *result;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002952 assert(o);
2953
2954 if (Future_CheckExact(o) || Task_CheckExact(o)) {
2955 PyObject *fut_result = NULL;
2956 int res = future_get_result((FutureObj*)o, &fut_result);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002957
2958 switch(res) {
2959 case -1:
2960 assert(fut_result == NULL);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002961 break; /* exception raised */
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002962 case 0:
2963 Py_DECREF(fut_result);
Yury Selivanov22feeb82018-01-24 11:31:01 -05002964 return task_step(task, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002965 default:
2966 assert(res == 1);
Yury Selivanov22feeb82018-01-24 11:31:01 -05002967 result = task_step(task, fut_result);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002968 Py_DECREF(fut_result);
2969 return result;
2970 }
2971 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002972 else {
Serhiy Storchakabca49392017-09-03 08:10:14 +03002973 PyObject *fut_result = PyObject_CallMethod(o, "result", NULL);
2974 if (fut_result != NULL) {
2975 Py_DECREF(fut_result);
Yury Selivanov22feeb82018-01-24 11:31:01 -05002976 return task_step(task, NULL);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002977 }
2978 /* exception raised */
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002979 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03002980
2981 PyErr_Fetch(&et, &ev, &tb);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002982 if (!ev || !PyObject_TypeCheck(ev, (PyTypeObject *) et)) {
2983 PyErr_NormalizeException(&et, &ev, &tb);
2984 }
2985
Yury Selivanov22feeb82018-01-24 11:31:01 -05002986 result = task_step(task, ev);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002987
2988 Py_DECREF(et);
2989 Py_XDECREF(tb);
2990 Py_XDECREF(ev);
2991
2992 return result;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002993}
2994
2995
Yury Selivanova70232f2017-12-13 14:49:42 -05002996/*********************** Functions **************************/
2997
2998
2999/*[clinic input]
3000_asyncio._get_running_loop
3001
3002Return the running event loop or None.
3003
3004This is a low-level function intended to be used by event loops.
3005This function is thread-specific.
3006
3007[clinic start generated code]*/
3008
3009static PyObject *
3010_asyncio__get_running_loop_impl(PyObject *module)
3011/*[clinic end generated code: output=b4390af721411a0a input=0a21627e25a4bd43]*/
3012{
3013 PyObject *loop;
3014 if (get_running_loop(&loop)) {
3015 return NULL;
3016 }
3017 if (loop == NULL) {
3018 /* There's no currently running event loop */
3019 Py_RETURN_NONE;
3020 }
3021 return loop;
3022}
3023
3024/*[clinic input]
3025_asyncio._set_running_loop
3026 loop: 'O'
3027 /
3028
3029Set the running event loop.
3030
3031This is a low-level function intended to be used by event loops.
3032This function is thread-specific.
3033[clinic start generated code]*/
3034
3035static PyObject *
3036_asyncio__set_running_loop(PyObject *module, PyObject *loop)
3037/*[clinic end generated code: output=ae56bf7a28ca189a input=4c9720233d606604]*/
3038{
3039 if (set_running_loop(loop)) {
3040 return NULL;
3041 }
3042 Py_RETURN_NONE;
3043}
3044
3045/*[clinic input]
3046_asyncio.get_event_loop
3047
3048Return an asyncio event loop.
3049
3050When called from a coroutine or a callback (e.g. scheduled with
3051call_soon or similar API), this function will always return the
3052running event loop.
3053
3054If there is no running event loop set, the function will return
3055the result of `get_event_loop_policy().get_event_loop()` call.
3056[clinic start generated code]*/
3057
3058static PyObject *
3059_asyncio_get_event_loop_impl(PyObject *module)
3060/*[clinic end generated code: output=2a2d8b2f824c648b input=9364bf2916c8655d]*/
3061{
3062 return get_event_loop();
3063}
3064
3065/*[clinic input]
3066_asyncio.get_running_loop
3067
3068Return the running event loop. Raise a RuntimeError if there is none.
3069
3070This function is thread-specific.
3071[clinic start generated code]*/
3072
3073static PyObject *
3074_asyncio_get_running_loop_impl(PyObject *module)
3075/*[clinic end generated code: output=c247b5f9e529530e input=2a3bf02ba39f173d]*/
3076{
3077 PyObject *loop;
3078 if (get_running_loop(&loop)) {
3079 return NULL;
3080 }
3081 if (loop == NULL) {
3082 /* There's no currently running event loop */
3083 PyErr_SetString(
3084 PyExc_RuntimeError, "no running event loop");
3085 }
3086 return loop;
3087}
3088
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003089/*[clinic input]
3090_asyncio._register_task
3091
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003092 task: object
3093
3094Register a new task in asyncio as executed by loop.
3095
3096Returns None.
3097[clinic start generated code]*/
3098
3099static PyObject *
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003100_asyncio__register_task_impl(PyObject *module, PyObject *task)
3101/*[clinic end generated code: output=8672dadd69a7d4e2 input=21075aaea14dfbad]*/
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003102{
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003103 if (register_task(task) < 0) {
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003104 return NULL;
3105 }
3106 Py_RETURN_NONE;
3107}
3108
3109
3110/*[clinic input]
3111_asyncio._unregister_task
3112
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003113 task: object
3114
3115Unregister a task.
3116
3117Returns None.
3118[clinic start generated code]*/
3119
3120static PyObject *
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003121_asyncio__unregister_task_impl(PyObject *module, PyObject *task)
3122/*[clinic end generated code: output=6e5585706d568a46 input=28fb98c3975f7bdc]*/
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003123{
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003124 if (unregister_task(task) < 0) {
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003125 return NULL;
3126 }
3127 Py_RETURN_NONE;
3128}
3129
3130
3131/*[clinic input]
3132_asyncio._enter_task
3133
3134 loop: object
3135 task: object
3136
3137Enter into task execution or resume suspended task.
3138
3139Task belongs to loop.
3140
3141Returns None.
3142[clinic start generated code]*/
3143
3144static PyObject *
3145_asyncio__enter_task_impl(PyObject *module, PyObject *loop, PyObject *task)
3146/*[clinic end generated code: output=a22611c858035b73 input=de1b06dca70d8737]*/
3147{
3148 if (enter_task(loop, task) < 0) {
3149 return NULL;
3150 }
3151 Py_RETURN_NONE;
3152}
3153
3154
3155/*[clinic input]
3156_asyncio._leave_task
3157
3158 loop: object
3159 task: object
3160
3161Leave task execution or suspend a task.
3162
3163Task belongs to loop.
3164
3165Returns None.
3166[clinic start generated code]*/
3167
3168static PyObject *
3169_asyncio__leave_task_impl(PyObject *module, PyObject *loop, PyObject *task)
3170/*[clinic end generated code: output=0ebf6db4b858fb41 input=51296a46313d1ad8]*/
3171{
3172 if (leave_task(loop, task) < 0) {
3173 return NULL;
3174 }
3175 Py_RETURN_NONE;
3176}
3177
Yury Selivanova70232f2017-12-13 14:49:42 -05003178
Yury Selivanov9d411c12018-01-23 15:10:03 -05003179/*********************** PyRunningLoopHolder ********************/
3180
3181
3182static PyRunningLoopHolder *
3183new_running_loop_holder(PyObject *loop)
3184{
3185 PyRunningLoopHolder *rl = PyObject_New(
3186 PyRunningLoopHolder, &PyRunningLoopHolder_Type);
3187 if (rl == NULL) {
3188 return NULL;
3189 }
3190
3191#if defined(HAVE_GETPID) && !defined(MS_WINDOWS)
3192 rl->rl_pid = getpid();
3193#endif
3194
3195 Py_INCREF(loop);
3196 rl->rl_loop = loop;
3197
3198 return rl;
3199}
3200
3201
3202static void
3203PyRunningLoopHolder_tp_dealloc(PyRunningLoopHolder *rl)
3204{
3205 Py_CLEAR(rl->rl_loop);
3206 PyObject_Free(rl);
3207}
3208
3209
3210static PyTypeObject PyRunningLoopHolder_Type = {
3211 PyVarObject_HEAD_INIT(NULL, 0)
3212 "_RunningLoopHolder",
3213 sizeof(PyRunningLoopHolder),
3214 .tp_getattro = PyObject_GenericGetAttr,
3215 .tp_flags = Py_TPFLAGS_DEFAULT,
3216 .tp_dealloc = (destructor)PyRunningLoopHolder_tp_dealloc,
3217};
3218
3219
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003220/*********************** Module **************************/
3221
3222
3223static void
Zackery Spytze40ad792017-12-19 11:48:13 -07003224module_free_freelists(void)
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05003225{
3226 PyObject *next;
3227 PyObject *current;
3228
3229 next = (PyObject*) fi_freelist;
3230 while (next != NULL) {
3231 assert(fi_freelist_len > 0);
3232 fi_freelist_len--;
3233
3234 current = next;
3235 next = (PyObject*) ((futureiterobject*) current)->future;
3236 PyObject_GC_Del(current);
3237 }
3238 assert(fi_freelist_len == 0);
3239 fi_freelist = NULL;
3240}
3241
3242
3243static void
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003244module_free(void *m)
3245{
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003246 Py_CLEAR(asyncio_mod);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003247 Py_CLEAR(traceback_extract_stack);
3248 Py_CLEAR(asyncio_future_repr_info_func);
3249 Py_CLEAR(asyncio_get_event_loop_policy);
3250 Py_CLEAR(asyncio_iscoroutine_func);
3251 Py_CLEAR(asyncio_task_get_stack_func);
3252 Py_CLEAR(asyncio_task_print_stack_func);
3253 Py_CLEAR(asyncio_task_repr_info_func);
3254 Py_CLEAR(asyncio_InvalidStateError);
3255 Py_CLEAR(asyncio_CancelledError);
3256
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003257 Py_CLEAR(all_tasks);
Yury Selivanova9d7e552017-12-19 07:18:45 -05003258 Py_CLEAR(current_tasks);
3259 Py_CLEAR(iscoroutine_typecache);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05003260
Yury Selivanovf23746a2018-01-22 19:11:18 -05003261 Py_CLEAR(context_kwname);
3262
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05003263 module_free_freelists();
Miss Islington (bot)6b0ca0a2020-04-16 19:29:50 -07003264
3265 module_initialized = 0;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003266}
3267
3268static int
3269module_init(void)
3270{
3271 PyObject *module = NULL;
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003272
3273 asyncio_mod = PyImport_ImportModule("asyncio");
3274 if (asyncio_mod == NULL) {
3275 goto fail;
3276 }
Miss Islington (bot)13915a32019-10-07 09:38:00 -07003277 if (module_initialized != 0) {
3278 return 0;
Miss Islington (bot)ce0a2a82019-12-07 03:41:41 -08003279 }
Miss Islington (bot)13915a32019-10-07 09:38:00 -07003280 else {
3281 module_initialized = 1;
3282 }
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003283
3284 current_tasks = PyDict_New();
3285 if (current_tasks == NULL) {
3286 goto fail;
3287 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003288
Yury Selivanova9d7e552017-12-19 07:18:45 -05003289 iscoroutine_typecache = PySet_New(NULL);
3290 if (iscoroutine_typecache == NULL) {
3291 goto fail;
3292 }
3293
Yury Selivanovf23746a2018-01-22 19:11:18 -05003294
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03003295 context_kwname = Py_BuildValue("(s)", "context");
Yury Selivanovf23746a2018-01-22 19:11:18 -05003296 if (context_kwname == NULL) {
3297 goto fail;
3298 }
Yury Selivanovf23746a2018-01-22 19:11:18 -05003299
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003300#define WITH_MOD(NAME) \
3301 Py_CLEAR(module); \
3302 module = PyImport_ImportModule(NAME); \
3303 if (module == NULL) { \
Serhiy Storchakabca49392017-09-03 08:10:14 +03003304 goto fail; \
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003305 }
3306
3307#define GET_MOD_ATTR(VAR, NAME) \
3308 VAR = PyObject_GetAttrString(module, NAME); \
3309 if (VAR == NULL) { \
3310 goto fail; \
3311 }
3312
3313 WITH_MOD("asyncio.events")
Yury Selivanova70232f2017-12-13 14:49:42 -05003314 GET_MOD_ATTR(asyncio_get_event_loop_policy, "get_event_loop_policy")
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003315
3316 WITH_MOD("asyncio.base_futures")
3317 GET_MOD_ATTR(asyncio_future_repr_info_func, "_future_repr_info")
Andrew Svetlov0baa72f2018-09-11 10:13:04 -07003318
3319 WITH_MOD("asyncio.exceptions")
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003320 GET_MOD_ATTR(asyncio_InvalidStateError, "InvalidStateError")
3321 GET_MOD_ATTR(asyncio_CancelledError, "CancelledError")
3322
3323 WITH_MOD("asyncio.base_tasks")
3324 GET_MOD_ATTR(asyncio_task_repr_info_func, "_task_repr_info")
3325 GET_MOD_ATTR(asyncio_task_get_stack_func, "_task_get_stack")
3326 GET_MOD_ATTR(asyncio_task_print_stack_func, "_task_print_stack")
3327
Andrew Svetlovf74ef452017-12-15 07:04:38 +02003328 WITH_MOD("asyncio.coroutines")
3329 GET_MOD_ATTR(asyncio_iscoroutine_func, "iscoroutine")
3330
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003331 WITH_MOD("traceback")
3332 GET_MOD_ATTR(traceback_extract_stack, "extract_stack")
3333
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003334 PyObject *weak_set;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003335 WITH_MOD("weakref")
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003336 GET_MOD_ATTR(weak_set, "WeakSet");
3337 all_tasks = _PyObject_CallNoArg(weak_set);
3338 Py_CLEAR(weak_set);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003339 if (all_tasks == NULL) {
INADA Naokic411a7d2016-10-18 11:48:14 +09003340 goto fail;
3341 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003342
Serhiy Storchakabca49392017-09-03 08:10:14 +03003343 Py_DECREF(module);
INADA Naokic411a7d2016-10-18 11:48:14 +09003344 return 0;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003345
INADA Naokic411a7d2016-10-18 11:48:14 +09003346fail:
INADA Naokic411a7d2016-10-18 11:48:14 +09003347 Py_CLEAR(module);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003348 module_free(NULL);
INADA Naokic411a7d2016-10-18 11:48:14 +09003349 return -1;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003350
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003351#undef WITH_MOD
3352#undef GET_MOD_ATTR
3353}
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003354
INADA Naokic411a7d2016-10-18 11:48:14 +09003355PyDoc_STRVAR(module_doc, "Accelerator module for asyncio");
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003356
Yury Selivanova70232f2017-12-13 14:49:42 -05003357static PyMethodDef asyncio_methods[] = {
3358 _ASYNCIO_GET_EVENT_LOOP_METHODDEF
3359 _ASYNCIO_GET_RUNNING_LOOP_METHODDEF
3360 _ASYNCIO__GET_RUNNING_LOOP_METHODDEF
3361 _ASYNCIO__SET_RUNNING_LOOP_METHODDEF
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003362 _ASYNCIO__REGISTER_TASK_METHODDEF
3363 _ASYNCIO__UNREGISTER_TASK_METHODDEF
3364 _ASYNCIO__ENTER_TASK_METHODDEF
3365 _ASYNCIO__LEAVE_TASK_METHODDEF
Yury Selivanova70232f2017-12-13 14:49:42 -05003366 {NULL, NULL}
3367};
3368
INADA Naoki9f2ce252016-10-15 15:39:19 +09003369static struct PyModuleDef _asynciomodule = {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003370 PyModuleDef_HEAD_INIT, /* m_base */
INADA Naoki9f2ce252016-10-15 15:39:19 +09003371 "_asyncio", /* m_name */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003372 module_doc, /* m_doc */
3373 -1, /* m_size */
Yury Selivanova70232f2017-12-13 14:49:42 -05003374 asyncio_methods, /* m_methods */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003375 NULL, /* m_slots */
3376 NULL, /* m_traverse */
3377 NULL, /* m_clear */
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003378 (freefunc)module_free /* m_free */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003379};
3380
3381
3382PyMODINIT_FUNC
INADA Naoki9f2ce252016-10-15 15:39:19 +09003383PyInit__asyncio(void)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003384{
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003385 if (module_init() < 0) {
INADA Naokic411a7d2016-10-18 11:48:14 +09003386 return NULL;
3387 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003388 if (PyType_Ready(&FutureType) < 0) {
3389 return NULL;
3390 }
3391 if (PyType_Ready(&FutureIterType) < 0) {
3392 return NULL;
3393 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03003394 if (PyType_Ready(&TaskStepMethWrapper_Type) < 0) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003395 return NULL;
3396 }
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03003397 if (PyType_Ready(&TaskWakeupMethWrapper_Type) < 0) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003398 return NULL;
3399 }
3400 if (PyType_Ready(&TaskType) < 0) {
3401 return NULL;
3402 }
Yury Selivanov9d411c12018-01-23 15:10:03 -05003403 if (PyType_Ready(&PyRunningLoopHolder_Type) < 0) {
3404 return NULL;
3405 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003406
INADA Naoki9f2ce252016-10-15 15:39:19 +09003407 PyObject *m = PyModule_Create(&_asynciomodule);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003408 if (m == NULL) {
3409 return NULL;
3410 }
3411
3412 Py_INCREF(&FutureType);
3413 if (PyModule_AddObject(m, "Future", (PyObject *)&FutureType) < 0) {
3414 Py_DECREF(&FutureType);
Miss Islington (bot)48f4f752019-11-16 14:44:15 -08003415 Py_DECREF(m);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003416 return NULL;
3417 }
3418
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003419 Py_INCREF(&TaskType);
3420 if (PyModule_AddObject(m, "Task", (PyObject *)&TaskType) < 0) {
3421 Py_DECREF(&TaskType);
Miss Islington (bot)48f4f752019-11-16 14:44:15 -08003422 Py_DECREF(m);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003423 return NULL;
3424 }
3425
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003426 Py_INCREF(all_tasks);
3427 if (PyModule_AddObject(m, "_all_tasks", all_tasks) < 0) {
3428 Py_DECREF(all_tasks);
Miss Islington (bot)48f4f752019-11-16 14:44:15 -08003429 Py_DECREF(m);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003430 return NULL;
3431 }
3432
3433 Py_INCREF(current_tasks);
3434 if (PyModule_AddObject(m, "_current_tasks", current_tasks) < 0) {
3435 Py_DECREF(current_tasks);
Miss Islington (bot)48f4f752019-11-16 14:44:15 -08003436 Py_DECREF(m);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003437 return NULL;
3438 }
3439
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003440 return m;
3441}