blob: 5261ed3d4c3d06977aa16bb824a3536ff0d48f34 [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{
1095 Py_INCREF(self->fut_loop);
1096 return self->fut_loop;
1097}
1098
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001099static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001100FutureObj_get_blocking(FutureObj *fut, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001101{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001102 if (future_is_alive(fut) && fut->fut_blocking) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001103 Py_RETURN_TRUE;
1104 }
1105 else {
1106 Py_RETURN_FALSE;
1107 }
1108}
1109
1110static int
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001111FutureObj_set_blocking(FutureObj *fut, PyObject *val, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001112{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001113 if (future_ensure_alive(fut)) {
1114 return -1;
1115 }
Zackery Spytz842acaa2018-12-17 07:52:45 -07001116 if (val == NULL) {
1117 PyErr_SetString(PyExc_AttributeError, "cannot delete attribute");
1118 return -1;
1119 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001120
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001121 int is_true = PyObject_IsTrue(val);
1122 if (is_true < 0) {
1123 return -1;
1124 }
1125 fut->fut_blocking = is_true;
1126 return 0;
1127}
1128
1129static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001130FutureObj_get_log_traceback(FutureObj *fut, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001131{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001132 ENSURE_FUTURE_ALIVE(fut)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001133 if (fut->fut_log_tb) {
1134 Py_RETURN_TRUE;
1135 }
1136 else {
1137 Py_RETURN_FALSE;
1138 }
1139}
1140
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +00001141static int
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001142FutureObj_set_log_traceback(FutureObj *fut, PyObject *val, void *Py_UNUSED(ignored))
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +00001143{
Zackery Spytz842acaa2018-12-17 07:52:45 -07001144 if (val == NULL) {
1145 PyErr_SetString(PyExc_AttributeError, "cannot delete attribute");
1146 return -1;
1147 }
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +00001148 int is_true = PyObject_IsTrue(val);
1149 if (is_true < 0) {
1150 return -1;
1151 }
Yury Selivanove0aef4f2017-12-25 16:16:10 -05001152 if (is_true) {
1153 PyErr_SetString(PyExc_ValueError,
1154 "_log_traceback can only be set to False");
1155 return -1;
1156 }
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +00001157 fut->fut_log_tb = is_true;
1158 return 0;
1159}
1160
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001161static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001162FutureObj_get_loop(FutureObj *fut, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001163{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001164 if (!future_is_alive(fut)) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001165 Py_RETURN_NONE;
1166 }
1167 Py_INCREF(fut->fut_loop);
1168 return fut->fut_loop;
1169}
1170
1171static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001172FutureObj_get_callbacks(FutureObj *fut, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001173{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001174 Py_ssize_t i;
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001175
1176 ENSURE_FUTURE_ALIVE(fut)
1177
Yury Selivanovf23746a2018-01-22 19:11:18 -05001178 if (fut->fut_callback0 == NULL) {
1179 if (fut->fut_callbacks == NULL) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001180 Py_RETURN_NONE;
1181 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001182
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001183 Py_INCREF(fut->fut_callbacks);
1184 return fut->fut_callbacks;
1185 }
1186
Yury Selivanovf23746a2018-01-22 19:11:18 -05001187 Py_ssize_t len = 1;
1188 if (fut->fut_callbacks != NULL) {
1189 len += PyList_GET_SIZE(fut->fut_callbacks);
1190 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001191
Yury Selivanovf23746a2018-01-22 19:11:18 -05001192
1193 PyObject *new_list = PyList_New(len);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001194 if (new_list == NULL) {
1195 return NULL;
1196 }
1197
Yury Selivanovf23746a2018-01-22 19:11:18 -05001198 PyObject *tup0 = PyTuple_New(2);
1199 if (tup0 == NULL) {
1200 Py_DECREF(new_list);
1201 return NULL;
1202 }
1203
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001204 Py_INCREF(fut->fut_callback0);
Yury Selivanovf23746a2018-01-22 19:11:18 -05001205 PyTuple_SET_ITEM(tup0, 0, fut->fut_callback0);
1206 assert(fut->fut_context0 != NULL);
1207 Py_INCREF(fut->fut_context0);
1208 PyTuple_SET_ITEM(tup0, 1, (PyObject *)fut->fut_context0);
1209
1210 PyList_SET_ITEM(new_list, 0, tup0);
1211
1212 if (fut->fut_callbacks != NULL) {
1213 for (i = 0; i < PyList_GET_SIZE(fut->fut_callbacks); i++) {
1214 PyObject *cb = PyList_GET_ITEM(fut->fut_callbacks, i);
1215 Py_INCREF(cb);
1216 PyList_SET_ITEM(new_list, i + 1, cb);
1217 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001218 }
1219
1220 return new_list;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001221}
1222
1223static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001224FutureObj_get_result(FutureObj *fut, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001225{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001226 ENSURE_FUTURE_ALIVE(fut)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001227 if (fut->fut_result == NULL) {
1228 Py_RETURN_NONE;
1229 }
1230 Py_INCREF(fut->fut_result);
1231 return fut->fut_result;
1232}
1233
1234static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001235FutureObj_get_exception(FutureObj *fut, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001236{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001237 ENSURE_FUTURE_ALIVE(fut)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001238 if (fut->fut_exception == NULL) {
1239 Py_RETURN_NONE;
1240 }
1241 Py_INCREF(fut->fut_exception);
1242 return fut->fut_exception;
1243}
1244
1245static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001246FutureObj_get_source_traceback(FutureObj *fut, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001247{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001248 if (!future_is_alive(fut) || fut->fut_source_tb == NULL) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001249 Py_RETURN_NONE;
1250 }
1251 Py_INCREF(fut->fut_source_tb);
1252 return fut->fut_source_tb;
1253}
1254
1255static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001256FutureObj_get_state(FutureObj *fut, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001257{
1258 _Py_IDENTIFIER(PENDING);
1259 _Py_IDENTIFIER(CANCELLED);
1260 _Py_IDENTIFIER(FINISHED);
1261 PyObject *ret = NULL;
1262
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001263 ENSURE_FUTURE_ALIVE(fut)
1264
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001265 switch (fut->fut_state) {
1266 case STATE_PENDING:
1267 ret = _PyUnicode_FromId(&PyId_PENDING);
1268 break;
1269 case STATE_CANCELLED:
1270 ret = _PyUnicode_FromId(&PyId_CANCELLED);
1271 break;
1272 case STATE_FINISHED:
1273 ret = _PyUnicode_FromId(&PyId_FINISHED);
1274 break;
1275 default:
1276 assert (0);
1277 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03001278 Py_XINCREF(ret);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001279 return ret;
1280}
1281
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001282/*[clinic input]
1283_asyncio.Future._repr_info
1284[clinic start generated code]*/
1285
1286static PyObject *
1287_asyncio_Future__repr_info_impl(FutureObj *self)
1288/*[clinic end generated code: output=fa69e901bd176cfb input=f21504d8e2ae1ca2]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001289{
Victor Stinnerde4ae3d2016-12-04 22:59:09 +01001290 return PyObject_CallFunctionObjArgs(
1291 asyncio_future_repr_info_func, self, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001292}
1293
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001294static PyObject *
1295FutureObj_repr(FutureObj *fut)
1296{
1297 _Py_IDENTIFIER(_repr_info);
1298
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001299 ENSURE_FUTURE_ALIVE(fut)
1300
Serhiy Storchakabca49392017-09-03 08:10:14 +03001301 PyObject *rinfo = _PyObject_CallMethodIdObjArgs((PyObject*)fut,
1302 &PyId__repr_info,
1303 NULL);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001304 if (rinfo == NULL) {
1305 return NULL;
1306 }
1307
Serhiy Storchakabca49392017-09-03 08:10:14 +03001308 PyObject *rinfo_s = PyUnicode_Join(NULL, rinfo);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001309 Py_DECREF(rinfo);
1310 if (rinfo_s == NULL) {
1311 return NULL;
1312 }
1313
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03001314 PyObject *rstr = PyUnicode_FromFormat("<%s %U>",
1315 _PyType_Name(Py_TYPE(fut)), rinfo_s);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001316 Py_DECREF(rinfo_s);
1317 return rstr;
1318}
1319
1320static void
1321FutureObj_finalize(FutureObj *fut)
1322{
1323 _Py_IDENTIFIER(call_exception_handler);
1324 _Py_IDENTIFIER(message);
1325 _Py_IDENTIFIER(exception);
1326 _Py_IDENTIFIER(future);
1327 _Py_IDENTIFIER(source_traceback);
1328
Serhiy Storchakabca49392017-09-03 08:10:14 +03001329 PyObject *error_type, *error_value, *error_traceback;
1330 PyObject *context;
Serhiy Storchakabca49392017-09-03 08:10:14 +03001331 PyObject *message = NULL;
1332 PyObject *func;
1333
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001334 if (!fut->fut_log_tb) {
1335 return;
1336 }
1337 assert(fut->fut_exception != NULL);
Serhiy Storchakabca49392017-09-03 08:10:14 +03001338 fut->fut_log_tb = 0;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001339
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001340 /* Save the current exception, if any. */
1341 PyErr_Fetch(&error_type, &error_value, &error_traceback);
1342
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001343 context = PyDict_New();
1344 if (context == NULL) {
1345 goto finally;
1346 }
1347
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001348 message = PyUnicode_FromFormat(
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03001349 "%s exception was never retrieved", _PyType_Name(Py_TYPE(fut)));
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001350 if (message == NULL) {
1351 goto finally;
1352 }
1353
1354 if (_PyDict_SetItemId(context, &PyId_message, message) < 0 ||
1355 _PyDict_SetItemId(context, &PyId_exception, fut->fut_exception) < 0 ||
1356 _PyDict_SetItemId(context, &PyId_future, (PyObject*)fut) < 0) {
1357 goto finally;
1358 }
1359 if (fut->fut_source_tb != NULL) {
1360 if (_PyDict_SetItemId(context, &PyId_source_traceback,
1361 fut->fut_source_tb) < 0) {
1362 goto finally;
1363 }
1364 }
1365
1366 func = _PyObject_GetAttrId(fut->fut_loop, &PyId_call_exception_handler);
1367 if (func != NULL) {
Serhiy Storchakabca49392017-09-03 08:10:14 +03001368 PyObject *res = PyObject_CallFunctionObjArgs(func, context, NULL);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001369 if (res == NULL) {
1370 PyErr_WriteUnraisable(func);
1371 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03001372 else {
1373 Py_DECREF(res);
1374 }
1375 Py_DECREF(func);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001376 }
1377
1378finally:
Serhiy Storchakabca49392017-09-03 08:10:14 +03001379 Py_XDECREF(context);
1380 Py_XDECREF(message);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001381
1382 /* Restore the saved exception. */
1383 PyErr_Restore(error_type, error_value, error_traceback);
1384}
1385
1386
1387static PyAsyncMethods FutureType_as_async = {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001388 (unaryfunc)future_new_iter, /* am_await */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001389 0, /* am_aiter */
1390 0 /* am_anext */
1391};
1392
1393static PyMethodDef FutureType_methods[] = {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001394 _ASYNCIO_FUTURE_RESULT_METHODDEF
1395 _ASYNCIO_FUTURE_EXCEPTION_METHODDEF
1396 _ASYNCIO_FUTURE_SET_RESULT_METHODDEF
1397 _ASYNCIO_FUTURE_SET_EXCEPTION_METHODDEF
1398 _ASYNCIO_FUTURE_ADD_DONE_CALLBACK_METHODDEF
1399 _ASYNCIO_FUTURE_REMOVE_DONE_CALLBACK_METHODDEF
1400 _ASYNCIO_FUTURE_CANCEL_METHODDEF
1401 _ASYNCIO_FUTURE_CANCELLED_METHODDEF
1402 _ASYNCIO_FUTURE_DONE_METHODDEF
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001403 _ASYNCIO_FUTURE_GET_LOOP_METHODDEF
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001404 _ASYNCIO_FUTURE__REPR_INFO_METHODDEF
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001405 {NULL, NULL} /* Sentinel */
1406};
1407
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001408#define FUTURE_COMMON_GETSETLIST \
1409 {"_state", (getter)FutureObj_get_state, NULL, NULL}, \
1410 {"_asyncio_future_blocking", (getter)FutureObj_get_blocking, \
1411 (setter)FutureObj_set_blocking, NULL}, \
1412 {"_loop", (getter)FutureObj_get_loop, NULL, NULL}, \
1413 {"_callbacks", (getter)FutureObj_get_callbacks, NULL, NULL}, \
1414 {"_result", (getter)FutureObj_get_result, NULL, NULL}, \
1415 {"_exception", (getter)FutureObj_get_exception, NULL, NULL}, \
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +00001416 {"_log_traceback", (getter)FutureObj_get_log_traceback, \
1417 (setter)FutureObj_set_log_traceback, NULL}, \
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001418 {"_source_traceback", (getter)FutureObj_get_source_traceback, NULL, NULL},
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001419
1420static PyGetSetDef FutureType_getsetlist[] = {
1421 FUTURE_COMMON_GETSETLIST
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001422 {NULL} /* Sentinel */
1423};
1424
1425static void FutureObj_dealloc(PyObject *self);
1426
1427static PyTypeObject FutureType = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02001428 PyVarObject_HEAD_INIT(NULL, 0)
INADA Naoki9f2ce252016-10-15 15:39:19 +09001429 "_asyncio.Future",
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001430 sizeof(FutureObj), /* tp_basicsize */
1431 .tp_dealloc = FutureObj_dealloc,
1432 .tp_as_async = &FutureType_as_async,
1433 .tp_repr = (reprfunc)FutureObj_repr,
Antoine Pitrouada319b2019-05-29 22:12:38 +02001434 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001435 .tp_doc = _asyncio_Future___init____doc__,
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001436 .tp_traverse = (traverseproc)FutureObj_traverse,
1437 .tp_clear = (inquiry)FutureObj_clear,
1438 .tp_weaklistoffset = offsetof(FutureObj, fut_weakreflist),
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001439 .tp_iter = (getiterfunc)future_new_iter,
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001440 .tp_methods = FutureType_methods,
1441 .tp_getset = FutureType_getsetlist,
1442 .tp_dictoffset = offsetof(FutureObj, dict),
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001443 .tp_init = (initproc)_asyncio_Future___init__,
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001444 .tp_new = PyType_GenericNew,
1445 .tp_finalize = (destructor)FutureObj_finalize,
1446};
1447
1448static void
1449FutureObj_dealloc(PyObject *self)
1450{
1451 FutureObj *fut = (FutureObj *)self;
1452
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001453 if (Future_CheckExact(fut)) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001454 /* When fut is subclass of Future, finalizer is called from
1455 * subtype_dealloc.
1456 */
1457 if (PyObject_CallFinalizerFromDealloc(self) < 0) {
1458 // resurrected.
1459 return;
1460 }
1461 }
1462
Alexander Mohrde34cbe2017-08-01 23:31:07 -07001463 PyObject_GC_UnTrack(self);
1464
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001465 if (fut->fut_weakreflist != NULL) {
1466 PyObject_ClearWeakRefs(self);
1467 }
1468
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001469 (void)FutureObj_clear(fut);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001470 Py_TYPE(fut)->tp_free(fut);
1471}
1472
1473
1474/*********************** Future Iterator **************************/
1475
1476typedef struct {
1477 PyObject_HEAD
1478 FutureObj *future;
1479} futureiterobject;
1480
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001481
1482#define FI_FREELIST_MAXLEN 255
1483static futureiterobject *fi_freelist = NULL;
1484static Py_ssize_t fi_freelist_len = 0;
1485
1486
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001487static void
1488FutureIter_dealloc(futureiterobject *it)
1489{
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001490 PyObject_GC_UnTrack(it);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001491 Py_CLEAR(it->future);
1492
1493 if (fi_freelist_len < FI_FREELIST_MAXLEN) {
1494 fi_freelist_len++;
1495 it->future = (FutureObj*) fi_freelist;
1496 fi_freelist = it;
1497 }
1498 else {
1499 PyObject_GC_Del(it);
1500 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001501}
1502
1503static PyObject *
1504FutureIter_iternext(futureiterobject *it)
1505{
1506 PyObject *res;
1507 FutureObj *fut = it->future;
1508
1509 if (fut == NULL) {
1510 return NULL;
1511 }
1512
1513 if (fut->fut_state == STATE_PENDING) {
1514 if (!fut->fut_blocking) {
1515 fut->fut_blocking = 1;
1516 Py_INCREF(fut);
1517 return (PyObject *)fut;
1518 }
Yury Selivanov0cf16f92017-12-25 10:48:15 -05001519 PyErr_SetString(PyExc_RuntimeError,
1520 "await wasn't used with future");
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001521 return NULL;
1522 }
1523
Serhiy Storchakabca49392017-09-03 08:10:14 +03001524 it->future = NULL;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001525 res = _asyncio_Future_result_impl(fut);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001526 if (res != NULL) {
Serhiy Storchaka60e49aa2016-11-06 18:47:03 +02001527 /* The result of the Future is not an exception. */
Serhiy Storchakabca49392017-09-03 08:10:14 +03001528 (void)_PyGen_SetStopIterationValue(res);
Serhiy Storchaka60e49aa2016-11-06 18:47:03 +02001529 Py_DECREF(res);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001530 }
1531
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001532 Py_DECREF(fut);
1533 return NULL;
1534}
1535
1536static PyObject *
INADA Naoki74c17532016-10-25 19:00:45 +09001537FutureIter_send(futureiterobject *self, PyObject *unused)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001538{
INADA Naoki74c17532016-10-25 19:00:45 +09001539 /* Future.__iter__ doesn't care about values that are pushed to the
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03001540 * generator, it just returns self.result().
INADA Naoki74c17532016-10-25 19:00:45 +09001541 */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001542 return FutureIter_iternext(self);
1543}
1544
1545static PyObject *
1546FutureIter_throw(futureiterobject *self, PyObject *args)
1547{
Serhiy Storchakabca49392017-09-03 08:10:14 +03001548 PyObject *type, *val = NULL, *tb = NULL;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001549 if (!PyArg_ParseTuple(args, "O|OO", &type, &val, &tb))
1550 return NULL;
1551
1552 if (val == Py_None) {
1553 val = NULL;
1554 }
1555 if (tb == Py_None) {
1556 tb = NULL;
Benjamin Peterson996fc1f2016-11-14 00:15:44 -08001557 } else if (tb != NULL && !PyTraceBack_Check(tb)) {
1558 PyErr_SetString(PyExc_TypeError, "throw() third argument must be a traceback");
1559 return NULL;
1560 }
1561
1562 Py_INCREF(type);
1563 Py_XINCREF(val);
1564 Py_XINCREF(tb);
1565
1566 if (PyExceptionClass_Check(type)) {
1567 PyErr_NormalizeException(&type, &val, &tb);
Yury Selivanovedfe8862016-12-01 11:37:47 -05001568 /* No need to call PyException_SetTraceback since we'll be calling
1569 PyErr_Restore for `type`, `val`, and `tb`. */
Benjamin Peterson996fc1f2016-11-14 00:15:44 -08001570 } else if (PyExceptionInstance_Check(type)) {
1571 if (val) {
1572 PyErr_SetString(PyExc_TypeError,
1573 "instance exception may not have a separate value");
1574 goto fail;
1575 }
1576 val = type;
1577 type = PyExceptionInstance_Class(type);
1578 Py_INCREF(type);
1579 if (tb == NULL)
1580 tb = PyException_GetTraceback(val);
1581 } else {
1582 PyErr_SetString(PyExc_TypeError,
1583 "exceptions must be classes deriving BaseException or "
1584 "instances of such a class");
1585 goto fail;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001586 }
1587
1588 Py_CLEAR(self->future);
1589
Benjamin Peterson996fc1f2016-11-14 00:15:44 -08001590 PyErr_Restore(type, val, tb);
1591
Serhiy Storchakabca49392017-09-03 08:10:14 +03001592 return NULL;
Benjamin Peterson996fc1f2016-11-14 00:15:44 -08001593
1594 fail:
1595 Py_DECREF(type);
1596 Py_XDECREF(val);
1597 Py_XDECREF(tb);
1598 return NULL;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001599}
1600
1601static PyObject *
1602FutureIter_close(futureiterobject *self, PyObject *arg)
1603{
1604 Py_CLEAR(self->future);
1605 Py_RETURN_NONE;
1606}
1607
1608static int
1609FutureIter_traverse(futureiterobject *it, visitproc visit, void *arg)
1610{
1611 Py_VISIT(it->future);
1612 return 0;
1613}
1614
1615static PyMethodDef FutureIter_methods[] = {
1616 {"send", (PyCFunction)FutureIter_send, METH_O, NULL},
1617 {"throw", (PyCFunction)FutureIter_throw, METH_VARARGS, NULL},
1618 {"close", (PyCFunction)FutureIter_close, METH_NOARGS, NULL},
1619 {NULL, NULL} /* Sentinel */
1620};
1621
1622static PyTypeObject FutureIterType = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02001623 PyVarObject_HEAD_INIT(NULL, 0)
INADA Naoki9f2ce252016-10-15 15:39:19 +09001624 "_asyncio.FutureIter",
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001625 .tp_basicsize = sizeof(futureiterobject),
1626 .tp_itemsize = 0,
1627 .tp_dealloc = (destructor)FutureIter_dealloc,
1628 .tp_getattro = PyObject_GenericGetAttr,
1629 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
1630 .tp_traverse = (traverseproc)FutureIter_traverse,
1631 .tp_iter = PyObject_SelfIter,
1632 .tp_iternext = (iternextfunc)FutureIter_iternext,
1633 .tp_methods = FutureIter_methods,
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001634};
1635
1636static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001637future_new_iter(PyObject *fut)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001638{
1639 futureiterobject *it;
1640
1641 if (!PyObject_TypeCheck(fut, &FutureType)) {
1642 PyErr_BadInternalCall();
1643 return NULL;
1644 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001645
1646 ENSURE_FUTURE_ALIVE(fut)
1647
1648 if (fi_freelist_len) {
1649 fi_freelist_len--;
1650 it = fi_freelist;
1651 fi_freelist = (futureiterobject*) it->future;
1652 it->future = NULL;
1653 _Py_NewReference((PyObject*) it);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001654 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001655 else {
1656 it = PyObject_GC_New(futureiterobject, &FutureIterType);
1657 if (it == NULL) {
1658 return NULL;
1659 }
1660 }
1661
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001662 Py_INCREF(fut);
1663 it->future = (FutureObj*)fut;
INADA Naoki1be427b2016-10-11 02:12:34 +09001664 PyObject_GC_Track(it);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001665 return (PyObject*)it;
1666}
1667
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001668
1669/*********************** Task **************************/
1670
1671
1672/*[clinic input]
1673class _asyncio.Task "TaskObj *" "&Task_Type"
1674[clinic start generated code]*/
1675/*[clinic end generated code: output=da39a3ee5e6b4b0d input=719dcef0fcc03b37]*/
1676
1677static int task_call_step_soon(TaskObj *, PyObject *);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001678static PyObject * task_wakeup(TaskObj *, PyObject *);
1679static PyObject * task_step(TaskObj *, PyObject *);
1680
1681/* ----- Task._step wrapper */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001682
INADA Naokic411a7d2016-10-18 11:48:14 +09001683static int
Serhiy Storchakabca49392017-09-03 08:10:14 +03001684TaskStepMethWrapper_clear(TaskStepMethWrapper *o)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001685{
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001686 Py_CLEAR(o->sw_task);
1687 Py_CLEAR(o->sw_arg);
1688 return 0;
1689}
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001690
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001691static void
Serhiy Storchakabca49392017-09-03 08:10:14 +03001692TaskStepMethWrapper_dealloc(TaskStepMethWrapper *o)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001693{
1694 PyObject_GC_UnTrack(o);
Serhiy Storchakabca49392017-09-03 08:10:14 +03001695 (void)TaskStepMethWrapper_clear(o);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001696 Py_TYPE(o)->tp_free(o);
1697}
1698
1699static PyObject *
Serhiy Storchakabca49392017-09-03 08:10:14 +03001700TaskStepMethWrapper_call(TaskStepMethWrapper *o,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001701 PyObject *args, PyObject *kwds)
1702{
Serhiy Storchakabca49392017-09-03 08:10:14 +03001703 if (kwds != NULL && PyDict_GET_SIZE(kwds) != 0) {
1704 PyErr_SetString(PyExc_TypeError, "function takes no keyword arguments");
1705 return NULL;
1706 }
1707 if (args != NULL && PyTuple_GET_SIZE(args) != 0) {
1708 PyErr_SetString(PyExc_TypeError, "function takes no positional arguments");
1709 return NULL;
1710 }
Yury Selivanov22feeb82018-01-24 11:31:01 -05001711 return task_step(o->sw_task, o->sw_arg);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001712}
1713
1714static int
Serhiy Storchakabca49392017-09-03 08:10:14 +03001715TaskStepMethWrapper_traverse(TaskStepMethWrapper *o,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001716 visitproc visit, void *arg)
1717{
1718 Py_VISIT(o->sw_task);
1719 Py_VISIT(o->sw_arg);
1720 return 0;
1721}
1722
1723static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001724TaskStepMethWrapper_get___self__(TaskStepMethWrapper *o, void *Py_UNUSED(ignored))
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001725{
1726 if (o->sw_task) {
1727 Py_INCREF(o->sw_task);
1728 return (PyObject*)o->sw_task;
1729 }
1730 Py_RETURN_NONE;
1731}
1732
Serhiy Storchakabca49392017-09-03 08:10:14 +03001733static PyGetSetDef TaskStepMethWrapper_getsetlist[] = {
1734 {"__self__", (getter)TaskStepMethWrapper_get___self__, NULL, NULL},
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001735 {NULL} /* Sentinel */
1736};
1737
Benjamin Peterson3c8aae92018-07-05 22:39:34 -07001738static PyTypeObject TaskStepMethWrapper_Type = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02001739 PyVarObject_HEAD_INIT(NULL, 0)
Serhiy Storchakabca49392017-09-03 08:10:14 +03001740 "TaskStepMethWrapper",
1741 .tp_basicsize = sizeof(TaskStepMethWrapper),
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001742 .tp_itemsize = 0,
Serhiy Storchakabca49392017-09-03 08:10:14 +03001743 .tp_getset = TaskStepMethWrapper_getsetlist,
1744 .tp_dealloc = (destructor)TaskStepMethWrapper_dealloc,
1745 .tp_call = (ternaryfunc)TaskStepMethWrapper_call,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001746 .tp_getattro = PyObject_GenericGetAttr,
1747 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
Serhiy Storchakabca49392017-09-03 08:10:14 +03001748 .tp_traverse = (traverseproc)TaskStepMethWrapper_traverse,
1749 .tp_clear = (inquiry)TaskStepMethWrapper_clear,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001750};
1751
1752static PyObject *
Serhiy Storchakabca49392017-09-03 08:10:14 +03001753TaskStepMethWrapper_new(TaskObj *task, PyObject *arg)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001754{
Serhiy Storchakabca49392017-09-03 08:10:14 +03001755 TaskStepMethWrapper *o;
1756 o = PyObject_GC_New(TaskStepMethWrapper, &TaskStepMethWrapper_Type);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001757 if (o == NULL) {
1758 return NULL;
1759 }
1760
1761 Py_INCREF(task);
1762 o->sw_task = task;
1763
1764 Py_XINCREF(arg);
1765 o->sw_arg = arg;
1766
1767 PyObject_GC_Track(o);
1768 return (PyObject*) o;
1769}
1770
1771/* ----- Task._wakeup wrapper */
1772
1773static PyObject *
1774TaskWakeupMethWrapper_call(TaskWakeupMethWrapper *o,
1775 PyObject *args, PyObject *kwds)
1776{
1777 PyObject *fut;
1778
Serhiy Storchakabca49392017-09-03 08:10:14 +03001779 if (kwds != NULL && PyDict_GET_SIZE(kwds) != 0) {
1780 PyErr_SetString(PyExc_TypeError, "function takes no keyword arguments");
1781 return NULL;
1782 }
1783 if (!PyArg_ParseTuple(args, "O", &fut)) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001784 return NULL;
1785 }
1786
Yury Selivanov22feeb82018-01-24 11:31:01 -05001787 return task_wakeup(o->ww_task, fut);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001788}
1789
1790static int
1791TaskWakeupMethWrapper_clear(TaskWakeupMethWrapper *o)
1792{
1793 Py_CLEAR(o->ww_task);
1794 return 0;
1795}
1796
1797static int
1798TaskWakeupMethWrapper_traverse(TaskWakeupMethWrapper *o,
1799 visitproc visit, void *arg)
1800{
1801 Py_VISIT(o->ww_task);
1802 return 0;
1803}
1804
1805static void
1806TaskWakeupMethWrapper_dealloc(TaskWakeupMethWrapper *o)
1807{
1808 PyObject_GC_UnTrack(o);
1809 (void)TaskWakeupMethWrapper_clear(o);
1810 Py_TYPE(o)->tp_free(o);
1811}
1812
Benjamin Peterson3c8aae92018-07-05 22:39:34 -07001813static PyTypeObject TaskWakeupMethWrapper_Type = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02001814 PyVarObject_HEAD_INIT(NULL, 0)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001815 "TaskWakeupMethWrapper",
1816 .tp_basicsize = sizeof(TaskWakeupMethWrapper),
1817 .tp_itemsize = 0,
1818 .tp_dealloc = (destructor)TaskWakeupMethWrapper_dealloc,
1819 .tp_call = (ternaryfunc)TaskWakeupMethWrapper_call,
1820 .tp_getattro = PyObject_GenericGetAttr,
1821 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
1822 .tp_traverse = (traverseproc)TaskWakeupMethWrapper_traverse,
1823 .tp_clear = (inquiry)TaskWakeupMethWrapper_clear,
1824};
1825
1826static PyObject *
1827TaskWakeupMethWrapper_new(TaskObj *task)
1828{
1829 TaskWakeupMethWrapper *o;
1830 o = PyObject_GC_New(TaskWakeupMethWrapper, &TaskWakeupMethWrapper_Type);
1831 if (o == NULL) {
1832 return NULL;
1833 }
1834
1835 Py_INCREF(task);
1836 o->ww_task = task;
1837
1838 PyObject_GC_Track(o);
1839 return (PyObject*) o;
1840}
1841
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001842/* ----- Task introspection helpers */
1843
1844static int
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001845register_task(PyObject *task)
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001846{
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001847 _Py_IDENTIFIER(add);
1848
1849 PyObject *res = _PyObject_CallMethodIdObjArgs(
1850 all_tasks, &PyId_add, task, NULL);
1851 if (res == NULL) {
1852 return -1;
1853 }
1854 Py_DECREF(res);
1855 return 0;
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001856}
1857
1858
1859static int
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001860unregister_task(PyObject *task)
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001861{
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001862 _Py_IDENTIFIER(discard);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001863
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001864 PyObject *res = _PyObject_CallMethodIdObjArgs(
1865 all_tasks, &PyId_discard, task, NULL);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001866 if (res == NULL) {
1867 return -1;
1868 }
1869 Py_DECREF(res);
1870 return 0;
1871}
1872
1873
1874static int
1875enter_task(PyObject *loop, PyObject *task)
1876{
1877 PyObject *item;
1878 Py_hash_t hash;
1879 hash = PyObject_Hash(loop);
1880 if (hash == -1) {
1881 return -1;
1882 }
1883 item = _PyDict_GetItem_KnownHash(current_tasks, loop, hash);
1884 if (item != NULL) {
Serhiy Storchaka66553542018-05-20 16:30:31 +03001885 Py_INCREF(item);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001886 PyErr_Format(
1887 PyExc_RuntimeError,
1888 "Cannot enter into task %R while another " \
1889 "task %R is being executed.",
1890 task, item, NULL);
Serhiy Storchaka66553542018-05-20 16:30:31 +03001891 Py_DECREF(item);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001892 return -1;
1893 }
Serhiy Storchaka66553542018-05-20 16:30:31 +03001894 if (PyErr_Occurred()) {
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001895 return -1;
1896 }
Serhiy Storchaka66553542018-05-20 16:30:31 +03001897 return _PyDict_SetItem_KnownHash(current_tasks, loop, task, hash);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001898}
1899
1900
1901static int
1902leave_task(PyObject *loop, PyObject *task)
1903/*[clinic end generated code: output=0ebf6db4b858fb41 input=51296a46313d1ad8]*/
1904{
1905 PyObject *item;
1906 Py_hash_t hash;
1907 hash = PyObject_Hash(loop);
1908 if (hash == -1) {
1909 return -1;
1910 }
1911 item = _PyDict_GetItem_KnownHash(current_tasks, loop, hash);
1912 if (item != task) {
1913 if (item == NULL) {
1914 /* Not entered, replace with None */
1915 item = Py_None;
1916 }
1917 PyErr_Format(
1918 PyExc_RuntimeError,
1919 "Leaving task %R does not match the current task %R.",
1920 task, item, NULL);
1921 return -1;
1922 }
1923 return _PyDict_DelItem_KnownHash(current_tasks, loop, hash);
1924}
1925
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001926/* ----- Task */
1927
1928/*[clinic input]
1929_asyncio.Task.__init__
1930
Serhiy Storchakabca49392017-09-03 08:10:14 +03001931 coro: object
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001932 *
Serhiy Storchakabca49392017-09-03 08:10:14 +03001933 loop: object = None
Alex Grönholmcca4eec2018-08-09 00:06:47 +03001934 name: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001935
1936A coroutine wrapped in a Future.
1937[clinic start generated code]*/
1938
1939static int
Alex Grönholmcca4eec2018-08-09 00:06:47 +03001940_asyncio_Task___init___impl(TaskObj *self, PyObject *coro, PyObject *loop,
1941 PyObject *name)
1942/*[clinic end generated code: output=88b12b83d570df50 input=352a3137fe60091d]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001943{
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001944 if (future_init((FutureObj*)self, loop)) {
INADA Naokic411a7d2016-10-18 11:48:14 +09001945 return -1;
1946 }
INADA Naokic411a7d2016-10-18 11:48:14 +09001947
Yury Selivanova9d7e552017-12-19 07:18:45 -05001948 int is_coro = is_coroutine(coro);
1949 if (is_coro == -1) {
1950 return -1;
1951 }
1952 if (is_coro == 0) {
1953 self->task_log_destroy_pending = 0;
1954 PyErr_Format(PyExc_TypeError,
1955 "a coroutine was expected, got %R",
1956 coro, NULL);
1957 return -1;
Andrew Svetlovf74ef452017-12-15 07:04:38 +02001958 }
1959
Oren Milmand019bc82018-02-13 12:28:33 +02001960 Py_XSETREF(self->task_context, PyContext_CopyCurrent());
Yury Selivanovf23746a2018-01-22 19:11:18 -05001961 if (self->task_context == NULL) {
1962 return -1;
1963 }
1964
Oren Milmand019bc82018-02-13 12:28:33 +02001965 Py_CLEAR(self->task_fut_waiter);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001966 self->task_must_cancel = 0;
1967 self->task_log_destroy_pending = 1;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001968 Py_INCREF(coro);
Oren Milmand019bc82018-02-13 12:28:33 +02001969 Py_XSETREF(self->task_coro, coro);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001970
Alex Grönholmcca4eec2018-08-09 00:06:47 +03001971 if (name == Py_None) {
1972 name = PyUnicode_FromFormat("Task-%" PRIu64, ++task_name_counter);
Alex Grönholma7548232018-08-09 23:49:49 +03001973 } else if (!PyUnicode_CheckExact(name)) {
Alex Grönholmcca4eec2018-08-09 00:06:47 +03001974 name = PyObject_Str(name);
1975 } else {
1976 Py_INCREF(name);
1977 }
1978 Py_XSETREF(self->task_name, name);
1979 if (self->task_name == NULL) {
1980 return -1;
1981 }
1982
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001983 if (task_call_step_soon(self, NULL)) {
1984 return -1;
INADA Naokic411a7d2016-10-18 11:48:14 +09001985 }
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001986 return register_task((PyObject*)self);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001987}
1988
1989static int
1990TaskObj_clear(TaskObj *task)
1991{
1992 (void)FutureObj_clear((FutureObj*) task);
Yury Selivanovf23746a2018-01-22 19:11:18 -05001993 Py_CLEAR(task->task_context);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001994 Py_CLEAR(task->task_coro);
Alex Grönholmcca4eec2018-08-09 00:06:47 +03001995 Py_CLEAR(task->task_name);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001996 Py_CLEAR(task->task_fut_waiter);
1997 return 0;
1998}
1999
2000static int
2001TaskObj_traverse(TaskObj *task, visitproc visit, void *arg)
2002{
Yury Selivanovf23746a2018-01-22 19:11:18 -05002003 Py_VISIT(task->task_context);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002004 Py_VISIT(task->task_coro);
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002005 Py_VISIT(task->task_name);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002006 Py_VISIT(task->task_fut_waiter);
2007 (void)FutureObj_traverse((FutureObj*) task, visit, arg);
2008 return 0;
2009}
2010
2011static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02002012TaskObj_get_log_destroy_pending(TaskObj *task, void *Py_UNUSED(ignored))
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002013{
2014 if (task->task_log_destroy_pending) {
2015 Py_RETURN_TRUE;
2016 }
2017 else {
2018 Py_RETURN_FALSE;
2019 }
2020}
2021
2022static int
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02002023TaskObj_set_log_destroy_pending(TaskObj *task, PyObject *val, void *Py_UNUSED(ignored))
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002024{
Zackery Spytz842acaa2018-12-17 07:52:45 -07002025 if (val == NULL) {
2026 PyErr_SetString(PyExc_AttributeError, "cannot delete attribute");
2027 return -1;
2028 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002029 int is_true = PyObject_IsTrue(val);
2030 if (is_true < 0) {
2031 return -1;
2032 }
2033 task->task_log_destroy_pending = is_true;
2034 return 0;
2035}
2036
2037static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02002038TaskObj_get_must_cancel(TaskObj *task, void *Py_UNUSED(ignored))
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002039{
2040 if (task->task_must_cancel) {
2041 Py_RETURN_TRUE;
2042 }
2043 else {
2044 Py_RETURN_FALSE;
2045 }
2046}
2047
2048static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02002049TaskObj_get_coro(TaskObj *task, void *Py_UNUSED(ignored))
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002050{
2051 if (task->task_coro) {
2052 Py_INCREF(task->task_coro);
2053 return task->task_coro;
2054 }
2055
2056 Py_RETURN_NONE;
2057}
2058
2059static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02002060TaskObj_get_fut_waiter(TaskObj *task, void *Py_UNUSED(ignored))
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002061{
2062 if (task->task_fut_waiter) {
2063 Py_INCREF(task->task_fut_waiter);
2064 return task->task_fut_waiter;
2065 }
2066
2067 Py_RETURN_NONE;
2068}
2069
2070/*[clinic input]
2071@classmethod
2072_asyncio.Task.current_task
2073
Serhiy Storchakabca49392017-09-03 08:10:14 +03002074 loop: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002075
2076Return the currently running task in an event loop or None.
2077
2078By default the current task for the current event loop is returned.
2079
2080None is returned when called not in the context of a Task.
2081[clinic start generated code]*/
2082
2083static PyObject *
2084_asyncio_Task_current_task_impl(PyTypeObject *type, PyObject *loop)
Serhiy Storchakabca49392017-09-03 08:10:14 +03002085/*[clinic end generated code: output=99fbe7332c516e03 input=cd14770c5b79c7eb]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002086{
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002087 PyObject *ret;
2088 PyObject *current_task_func;
2089
Inada Naokic5c6cda2019-03-22 20:07:32 +09002090 if (PyErr_WarnEx(PyExc_DeprecationWarning,
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002091 "Task.current_task() is deprecated, " \
2092 "use asyncio.current_task() instead",
2093 1) < 0) {
2094 return NULL;
2095 }
2096
2097 current_task_func = _PyObject_GetAttrId(asyncio_mod, &PyId_current_task);
2098 if (current_task_func == NULL) {
2099 return NULL;
2100 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002101
Yury Selivanov8d26aa92017-03-02 22:16:33 -05002102 if (loop == Py_None) {
Yury Selivanova70232f2017-12-13 14:49:42 -05002103 loop = get_event_loop();
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002104 if (loop == NULL) {
Serhiy Storchaka66553542018-05-20 16:30:31 +03002105 Py_DECREF(current_task_func);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002106 return NULL;
2107 }
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002108 ret = PyObject_CallFunctionObjArgs(current_task_func, loop, NULL);
2109 Py_DECREF(current_task_func);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002110 Py_DECREF(loop);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002111 return ret;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002112 }
2113 else {
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002114 ret = PyObject_CallFunctionObjArgs(current_task_func, loop, NULL);
2115 Py_DECREF(current_task_func);
2116 return ret;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002117 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002118}
2119
2120/*[clinic input]
2121@classmethod
2122_asyncio.Task.all_tasks
2123
Serhiy Storchakabca49392017-09-03 08:10:14 +03002124 loop: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002125
2126Return a set of all tasks for an event loop.
2127
2128By default all tasks for the current event loop are returned.
2129[clinic start generated code]*/
2130
2131static PyObject *
2132_asyncio_Task_all_tasks_impl(PyTypeObject *type, PyObject *loop)
Serhiy Storchakabca49392017-09-03 08:10:14 +03002133/*[clinic end generated code: output=11f9b20749ccca5d input=497f80bc9ce726b5]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002134{
2135 PyObject *res;
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002136 PyObject *all_tasks_func;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002137
Inada Naokic5c6cda2019-03-22 20:07:32 +09002138 if (PyErr_WarnEx(PyExc_DeprecationWarning,
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002139 "Task.all_tasks() is deprecated, " \
2140 "use asyncio.all_tasks() instead",
2141 1) < 0) {
2142 return NULL;
2143 }
2144
Yury Selivanov416c1eb2018-05-28 17:54:02 -04002145 all_tasks_func = _PyObject_GetAttrId(asyncio_mod, &PyId__all_tasks_compat);
Serhiy Storchaka66553542018-05-20 16:30:31 +03002146 if (all_tasks_func == NULL) {
2147 return NULL;
2148 }
2149
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002150 res = PyObject_CallFunctionObjArgs(all_tasks_func, loop, NULL);
2151 Py_DECREF(all_tasks_func);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002152 return res;
2153}
2154
2155/*[clinic input]
2156_asyncio.Task._repr_info
2157[clinic start generated code]*/
2158
2159static PyObject *
2160_asyncio_Task__repr_info_impl(TaskObj *self)
2161/*[clinic end generated code: output=6a490eb66d5ba34b input=3c6d051ed3ddec8b]*/
2162{
Victor Stinnerde4ae3d2016-12-04 22:59:09 +01002163 return PyObject_CallFunctionObjArgs(
2164 asyncio_task_repr_info_func, self, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002165}
2166
2167/*[clinic input]
2168_asyncio.Task.cancel
2169
2170Request that this task cancel itself.
2171
2172This arranges for a CancelledError to be thrown into the
2173wrapped coroutine on the next cycle through the event loop.
2174The coroutine then has a chance to clean up or even deny
2175the request using try/except/finally.
2176
2177Unlike Future.cancel, this does not guarantee that the
2178task will be cancelled: the exception might be caught and
2179acted upon, delaying cancellation of the task or preventing
2180cancellation completely. The task may also return a value or
2181raise a different exception.
2182
2183Immediately after this method is called, Task.cancelled() will
2184not return True (unless the task was already cancelled). A
2185task will be marked as cancelled when the wrapped coroutine
2186terminates with a CancelledError exception (even if cancel()
2187was not called).
2188[clinic start generated code]*/
2189
2190static PyObject *
2191_asyncio_Task_cancel_impl(TaskObj *self)
2192/*[clinic end generated code: output=6bfc0479da9d5757 input=13f9bf496695cb52]*/
2193{
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +00002194 self->task_log_tb = 0;
2195
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002196 if (self->task_state != STATE_PENDING) {
2197 Py_RETURN_FALSE;
2198 }
2199
2200 if (self->task_fut_waiter) {
2201 PyObject *res;
2202 int is_true;
2203
2204 res = _PyObject_CallMethodId(
2205 self->task_fut_waiter, &PyId_cancel, NULL);
2206 if (res == NULL) {
2207 return NULL;
2208 }
2209
2210 is_true = PyObject_IsTrue(res);
2211 Py_DECREF(res);
2212 if (is_true < 0) {
2213 return NULL;
2214 }
2215
2216 if (is_true) {
2217 Py_RETURN_TRUE;
2218 }
2219 }
2220
2221 self->task_must_cancel = 1;
2222 Py_RETURN_TRUE;
2223}
2224
2225/*[clinic input]
2226_asyncio.Task.get_stack
2227
2228 *
Serhiy Storchakabca49392017-09-03 08:10:14 +03002229 limit: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002230
2231Return the list of stack frames for this task's coroutine.
2232
2233If the coroutine is not done, this returns the stack where it is
2234suspended. If the coroutine has completed successfully or was
2235cancelled, this returns an empty list. If the coroutine was
2236terminated by an exception, this returns the list of traceback
2237frames.
2238
2239The frames are always ordered from oldest to newest.
2240
2241The optional limit gives the maximum number of frames to
2242return; by default all available frames are returned. Its
2243meaning differs depending on whether a stack or a traceback is
2244returned: the newest frames of a stack are returned, but the
2245oldest frames of a traceback are returned. (This matches the
2246behavior of the traceback module.)
2247
2248For reasons beyond our control, only one stack frame is
2249returned for a suspended coroutine.
2250[clinic start generated code]*/
2251
2252static PyObject *
2253_asyncio_Task_get_stack_impl(TaskObj *self, PyObject *limit)
Serhiy Storchakabca49392017-09-03 08:10:14 +03002254/*[clinic end generated code: output=c9aeeeebd1e18118 input=05b323d42b809b90]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002255{
2256 return PyObject_CallFunctionObjArgs(
2257 asyncio_task_get_stack_func, self, limit, NULL);
2258}
2259
2260/*[clinic input]
2261_asyncio.Task.print_stack
2262
2263 *
Serhiy Storchakabca49392017-09-03 08:10:14 +03002264 limit: object = None
2265 file: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002266
2267Print the stack or traceback for this task's coroutine.
2268
2269This produces output similar to that of the traceback module,
2270for the frames retrieved by get_stack(). The limit argument
2271is passed to get_stack(). The file argument is an I/O stream
2272to which the output is written; by default output is written
2273to sys.stderr.
2274[clinic start generated code]*/
2275
2276static PyObject *
2277_asyncio_Task_print_stack_impl(TaskObj *self, PyObject *limit,
2278 PyObject *file)
Serhiy Storchakabca49392017-09-03 08:10:14 +03002279/*[clinic end generated code: output=7339e10314cd3f4d input=1a0352913b7fcd92]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002280{
2281 return PyObject_CallFunctionObjArgs(
2282 asyncio_task_print_stack_func, self, limit, file, NULL);
2283}
2284
2285/*[clinic input]
Yury Selivanov0cf16f92017-12-25 10:48:15 -05002286_asyncio.Task.set_result
2287
2288 result: object
2289 /
2290[clinic start generated code]*/
2291
2292static PyObject *
2293_asyncio_Task_set_result(TaskObj *self, PyObject *result)
2294/*[clinic end generated code: output=1dcae308bfcba318 input=9d1a00c07be41bab]*/
2295{
2296 PyErr_SetString(PyExc_RuntimeError,
2297 "Task does not support set_result operation");
2298 return NULL;
2299}
2300
2301/*[clinic input]
2302_asyncio.Task.set_exception
2303
2304 exception: object
2305 /
2306[clinic start generated code]*/
2307
2308static PyObject *
2309_asyncio_Task_set_exception(TaskObj *self, PyObject *exception)
2310/*[clinic end generated code: output=bc377fc28067303d input=9a8f65c83dcf893a]*/
2311{
2312 PyErr_SetString(PyExc_RuntimeError,
Andrew Svetlovfc359322017-12-30 15:40:27 +02002313 "Task does not support set_exception operation");
Yury Selivanov0cf16f92017-12-25 10:48:15 -05002314 return NULL;
2315}
2316
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002317/*[clinic input]
Alex Grönholm98ef9202019-05-30 18:30:09 +03002318_asyncio.Task.get_coro
2319[clinic start generated code]*/
2320
2321static PyObject *
2322_asyncio_Task_get_coro_impl(TaskObj *self)
2323/*[clinic end generated code: output=bcac27c8cc6c8073 input=d2e8606c42a7b403]*/
2324{
2325 Py_INCREF(self->task_coro);
2326 return self->task_coro;
2327}
2328
2329/*[clinic input]
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002330_asyncio.Task.get_name
2331[clinic start generated code]*/
2332
2333static PyObject *
2334_asyncio_Task_get_name_impl(TaskObj *self)
2335/*[clinic end generated code: output=0ecf1570c3b37a8f input=a4a6595d12f4f0f8]*/
2336{
2337 if (self->task_name) {
2338 Py_INCREF(self->task_name);
2339 return self->task_name;
2340 }
2341
2342 Py_RETURN_NONE;
2343}
2344
2345/*[clinic input]
2346_asyncio.Task.set_name
2347
2348 value: object
2349 /
2350[clinic start generated code]*/
2351
2352static PyObject *
2353_asyncio_Task_set_name(TaskObj *self, PyObject *value)
2354/*[clinic end generated code: output=138a8d51e32057d6 input=a8359b6e65f8fd31]*/
2355{
Alex Grönholma7548232018-08-09 23:49:49 +03002356 if (!PyUnicode_CheckExact(value)) {
2357 value = PyObject_Str(value);
2358 if (value == NULL) {
2359 return NULL;
2360 }
2361 } else {
2362 Py_INCREF(value);
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002363 }
2364
Alex Grönholma7548232018-08-09 23:49:49 +03002365 Py_XSETREF(self->task_name, value);
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002366 Py_RETURN_NONE;
2367}
Yury Selivanov0cf16f92017-12-25 10:48:15 -05002368
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002369static void
2370TaskObj_finalize(TaskObj *task)
2371{
2372 _Py_IDENTIFIER(call_exception_handler);
2373 _Py_IDENTIFIER(task);
2374 _Py_IDENTIFIER(message);
2375 _Py_IDENTIFIER(source_traceback);
2376
Serhiy Storchakabca49392017-09-03 08:10:14 +03002377 PyObject *context;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002378 PyObject *message = NULL;
Serhiy Storchakabca49392017-09-03 08:10:14 +03002379 PyObject *func;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002380 PyObject *error_type, *error_value, *error_traceback;
2381
2382 if (task->task_state != STATE_PENDING || !task->task_log_destroy_pending) {
2383 goto done;
2384 }
2385
2386 /* Save the current exception, if any. */
2387 PyErr_Fetch(&error_type, &error_value, &error_traceback);
2388
2389 context = PyDict_New();
2390 if (context == NULL) {
2391 goto finally;
2392 }
2393
2394 message = PyUnicode_FromString("Task was destroyed but it is pending!");
2395 if (message == NULL) {
2396 goto finally;
2397 }
2398
2399 if (_PyDict_SetItemId(context, &PyId_message, message) < 0 ||
2400 _PyDict_SetItemId(context, &PyId_task, (PyObject*)task) < 0)
2401 {
2402 goto finally;
2403 }
2404
2405 if (task->task_source_tb != NULL) {
2406 if (_PyDict_SetItemId(context, &PyId_source_traceback,
2407 task->task_source_tb) < 0)
2408 {
2409 goto finally;
2410 }
2411 }
2412
2413 func = _PyObject_GetAttrId(task->task_loop, &PyId_call_exception_handler);
2414 if (func != NULL) {
Serhiy Storchakabca49392017-09-03 08:10:14 +03002415 PyObject *res = PyObject_CallFunctionObjArgs(func, context, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002416 if (res == NULL) {
2417 PyErr_WriteUnraisable(func);
2418 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03002419 else {
2420 Py_DECREF(res);
2421 }
2422 Py_DECREF(func);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002423 }
2424
2425finally:
Serhiy Storchakabca49392017-09-03 08:10:14 +03002426 Py_XDECREF(context);
2427 Py_XDECREF(message);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002428
2429 /* Restore the saved exception. */
2430 PyErr_Restore(error_type, error_value, error_traceback);
2431
2432done:
2433 FutureObj_finalize((FutureObj*)task);
2434}
2435
2436static void TaskObj_dealloc(PyObject *); /* Needs Task_CheckExact */
2437
2438static PyMethodDef TaskType_methods[] = {
2439 _ASYNCIO_FUTURE_RESULT_METHODDEF
2440 _ASYNCIO_FUTURE_EXCEPTION_METHODDEF
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002441 _ASYNCIO_FUTURE_ADD_DONE_CALLBACK_METHODDEF
2442 _ASYNCIO_FUTURE_REMOVE_DONE_CALLBACK_METHODDEF
2443 _ASYNCIO_FUTURE_CANCELLED_METHODDEF
2444 _ASYNCIO_FUTURE_DONE_METHODDEF
Yury Selivanov0cf16f92017-12-25 10:48:15 -05002445 _ASYNCIO_TASK_SET_RESULT_METHODDEF
2446 _ASYNCIO_TASK_SET_EXCEPTION_METHODDEF
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002447 _ASYNCIO_TASK_CURRENT_TASK_METHODDEF
2448 _ASYNCIO_TASK_ALL_TASKS_METHODDEF
2449 _ASYNCIO_TASK_CANCEL_METHODDEF
2450 _ASYNCIO_TASK_GET_STACK_METHODDEF
2451 _ASYNCIO_TASK_PRINT_STACK_METHODDEF
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002452 _ASYNCIO_TASK__REPR_INFO_METHODDEF
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002453 _ASYNCIO_TASK_GET_NAME_METHODDEF
2454 _ASYNCIO_TASK_SET_NAME_METHODDEF
Alex Grönholm98ef9202019-05-30 18:30:09 +03002455 _ASYNCIO_TASK_GET_CORO_METHODDEF
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002456 {NULL, NULL} /* Sentinel */
2457};
2458
2459static PyGetSetDef TaskType_getsetlist[] = {
2460 FUTURE_COMMON_GETSETLIST
2461 {"_log_destroy_pending", (getter)TaskObj_get_log_destroy_pending,
2462 (setter)TaskObj_set_log_destroy_pending, NULL},
2463 {"_must_cancel", (getter)TaskObj_get_must_cancel, NULL, NULL},
2464 {"_coro", (getter)TaskObj_get_coro, NULL, NULL},
2465 {"_fut_waiter", (getter)TaskObj_get_fut_waiter, NULL, NULL},
2466 {NULL} /* Sentinel */
2467};
2468
2469static PyTypeObject TaskType = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02002470 PyVarObject_HEAD_INIT(NULL, 0)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002471 "_asyncio.Task",
2472 sizeof(TaskObj), /* tp_basicsize */
2473 .tp_base = &FutureType,
2474 .tp_dealloc = TaskObj_dealloc,
2475 .tp_as_async = &FutureType_as_async,
2476 .tp_repr = (reprfunc)FutureObj_repr,
Antoine Pitrouada319b2019-05-29 22:12:38 +02002477 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002478 .tp_doc = _asyncio_Task___init____doc__,
2479 .tp_traverse = (traverseproc)TaskObj_traverse,
2480 .tp_clear = (inquiry)TaskObj_clear,
2481 .tp_weaklistoffset = offsetof(TaskObj, task_weakreflist),
2482 .tp_iter = (getiterfunc)future_new_iter,
2483 .tp_methods = TaskType_methods,
2484 .tp_getset = TaskType_getsetlist,
2485 .tp_dictoffset = offsetof(TaskObj, dict),
2486 .tp_init = (initproc)_asyncio_Task___init__,
2487 .tp_new = PyType_GenericNew,
2488 .tp_finalize = (destructor)TaskObj_finalize,
2489};
2490
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002491static void
2492TaskObj_dealloc(PyObject *self)
2493{
2494 TaskObj *task = (TaskObj *)self;
2495
2496 if (Task_CheckExact(self)) {
2497 /* When fut is subclass of Task, finalizer is called from
2498 * subtype_dealloc.
2499 */
2500 if (PyObject_CallFinalizerFromDealloc(self) < 0) {
2501 // resurrected.
2502 return;
2503 }
2504 }
2505
Alexander Mohrde34cbe2017-08-01 23:31:07 -07002506 PyObject_GC_UnTrack(self);
2507
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002508 if (task->task_weakreflist != NULL) {
2509 PyObject_ClearWeakRefs(self);
2510 }
2511
2512 (void)TaskObj_clear(task);
2513 Py_TYPE(task)->tp_free(task);
2514}
2515
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002516static int
2517task_call_step_soon(TaskObj *task, PyObject *arg)
2518{
Serhiy Storchakabca49392017-09-03 08:10:14 +03002519 PyObject *cb = TaskStepMethWrapper_new(task, arg);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002520 if (cb == NULL) {
2521 return -1;
2522 }
2523
Yury Selivanovf23746a2018-01-22 19:11:18 -05002524 int ret = call_soon(task->task_loop, cb, NULL, task->task_context);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002525 Py_DECREF(cb);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05002526 return ret;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002527}
2528
2529static PyObject *
2530task_set_error_soon(TaskObj *task, PyObject *et, const char *format, ...)
2531{
2532 PyObject* msg;
2533
2534 va_list vargs;
2535#ifdef HAVE_STDARG_PROTOTYPES
2536 va_start(vargs, format);
2537#else
2538 va_start(vargs);
2539#endif
2540 msg = PyUnicode_FromFormatV(format, vargs);
2541 va_end(vargs);
2542
2543 if (msg == NULL) {
2544 return NULL;
2545 }
2546
Victor Stinnerde4ae3d2016-12-04 22:59:09 +01002547 PyObject *e = PyObject_CallFunctionObjArgs(et, msg, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002548 Py_DECREF(msg);
2549 if (e == NULL) {
2550 return NULL;
2551 }
2552
2553 if (task_call_step_soon(task, e) == -1) {
2554 Py_DECREF(e);
2555 return NULL;
2556 }
2557
2558 Py_DECREF(e);
2559 Py_RETURN_NONE;
2560}
2561
2562static PyObject *
2563task_step_impl(TaskObj *task, PyObject *exc)
2564{
2565 int res;
2566 int clear_exc = 0;
2567 PyObject *result = NULL;
Serhiy Storchakabca49392017-09-03 08:10:14 +03002568 PyObject *coro;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002569 PyObject *o;
2570
2571 if (task->task_state != STATE_PENDING) {
Yury Selivanov0cf16f92017-12-25 10:48:15 -05002572 PyErr_Format(asyncio_InvalidStateError,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002573 "_step(): already done: %R %R",
2574 task,
2575 exc ? exc : Py_None);
INADA Naokic411a7d2016-10-18 11:48:14 +09002576 goto fail;
2577 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09002578
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002579 if (task->task_must_cancel) {
2580 assert(exc != Py_None);
2581
2582 if (exc) {
2583 /* Check if exc is a CancelledError */
2584 res = PyObject_IsInstance(exc, asyncio_CancelledError);
2585 if (res == -1) {
2586 /* An error occurred, abort */
2587 goto fail;
2588 }
2589 if (res == 0) {
2590 /* exc is not CancelledError; reset it to NULL */
2591 exc = NULL;
2592 }
2593 }
2594
2595 if (!exc) {
2596 /* exc was not a CancelledError */
Victor Stinnerf17c3de2016-12-06 18:46:19 +01002597 exc = _PyObject_CallNoArg(asyncio_CancelledError);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002598 if (!exc) {
2599 goto fail;
2600 }
2601 clear_exc = 1;
2602 }
2603
2604 task->task_must_cancel = 0;
2605 }
2606
2607 Py_CLEAR(task->task_fut_waiter);
2608
Serhiy Storchakabca49392017-09-03 08:10:14 +03002609 coro = task->task_coro;
2610 if (coro == NULL) {
2611 PyErr_SetString(PyExc_RuntimeError, "uninitialized Task object");
2612 return NULL;
2613 }
2614
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002615 if (exc == NULL) {
2616 if (PyGen_CheckExact(coro) || PyCoro_CheckExact(coro)) {
2617 result = _PyGen_Send((PyGenObject*)coro, Py_None);
2618 }
2619 else {
Victor Stinnerb6ed57d2016-12-09 14:24:02 +01002620 result = _PyObject_CallMethodIdObjArgs(coro, &PyId_send,
2621 Py_None, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002622 }
2623 }
2624 else {
Victor Stinnerb6ed57d2016-12-09 14:24:02 +01002625 result = _PyObject_CallMethodIdObjArgs(coro, &PyId_throw,
2626 exc, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002627 if (clear_exc) {
2628 /* We created 'exc' during this call */
Serhiy Storchakabca49392017-09-03 08:10:14 +03002629 Py_DECREF(exc);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002630 }
2631 }
2632
2633 if (result == NULL) {
2634 PyObject *et, *ev, *tb;
2635
2636 if (_PyGen_FetchStopIterationValue(&o) == 0) {
2637 /* The error is StopIteration and that means that
2638 the underlying coroutine has resolved */
Miss Islington (bot)16cec132019-09-25 04:48:52 -07002639
2640 PyObject *res;
INADA Naoki991adca2017-05-11 21:18:38 +09002641 if (task->task_must_cancel) {
2642 // Task is cancelled right before coro stops.
INADA Naoki991adca2017-05-11 21:18:38 +09002643 task->task_must_cancel = 0;
Miss Islington (bot)16cec132019-09-25 04:48:52 -07002644 res = future_cancel((FutureObj*)task);
INADA Naoki991adca2017-05-11 21:18:38 +09002645 }
Miss Islington (bot)16cec132019-09-25 04:48:52 -07002646 else {
2647 res = future_set_result((FutureObj*)task, o);
2648 }
2649
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002650 Py_DECREF(o);
Miss Islington (bot)16cec132019-09-25 04:48:52 -07002651
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002652 if (res == NULL) {
2653 return NULL;
2654 }
2655 Py_DECREF(res);
2656 Py_RETURN_NONE;
2657 }
2658
2659 if (PyErr_ExceptionMatches(asyncio_CancelledError)) {
2660 /* CancelledError */
2661 PyErr_Clear();
2662 return future_cancel((FutureObj*)task);
2663 }
2664
2665 /* Some other exception; pop it and call Task.set_exception() */
2666 PyErr_Fetch(&et, &ev, &tb);
INADA Naoki991adca2017-05-11 21:18:38 +09002667
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002668 assert(et);
2669 if (!ev || !PyObject_TypeCheck(ev, (PyTypeObject *) et)) {
2670 PyErr_NormalizeException(&et, &ev, &tb);
2671 }
Yury Selivanovedfe8862016-12-01 11:37:47 -05002672 if (tb != NULL) {
2673 PyException_SetTraceback(ev, tb);
2674 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002675 o = future_set_exception((FutureObj*)task, ev);
2676 if (!o) {
2677 /* An exception in Task.set_exception() */
Serhiy Storchakabca49392017-09-03 08:10:14 +03002678 Py_DECREF(et);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002679 Py_XDECREF(tb);
2680 Py_XDECREF(ev);
2681 goto fail;
2682 }
2683 assert(o == Py_None);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002684 Py_DECREF(o);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002685
Yury Selivanov431b5402019-05-27 14:45:12 +02002686 if (PyErr_GivenExceptionMatches(et, PyExc_KeyboardInterrupt) ||
2687 PyErr_GivenExceptionMatches(et, PyExc_SystemExit))
2688 {
2689 /* We've got a KeyboardInterrupt or a SystemError; re-raise it */
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002690 PyErr_Restore(et, ev, tb);
2691 goto fail;
2692 }
2693
Serhiy Storchakabca49392017-09-03 08:10:14 +03002694 Py_DECREF(et);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002695 Py_XDECREF(tb);
2696 Py_XDECREF(ev);
2697
2698 Py_RETURN_NONE;
2699 }
2700
2701 if (result == (PyObject*)task) {
2702 /* We have a task that wants to await on itself */
2703 goto self_await;
2704 }
2705
2706 /* Check if `result` is FutureObj or TaskObj (and not a subclass) */
2707 if (Future_CheckExact(result) || Task_CheckExact(result)) {
2708 PyObject *wrapper;
2709 PyObject *res;
2710 FutureObj *fut = (FutureObj*)result;
2711
2712 /* Check if `result` future is attached to a different loop */
2713 if (fut->fut_loop != task->task_loop) {
2714 goto different_loop;
2715 }
2716
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002717 if (!fut->fut_blocking) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002718 goto yield_insteadof_yf;
2719 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002720
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002721 fut->fut_blocking = 0;
2722
2723 /* result.add_done_callback(task._wakeup) */
2724 wrapper = TaskWakeupMethWrapper_new(task);
2725 if (wrapper == NULL) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002726 goto fail;
2727 }
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002728 res = future_add_done_callback(
2729 (FutureObj*)result, wrapper, task->task_context);
2730 Py_DECREF(wrapper);
2731 if (res == NULL) {
2732 goto fail;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002733 }
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002734 Py_DECREF(res);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002735
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002736 /* task._fut_waiter = result */
2737 task->task_fut_waiter = result; /* no incref is necessary */
2738
2739 if (task->task_must_cancel) {
2740 PyObject *r;
Elvis Pranskevichus0c797a62018-10-03 10:30:31 -04002741 int is_true;
Serhiy Storchakaaddf8af2018-10-05 21:20:02 +03002742 r = _PyObject_CallMethodId(result, &PyId_cancel, NULL);
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002743 if (r == NULL) {
2744 return NULL;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002745 }
Elvis Pranskevichus0c797a62018-10-03 10:30:31 -04002746 is_true = PyObject_IsTrue(r);
2747 Py_DECREF(r);
2748 if (is_true < 0) {
2749 return NULL;
2750 }
2751 else if (is_true) {
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002752 task->task_must_cancel = 0;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002753 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002754 }
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002755
2756 Py_RETURN_NONE;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002757 }
2758
2759 /* Check if `result` is None */
2760 if (result == Py_None) {
2761 /* Bare yield relinquishes control for one event loop iteration. */
2762 if (task_call_step_soon(task, NULL)) {
2763 goto fail;
2764 }
2765 return result;
2766 }
2767
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002768 /* Check if `result` is a Future-compatible object */
2769 if (_PyObject_LookupAttrId(result, &PyId__asyncio_future_blocking, &o) < 0) {
2770 goto fail;
2771 }
2772 if (o != NULL && o != Py_None) {
2773 /* `result` is a Future-compatible object */
2774 PyObject *wrapper;
2775 PyObject *res;
2776
2777 int blocking = PyObject_IsTrue(o);
2778 Py_DECREF(o);
2779 if (blocking < 0) {
2780 goto fail;
2781 }
2782
2783 /* Check if `result` future is attached to a different loop */
2784 PyObject *oloop = get_future_loop(result);
2785 if (oloop == NULL) {
2786 goto fail;
2787 }
2788 if (oloop != task->task_loop) {
2789 Py_DECREF(oloop);
2790 goto different_loop;
2791 }
2792 Py_DECREF(oloop);
2793
2794 if (!blocking) {
2795 goto yield_insteadof_yf;
2796 }
2797
2798 /* result._asyncio_future_blocking = False */
2799 if (_PyObject_SetAttrId(
2800 result, &PyId__asyncio_future_blocking, Py_False) == -1) {
2801 goto fail;
2802 }
2803
2804 wrapper = TaskWakeupMethWrapper_new(task);
2805 if (wrapper == NULL) {
2806 goto fail;
2807 }
2808
2809 /* result.add_done_callback(task._wakeup) */
2810 PyObject *add_cb = _PyObject_GetAttrId(
2811 result, &PyId_add_done_callback);
2812 if (add_cb == NULL) {
2813 Py_DECREF(wrapper);
2814 goto fail;
2815 }
2816 PyObject *stack[2];
2817 stack[0] = wrapper;
2818 stack[1] = (PyObject *)task->task_context;
Jeroen Demeyeraacc77f2019-05-29 20:31:52 +02002819 res = _PyObject_Vectorcall(add_cb, stack, 1, context_kwname);
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002820 Py_DECREF(add_cb);
2821 Py_DECREF(wrapper);
2822 if (res == NULL) {
2823 goto fail;
2824 }
2825 Py_DECREF(res);
2826
2827 /* task._fut_waiter = result */
2828 task->task_fut_waiter = result; /* no incref is necessary */
2829
2830 if (task->task_must_cancel) {
2831 PyObject *r;
2832 int is_true;
2833 r = _PyObject_CallMethodId(result, &PyId_cancel, NULL);
2834 if (r == NULL) {
2835 return NULL;
2836 }
2837 is_true = PyObject_IsTrue(r);
2838 Py_DECREF(r);
2839 if (is_true < 0) {
2840 return NULL;
2841 }
2842 else if (is_true) {
2843 task->task_must_cancel = 0;
2844 }
2845 }
2846
2847 Py_RETURN_NONE;
2848 }
2849
2850 Py_XDECREF(o);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002851 /* Check if `result` is a generator */
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002852 res = PyObject_IsInstance(result, (PyObject*)&PyGen_Type);
2853 if (res < 0) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002854 goto fail;
2855 }
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002856 if (res) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002857 /* `result` is a generator */
Serhiy Storchaka66553542018-05-20 16:30:31 +03002858 o = task_set_error_soon(
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002859 task, PyExc_RuntimeError,
2860 "yield was used instead of yield from for "
Serhiy Storchaka66553542018-05-20 16:30:31 +03002861 "generator in task %R with %R", task, result);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002862 Py_DECREF(result);
Serhiy Storchaka66553542018-05-20 16:30:31 +03002863 return o;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002864 }
2865
2866 /* The `result` is none of the above */
Serhiy Storchaka66553542018-05-20 16:30:31 +03002867 o = task_set_error_soon(
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002868 task, PyExc_RuntimeError, "Task got bad yield: %R", result);
Serhiy Storchaka66553542018-05-20 16:30:31 +03002869 Py_DECREF(result);
2870 return o;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002871
2872self_await:
2873 o = task_set_error_soon(
2874 task, PyExc_RuntimeError,
2875 "Task cannot await on itself: %R", task);
2876 Py_DECREF(result);
2877 return o;
2878
2879yield_insteadof_yf:
2880 o = task_set_error_soon(
2881 task, PyExc_RuntimeError,
2882 "yield was used instead of yield from "
2883 "in task %R with %R",
2884 task, result);
2885 Py_DECREF(result);
2886 return o;
2887
2888different_loop:
2889 o = task_set_error_soon(
2890 task, PyExc_RuntimeError,
2891 "Task %R got Future %R attached to a different loop",
2892 task, result);
2893 Py_DECREF(result);
2894 return o;
2895
2896fail:
2897 Py_XDECREF(result);
2898 return NULL;
2899}
2900
2901static PyObject *
2902task_step(TaskObj *task, PyObject *exc)
2903{
2904 PyObject *res;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002905
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002906 if (enter_task(task->task_loop, (PyObject*)task) < 0) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002907 return NULL;
2908 }
2909
2910 res = task_step_impl(task, exc);
2911
2912 if (res == NULL) {
2913 PyObject *et, *ev, *tb;
2914 PyErr_Fetch(&et, &ev, &tb);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002915 leave_task(task->task_loop, (PyObject*)task);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002916 _PyErr_ChainExceptions(et, ev, tb);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002917 return NULL;
2918 }
2919 else {
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002920 if (leave_task(task->task_loop, (PyObject*)task) < 0) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002921 Py_DECREF(res);
2922 return NULL;
2923 }
2924 else {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002925 return res;
2926 }
2927 }
2928}
2929
2930static PyObject *
2931task_wakeup(TaskObj *task, PyObject *o)
2932{
Serhiy Storchakabca49392017-09-03 08:10:14 +03002933 PyObject *et, *ev, *tb;
2934 PyObject *result;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002935 assert(o);
2936
2937 if (Future_CheckExact(o) || Task_CheckExact(o)) {
2938 PyObject *fut_result = NULL;
2939 int res = future_get_result((FutureObj*)o, &fut_result);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002940
2941 switch(res) {
2942 case -1:
2943 assert(fut_result == NULL);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002944 break; /* exception raised */
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002945 case 0:
2946 Py_DECREF(fut_result);
Yury Selivanov22feeb82018-01-24 11:31:01 -05002947 return task_step(task, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002948 default:
2949 assert(res == 1);
Yury Selivanov22feeb82018-01-24 11:31:01 -05002950 result = task_step(task, fut_result);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002951 Py_DECREF(fut_result);
2952 return result;
2953 }
2954 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002955 else {
Serhiy Storchakabca49392017-09-03 08:10:14 +03002956 PyObject *fut_result = PyObject_CallMethod(o, "result", NULL);
2957 if (fut_result != NULL) {
2958 Py_DECREF(fut_result);
Yury Selivanov22feeb82018-01-24 11:31:01 -05002959 return task_step(task, NULL);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002960 }
2961 /* exception raised */
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002962 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03002963
2964 PyErr_Fetch(&et, &ev, &tb);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002965 if (!ev || !PyObject_TypeCheck(ev, (PyTypeObject *) et)) {
2966 PyErr_NormalizeException(&et, &ev, &tb);
2967 }
2968
Yury Selivanov22feeb82018-01-24 11:31:01 -05002969 result = task_step(task, ev);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002970
2971 Py_DECREF(et);
2972 Py_XDECREF(tb);
2973 Py_XDECREF(ev);
2974
2975 return result;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002976}
2977
2978
Yury Selivanova70232f2017-12-13 14:49:42 -05002979/*********************** Functions **************************/
2980
2981
2982/*[clinic input]
2983_asyncio._get_running_loop
2984
2985Return the running event loop or None.
2986
2987This is a low-level function intended to be used by event loops.
2988This function is thread-specific.
2989
2990[clinic start generated code]*/
2991
2992static PyObject *
2993_asyncio__get_running_loop_impl(PyObject *module)
2994/*[clinic end generated code: output=b4390af721411a0a input=0a21627e25a4bd43]*/
2995{
2996 PyObject *loop;
2997 if (get_running_loop(&loop)) {
2998 return NULL;
2999 }
3000 if (loop == NULL) {
3001 /* There's no currently running event loop */
3002 Py_RETURN_NONE;
3003 }
3004 return loop;
3005}
3006
3007/*[clinic input]
3008_asyncio._set_running_loop
3009 loop: 'O'
3010 /
3011
3012Set the running event loop.
3013
3014This is a low-level function intended to be used by event loops.
3015This function is thread-specific.
3016[clinic start generated code]*/
3017
3018static PyObject *
3019_asyncio__set_running_loop(PyObject *module, PyObject *loop)
3020/*[clinic end generated code: output=ae56bf7a28ca189a input=4c9720233d606604]*/
3021{
3022 if (set_running_loop(loop)) {
3023 return NULL;
3024 }
3025 Py_RETURN_NONE;
3026}
3027
3028/*[clinic input]
3029_asyncio.get_event_loop
3030
3031Return an asyncio event loop.
3032
3033When called from a coroutine or a callback (e.g. scheduled with
3034call_soon or similar API), this function will always return the
3035running event loop.
3036
3037If there is no running event loop set, the function will return
3038the result of `get_event_loop_policy().get_event_loop()` call.
3039[clinic start generated code]*/
3040
3041static PyObject *
3042_asyncio_get_event_loop_impl(PyObject *module)
3043/*[clinic end generated code: output=2a2d8b2f824c648b input=9364bf2916c8655d]*/
3044{
3045 return get_event_loop();
3046}
3047
3048/*[clinic input]
3049_asyncio.get_running_loop
3050
3051Return the running event loop. Raise a RuntimeError if there is none.
3052
3053This function is thread-specific.
3054[clinic start generated code]*/
3055
3056static PyObject *
3057_asyncio_get_running_loop_impl(PyObject *module)
3058/*[clinic end generated code: output=c247b5f9e529530e input=2a3bf02ba39f173d]*/
3059{
3060 PyObject *loop;
3061 if (get_running_loop(&loop)) {
3062 return NULL;
3063 }
3064 if (loop == NULL) {
3065 /* There's no currently running event loop */
3066 PyErr_SetString(
3067 PyExc_RuntimeError, "no running event loop");
3068 }
3069 return loop;
3070}
3071
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003072/*[clinic input]
3073_asyncio._register_task
3074
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003075 task: object
3076
3077Register a new task in asyncio as executed by loop.
3078
3079Returns None.
3080[clinic start generated code]*/
3081
3082static PyObject *
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003083_asyncio__register_task_impl(PyObject *module, PyObject *task)
3084/*[clinic end generated code: output=8672dadd69a7d4e2 input=21075aaea14dfbad]*/
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003085{
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003086 if (register_task(task) < 0) {
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003087 return NULL;
3088 }
3089 Py_RETURN_NONE;
3090}
3091
3092
3093/*[clinic input]
3094_asyncio._unregister_task
3095
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003096 task: object
3097
3098Unregister a task.
3099
3100Returns None.
3101[clinic start generated code]*/
3102
3103static PyObject *
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003104_asyncio__unregister_task_impl(PyObject *module, PyObject *task)
3105/*[clinic end generated code: output=6e5585706d568a46 input=28fb98c3975f7bdc]*/
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003106{
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003107 if (unregister_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._enter_task
3116
3117 loop: object
3118 task: object
3119
3120Enter into task execution or resume suspended task.
3121
3122Task belongs to loop.
3123
3124Returns None.
3125[clinic start generated code]*/
3126
3127static PyObject *
3128_asyncio__enter_task_impl(PyObject *module, PyObject *loop, PyObject *task)
3129/*[clinic end generated code: output=a22611c858035b73 input=de1b06dca70d8737]*/
3130{
3131 if (enter_task(loop, task) < 0) {
3132 return NULL;
3133 }
3134 Py_RETURN_NONE;
3135}
3136
3137
3138/*[clinic input]
3139_asyncio._leave_task
3140
3141 loop: object
3142 task: object
3143
3144Leave task execution or suspend a task.
3145
3146Task belongs to loop.
3147
3148Returns None.
3149[clinic start generated code]*/
3150
3151static PyObject *
3152_asyncio__leave_task_impl(PyObject *module, PyObject *loop, PyObject *task)
3153/*[clinic end generated code: output=0ebf6db4b858fb41 input=51296a46313d1ad8]*/
3154{
3155 if (leave_task(loop, task) < 0) {
3156 return NULL;
3157 }
3158 Py_RETURN_NONE;
3159}
3160
Yury Selivanova70232f2017-12-13 14:49:42 -05003161
Yury Selivanov9d411c12018-01-23 15:10:03 -05003162/*********************** PyRunningLoopHolder ********************/
3163
3164
3165static PyRunningLoopHolder *
3166new_running_loop_holder(PyObject *loop)
3167{
3168 PyRunningLoopHolder *rl = PyObject_New(
3169 PyRunningLoopHolder, &PyRunningLoopHolder_Type);
3170 if (rl == NULL) {
3171 return NULL;
3172 }
3173
3174#if defined(HAVE_GETPID) && !defined(MS_WINDOWS)
3175 rl->rl_pid = getpid();
3176#endif
3177
3178 Py_INCREF(loop);
3179 rl->rl_loop = loop;
3180
3181 return rl;
3182}
3183
3184
3185static void
3186PyRunningLoopHolder_tp_dealloc(PyRunningLoopHolder *rl)
3187{
3188 Py_CLEAR(rl->rl_loop);
3189 PyObject_Free(rl);
3190}
3191
3192
3193static PyTypeObject PyRunningLoopHolder_Type = {
3194 PyVarObject_HEAD_INIT(NULL, 0)
3195 "_RunningLoopHolder",
3196 sizeof(PyRunningLoopHolder),
3197 .tp_getattro = PyObject_GenericGetAttr,
3198 .tp_flags = Py_TPFLAGS_DEFAULT,
3199 .tp_dealloc = (destructor)PyRunningLoopHolder_tp_dealloc,
3200};
3201
3202
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003203/*********************** Module **************************/
3204
3205
3206static void
Zackery Spytze40ad792017-12-19 11:48:13 -07003207module_free_freelists(void)
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05003208{
3209 PyObject *next;
3210 PyObject *current;
3211
3212 next = (PyObject*) fi_freelist;
3213 while (next != NULL) {
3214 assert(fi_freelist_len > 0);
3215 fi_freelist_len--;
3216
3217 current = next;
3218 next = (PyObject*) ((futureiterobject*) current)->future;
3219 PyObject_GC_Del(current);
3220 }
3221 assert(fi_freelist_len == 0);
3222 fi_freelist = NULL;
3223}
3224
3225
3226static void
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003227module_free(void *m)
3228{
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003229 Py_CLEAR(asyncio_mod);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003230 Py_CLEAR(traceback_extract_stack);
3231 Py_CLEAR(asyncio_future_repr_info_func);
3232 Py_CLEAR(asyncio_get_event_loop_policy);
3233 Py_CLEAR(asyncio_iscoroutine_func);
3234 Py_CLEAR(asyncio_task_get_stack_func);
3235 Py_CLEAR(asyncio_task_print_stack_func);
3236 Py_CLEAR(asyncio_task_repr_info_func);
3237 Py_CLEAR(asyncio_InvalidStateError);
3238 Py_CLEAR(asyncio_CancelledError);
3239
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003240 Py_CLEAR(all_tasks);
Yury Selivanova9d7e552017-12-19 07:18:45 -05003241 Py_CLEAR(current_tasks);
3242 Py_CLEAR(iscoroutine_typecache);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05003243
Yury Selivanovf23746a2018-01-22 19:11:18 -05003244 Py_CLEAR(context_kwname);
3245
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05003246 module_free_freelists();
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003247}
3248
3249static int
3250module_init(void)
3251{
3252 PyObject *module = NULL;
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003253
3254 asyncio_mod = PyImport_ImportModule("asyncio");
3255 if (asyncio_mod == NULL) {
3256 goto fail;
3257 }
Miss Islington (bot)13915a32019-10-07 09:38:00 -07003258 if (module_initialized != 0) {
3259 return 0;
3260 }
3261 else {
3262 module_initialized = 1;
3263 }
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003264
3265 current_tasks = PyDict_New();
3266 if (current_tasks == NULL) {
3267 goto fail;
3268 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003269
Yury Selivanova9d7e552017-12-19 07:18:45 -05003270 iscoroutine_typecache = PySet_New(NULL);
3271 if (iscoroutine_typecache == NULL) {
3272 goto fail;
3273 }
3274
Yury Selivanovf23746a2018-01-22 19:11:18 -05003275
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03003276 context_kwname = Py_BuildValue("(s)", "context");
Yury Selivanovf23746a2018-01-22 19:11:18 -05003277 if (context_kwname == NULL) {
3278 goto fail;
3279 }
Yury Selivanovf23746a2018-01-22 19:11:18 -05003280
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003281#define WITH_MOD(NAME) \
3282 Py_CLEAR(module); \
3283 module = PyImport_ImportModule(NAME); \
3284 if (module == NULL) { \
Serhiy Storchakabca49392017-09-03 08:10:14 +03003285 goto fail; \
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003286 }
3287
3288#define GET_MOD_ATTR(VAR, NAME) \
3289 VAR = PyObject_GetAttrString(module, NAME); \
3290 if (VAR == NULL) { \
3291 goto fail; \
3292 }
3293
3294 WITH_MOD("asyncio.events")
Yury Selivanova70232f2017-12-13 14:49:42 -05003295 GET_MOD_ATTR(asyncio_get_event_loop_policy, "get_event_loop_policy")
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003296
3297 WITH_MOD("asyncio.base_futures")
3298 GET_MOD_ATTR(asyncio_future_repr_info_func, "_future_repr_info")
Andrew Svetlov0baa72f2018-09-11 10:13:04 -07003299
3300 WITH_MOD("asyncio.exceptions")
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003301 GET_MOD_ATTR(asyncio_InvalidStateError, "InvalidStateError")
3302 GET_MOD_ATTR(asyncio_CancelledError, "CancelledError")
3303
3304 WITH_MOD("asyncio.base_tasks")
3305 GET_MOD_ATTR(asyncio_task_repr_info_func, "_task_repr_info")
3306 GET_MOD_ATTR(asyncio_task_get_stack_func, "_task_get_stack")
3307 GET_MOD_ATTR(asyncio_task_print_stack_func, "_task_print_stack")
3308
Andrew Svetlovf74ef452017-12-15 07:04:38 +02003309 WITH_MOD("asyncio.coroutines")
3310 GET_MOD_ATTR(asyncio_iscoroutine_func, "iscoroutine")
3311
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003312 WITH_MOD("traceback")
3313 GET_MOD_ATTR(traceback_extract_stack, "extract_stack")
3314
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003315 PyObject *weak_set;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003316 WITH_MOD("weakref")
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003317 GET_MOD_ATTR(weak_set, "WeakSet");
3318 all_tasks = _PyObject_CallNoArg(weak_set);
3319 Py_CLEAR(weak_set);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003320 if (all_tasks == NULL) {
INADA Naokic411a7d2016-10-18 11:48:14 +09003321 goto fail;
3322 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003323
Serhiy Storchakabca49392017-09-03 08:10:14 +03003324 Py_DECREF(module);
INADA Naokic411a7d2016-10-18 11:48:14 +09003325 return 0;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003326
INADA Naokic411a7d2016-10-18 11:48:14 +09003327fail:
INADA Naokic411a7d2016-10-18 11:48:14 +09003328 Py_CLEAR(module);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003329 module_free(NULL);
INADA Naokic411a7d2016-10-18 11:48:14 +09003330 return -1;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003331
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003332#undef WITH_MOD
3333#undef GET_MOD_ATTR
3334}
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003335
INADA Naokic411a7d2016-10-18 11:48:14 +09003336PyDoc_STRVAR(module_doc, "Accelerator module for asyncio");
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003337
Yury Selivanova70232f2017-12-13 14:49:42 -05003338static PyMethodDef asyncio_methods[] = {
3339 _ASYNCIO_GET_EVENT_LOOP_METHODDEF
3340 _ASYNCIO_GET_RUNNING_LOOP_METHODDEF
3341 _ASYNCIO__GET_RUNNING_LOOP_METHODDEF
3342 _ASYNCIO__SET_RUNNING_LOOP_METHODDEF
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003343 _ASYNCIO__REGISTER_TASK_METHODDEF
3344 _ASYNCIO__UNREGISTER_TASK_METHODDEF
3345 _ASYNCIO__ENTER_TASK_METHODDEF
3346 _ASYNCIO__LEAVE_TASK_METHODDEF
Yury Selivanova70232f2017-12-13 14:49:42 -05003347 {NULL, NULL}
3348};
3349
INADA Naoki9f2ce252016-10-15 15:39:19 +09003350static struct PyModuleDef _asynciomodule = {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003351 PyModuleDef_HEAD_INIT, /* m_base */
INADA Naoki9f2ce252016-10-15 15:39:19 +09003352 "_asyncio", /* m_name */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003353 module_doc, /* m_doc */
3354 -1, /* m_size */
Yury Selivanova70232f2017-12-13 14:49:42 -05003355 asyncio_methods, /* m_methods */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003356 NULL, /* m_slots */
3357 NULL, /* m_traverse */
3358 NULL, /* m_clear */
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003359 (freefunc)module_free /* m_free */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003360};
3361
3362
3363PyMODINIT_FUNC
INADA Naoki9f2ce252016-10-15 15:39:19 +09003364PyInit__asyncio(void)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003365{
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003366 if (module_init() < 0) {
INADA Naokic411a7d2016-10-18 11:48:14 +09003367 return NULL;
3368 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003369 if (PyType_Ready(&FutureType) < 0) {
3370 return NULL;
3371 }
3372 if (PyType_Ready(&FutureIterType) < 0) {
3373 return NULL;
3374 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03003375 if (PyType_Ready(&TaskStepMethWrapper_Type) < 0) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003376 return NULL;
3377 }
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03003378 if (PyType_Ready(&TaskWakeupMethWrapper_Type) < 0) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003379 return NULL;
3380 }
3381 if (PyType_Ready(&TaskType) < 0) {
3382 return NULL;
3383 }
Yury Selivanov9d411c12018-01-23 15:10:03 -05003384 if (PyType_Ready(&PyRunningLoopHolder_Type) < 0) {
3385 return NULL;
3386 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003387
INADA Naoki9f2ce252016-10-15 15:39:19 +09003388 PyObject *m = PyModule_Create(&_asynciomodule);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003389 if (m == NULL) {
3390 return NULL;
3391 }
3392
3393 Py_INCREF(&FutureType);
3394 if (PyModule_AddObject(m, "Future", (PyObject *)&FutureType) < 0) {
3395 Py_DECREF(&FutureType);
3396 return NULL;
3397 }
3398
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003399 Py_INCREF(&TaskType);
3400 if (PyModule_AddObject(m, "Task", (PyObject *)&TaskType) < 0) {
3401 Py_DECREF(&TaskType);
3402 return NULL;
3403 }
3404
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003405 Py_INCREF(all_tasks);
3406 if (PyModule_AddObject(m, "_all_tasks", all_tasks) < 0) {
3407 Py_DECREF(all_tasks);
3408 return NULL;
3409 }
3410
3411 Py_INCREF(current_tasks);
3412 if (PyModule_AddObject(m, "_current_tasks", current_tasks) < 0) {
3413 Py_DECREF(current_tasks);
3414 return NULL;
3415 }
3416
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003417 return m;
3418}