blob: 8e1cd4f52a540a285ce10c0d23bda1195a73818d [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");
Miss Islington (bot)0e4a5e92020-05-08 04:28:38 -07002629 if (clear_exc) {
2630 /* We created 'exc' during this call */
2631 Py_DECREF(exc);
2632 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03002633 return NULL;
2634 }
2635
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002636 if (exc == NULL) {
2637 if (PyGen_CheckExact(coro) || PyCoro_CheckExact(coro)) {
2638 result = _PyGen_Send((PyGenObject*)coro, Py_None);
2639 }
2640 else {
Victor Stinnerb6ed57d2016-12-09 14:24:02 +01002641 result = _PyObject_CallMethodIdObjArgs(coro, &PyId_send,
2642 Py_None, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002643 }
2644 }
2645 else {
Victor Stinnerb6ed57d2016-12-09 14:24:02 +01002646 result = _PyObject_CallMethodIdObjArgs(coro, &PyId_throw,
2647 exc, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002648 if (clear_exc) {
2649 /* We created 'exc' during this call */
Serhiy Storchakabca49392017-09-03 08:10:14 +03002650 Py_DECREF(exc);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002651 }
2652 }
2653
2654 if (result == NULL) {
2655 PyObject *et, *ev, *tb;
2656
2657 if (_PyGen_FetchStopIterationValue(&o) == 0) {
2658 /* The error is StopIteration and that means that
2659 the underlying coroutine has resolved */
Miss Islington (bot)16cec132019-09-25 04:48:52 -07002660
2661 PyObject *res;
INADA Naoki991adca2017-05-11 21:18:38 +09002662 if (task->task_must_cancel) {
2663 // Task is cancelled right before coro stops.
INADA Naoki991adca2017-05-11 21:18:38 +09002664 task->task_must_cancel = 0;
Miss Islington (bot)16cec132019-09-25 04:48:52 -07002665 res = future_cancel((FutureObj*)task);
INADA Naoki991adca2017-05-11 21:18:38 +09002666 }
Miss Islington (bot)16cec132019-09-25 04:48:52 -07002667 else {
2668 res = future_set_result((FutureObj*)task, o);
2669 }
2670
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002671 Py_DECREF(o);
Miss Islington (bot)16cec132019-09-25 04:48:52 -07002672
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002673 if (res == NULL) {
2674 return NULL;
2675 }
2676 Py_DECREF(res);
2677 Py_RETURN_NONE;
2678 }
2679
2680 if (PyErr_ExceptionMatches(asyncio_CancelledError)) {
2681 /* CancelledError */
2682 PyErr_Clear();
2683 return future_cancel((FutureObj*)task);
2684 }
2685
2686 /* Some other exception; pop it and call Task.set_exception() */
2687 PyErr_Fetch(&et, &ev, &tb);
INADA Naoki991adca2017-05-11 21:18:38 +09002688
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002689 assert(et);
2690 if (!ev || !PyObject_TypeCheck(ev, (PyTypeObject *) et)) {
2691 PyErr_NormalizeException(&et, &ev, &tb);
2692 }
Yury Selivanovedfe8862016-12-01 11:37:47 -05002693 if (tb != NULL) {
2694 PyException_SetTraceback(ev, tb);
2695 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002696 o = future_set_exception((FutureObj*)task, ev);
2697 if (!o) {
2698 /* An exception in Task.set_exception() */
Serhiy Storchakabca49392017-09-03 08:10:14 +03002699 Py_DECREF(et);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002700 Py_XDECREF(tb);
2701 Py_XDECREF(ev);
2702 goto fail;
2703 }
2704 assert(o == Py_None);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002705 Py_DECREF(o);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002706
Yury Selivanov431b5402019-05-27 14:45:12 +02002707 if (PyErr_GivenExceptionMatches(et, PyExc_KeyboardInterrupt) ||
2708 PyErr_GivenExceptionMatches(et, PyExc_SystemExit))
2709 {
2710 /* We've got a KeyboardInterrupt or a SystemError; re-raise it */
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002711 PyErr_Restore(et, ev, tb);
2712 goto fail;
2713 }
2714
Serhiy Storchakabca49392017-09-03 08:10:14 +03002715 Py_DECREF(et);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002716 Py_XDECREF(tb);
2717 Py_XDECREF(ev);
2718
2719 Py_RETURN_NONE;
2720 }
2721
2722 if (result == (PyObject*)task) {
2723 /* We have a task that wants to await on itself */
2724 goto self_await;
2725 }
2726
2727 /* Check if `result` is FutureObj or TaskObj (and not a subclass) */
2728 if (Future_CheckExact(result) || Task_CheckExact(result)) {
2729 PyObject *wrapper;
2730 PyObject *res;
2731 FutureObj *fut = (FutureObj*)result;
2732
2733 /* Check if `result` future is attached to a different loop */
2734 if (fut->fut_loop != task->task_loop) {
2735 goto different_loop;
2736 }
2737
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002738 if (!fut->fut_blocking) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002739 goto yield_insteadof_yf;
2740 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002741
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002742 fut->fut_blocking = 0;
2743
2744 /* result.add_done_callback(task._wakeup) */
2745 wrapper = TaskWakeupMethWrapper_new(task);
2746 if (wrapper == NULL) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002747 goto fail;
2748 }
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002749 res = future_add_done_callback(
2750 (FutureObj*)result, wrapper, task->task_context);
2751 Py_DECREF(wrapper);
2752 if (res == NULL) {
2753 goto fail;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002754 }
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002755 Py_DECREF(res);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002756
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002757 /* task._fut_waiter = result */
2758 task->task_fut_waiter = result; /* no incref is necessary */
2759
2760 if (task->task_must_cancel) {
2761 PyObject *r;
Elvis Pranskevichus0c797a62018-10-03 10:30:31 -04002762 int is_true;
Serhiy Storchakaaddf8af2018-10-05 21:20:02 +03002763 r = _PyObject_CallMethodId(result, &PyId_cancel, NULL);
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002764 if (r == NULL) {
2765 return NULL;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002766 }
Elvis Pranskevichus0c797a62018-10-03 10:30:31 -04002767 is_true = PyObject_IsTrue(r);
2768 Py_DECREF(r);
2769 if (is_true < 0) {
2770 return NULL;
2771 }
2772 else if (is_true) {
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002773 task->task_must_cancel = 0;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002774 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002775 }
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002776
2777 Py_RETURN_NONE;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002778 }
2779
2780 /* Check if `result` is None */
2781 if (result == Py_None) {
2782 /* Bare yield relinquishes control for one event loop iteration. */
2783 if (task_call_step_soon(task, NULL)) {
2784 goto fail;
2785 }
2786 return result;
2787 }
2788
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002789 /* Check if `result` is a Future-compatible object */
2790 if (_PyObject_LookupAttrId(result, &PyId__asyncio_future_blocking, &o) < 0) {
2791 goto fail;
2792 }
2793 if (o != NULL && o != Py_None) {
2794 /* `result` is a Future-compatible object */
2795 PyObject *wrapper;
2796 PyObject *res;
2797
2798 int blocking = PyObject_IsTrue(o);
2799 Py_DECREF(o);
2800 if (blocking < 0) {
2801 goto fail;
2802 }
2803
2804 /* Check if `result` future is attached to a different loop */
2805 PyObject *oloop = get_future_loop(result);
2806 if (oloop == NULL) {
2807 goto fail;
2808 }
2809 if (oloop != task->task_loop) {
2810 Py_DECREF(oloop);
2811 goto different_loop;
2812 }
2813 Py_DECREF(oloop);
2814
2815 if (!blocking) {
2816 goto yield_insteadof_yf;
2817 }
2818
2819 /* result._asyncio_future_blocking = False */
2820 if (_PyObject_SetAttrId(
2821 result, &PyId__asyncio_future_blocking, Py_False) == -1) {
2822 goto fail;
2823 }
2824
2825 wrapper = TaskWakeupMethWrapper_new(task);
2826 if (wrapper == NULL) {
2827 goto fail;
2828 }
2829
2830 /* result.add_done_callback(task._wakeup) */
2831 PyObject *add_cb = _PyObject_GetAttrId(
2832 result, &PyId_add_done_callback);
2833 if (add_cb == NULL) {
2834 Py_DECREF(wrapper);
2835 goto fail;
2836 }
2837 PyObject *stack[2];
2838 stack[0] = wrapper;
2839 stack[1] = (PyObject *)task->task_context;
Jeroen Demeyeraacc77f2019-05-29 20:31:52 +02002840 res = _PyObject_Vectorcall(add_cb, stack, 1, context_kwname);
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002841 Py_DECREF(add_cb);
2842 Py_DECREF(wrapper);
2843 if (res == NULL) {
2844 goto fail;
2845 }
2846 Py_DECREF(res);
2847
2848 /* task._fut_waiter = result */
2849 task->task_fut_waiter = result; /* no incref is necessary */
2850
2851 if (task->task_must_cancel) {
2852 PyObject *r;
2853 int is_true;
2854 r = _PyObject_CallMethodId(result, &PyId_cancel, NULL);
2855 if (r == NULL) {
2856 return NULL;
2857 }
2858 is_true = PyObject_IsTrue(r);
2859 Py_DECREF(r);
2860 if (is_true < 0) {
2861 return NULL;
2862 }
2863 else if (is_true) {
2864 task->task_must_cancel = 0;
2865 }
2866 }
2867
2868 Py_RETURN_NONE;
2869 }
2870
2871 Py_XDECREF(o);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002872 /* Check if `result` is a generator */
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002873 res = PyObject_IsInstance(result, (PyObject*)&PyGen_Type);
2874 if (res < 0) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002875 goto fail;
2876 }
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002877 if (res) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002878 /* `result` is a generator */
Serhiy Storchaka66553542018-05-20 16:30:31 +03002879 o = task_set_error_soon(
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002880 task, PyExc_RuntimeError,
2881 "yield was used instead of yield from for "
Serhiy Storchaka66553542018-05-20 16:30:31 +03002882 "generator in task %R with %R", task, result);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002883 Py_DECREF(result);
Serhiy Storchaka66553542018-05-20 16:30:31 +03002884 return o;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002885 }
2886
2887 /* The `result` is none of the above */
Serhiy Storchaka66553542018-05-20 16:30:31 +03002888 o = task_set_error_soon(
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002889 task, PyExc_RuntimeError, "Task got bad yield: %R", result);
Serhiy Storchaka66553542018-05-20 16:30:31 +03002890 Py_DECREF(result);
2891 return o;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002892
2893self_await:
2894 o = task_set_error_soon(
2895 task, PyExc_RuntimeError,
2896 "Task cannot await on itself: %R", task);
2897 Py_DECREF(result);
2898 return o;
2899
2900yield_insteadof_yf:
2901 o = task_set_error_soon(
2902 task, PyExc_RuntimeError,
2903 "yield was used instead of yield from "
2904 "in task %R with %R",
2905 task, result);
2906 Py_DECREF(result);
2907 return o;
2908
2909different_loop:
2910 o = task_set_error_soon(
2911 task, PyExc_RuntimeError,
2912 "Task %R got Future %R attached to a different loop",
2913 task, result);
2914 Py_DECREF(result);
2915 return o;
2916
2917fail:
2918 Py_XDECREF(result);
2919 return NULL;
2920}
2921
2922static PyObject *
2923task_step(TaskObj *task, PyObject *exc)
2924{
2925 PyObject *res;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002926
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002927 if (enter_task(task->task_loop, (PyObject*)task) < 0) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002928 return NULL;
2929 }
2930
2931 res = task_step_impl(task, exc);
2932
2933 if (res == NULL) {
2934 PyObject *et, *ev, *tb;
2935 PyErr_Fetch(&et, &ev, &tb);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002936 leave_task(task->task_loop, (PyObject*)task);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002937 _PyErr_ChainExceptions(et, ev, tb);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002938 return NULL;
2939 }
2940 else {
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002941 if (leave_task(task->task_loop, (PyObject*)task) < 0) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002942 Py_DECREF(res);
2943 return NULL;
2944 }
2945 else {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002946 return res;
2947 }
2948 }
2949}
2950
2951static PyObject *
2952task_wakeup(TaskObj *task, PyObject *o)
2953{
Serhiy Storchakabca49392017-09-03 08:10:14 +03002954 PyObject *et, *ev, *tb;
2955 PyObject *result;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002956 assert(o);
2957
2958 if (Future_CheckExact(o) || Task_CheckExact(o)) {
2959 PyObject *fut_result = NULL;
2960 int res = future_get_result((FutureObj*)o, &fut_result);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002961
2962 switch(res) {
2963 case -1:
2964 assert(fut_result == NULL);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002965 break; /* exception raised */
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002966 case 0:
2967 Py_DECREF(fut_result);
Yury Selivanov22feeb82018-01-24 11:31:01 -05002968 return task_step(task, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002969 default:
2970 assert(res == 1);
Yury Selivanov22feeb82018-01-24 11:31:01 -05002971 result = task_step(task, fut_result);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002972 Py_DECREF(fut_result);
2973 return result;
2974 }
2975 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002976 else {
Serhiy Storchakabca49392017-09-03 08:10:14 +03002977 PyObject *fut_result = PyObject_CallMethod(o, "result", NULL);
2978 if (fut_result != NULL) {
2979 Py_DECREF(fut_result);
Yury Selivanov22feeb82018-01-24 11:31:01 -05002980 return task_step(task, NULL);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002981 }
2982 /* exception raised */
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002983 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03002984
2985 PyErr_Fetch(&et, &ev, &tb);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002986 if (!ev || !PyObject_TypeCheck(ev, (PyTypeObject *) et)) {
2987 PyErr_NormalizeException(&et, &ev, &tb);
2988 }
2989
Yury Selivanov22feeb82018-01-24 11:31:01 -05002990 result = task_step(task, ev);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002991
2992 Py_DECREF(et);
2993 Py_XDECREF(tb);
2994 Py_XDECREF(ev);
2995
2996 return result;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002997}
2998
2999
Yury Selivanova70232f2017-12-13 14:49:42 -05003000/*********************** Functions **************************/
3001
3002
3003/*[clinic input]
3004_asyncio._get_running_loop
3005
3006Return the running event loop or None.
3007
3008This is a low-level function intended to be used by event loops.
3009This function is thread-specific.
3010
3011[clinic start generated code]*/
3012
3013static PyObject *
3014_asyncio__get_running_loop_impl(PyObject *module)
3015/*[clinic end generated code: output=b4390af721411a0a input=0a21627e25a4bd43]*/
3016{
3017 PyObject *loop;
3018 if (get_running_loop(&loop)) {
3019 return NULL;
3020 }
3021 if (loop == NULL) {
3022 /* There's no currently running event loop */
3023 Py_RETURN_NONE;
3024 }
3025 return loop;
3026}
3027
3028/*[clinic input]
3029_asyncio._set_running_loop
3030 loop: 'O'
3031 /
3032
3033Set the running event loop.
3034
3035This is a low-level function intended to be used by event loops.
3036This function is thread-specific.
3037[clinic start generated code]*/
3038
3039static PyObject *
3040_asyncio__set_running_loop(PyObject *module, PyObject *loop)
3041/*[clinic end generated code: output=ae56bf7a28ca189a input=4c9720233d606604]*/
3042{
3043 if (set_running_loop(loop)) {
3044 return NULL;
3045 }
3046 Py_RETURN_NONE;
3047}
3048
3049/*[clinic input]
3050_asyncio.get_event_loop
3051
3052Return an asyncio event loop.
3053
3054When called from a coroutine or a callback (e.g. scheduled with
3055call_soon or similar API), this function will always return the
3056running event loop.
3057
3058If there is no running event loop set, the function will return
3059the result of `get_event_loop_policy().get_event_loop()` call.
3060[clinic start generated code]*/
3061
3062static PyObject *
3063_asyncio_get_event_loop_impl(PyObject *module)
3064/*[clinic end generated code: output=2a2d8b2f824c648b input=9364bf2916c8655d]*/
3065{
3066 return get_event_loop();
3067}
3068
3069/*[clinic input]
3070_asyncio.get_running_loop
3071
3072Return the running event loop. Raise a RuntimeError if there is none.
3073
3074This function is thread-specific.
3075[clinic start generated code]*/
3076
3077static PyObject *
3078_asyncio_get_running_loop_impl(PyObject *module)
3079/*[clinic end generated code: output=c247b5f9e529530e input=2a3bf02ba39f173d]*/
3080{
3081 PyObject *loop;
3082 if (get_running_loop(&loop)) {
3083 return NULL;
3084 }
3085 if (loop == NULL) {
3086 /* There's no currently running event loop */
3087 PyErr_SetString(
3088 PyExc_RuntimeError, "no running event loop");
3089 }
3090 return loop;
3091}
3092
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003093/*[clinic input]
3094_asyncio._register_task
3095
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003096 task: object
3097
3098Register a new task in asyncio as executed by loop.
3099
3100Returns None.
3101[clinic start generated code]*/
3102
3103static PyObject *
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003104_asyncio__register_task_impl(PyObject *module, PyObject *task)
3105/*[clinic end generated code: output=8672dadd69a7d4e2 input=21075aaea14dfbad]*/
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003106{
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003107 if (register_task(task) < 0) {
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003108 return NULL;
3109 }
3110 Py_RETURN_NONE;
3111}
3112
3113
3114/*[clinic input]
3115_asyncio._unregister_task
3116
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003117 task: object
3118
3119Unregister a task.
3120
3121Returns None.
3122[clinic start generated code]*/
3123
3124static PyObject *
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003125_asyncio__unregister_task_impl(PyObject *module, PyObject *task)
3126/*[clinic end generated code: output=6e5585706d568a46 input=28fb98c3975f7bdc]*/
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003127{
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003128 if (unregister_task(task) < 0) {
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003129 return NULL;
3130 }
3131 Py_RETURN_NONE;
3132}
3133
3134
3135/*[clinic input]
3136_asyncio._enter_task
3137
3138 loop: object
3139 task: object
3140
3141Enter into task execution or resume suspended task.
3142
3143Task belongs to loop.
3144
3145Returns None.
3146[clinic start generated code]*/
3147
3148static PyObject *
3149_asyncio__enter_task_impl(PyObject *module, PyObject *loop, PyObject *task)
3150/*[clinic end generated code: output=a22611c858035b73 input=de1b06dca70d8737]*/
3151{
3152 if (enter_task(loop, task) < 0) {
3153 return NULL;
3154 }
3155 Py_RETURN_NONE;
3156}
3157
3158
3159/*[clinic input]
3160_asyncio._leave_task
3161
3162 loop: object
3163 task: object
3164
3165Leave task execution or suspend a task.
3166
3167Task belongs to loop.
3168
3169Returns None.
3170[clinic start generated code]*/
3171
3172static PyObject *
3173_asyncio__leave_task_impl(PyObject *module, PyObject *loop, PyObject *task)
3174/*[clinic end generated code: output=0ebf6db4b858fb41 input=51296a46313d1ad8]*/
3175{
3176 if (leave_task(loop, task) < 0) {
3177 return NULL;
3178 }
3179 Py_RETURN_NONE;
3180}
3181
Yury Selivanova70232f2017-12-13 14:49:42 -05003182
Yury Selivanov9d411c12018-01-23 15:10:03 -05003183/*********************** PyRunningLoopHolder ********************/
3184
3185
3186static PyRunningLoopHolder *
3187new_running_loop_holder(PyObject *loop)
3188{
3189 PyRunningLoopHolder *rl = PyObject_New(
3190 PyRunningLoopHolder, &PyRunningLoopHolder_Type);
3191 if (rl == NULL) {
3192 return NULL;
3193 }
3194
3195#if defined(HAVE_GETPID) && !defined(MS_WINDOWS)
3196 rl->rl_pid = getpid();
3197#endif
3198
3199 Py_INCREF(loop);
3200 rl->rl_loop = loop;
3201
3202 return rl;
3203}
3204
3205
3206static void
3207PyRunningLoopHolder_tp_dealloc(PyRunningLoopHolder *rl)
3208{
3209 Py_CLEAR(rl->rl_loop);
3210 PyObject_Free(rl);
3211}
3212
3213
3214static PyTypeObject PyRunningLoopHolder_Type = {
3215 PyVarObject_HEAD_INIT(NULL, 0)
3216 "_RunningLoopHolder",
3217 sizeof(PyRunningLoopHolder),
3218 .tp_getattro = PyObject_GenericGetAttr,
3219 .tp_flags = Py_TPFLAGS_DEFAULT,
3220 .tp_dealloc = (destructor)PyRunningLoopHolder_tp_dealloc,
3221};
3222
3223
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003224/*********************** Module **************************/
3225
3226
3227static void
Zackery Spytze40ad792017-12-19 11:48:13 -07003228module_free_freelists(void)
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05003229{
3230 PyObject *next;
3231 PyObject *current;
3232
3233 next = (PyObject*) fi_freelist;
3234 while (next != NULL) {
3235 assert(fi_freelist_len > 0);
3236 fi_freelist_len--;
3237
3238 current = next;
3239 next = (PyObject*) ((futureiterobject*) current)->future;
3240 PyObject_GC_Del(current);
3241 }
3242 assert(fi_freelist_len == 0);
3243 fi_freelist = NULL;
3244}
3245
3246
3247static void
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003248module_free(void *m)
3249{
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003250 Py_CLEAR(asyncio_mod);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003251 Py_CLEAR(traceback_extract_stack);
3252 Py_CLEAR(asyncio_future_repr_info_func);
3253 Py_CLEAR(asyncio_get_event_loop_policy);
3254 Py_CLEAR(asyncio_iscoroutine_func);
3255 Py_CLEAR(asyncio_task_get_stack_func);
3256 Py_CLEAR(asyncio_task_print_stack_func);
3257 Py_CLEAR(asyncio_task_repr_info_func);
3258 Py_CLEAR(asyncio_InvalidStateError);
3259 Py_CLEAR(asyncio_CancelledError);
3260
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003261 Py_CLEAR(all_tasks);
Yury Selivanova9d7e552017-12-19 07:18:45 -05003262 Py_CLEAR(current_tasks);
3263 Py_CLEAR(iscoroutine_typecache);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05003264
Yury Selivanovf23746a2018-01-22 19:11:18 -05003265 Py_CLEAR(context_kwname);
3266
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05003267 module_free_freelists();
Miss Islington (bot)6b0ca0a2020-04-16 19:29:50 -07003268
3269 module_initialized = 0;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003270}
3271
3272static int
3273module_init(void)
3274{
3275 PyObject *module = NULL;
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003276
3277 asyncio_mod = PyImport_ImportModule("asyncio");
3278 if (asyncio_mod == NULL) {
3279 goto fail;
3280 }
Miss Islington (bot)13915a32019-10-07 09:38:00 -07003281 if (module_initialized != 0) {
3282 return 0;
Miss Islington (bot)ce0a2a82019-12-07 03:41:41 -08003283 }
Miss Islington (bot)13915a32019-10-07 09:38:00 -07003284 else {
3285 module_initialized = 1;
3286 }
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003287
3288 current_tasks = PyDict_New();
3289 if (current_tasks == NULL) {
3290 goto fail;
3291 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003292
Yury Selivanova9d7e552017-12-19 07:18:45 -05003293 iscoroutine_typecache = PySet_New(NULL);
3294 if (iscoroutine_typecache == NULL) {
3295 goto fail;
3296 }
3297
Yury Selivanovf23746a2018-01-22 19:11:18 -05003298
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03003299 context_kwname = Py_BuildValue("(s)", "context");
Yury Selivanovf23746a2018-01-22 19:11:18 -05003300 if (context_kwname == NULL) {
3301 goto fail;
3302 }
Yury Selivanovf23746a2018-01-22 19:11:18 -05003303
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003304#define WITH_MOD(NAME) \
3305 Py_CLEAR(module); \
3306 module = PyImport_ImportModule(NAME); \
3307 if (module == NULL) { \
Serhiy Storchakabca49392017-09-03 08:10:14 +03003308 goto fail; \
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003309 }
3310
3311#define GET_MOD_ATTR(VAR, NAME) \
3312 VAR = PyObject_GetAttrString(module, NAME); \
3313 if (VAR == NULL) { \
3314 goto fail; \
3315 }
3316
3317 WITH_MOD("asyncio.events")
Yury Selivanova70232f2017-12-13 14:49:42 -05003318 GET_MOD_ATTR(asyncio_get_event_loop_policy, "get_event_loop_policy")
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003319
3320 WITH_MOD("asyncio.base_futures")
3321 GET_MOD_ATTR(asyncio_future_repr_info_func, "_future_repr_info")
Andrew Svetlov0baa72f2018-09-11 10:13:04 -07003322
3323 WITH_MOD("asyncio.exceptions")
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003324 GET_MOD_ATTR(asyncio_InvalidStateError, "InvalidStateError")
3325 GET_MOD_ATTR(asyncio_CancelledError, "CancelledError")
3326
3327 WITH_MOD("asyncio.base_tasks")
3328 GET_MOD_ATTR(asyncio_task_repr_info_func, "_task_repr_info")
3329 GET_MOD_ATTR(asyncio_task_get_stack_func, "_task_get_stack")
3330 GET_MOD_ATTR(asyncio_task_print_stack_func, "_task_print_stack")
3331
Andrew Svetlovf74ef452017-12-15 07:04:38 +02003332 WITH_MOD("asyncio.coroutines")
3333 GET_MOD_ATTR(asyncio_iscoroutine_func, "iscoroutine")
3334
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003335 WITH_MOD("traceback")
3336 GET_MOD_ATTR(traceback_extract_stack, "extract_stack")
3337
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003338 PyObject *weak_set;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003339 WITH_MOD("weakref")
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003340 GET_MOD_ATTR(weak_set, "WeakSet");
3341 all_tasks = _PyObject_CallNoArg(weak_set);
3342 Py_CLEAR(weak_set);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003343 if (all_tasks == NULL) {
INADA Naokic411a7d2016-10-18 11:48:14 +09003344 goto fail;
3345 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003346
Serhiy Storchakabca49392017-09-03 08:10:14 +03003347 Py_DECREF(module);
INADA Naokic411a7d2016-10-18 11:48:14 +09003348 return 0;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003349
INADA Naokic411a7d2016-10-18 11:48:14 +09003350fail:
INADA Naokic411a7d2016-10-18 11:48:14 +09003351 Py_CLEAR(module);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003352 module_free(NULL);
INADA Naokic411a7d2016-10-18 11:48:14 +09003353 return -1;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003354
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003355#undef WITH_MOD
3356#undef GET_MOD_ATTR
3357}
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003358
INADA Naokic411a7d2016-10-18 11:48:14 +09003359PyDoc_STRVAR(module_doc, "Accelerator module for asyncio");
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003360
Yury Selivanova70232f2017-12-13 14:49:42 -05003361static PyMethodDef asyncio_methods[] = {
3362 _ASYNCIO_GET_EVENT_LOOP_METHODDEF
3363 _ASYNCIO_GET_RUNNING_LOOP_METHODDEF
3364 _ASYNCIO__GET_RUNNING_LOOP_METHODDEF
3365 _ASYNCIO__SET_RUNNING_LOOP_METHODDEF
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003366 _ASYNCIO__REGISTER_TASK_METHODDEF
3367 _ASYNCIO__UNREGISTER_TASK_METHODDEF
3368 _ASYNCIO__ENTER_TASK_METHODDEF
3369 _ASYNCIO__LEAVE_TASK_METHODDEF
Yury Selivanova70232f2017-12-13 14:49:42 -05003370 {NULL, NULL}
3371};
3372
INADA Naoki9f2ce252016-10-15 15:39:19 +09003373static struct PyModuleDef _asynciomodule = {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003374 PyModuleDef_HEAD_INIT, /* m_base */
INADA Naoki9f2ce252016-10-15 15:39:19 +09003375 "_asyncio", /* m_name */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003376 module_doc, /* m_doc */
3377 -1, /* m_size */
Yury Selivanova70232f2017-12-13 14:49:42 -05003378 asyncio_methods, /* m_methods */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003379 NULL, /* m_slots */
3380 NULL, /* m_traverse */
3381 NULL, /* m_clear */
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003382 (freefunc)module_free /* m_free */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003383};
3384
3385
3386PyMODINIT_FUNC
INADA Naoki9f2ce252016-10-15 15:39:19 +09003387PyInit__asyncio(void)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003388{
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003389 if (module_init() < 0) {
INADA Naokic411a7d2016-10-18 11:48:14 +09003390 return NULL;
3391 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003392 if (PyType_Ready(&FutureType) < 0) {
3393 return NULL;
3394 }
3395 if (PyType_Ready(&FutureIterType) < 0) {
3396 return NULL;
3397 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03003398 if (PyType_Ready(&TaskStepMethWrapper_Type) < 0) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003399 return NULL;
3400 }
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03003401 if (PyType_Ready(&TaskWakeupMethWrapper_Type) < 0) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003402 return NULL;
3403 }
3404 if (PyType_Ready(&TaskType) < 0) {
3405 return NULL;
3406 }
Yury Selivanov9d411c12018-01-23 15:10:03 -05003407 if (PyType_Ready(&PyRunningLoopHolder_Type) < 0) {
3408 return NULL;
3409 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003410
INADA Naoki9f2ce252016-10-15 15:39:19 +09003411 PyObject *m = PyModule_Create(&_asynciomodule);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003412 if (m == NULL) {
3413 return NULL;
3414 }
3415
3416 Py_INCREF(&FutureType);
3417 if (PyModule_AddObject(m, "Future", (PyObject *)&FutureType) < 0) {
3418 Py_DECREF(&FutureType);
Miss Islington (bot)48f4f752019-11-16 14:44:15 -08003419 Py_DECREF(m);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003420 return NULL;
3421 }
3422
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003423 Py_INCREF(&TaskType);
3424 if (PyModule_AddObject(m, "Task", (PyObject *)&TaskType) < 0) {
3425 Py_DECREF(&TaskType);
Miss Islington (bot)48f4f752019-11-16 14:44:15 -08003426 Py_DECREF(m);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003427 return NULL;
3428 }
3429
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003430 Py_INCREF(all_tasks);
3431 if (PyModule_AddObject(m, "_all_tasks", all_tasks) < 0) {
3432 Py_DECREF(all_tasks);
Miss Islington (bot)48f4f752019-11-16 14:44:15 -08003433 Py_DECREF(m);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003434 return NULL;
3435 }
3436
3437 Py_INCREF(current_tasks);
3438 if (PyModule_AddObject(m, "_current_tasks", current_tasks) < 0) {
3439 Py_DECREF(current_tasks);
Miss Islington (bot)48f4f752019-11-16 14:44:15 -08003440 Py_DECREF(m);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003441 return NULL;
3442 }
3443
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003444 return m;
3445}