blob: 88b834c113322c20d829423ed4c7e19a9759325e [file] [log] [blame]
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001#include "Python.h"
2#include "structmember.h"
3
4
Yury Selivanova0c1ba62016-10-28 12:52:37 -04005/*[clinic input]
6module _asyncio
7[clinic start generated code]*/
8/*[clinic end generated code: output=da39a3ee5e6b4b0d input=8fd17862aa989c69]*/
9
10
INADA Naoki9e4e38e2016-10-09 14:44:47 +090011/* identifiers used from some functions */
Yury Selivanova70232f2017-12-13 14:49:42 -050012_Py_IDENTIFIER(__asyncio_running_event_loop__);
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +030013_Py_IDENTIFIER(_asyncio_future_blocking);
Yury Selivanova0c1ba62016-10-28 12:52:37 -040014_Py_IDENTIFIER(add_done_callback);
Yury Selivanov416c1eb2018-05-28 17:54:02 -040015_Py_IDENTIFIER(_all_tasks_compat);
INADA Naoki9e4e38e2016-10-09 14:44:47 +090016_Py_IDENTIFIER(call_soon);
Yury Selivanova0c1ba62016-10-28 12:52:37 -040017_Py_IDENTIFIER(cancel);
Andrew Svetlov44d1a592017-12-16 21:58:38 +020018_Py_IDENTIFIER(current_task);
Yury Selivanova70232f2017-12-13 14:49:42 -050019_Py_IDENTIFIER(get_event_loop);
Yury Selivanova0c1ba62016-10-28 12:52:37 -040020_Py_IDENTIFIER(send);
21_Py_IDENTIFIER(throw);
INADA Naoki9e4e38e2016-10-09 14:44:47 +090022
23
INADA Naoki9f2ce252016-10-15 15:39:19 +090024/* State of the _asyncio module */
Andrew Svetlov44d1a592017-12-16 21:58:38 +020025static PyObject *asyncio_mod;
Andrew Svetlov44d1a592017-12-16 21:58:38 +020026static PyObject *traceback_extract_stack;
27static PyObject *asyncio_get_event_loop_policy;
28static PyObject *asyncio_future_repr_info_func;
29static PyObject *asyncio_iscoroutine_func;
30static PyObject *asyncio_task_get_stack_func;
31static PyObject *asyncio_task_print_stack_func;
32static PyObject *asyncio_task_repr_info_func;
33static PyObject *asyncio_InvalidStateError;
34static PyObject *asyncio_CancelledError;
Yury Selivanovf23746a2018-01-22 19:11:18 -050035static PyObject *context_kwname;
Miss Islington (bot)13915a32019-10-07 09:38:00 -070036static int module_initialized;
Andrew Svetlov44d1a592017-12-16 21:58:38 +020037
Yury Selivanov9d411c12018-01-23 15:10:03 -050038static PyObject *cached_running_holder;
39static volatile uint64_t cached_running_holder_tsid;
40
Alex Grönholmcca4eec2018-08-09 00:06:47 +030041/* Counter for autogenerated Task names */
42static uint64_t task_name_counter = 0;
Andrew Svetlov44d1a592017-12-16 21:58:38 +020043
Yury Selivanovca9b36c2017-12-23 15:04:15 -050044/* WeakSet containing all alive tasks. */
45static PyObject *all_tasks;
Andrew Svetlov44d1a592017-12-16 21:58:38 +020046
47/* Dictionary containing tasks that are currently active in
48 all running event loops. {EventLoop: Task} */
Yury Selivanovca9b36c2017-12-23 15:04:15 -050049static PyObject *current_tasks;
INADA Naoki9e4e38e2016-10-09 14:44:47 +090050
Yury Selivanova9d7e552017-12-19 07:18:45 -050051/* An isinstance type cache for the 'is_coroutine()' function. */
52static PyObject *iscoroutine_typecache;
53
INADA Naoki9e4e38e2016-10-09 14:44:47 +090054
INADA Naoki9e4e38e2016-10-09 14:44:47 +090055typedef enum {
56 STATE_PENDING,
57 STATE_CANCELLED,
58 STATE_FINISHED
59} fut_state;
60
Yury Selivanova0c1ba62016-10-28 12:52:37 -040061#define FutureObj_HEAD(prefix) \
62 PyObject_HEAD \
63 PyObject *prefix##_loop; \
Yury Selivanov1b7c11f2017-12-17 20:19:47 -050064 PyObject *prefix##_callback0; \
Yury Selivanov994269c2018-09-27 14:55:55 -040065 PyObject *prefix##_context0; \
Yury Selivanova0c1ba62016-10-28 12:52:37 -040066 PyObject *prefix##_callbacks; \
67 PyObject *prefix##_exception; \
68 PyObject *prefix##_result; \
69 PyObject *prefix##_source_tb; \
70 fut_state prefix##_state; \
71 int prefix##_log_tb; \
72 int prefix##_blocking; \
73 PyObject *dict; \
74 PyObject *prefix##_weakreflist;
75
76typedef struct {
77 FutureObj_HEAD(fut)
78} FutureObj;
79
80typedef struct {
81 FutureObj_HEAD(task)
82 PyObject *task_fut_waiter;
83 PyObject *task_coro;
Alex Grönholmcca4eec2018-08-09 00:06:47 +030084 PyObject *task_name;
Yury Selivanov994269c2018-09-27 14:55:55 -040085 PyObject *task_context;
Yury Selivanova0c1ba62016-10-28 12:52:37 -040086 int task_must_cancel;
87 int task_log_destroy_pending;
88} TaskObj;
INADA Naoki9e4e38e2016-10-09 14:44:47 +090089
90typedef struct {
91 PyObject_HEAD
Yury Selivanova0c1ba62016-10-28 12:52:37 -040092 TaskObj *sw_task;
93 PyObject *sw_arg;
Serhiy Storchakabca49392017-09-03 08:10:14 +030094} TaskStepMethWrapper;
INADA Naoki9e4e38e2016-10-09 14:44:47 +090095
Yury Selivanova0c1ba62016-10-28 12:52:37 -040096typedef struct {
97 PyObject_HEAD
98 TaskObj *ww_task;
99} TaskWakeupMethWrapper;
100
Yury Selivanov9d411c12018-01-23 15:10:03 -0500101typedef struct {
102 PyObject_HEAD
103 PyObject *rl_loop;
104#if defined(HAVE_GETPID) && !defined(MS_WINDOWS)
105 pid_t rl_pid;
106#endif
107} PyRunningLoopHolder;
108
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400109
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500110static PyTypeObject FutureType;
111static PyTypeObject TaskType;
Yury Selivanov9d411c12018-01-23 15:10:03 -0500112static PyTypeObject PyRunningLoopHolder_Type;
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500113
114
115#define Future_CheckExact(obj) (Py_TYPE(obj) == &FutureType)
116#define Task_CheckExact(obj) (Py_TYPE(obj) == &TaskType)
117
118#define Future_Check(obj) PyObject_TypeCheck(obj, &FutureType)
119#define Task_Check(obj) PyObject_TypeCheck(obj, &TaskType)
120
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400121#include "clinic/_asynciomodule.c.h"
122
123
124/*[clinic input]
125class _asyncio.Future "FutureObj *" "&Future_Type"
126[clinic start generated code]*/
127/*[clinic end generated code: output=da39a3ee5e6b4b0d input=00d3e4abca711e0f]*/
128
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500129
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400130/* Get FutureIter from Future */
Yury Selivanov9d411c12018-01-23 15:10:03 -0500131static PyObject * future_new_iter(PyObject *);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900132
Yury Selivanov9d411c12018-01-23 15:10:03 -0500133static PyRunningLoopHolder * new_running_loop_holder(PyObject *);
134
Yury Selivanova70232f2017-12-13 14:49:42 -0500135
136static int
Yury Selivanova9d7e552017-12-19 07:18:45 -0500137_is_coroutine(PyObject *coro)
138{
139 /* 'coro' is not a native coroutine, call asyncio.iscoroutine()
140 to check if it's another coroutine flavour.
141
142 Do this check after 'future_init()'; in case we need to raise
143 an error, __del__ needs a properly initialized object.
144 */
145 PyObject *res = PyObject_CallFunctionObjArgs(
146 asyncio_iscoroutine_func, coro, NULL);
147 if (res == NULL) {
148 return -1;
149 }
150
151 int is_res_true = PyObject_IsTrue(res);
152 Py_DECREF(res);
153 if (is_res_true <= 0) {
154 return is_res_true;
155 }
156
Andrew Svetlov0f47fa22017-12-23 22:06:46 +0200157 if (PySet_GET_SIZE(iscoroutine_typecache) < 100) {
Yury Selivanova9d7e552017-12-19 07:18:45 -0500158 /* Just in case we don't want to cache more than 100
159 positive types. That shouldn't ever happen, unless
160 someone stressing the system on purpose.
161 */
162 if (PySet_Add(iscoroutine_typecache, (PyObject*) Py_TYPE(coro))) {
163 return -1;
164 }
165 }
166
167 return 1;
168}
169
170
171static inline int
172is_coroutine(PyObject *coro)
173{
174 if (PyCoro_CheckExact(coro)) {
175 return 1;
176 }
177
178 /* Check if `type(coro)` is in the cache.
179 Caching makes is_coroutine() function almost as fast as
180 PyCoro_CheckExact() for non-native coroutine-like objects
181 (like coroutines compiled with Cython).
182
183 asyncio.iscoroutine() has its own type caching mechanism.
184 This cache allows us to avoid the cost of even calling
185 a pure-Python function in 99.9% cases.
186 */
187 int has_it = PySet_Contains(
188 iscoroutine_typecache, (PyObject*) Py_TYPE(coro));
189 if (has_it == 0) {
190 /* type(coro) is not in iscoroutine_typecache */
191 return _is_coroutine(coro);
192 }
193
Leo Ariasc3d95082018-02-03 18:36:10 -0600194 /* either an error has occurred or
Yury Selivanova9d7e552017-12-19 07:18:45 -0500195 type(coro) is in iscoroutine_typecache
196 */
197 return has_it;
198}
199
200
Yury Selivanovca9b36c2017-12-23 15:04:15 -0500201static PyObject *
202get_future_loop(PyObject *fut)
203{
204 /* Implementation of `asyncio.futures._get_loop` */
205
206 _Py_IDENTIFIER(get_loop);
207 _Py_IDENTIFIER(_loop);
Serhiy Storchaka66553542018-05-20 16:30:31 +0300208 PyObject *getloop;
Yury Selivanovca9b36c2017-12-23 15:04:15 -0500209
210 if (Future_CheckExact(fut) || Task_CheckExact(fut)) {
211 PyObject *loop = ((FutureObj *)fut)->fut_loop;
212 Py_INCREF(loop);
213 return loop;
214 }
215
Serhiy Storchaka66553542018-05-20 16:30:31 +0300216 if (_PyObject_LookupAttrId(fut, &PyId_get_loop, &getloop) < 0) {
217 return NULL;
218 }
Yury Selivanovca9b36c2017-12-23 15:04:15 -0500219 if (getloop != NULL) {
220 PyObject *res = _PyObject_CallNoArg(getloop);
221 Py_DECREF(getloop);
222 return res;
223 }
224
225 return _PyObject_GetAttrId(fut, &PyId__loop);
226}
227
228
Yury Selivanova9d7e552017-12-19 07:18:45 -0500229static int
Yury Selivanova70232f2017-12-13 14:49:42 -0500230get_running_loop(PyObject **loop)
231{
Yury Selivanov9d411c12018-01-23 15:10:03 -0500232 PyObject *rl;
Yury Selivanova70232f2017-12-13 14:49:42 -0500233
Yury Selivanov9d411c12018-01-23 15:10:03 -0500234 PyThreadState *ts = PyThreadState_Get();
235 if (ts->id == cached_running_holder_tsid && cached_running_holder != NULL) {
236 // Fast path, check the cache.
237 rl = cached_running_holder; // borrowed
238 }
239 else {
240 if (ts->dict == NULL) {
241 goto not_found;
242 }
243
244 rl = _PyDict_GetItemIdWithError(
245 ts->dict, &PyId___asyncio_running_event_loop__); // borrowed
246 if (rl == NULL) {
247 if (PyErr_Occurred()) {
248 goto error;
249 }
250 else {
251 goto not_found;
252 }
253 }
254
255 cached_running_holder = rl; // borrowed
256 cached_running_holder_tsid = ts->id;
Yury Selivanova70232f2017-12-13 14:49:42 -0500257 }
258
Yury Selivanov9d411c12018-01-23 15:10:03 -0500259 assert(Py_TYPE(rl) == &PyRunningLoopHolder_Type);
260 PyObject *running_loop = ((PyRunningLoopHolder *)rl)->rl_loop;
Yury Selivanova70232f2017-12-13 14:49:42 -0500261
262 if (running_loop == Py_None) {
263 goto not_found;
264 }
265
Yury Selivanov9d411c12018-01-23 15:10:03 -0500266#if defined(HAVE_GETPID) && !defined(MS_WINDOWS)
267 /* On Windows there is no getpid, but there is also no os.fork(),
268 so there is no need for this check.
269 */
270 if (getpid() != ((PyRunningLoopHolder *)rl)->rl_pid) {
271 goto not_found;
Yury Selivanova70232f2017-12-13 14:49:42 -0500272 }
Yury Selivanov9d411c12018-01-23 15:10:03 -0500273#endif
Yury Selivanova70232f2017-12-13 14:49:42 -0500274
Yury Selivanov9d411c12018-01-23 15:10:03 -0500275 Py_INCREF(running_loop);
276 *loop = running_loop;
277 return 0;
Yury Selivanova70232f2017-12-13 14:49:42 -0500278
279not_found:
280 *loop = NULL;
281 return 0;
282
Yury Selivanova70232f2017-12-13 14:49:42 -0500283error:
284 *loop = NULL;
285 return -1;
286}
287
288
289static int
290set_running_loop(PyObject *loop)
291{
Yury Selivanov9d411c12018-01-23 15:10:03 -0500292 cached_running_holder = NULL;
293 cached_running_holder_tsid = 0;
Yury Selivanova70232f2017-12-13 14:49:42 -0500294
Yury Selivanov9d411c12018-01-23 15:10:03 -0500295 PyObject *ts_dict = PyThreadState_GetDict(); // borrowed
Yury Selivanova70232f2017-12-13 14:49:42 -0500296 if (ts_dict == NULL) {
297 PyErr_SetString(
298 PyExc_RuntimeError, "thread-local storage is not available");
299 return -1;
300 }
301
Yury Selivanov9d411c12018-01-23 15:10:03 -0500302 PyRunningLoopHolder *rl = new_running_loop_holder(loop);
303 if (rl == NULL) {
Yury Selivanova70232f2017-12-13 14:49:42 -0500304 return -1;
305 }
306
Yury Selivanova70232f2017-12-13 14:49:42 -0500307 if (_PyDict_SetItemId(
Yury Selivanov9d411c12018-01-23 15:10:03 -0500308 ts_dict, &PyId___asyncio_running_event_loop__, (PyObject *)rl) < 0)
309 {
310 Py_DECREF(rl); // will cleanup loop & current_pid
Yury Selivanova70232f2017-12-13 14:49:42 -0500311 return -1;
312 }
Yury Selivanov9d411c12018-01-23 15:10:03 -0500313 Py_DECREF(rl);
Yury Selivanova70232f2017-12-13 14:49:42 -0500314
315 return 0;
316}
317
318
319static PyObject *
320get_event_loop(void)
321{
322 PyObject *loop;
323 PyObject *policy;
324
325 if (get_running_loop(&loop)) {
326 return NULL;
327 }
328 if (loop != NULL) {
329 return loop;
330 }
331
332 policy = _PyObject_CallNoArg(asyncio_get_event_loop_policy);
333 if (policy == NULL) {
334 return NULL;
335 }
336
337 loop = _PyObject_CallMethodId(policy, &PyId_get_event_loop, NULL);
338 Py_DECREF(policy);
339 return loop;
340}
341
342
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900343static int
Yury Selivanov994269c2018-09-27 14:55:55 -0400344call_soon(PyObject *loop, PyObject *func, PyObject *arg, PyObject *ctx)
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500345{
346 PyObject *handle;
Yury Selivanovf23746a2018-01-22 19:11:18 -0500347 PyObject *stack[3];
348 Py_ssize_t nargs;
349
350 if (ctx == NULL) {
351 handle = _PyObject_CallMethodIdObjArgs(
352 loop, &PyId_call_soon, func, arg, NULL);
353 }
354 else {
355 /* Use FASTCALL to pass a keyword-only argument to call_soon */
356
357 PyObject *callable = _PyObject_GetAttrId(loop, &PyId_call_soon);
358 if (callable == NULL) {
359 return -1;
360 }
361
362 /* All refs in 'stack' are borrowed. */
363 nargs = 1;
364 stack[0] = func;
365 if (arg != NULL) {
366 stack[1] = arg;
367 nargs++;
368 }
369 stack[nargs] = (PyObject *)ctx;
370
Jeroen Demeyeraacc77f2019-05-29 20:31:52 +0200371 handle = _PyObject_Vectorcall(callable, stack, nargs, context_kwname);
Yury Selivanovf23746a2018-01-22 19:11:18 -0500372 Py_DECREF(callable);
373 }
374
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500375 if (handle == NULL) {
376 return -1;
377 }
378 Py_DECREF(handle);
379 return 0;
380}
381
382
383static inline int
384future_is_alive(FutureObj *fut)
385{
386 return fut->fut_loop != NULL;
387}
388
389
390static inline int
391future_ensure_alive(FutureObj *fut)
392{
393 if (!future_is_alive(fut)) {
394 PyErr_SetString(PyExc_RuntimeError,
395 "Future object is not initialized.");
396 return -1;
397 }
398 return 0;
399}
400
401
402#define ENSURE_FUTURE_ALIVE(fut) \
403 do { \
404 assert(Future_Check(fut) || Task_Check(fut)); \
405 if (future_ensure_alive((FutureObj*)fut)) { \
406 return NULL; \
407 } \
408 } while(0);
409
410
411static int
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400412future_schedule_callbacks(FutureObj *fut)
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900413{
414 Py_ssize_t len;
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500415 Py_ssize_t i;
416
417 if (fut->fut_callback0 != NULL) {
418 /* There's a 1st callback */
419
420 int ret = call_soon(
Yury Selivanovf23746a2018-01-22 19:11:18 -0500421 fut->fut_loop, fut->fut_callback0,
422 (PyObject *)fut, fut->fut_context0);
423
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500424 Py_CLEAR(fut->fut_callback0);
Yury Selivanovf23746a2018-01-22 19:11:18 -0500425 Py_CLEAR(fut->fut_context0);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500426 if (ret) {
427 /* If an error occurs in pure-Python implementation,
428 all callbacks are cleared. */
429 Py_CLEAR(fut->fut_callbacks);
430 return ret;
431 }
432
433 /* we called the first callback, now try calling
434 callbacks from the 'fut_callbacks' list. */
435 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900436
437 if (fut->fut_callbacks == NULL) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500438 /* No more callbacks, return. */
439 return 0;
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900440 }
441
442 len = PyList_GET_SIZE(fut->fut_callbacks);
443 if (len == 0) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500444 /* The list of callbacks was empty; clear it and return. */
445 Py_CLEAR(fut->fut_callbacks);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900446 return 0;
447 }
448
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900449 for (i = 0; i < len; i++) {
Yury Selivanovf23746a2018-01-22 19:11:18 -0500450 PyObject *cb_tup = PyList_GET_ITEM(fut->fut_callbacks, i);
451 PyObject *cb = PyTuple_GET_ITEM(cb_tup, 0);
452 PyObject *ctx = PyTuple_GET_ITEM(cb_tup, 1);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900453
Yury Selivanov994269c2018-09-27 14:55:55 -0400454 if (call_soon(fut->fut_loop, cb, (PyObject *)fut, ctx)) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500455 /* If an error occurs in pure-Python implementation,
456 all callbacks are cleared. */
457 Py_CLEAR(fut->fut_callbacks);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900458 return -1;
459 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900460 }
461
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500462 Py_CLEAR(fut->fut_callbacks);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900463 return 0;
464}
465
Oren Milmand019bc82018-02-13 12:28:33 +0200466
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900467static int
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400468future_init(FutureObj *fut, PyObject *loop)
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900469{
Serhiy Storchakabca49392017-09-03 08:10:14 +0300470 PyObject *res;
471 int is_true;
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900472 _Py_IDENTIFIER(get_debug);
473
Oren Milmand019bc82018-02-13 12:28:33 +0200474 // Same to FutureObj_clear() but not clearing fut->dict
475 Py_CLEAR(fut->fut_loop);
476 Py_CLEAR(fut->fut_callback0);
477 Py_CLEAR(fut->fut_context0);
478 Py_CLEAR(fut->fut_callbacks);
479 Py_CLEAR(fut->fut_result);
480 Py_CLEAR(fut->fut_exception);
481 Py_CLEAR(fut->fut_source_tb);
482
483 fut->fut_state = STATE_PENDING;
484 fut->fut_log_tb = 0;
485 fut->fut_blocking = 0;
486
Serhiy Storchakabca49392017-09-03 08:10:14 +0300487 if (loop == Py_None) {
Yury Selivanova70232f2017-12-13 14:49:42 -0500488 loop = get_event_loop();
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900489 if (loop == NULL) {
490 return -1;
491 }
492 }
493 else {
494 Py_INCREF(loop);
495 }
Oren Milmand019bc82018-02-13 12:28:33 +0200496 fut->fut_loop = loop;
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900497
Victor Stinnerf94d1ee2016-10-29 09:05:39 +0200498 res = _PyObject_CallMethodId(fut->fut_loop, &PyId_get_debug, NULL);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900499 if (res == NULL) {
500 return -1;
501 }
Serhiy Storchakabca49392017-09-03 08:10:14 +0300502 is_true = PyObject_IsTrue(res);
503 Py_DECREF(res);
504 if (is_true < 0) {
505 return -1;
506 }
Yury Selivanov35230d02018-05-28 11:11:31 -0400507 if (is_true && !_Py_IsFinalizing()) {
508 /* Only try to capture the traceback if the interpreter is not being
509 finalized. The original motivation to add a `_Py_IsFinalizing()`
510 call was to prevent SIGSEGV when a Future is created in a __del__
511 method, which is called during the interpreter shutdown and the
512 traceback module is already unloaded.
513 */
Oren Milmand019bc82018-02-13 12:28:33 +0200514 fut->fut_source_tb = _PyObject_CallNoArg(traceback_extract_stack);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900515 if (fut->fut_source_tb == NULL) {
516 return -1;
517 }
518 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900519
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900520 return 0;
521}
522
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900523static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400524future_set_result(FutureObj *fut, PyObject *res)
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900525{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500526 if (future_ensure_alive(fut)) {
527 return NULL;
528 }
529
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900530 if (fut->fut_state != STATE_PENDING) {
531 PyErr_SetString(asyncio_InvalidStateError, "invalid state");
532 return NULL;
533 }
534
Serhiy Storchakabca49392017-09-03 08:10:14 +0300535 assert(!fut->fut_result);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900536 Py_INCREF(res);
537 fut->fut_result = res;
538 fut->fut_state = STATE_FINISHED;
539
Yury Selivanov22feeb82018-01-24 11:31:01 -0500540 if (future_schedule_callbacks(fut) == -1) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900541 return NULL;
542 }
543 Py_RETURN_NONE;
544}
545
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900546static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400547future_set_exception(FutureObj *fut, PyObject *exc)
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900548{
549 PyObject *exc_val = NULL;
550
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900551 if (fut->fut_state != STATE_PENDING) {
552 PyErr_SetString(asyncio_InvalidStateError, "invalid state");
553 return NULL;
554 }
555
556 if (PyExceptionClass_Check(exc)) {
Victor Stinnera5ed5f02016-12-06 18:45:50 +0100557 exc_val = _PyObject_CallNoArg(exc);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900558 if (exc_val == NULL) {
559 return NULL;
560 }
Serhiy Storchakabca49392017-09-03 08:10:14 +0300561 if (fut->fut_state != STATE_PENDING) {
562 Py_DECREF(exc_val);
563 PyErr_SetString(asyncio_InvalidStateError, "invalid state");
564 return NULL;
565 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900566 }
567 else {
568 exc_val = exc;
569 Py_INCREF(exc_val);
570 }
571 if (!PyExceptionInstance_Check(exc_val)) {
572 Py_DECREF(exc_val);
573 PyErr_SetString(PyExc_TypeError, "invalid exception object");
574 return NULL;
575 }
576 if ((PyObject*)Py_TYPE(exc_val) == PyExc_StopIteration) {
577 Py_DECREF(exc_val);
578 PyErr_SetString(PyExc_TypeError,
579 "StopIteration interacts badly with generators "
580 "and cannot be raised into a Future");
581 return NULL;
582 }
583
Serhiy Storchakabca49392017-09-03 08:10:14 +0300584 assert(!fut->fut_exception);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900585 fut->fut_exception = exc_val;
586 fut->fut_state = STATE_FINISHED;
587
Yury Selivanov22feeb82018-01-24 11:31:01 -0500588 if (future_schedule_callbacks(fut) == -1) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900589 return NULL;
590 }
591
592 fut->fut_log_tb = 1;
593 Py_RETURN_NONE;
594}
595
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400596static int
597future_get_result(FutureObj *fut, PyObject **result)
598{
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400599 if (fut->fut_state == STATE_CANCELLED) {
Serhiy Storchakabca49392017-09-03 08:10:14 +0300600 PyErr_SetNone(asyncio_CancelledError);
601 return -1;
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400602 }
603
604 if (fut->fut_state != STATE_FINISHED) {
Serhiy Storchakabca49392017-09-03 08:10:14 +0300605 PyErr_SetString(asyncio_InvalidStateError, "Result is not set.");
606 return -1;
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400607 }
608
609 fut->fut_log_tb = 0;
610 if (fut->fut_exception != NULL) {
611 Py_INCREF(fut->fut_exception);
612 *result = fut->fut_exception;
613 return 1;
614 }
615
616 Py_INCREF(fut->fut_result);
617 *result = fut->fut_result;
618 return 0;
619}
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900620
621static PyObject *
Yury Selivanov994269c2018-09-27 14:55:55 -0400622future_add_done_callback(FutureObj *fut, PyObject *arg, PyObject *ctx)
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900623{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500624 if (!future_is_alive(fut)) {
625 PyErr_SetString(PyExc_RuntimeError, "uninitialized Future object");
626 return NULL;
627 }
628
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900629 if (fut->fut_state != STATE_PENDING) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500630 /* The future is done/cancelled, so schedule the callback
631 right away. */
Yury Selivanovf23746a2018-01-22 19:11:18 -0500632 if (call_soon(fut->fut_loop, arg, (PyObject*) fut, ctx)) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900633 return NULL;
634 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900635 }
636 else {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500637 /* The future is pending, add a callback.
638
639 Callbacks in the future object are stored as follows:
640
641 callback0 -- a pointer to the first callback
642 callbacks -- a list of 2nd, 3rd, ... callbacks
643
644 Invariants:
645
646 * callbacks != NULL:
647 There are some callbacks in in the list. Just
648 add the new callback to it.
649
650 * callbacks == NULL and callback0 == NULL:
651 This is the first callback. Set it to callback0.
652
653 * callbacks == NULL and callback0 != NULL:
654 This is a second callback. Initialize callbacks
655 with a new list and add the new callback to it.
656 */
657
Yury Selivanovf23746a2018-01-22 19:11:18 -0500658 if (fut->fut_callbacks == NULL && fut->fut_callback0 == NULL) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500659 Py_INCREF(arg);
660 fut->fut_callback0 = arg;
Yury Selivanovf23746a2018-01-22 19:11:18 -0500661 Py_INCREF(ctx);
662 fut->fut_context0 = ctx;
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500663 }
664 else {
Yury Selivanovf23746a2018-01-22 19:11:18 -0500665 PyObject *tup = PyTuple_New(2);
666 if (tup == NULL) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500667 return NULL;
668 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500669 Py_INCREF(arg);
Yury Selivanovf23746a2018-01-22 19:11:18 -0500670 PyTuple_SET_ITEM(tup, 0, arg);
671 Py_INCREF(ctx);
672 PyTuple_SET_ITEM(tup, 1, (PyObject *)ctx);
673
674 if (fut->fut_callbacks != NULL) {
675 int err = PyList_Append(fut->fut_callbacks, tup);
676 if (err) {
677 Py_DECREF(tup);
678 return NULL;
679 }
680 Py_DECREF(tup);
681 }
682 else {
683 fut->fut_callbacks = PyList_New(1);
684 if (fut->fut_callbacks == NULL) {
685 return NULL;
686 }
687
688 PyList_SET_ITEM(fut->fut_callbacks, 0, tup); /* borrow */
689 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900690 }
691 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500692
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900693 Py_RETURN_NONE;
694}
695
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400696static PyObject *
697future_cancel(FutureObj *fut)
698{
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +0000699 fut->fut_log_tb = 0;
700
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400701 if (fut->fut_state != STATE_PENDING) {
702 Py_RETURN_FALSE;
703 }
704 fut->fut_state = STATE_CANCELLED;
705
Yury Selivanov22feeb82018-01-24 11:31:01 -0500706 if (future_schedule_callbacks(fut) == -1) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400707 return NULL;
708 }
709
710 Py_RETURN_TRUE;
711}
712
713/*[clinic input]
714_asyncio.Future.__init__
715
716 *
Serhiy Storchakabca49392017-09-03 08:10:14 +0300717 loop: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400718
719This class is *almost* compatible with concurrent.futures.Future.
720
721 Differences:
722
723 - result() and exception() do not take a timeout argument and
724 raise an exception when the future isn't done yet.
725
726 - Callbacks registered with add_done_callback() are always called
727 via the event loop's call_soon_threadsafe().
728
729 - This class is not compatible with the wait() and as_completed()
730 methods in the concurrent.futures package.
731[clinic start generated code]*/
732
733static int
734_asyncio_Future___init___impl(FutureObj *self, PyObject *loop)
Serhiy Storchakabca49392017-09-03 08:10:14 +0300735/*[clinic end generated code: output=9ed75799eaccb5d6 input=89af317082bc0bf8]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400736
737{
738 return future_init(self, loop);
739}
740
741static int
742FutureObj_clear(FutureObj *fut)
743{
744 Py_CLEAR(fut->fut_loop);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500745 Py_CLEAR(fut->fut_callback0);
Yury Selivanovf23746a2018-01-22 19:11:18 -0500746 Py_CLEAR(fut->fut_context0);
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400747 Py_CLEAR(fut->fut_callbacks);
748 Py_CLEAR(fut->fut_result);
749 Py_CLEAR(fut->fut_exception);
750 Py_CLEAR(fut->fut_source_tb);
751 Py_CLEAR(fut->dict);
752 return 0;
753}
754
755static int
756FutureObj_traverse(FutureObj *fut, visitproc visit, void *arg)
757{
758 Py_VISIT(fut->fut_loop);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500759 Py_VISIT(fut->fut_callback0);
Yury Selivanovf23746a2018-01-22 19:11:18 -0500760 Py_VISIT(fut->fut_context0);
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400761 Py_VISIT(fut->fut_callbacks);
762 Py_VISIT(fut->fut_result);
763 Py_VISIT(fut->fut_exception);
764 Py_VISIT(fut->fut_source_tb);
765 Py_VISIT(fut->dict);
766 return 0;
767}
768
769/*[clinic input]
770_asyncio.Future.result
771
772Return the result this future represents.
773
774If the future has been cancelled, raises CancelledError. If the
775future's result isn't yet available, raises InvalidStateError. If
776the future is done and has an exception set, this exception is raised.
777[clinic start generated code]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900778
779static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400780_asyncio_Future_result_impl(FutureObj *self)
781/*[clinic end generated code: output=f35f940936a4b1e5 input=49ecf9cf5ec50dc5]*/
782{
783 PyObject *result;
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500784
785 if (!future_is_alive(self)) {
786 PyErr_SetString(asyncio_InvalidStateError,
787 "Future object is not initialized.");
788 return NULL;
789 }
790
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400791 int res = future_get_result(self, &result);
792
793 if (res == -1) {
794 return NULL;
795 }
796
797 if (res == 0) {
798 return result;
799 }
800
801 assert(res == 1);
802
803 PyErr_SetObject(PyExceptionInstance_Class(result), result);
804 Py_DECREF(result);
805 return NULL;
806}
807
808/*[clinic input]
809_asyncio.Future.exception
810
811Return the exception that was set on this future.
812
813The exception (or None if no exception was set) is returned only if
814the future is done. If the future has been cancelled, raises
815CancelledError. If the future isn't done yet, raises
816InvalidStateError.
817[clinic start generated code]*/
818
819static PyObject *
820_asyncio_Future_exception_impl(FutureObj *self)
821/*[clinic end generated code: output=88b20d4f855e0710 input=733547a70c841c68]*/
822{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500823 if (!future_is_alive(self)) {
824 PyErr_SetString(asyncio_InvalidStateError,
825 "Future object is not initialized.");
826 return NULL;
827 }
828
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400829 if (self->fut_state == STATE_CANCELLED) {
Serhiy Storchakabca49392017-09-03 08:10:14 +0300830 PyErr_SetNone(asyncio_CancelledError);
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400831 return NULL;
832 }
833
834 if (self->fut_state != STATE_FINISHED) {
Serhiy Storchakabca49392017-09-03 08:10:14 +0300835 PyErr_SetString(asyncio_InvalidStateError, "Exception is not set.");
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400836 return NULL;
837 }
838
839 if (self->fut_exception != NULL) {
840 self->fut_log_tb = 0;
841 Py_INCREF(self->fut_exception);
842 return self->fut_exception;
843 }
844
845 Py_RETURN_NONE;
846}
847
848/*[clinic input]
849_asyncio.Future.set_result
850
Yury Selivanov0cf16f92017-12-25 10:48:15 -0500851 result: object
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400852 /
853
854Mark the future done and set its result.
855
856If the future is already done when this method is called, raises
857InvalidStateError.
858[clinic start generated code]*/
859
860static PyObject *
Yury Selivanov0cf16f92017-12-25 10:48:15 -0500861_asyncio_Future_set_result(FutureObj *self, PyObject *result)
862/*[clinic end generated code: output=1ec2e6bcccd6f2ce input=8b75172c2a7b05f1]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400863{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500864 ENSURE_FUTURE_ALIVE(self)
Yury Selivanov0cf16f92017-12-25 10:48:15 -0500865 return future_set_result(self, result);
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400866}
867
868/*[clinic input]
869_asyncio.Future.set_exception
870
Serhiy Storchakabca49392017-09-03 08:10:14 +0300871 exception: object
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400872 /
873
874Mark the future done and set an exception.
875
876If the future is already done when this method is called, raises
877InvalidStateError.
878[clinic start generated code]*/
879
880static PyObject *
881_asyncio_Future_set_exception(FutureObj *self, PyObject *exception)
Serhiy Storchakabca49392017-09-03 08:10:14 +0300882/*[clinic end generated code: output=f1c1b0cd321be360 input=e45b7d7aa71cc66d]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400883{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500884 ENSURE_FUTURE_ALIVE(self)
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400885 return future_set_exception(self, exception);
886}
887
888/*[clinic input]
889_asyncio.Future.add_done_callback
890
Serhiy Storchakabca49392017-09-03 08:10:14 +0300891 fn: object
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400892 /
Yury Selivanovf23746a2018-01-22 19:11:18 -0500893 *
894 context: object = NULL
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400895
896Add a callback to be run when the future becomes done.
897
898The callback is called with a single argument - the future object. If
899the future is already done when this is called, the callback is
900scheduled with call_soon.
901[clinic start generated code]*/
902
903static PyObject *
Yury Selivanovf23746a2018-01-22 19:11:18 -0500904_asyncio_Future_add_done_callback_impl(FutureObj *self, PyObject *fn,
905 PyObject *context)
906/*[clinic end generated code: output=7ce635bbc9554c1e input=15ab0693a96e9533]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400907{
Yury Selivanovf23746a2018-01-22 19:11:18 -0500908 if (context == NULL) {
Yury Selivanov994269c2018-09-27 14:55:55 -0400909 context = PyContext_CopyCurrent();
Yury Selivanovf23746a2018-01-22 19:11:18 -0500910 if (context == NULL) {
911 return NULL;
912 }
Yury Selivanov994269c2018-09-27 14:55:55 -0400913 PyObject *res = future_add_done_callback(self, fn, context);
Yury Selivanovf23746a2018-01-22 19:11:18 -0500914 Py_DECREF(context);
915 return res;
916 }
Yury Selivanov994269c2018-09-27 14:55:55 -0400917 return future_add_done_callback(self, fn, context);
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400918}
919
920/*[clinic input]
921_asyncio.Future.remove_done_callback
922
Serhiy Storchakabca49392017-09-03 08:10:14 +0300923 fn: object
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400924 /
925
926Remove all instances of a callback from the "call when done" list.
927
928Returns the number of callbacks removed.
929[clinic start generated code]*/
930
931static PyObject *
932_asyncio_Future_remove_done_callback(FutureObj *self, PyObject *fn)
Serhiy Storchakabca49392017-09-03 08:10:14 +0300933/*[clinic end generated code: output=5ab1fb52b24ef31f input=0a43280a149d505b]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900934{
935 PyObject *newlist;
936 Py_ssize_t len, i, j=0;
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500937 Py_ssize_t cleared_callback0 = 0;
938
939 ENSURE_FUTURE_ALIVE(self)
940
941 if (self->fut_callback0 != NULL) {
942 int cmp = PyObject_RichCompareBool(fn, self->fut_callback0, Py_EQ);
943 if (cmp == -1) {
944 return NULL;
945 }
946 if (cmp == 1) {
947 /* callback0 == fn */
948 Py_CLEAR(self->fut_callback0);
Yury Selivanovf23746a2018-01-22 19:11:18 -0500949 Py_CLEAR(self->fut_context0);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500950 cleared_callback0 = 1;
951 }
952 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900953
Serhiy Storchakabca49392017-09-03 08:10:14 +0300954 if (self->fut_callbacks == NULL) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500955 return PyLong_FromSsize_t(cleared_callback0);
Serhiy Storchakabca49392017-09-03 08:10:14 +0300956 }
957
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400958 len = PyList_GET_SIZE(self->fut_callbacks);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900959 if (len == 0) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500960 Py_CLEAR(self->fut_callbacks);
961 return PyLong_FromSsize_t(cleared_callback0);
962 }
963
964 if (len == 1) {
Yury Selivanovf23746a2018-01-22 19:11:18 -0500965 PyObject *cb_tup = PyList_GET_ITEM(self->fut_callbacks, 0);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500966 int cmp = PyObject_RichCompareBool(
Yury Selivanovf23746a2018-01-22 19:11:18 -0500967 fn, PyTuple_GET_ITEM(cb_tup, 0), Py_EQ);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500968 if (cmp == -1) {
969 return NULL;
970 }
971 if (cmp == 1) {
972 /* callbacks[0] == fn */
973 Py_CLEAR(self->fut_callbacks);
974 return PyLong_FromSsize_t(1 + cleared_callback0);
975 }
976 /* callbacks[0] != fn and len(callbacks) == 1 */
977 return PyLong_FromSsize_t(cleared_callback0);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900978 }
979
980 newlist = PyList_New(len);
981 if (newlist == NULL) {
982 return NULL;
983 }
984
Yury Selivanov84af9032017-03-02 23:46:56 -0500985 for (i = 0; i < PyList_GET_SIZE(self->fut_callbacks); i++) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900986 int ret;
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400987 PyObject *item = PyList_GET_ITEM(self->fut_callbacks, i);
Serhiy Storchakabca49392017-09-03 08:10:14 +0300988 Py_INCREF(item);
Yury Selivanovf23746a2018-01-22 19:11:18 -0500989 ret = PyObject_RichCompareBool(fn, PyTuple_GET_ITEM(item, 0), Py_EQ);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900990 if (ret == 0) {
Yury Selivanov833a3b02017-07-05 13:32:03 -0400991 if (j < len) {
Yury Selivanov833a3b02017-07-05 13:32:03 -0400992 PyList_SET_ITEM(newlist, j, item);
993 j++;
Serhiy Storchakabca49392017-09-03 08:10:14 +0300994 continue;
Yury Selivanov833a3b02017-07-05 13:32:03 -0400995 }
Serhiy Storchakabca49392017-09-03 08:10:14 +0300996 ret = PyList_Append(newlist, item);
997 }
998 Py_DECREF(item);
999 if (ret < 0) {
1000 goto fail;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001001 }
1002 }
1003
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001004 if (j == 0) {
1005 Py_CLEAR(self->fut_callbacks);
1006 Py_DECREF(newlist);
1007 return PyLong_FromSsize_t(len + cleared_callback0);
1008 }
1009
Serhiy Storchakabca49392017-09-03 08:10:14 +03001010 if (j < len) {
1011 Py_SIZE(newlist) = j;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001012 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03001013 j = PyList_GET_SIZE(newlist);
1014 len = PyList_GET_SIZE(self->fut_callbacks);
1015 if (j != len) {
1016 if (PyList_SetSlice(self->fut_callbacks, 0, len, newlist) < 0) {
1017 goto fail;
1018 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001019 }
1020 Py_DECREF(newlist);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001021 return PyLong_FromSsize_t(len - j + cleared_callback0);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001022
1023fail:
1024 Py_DECREF(newlist);
1025 return NULL;
1026}
1027
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001028/*[clinic input]
1029_asyncio.Future.cancel
1030
1031Cancel the future and schedule callbacks.
1032
1033If the future is already done or cancelled, return False. Otherwise,
1034change the future's state to cancelled, schedule the callbacks and
1035return True.
1036[clinic start generated code]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001037
1038static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001039_asyncio_Future_cancel_impl(FutureObj *self)
1040/*[clinic end generated code: output=e45b932ba8bd68a1 input=515709a127995109]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001041{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001042 ENSURE_FUTURE_ALIVE(self)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001043 return future_cancel(self);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001044}
1045
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001046/*[clinic input]
1047_asyncio.Future.cancelled
1048
1049Return True if the future was cancelled.
1050[clinic start generated code]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001051
1052static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001053_asyncio_Future_cancelled_impl(FutureObj *self)
1054/*[clinic end generated code: output=145197ced586357d input=943ab8b7b7b17e45]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001055{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001056 if (future_is_alive(self) && self->fut_state == STATE_CANCELLED) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001057 Py_RETURN_TRUE;
1058 }
1059 else {
1060 Py_RETURN_FALSE;
1061 }
1062}
1063
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001064/*[clinic input]
1065_asyncio.Future.done
1066
1067Return True if the future is done.
1068
1069Done means either that a result / exception are available, or that the
1070future was cancelled.
1071[clinic start generated code]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001072
1073static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001074_asyncio_Future_done_impl(FutureObj *self)
1075/*[clinic end generated code: output=244c5ac351145096 input=28d7b23fdb65d2ac]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001076{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001077 if (!future_is_alive(self) || self->fut_state == STATE_PENDING) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001078 Py_RETURN_FALSE;
1079 }
1080 else {
1081 Py_RETURN_TRUE;
1082 }
1083}
1084
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001085/*[clinic input]
1086_asyncio.Future.get_loop
1087
1088Return the event loop the Future is bound to.
1089[clinic start generated code]*/
1090
1091static PyObject *
1092_asyncio_Future_get_loop_impl(FutureObj *self)
1093/*[clinic end generated code: output=119b6ea0c9816c3f input=cba48c2136c79d1f]*/
1094{
Miss Islington (bot)694c03f2019-11-13 13:54:56 -08001095 ENSURE_FUTURE_ALIVE(self)
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001096 Py_INCREF(self->fut_loop);
1097 return self->fut_loop;
1098}
1099
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001100static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001101FutureObj_get_blocking(FutureObj *fut, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001102{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001103 if (future_is_alive(fut) && fut->fut_blocking) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001104 Py_RETURN_TRUE;
1105 }
1106 else {
1107 Py_RETURN_FALSE;
1108 }
1109}
1110
1111static int
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001112FutureObj_set_blocking(FutureObj *fut, PyObject *val, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001113{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001114 if (future_ensure_alive(fut)) {
1115 return -1;
1116 }
Zackery Spytz842acaa2018-12-17 07:52:45 -07001117 if (val == NULL) {
1118 PyErr_SetString(PyExc_AttributeError, "cannot delete attribute");
1119 return -1;
1120 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001121
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001122 int is_true = PyObject_IsTrue(val);
1123 if (is_true < 0) {
1124 return -1;
1125 }
1126 fut->fut_blocking = is_true;
1127 return 0;
1128}
1129
1130static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001131FutureObj_get_log_traceback(FutureObj *fut, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001132{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001133 ENSURE_FUTURE_ALIVE(fut)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001134 if (fut->fut_log_tb) {
1135 Py_RETURN_TRUE;
1136 }
1137 else {
1138 Py_RETURN_FALSE;
1139 }
1140}
1141
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +00001142static int
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001143FutureObj_set_log_traceback(FutureObj *fut, PyObject *val, void *Py_UNUSED(ignored))
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +00001144{
Zackery Spytz842acaa2018-12-17 07:52:45 -07001145 if (val == NULL) {
1146 PyErr_SetString(PyExc_AttributeError, "cannot delete attribute");
1147 return -1;
1148 }
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +00001149 int is_true = PyObject_IsTrue(val);
1150 if (is_true < 0) {
1151 return -1;
1152 }
Yury Selivanove0aef4f2017-12-25 16:16:10 -05001153 if (is_true) {
1154 PyErr_SetString(PyExc_ValueError,
1155 "_log_traceback can only be set to False");
1156 return -1;
1157 }
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +00001158 fut->fut_log_tb = is_true;
1159 return 0;
1160}
1161
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001162static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001163FutureObj_get_loop(FutureObj *fut, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001164{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001165 if (!future_is_alive(fut)) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001166 Py_RETURN_NONE;
1167 }
1168 Py_INCREF(fut->fut_loop);
1169 return fut->fut_loop;
1170}
1171
1172static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001173FutureObj_get_callbacks(FutureObj *fut, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001174{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001175 Py_ssize_t i;
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001176
1177 ENSURE_FUTURE_ALIVE(fut)
1178
Yury Selivanovf23746a2018-01-22 19:11:18 -05001179 if (fut->fut_callback0 == NULL) {
1180 if (fut->fut_callbacks == NULL) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001181 Py_RETURN_NONE;
1182 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001183
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001184 Py_INCREF(fut->fut_callbacks);
1185 return fut->fut_callbacks;
1186 }
1187
Yury Selivanovf23746a2018-01-22 19:11:18 -05001188 Py_ssize_t len = 1;
1189 if (fut->fut_callbacks != NULL) {
1190 len += PyList_GET_SIZE(fut->fut_callbacks);
1191 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001192
Yury Selivanovf23746a2018-01-22 19:11:18 -05001193
1194 PyObject *new_list = PyList_New(len);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001195 if (new_list == NULL) {
1196 return NULL;
1197 }
1198
Yury Selivanovf23746a2018-01-22 19:11:18 -05001199 PyObject *tup0 = PyTuple_New(2);
1200 if (tup0 == NULL) {
1201 Py_DECREF(new_list);
1202 return NULL;
1203 }
1204
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001205 Py_INCREF(fut->fut_callback0);
Yury Selivanovf23746a2018-01-22 19:11:18 -05001206 PyTuple_SET_ITEM(tup0, 0, fut->fut_callback0);
1207 assert(fut->fut_context0 != NULL);
1208 Py_INCREF(fut->fut_context0);
1209 PyTuple_SET_ITEM(tup0, 1, (PyObject *)fut->fut_context0);
1210
1211 PyList_SET_ITEM(new_list, 0, tup0);
1212
1213 if (fut->fut_callbacks != NULL) {
1214 for (i = 0; i < PyList_GET_SIZE(fut->fut_callbacks); i++) {
1215 PyObject *cb = PyList_GET_ITEM(fut->fut_callbacks, i);
1216 Py_INCREF(cb);
1217 PyList_SET_ITEM(new_list, i + 1, cb);
1218 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001219 }
1220
1221 return new_list;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001222}
1223
1224static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001225FutureObj_get_result(FutureObj *fut, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001226{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001227 ENSURE_FUTURE_ALIVE(fut)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001228 if (fut->fut_result == NULL) {
1229 Py_RETURN_NONE;
1230 }
1231 Py_INCREF(fut->fut_result);
1232 return fut->fut_result;
1233}
1234
1235static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001236FutureObj_get_exception(FutureObj *fut, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001237{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001238 ENSURE_FUTURE_ALIVE(fut)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001239 if (fut->fut_exception == NULL) {
1240 Py_RETURN_NONE;
1241 }
1242 Py_INCREF(fut->fut_exception);
1243 return fut->fut_exception;
1244}
1245
1246static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001247FutureObj_get_source_traceback(FutureObj *fut, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001248{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001249 if (!future_is_alive(fut) || fut->fut_source_tb == NULL) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001250 Py_RETURN_NONE;
1251 }
1252 Py_INCREF(fut->fut_source_tb);
1253 return fut->fut_source_tb;
1254}
1255
1256static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001257FutureObj_get_state(FutureObj *fut, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001258{
1259 _Py_IDENTIFIER(PENDING);
1260 _Py_IDENTIFIER(CANCELLED);
1261 _Py_IDENTIFIER(FINISHED);
1262 PyObject *ret = NULL;
1263
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001264 ENSURE_FUTURE_ALIVE(fut)
1265
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001266 switch (fut->fut_state) {
1267 case STATE_PENDING:
1268 ret = _PyUnicode_FromId(&PyId_PENDING);
1269 break;
1270 case STATE_CANCELLED:
1271 ret = _PyUnicode_FromId(&PyId_CANCELLED);
1272 break;
1273 case STATE_FINISHED:
1274 ret = _PyUnicode_FromId(&PyId_FINISHED);
1275 break;
1276 default:
1277 assert (0);
1278 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03001279 Py_XINCREF(ret);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001280 return ret;
1281}
1282
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001283/*[clinic input]
1284_asyncio.Future._repr_info
1285[clinic start generated code]*/
1286
1287static PyObject *
1288_asyncio_Future__repr_info_impl(FutureObj *self)
1289/*[clinic end generated code: output=fa69e901bd176cfb input=f21504d8e2ae1ca2]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001290{
Victor Stinnerde4ae3d2016-12-04 22:59:09 +01001291 return PyObject_CallFunctionObjArgs(
1292 asyncio_future_repr_info_func, self, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001293}
1294
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001295static PyObject *
1296FutureObj_repr(FutureObj *fut)
1297{
1298 _Py_IDENTIFIER(_repr_info);
1299
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001300 ENSURE_FUTURE_ALIVE(fut)
1301
Serhiy Storchakabca49392017-09-03 08:10:14 +03001302 PyObject *rinfo = _PyObject_CallMethodIdObjArgs((PyObject*)fut,
1303 &PyId__repr_info,
1304 NULL);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001305 if (rinfo == NULL) {
1306 return NULL;
1307 }
1308
Serhiy Storchakabca49392017-09-03 08:10:14 +03001309 PyObject *rinfo_s = PyUnicode_Join(NULL, rinfo);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001310 Py_DECREF(rinfo);
1311 if (rinfo_s == NULL) {
1312 return NULL;
1313 }
1314
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03001315 PyObject *rstr = PyUnicode_FromFormat("<%s %U>",
1316 _PyType_Name(Py_TYPE(fut)), rinfo_s);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001317 Py_DECREF(rinfo_s);
1318 return rstr;
1319}
1320
1321static void
1322FutureObj_finalize(FutureObj *fut)
1323{
1324 _Py_IDENTIFIER(call_exception_handler);
1325 _Py_IDENTIFIER(message);
1326 _Py_IDENTIFIER(exception);
1327 _Py_IDENTIFIER(future);
1328 _Py_IDENTIFIER(source_traceback);
1329
Serhiy Storchakabca49392017-09-03 08:10:14 +03001330 PyObject *error_type, *error_value, *error_traceback;
1331 PyObject *context;
Serhiy Storchakabca49392017-09-03 08:10:14 +03001332 PyObject *message = NULL;
1333 PyObject *func;
1334
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001335 if (!fut->fut_log_tb) {
1336 return;
1337 }
1338 assert(fut->fut_exception != NULL);
Serhiy Storchakabca49392017-09-03 08:10:14 +03001339 fut->fut_log_tb = 0;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001340
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001341 /* Save the current exception, if any. */
1342 PyErr_Fetch(&error_type, &error_value, &error_traceback);
1343
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001344 context = PyDict_New();
1345 if (context == NULL) {
1346 goto finally;
1347 }
1348
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001349 message = PyUnicode_FromFormat(
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03001350 "%s exception was never retrieved", _PyType_Name(Py_TYPE(fut)));
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001351 if (message == NULL) {
1352 goto finally;
1353 }
1354
1355 if (_PyDict_SetItemId(context, &PyId_message, message) < 0 ||
1356 _PyDict_SetItemId(context, &PyId_exception, fut->fut_exception) < 0 ||
1357 _PyDict_SetItemId(context, &PyId_future, (PyObject*)fut) < 0) {
1358 goto finally;
1359 }
1360 if (fut->fut_source_tb != NULL) {
1361 if (_PyDict_SetItemId(context, &PyId_source_traceback,
1362 fut->fut_source_tb) < 0) {
1363 goto finally;
1364 }
1365 }
1366
1367 func = _PyObject_GetAttrId(fut->fut_loop, &PyId_call_exception_handler);
1368 if (func != NULL) {
Serhiy Storchakabca49392017-09-03 08:10:14 +03001369 PyObject *res = PyObject_CallFunctionObjArgs(func, context, NULL);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001370 if (res == NULL) {
1371 PyErr_WriteUnraisable(func);
1372 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03001373 else {
1374 Py_DECREF(res);
1375 }
1376 Py_DECREF(func);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001377 }
1378
1379finally:
Serhiy Storchakabca49392017-09-03 08:10:14 +03001380 Py_XDECREF(context);
1381 Py_XDECREF(message);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001382
1383 /* Restore the saved exception. */
1384 PyErr_Restore(error_type, error_value, error_traceback);
1385}
1386
1387
1388static PyAsyncMethods FutureType_as_async = {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001389 (unaryfunc)future_new_iter, /* am_await */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001390 0, /* am_aiter */
1391 0 /* am_anext */
1392};
1393
1394static PyMethodDef FutureType_methods[] = {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001395 _ASYNCIO_FUTURE_RESULT_METHODDEF
1396 _ASYNCIO_FUTURE_EXCEPTION_METHODDEF
1397 _ASYNCIO_FUTURE_SET_RESULT_METHODDEF
1398 _ASYNCIO_FUTURE_SET_EXCEPTION_METHODDEF
1399 _ASYNCIO_FUTURE_ADD_DONE_CALLBACK_METHODDEF
1400 _ASYNCIO_FUTURE_REMOVE_DONE_CALLBACK_METHODDEF
1401 _ASYNCIO_FUTURE_CANCEL_METHODDEF
1402 _ASYNCIO_FUTURE_CANCELLED_METHODDEF
1403 _ASYNCIO_FUTURE_DONE_METHODDEF
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001404 _ASYNCIO_FUTURE_GET_LOOP_METHODDEF
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001405 _ASYNCIO_FUTURE__REPR_INFO_METHODDEF
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001406 {NULL, NULL} /* Sentinel */
1407};
1408
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001409#define FUTURE_COMMON_GETSETLIST \
1410 {"_state", (getter)FutureObj_get_state, NULL, NULL}, \
1411 {"_asyncio_future_blocking", (getter)FutureObj_get_blocking, \
1412 (setter)FutureObj_set_blocking, NULL}, \
1413 {"_loop", (getter)FutureObj_get_loop, NULL, NULL}, \
1414 {"_callbacks", (getter)FutureObj_get_callbacks, NULL, NULL}, \
1415 {"_result", (getter)FutureObj_get_result, NULL, NULL}, \
1416 {"_exception", (getter)FutureObj_get_exception, NULL, NULL}, \
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +00001417 {"_log_traceback", (getter)FutureObj_get_log_traceback, \
1418 (setter)FutureObj_set_log_traceback, NULL}, \
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001419 {"_source_traceback", (getter)FutureObj_get_source_traceback, NULL, NULL},
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001420
1421static PyGetSetDef FutureType_getsetlist[] = {
1422 FUTURE_COMMON_GETSETLIST
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001423 {NULL} /* Sentinel */
1424};
1425
1426static void FutureObj_dealloc(PyObject *self);
1427
1428static PyTypeObject FutureType = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02001429 PyVarObject_HEAD_INIT(NULL, 0)
INADA Naoki9f2ce252016-10-15 15:39:19 +09001430 "_asyncio.Future",
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001431 sizeof(FutureObj), /* tp_basicsize */
1432 .tp_dealloc = FutureObj_dealloc,
1433 .tp_as_async = &FutureType_as_async,
1434 .tp_repr = (reprfunc)FutureObj_repr,
Antoine Pitrouada319b2019-05-29 22:12:38 +02001435 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001436 .tp_doc = _asyncio_Future___init____doc__,
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001437 .tp_traverse = (traverseproc)FutureObj_traverse,
1438 .tp_clear = (inquiry)FutureObj_clear,
1439 .tp_weaklistoffset = offsetof(FutureObj, fut_weakreflist),
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001440 .tp_iter = (getiterfunc)future_new_iter,
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001441 .tp_methods = FutureType_methods,
1442 .tp_getset = FutureType_getsetlist,
1443 .tp_dictoffset = offsetof(FutureObj, dict),
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001444 .tp_init = (initproc)_asyncio_Future___init__,
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001445 .tp_new = PyType_GenericNew,
1446 .tp_finalize = (destructor)FutureObj_finalize,
1447};
1448
1449static void
1450FutureObj_dealloc(PyObject *self)
1451{
1452 FutureObj *fut = (FutureObj *)self;
1453
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001454 if (Future_CheckExact(fut)) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001455 /* When fut is subclass of Future, finalizer is called from
1456 * subtype_dealloc.
1457 */
1458 if (PyObject_CallFinalizerFromDealloc(self) < 0) {
1459 // resurrected.
1460 return;
1461 }
1462 }
1463
Alexander Mohrde34cbe2017-08-01 23:31:07 -07001464 PyObject_GC_UnTrack(self);
1465
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001466 if (fut->fut_weakreflist != NULL) {
1467 PyObject_ClearWeakRefs(self);
1468 }
1469
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001470 (void)FutureObj_clear(fut);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001471 Py_TYPE(fut)->tp_free(fut);
1472}
1473
1474
1475/*********************** Future Iterator **************************/
1476
1477typedef struct {
1478 PyObject_HEAD
1479 FutureObj *future;
1480} futureiterobject;
1481
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001482
1483#define FI_FREELIST_MAXLEN 255
1484static futureiterobject *fi_freelist = NULL;
1485static Py_ssize_t fi_freelist_len = 0;
1486
1487
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001488static void
1489FutureIter_dealloc(futureiterobject *it)
1490{
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001491 PyObject_GC_UnTrack(it);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001492 Py_CLEAR(it->future);
1493
1494 if (fi_freelist_len < FI_FREELIST_MAXLEN) {
1495 fi_freelist_len++;
1496 it->future = (FutureObj*) fi_freelist;
1497 fi_freelist = it;
1498 }
1499 else {
1500 PyObject_GC_Del(it);
1501 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001502}
1503
1504static PyObject *
1505FutureIter_iternext(futureiterobject *it)
1506{
1507 PyObject *res;
1508 FutureObj *fut = it->future;
1509
1510 if (fut == NULL) {
1511 return NULL;
1512 }
1513
1514 if (fut->fut_state == STATE_PENDING) {
1515 if (!fut->fut_blocking) {
1516 fut->fut_blocking = 1;
1517 Py_INCREF(fut);
1518 return (PyObject *)fut;
1519 }
Yury Selivanov0cf16f92017-12-25 10:48:15 -05001520 PyErr_SetString(PyExc_RuntimeError,
1521 "await wasn't used with future");
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001522 return NULL;
1523 }
1524
Serhiy Storchakabca49392017-09-03 08:10:14 +03001525 it->future = NULL;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001526 res = _asyncio_Future_result_impl(fut);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001527 if (res != NULL) {
Serhiy Storchaka60e49aa2016-11-06 18:47:03 +02001528 /* The result of the Future is not an exception. */
Serhiy Storchakabca49392017-09-03 08:10:14 +03001529 (void)_PyGen_SetStopIterationValue(res);
Serhiy Storchaka60e49aa2016-11-06 18:47:03 +02001530 Py_DECREF(res);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001531 }
1532
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001533 Py_DECREF(fut);
1534 return NULL;
1535}
1536
1537static PyObject *
INADA Naoki74c17532016-10-25 19:00:45 +09001538FutureIter_send(futureiterobject *self, PyObject *unused)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001539{
INADA Naoki74c17532016-10-25 19:00:45 +09001540 /* Future.__iter__ doesn't care about values that are pushed to the
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03001541 * generator, it just returns self.result().
INADA Naoki74c17532016-10-25 19:00:45 +09001542 */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001543 return FutureIter_iternext(self);
1544}
1545
1546static PyObject *
1547FutureIter_throw(futureiterobject *self, PyObject *args)
1548{
Serhiy Storchakabca49392017-09-03 08:10:14 +03001549 PyObject *type, *val = NULL, *tb = NULL;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001550 if (!PyArg_ParseTuple(args, "O|OO", &type, &val, &tb))
1551 return NULL;
1552
1553 if (val == Py_None) {
1554 val = NULL;
1555 }
1556 if (tb == Py_None) {
1557 tb = NULL;
Benjamin Peterson996fc1f2016-11-14 00:15:44 -08001558 } else if (tb != NULL && !PyTraceBack_Check(tb)) {
1559 PyErr_SetString(PyExc_TypeError, "throw() third argument must be a traceback");
1560 return NULL;
1561 }
1562
1563 Py_INCREF(type);
1564 Py_XINCREF(val);
1565 Py_XINCREF(tb);
1566
1567 if (PyExceptionClass_Check(type)) {
1568 PyErr_NormalizeException(&type, &val, &tb);
Yury Selivanovedfe8862016-12-01 11:37:47 -05001569 /* No need to call PyException_SetTraceback since we'll be calling
1570 PyErr_Restore for `type`, `val`, and `tb`. */
Benjamin Peterson996fc1f2016-11-14 00:15:44 -08001571 } else if (PyExceptionInstance_Check(type)) {
1572 if (val) {
1573 PyErr_SetString(PyExc_TypeError,
1574 "instance exception may not have a separate value");
1575 goto fail;
1576 }
1577 val = type;
1578 type = PyExceptionInstance_Class(type);
1579 Py_INCREF(type);
1580 if (tb == NULL)
1581 tb = PyException_GetTraceback(val);
1582 } else {
1583 PyErr_SetString(PyExc_TypeError,
1584 "exceptions must be classes deriving BaseException or "
1585 "instances of such a class");
1586 goto fail;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001587 }
1588
1589 Py_CLEAR(self->future);
1590
Benjamin Peterson996fc1f2016-11-14 00:15:44 -08001591 PyErr_Restore(type, val, tb);
1592
Serhiy Storchakabca49392017-09-03 08:10:14 +03001593 return NULL;
Benjamin Peterson996fc1f2016-11-14 00:15:44 -08001594
1595 fail:
1596 Py_DECREF(type);
1597 Py_XDECREF(val);
1598 Py_XDECREF(tb);
1599 return NULL;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001600}
1601
1602static PyObject *
1603FutureIter_close(futureiterobject *self, PyObject *arg)
1604{
1605 Py_CLEAR(self->future);
1606 Py_RETURN_NONE;
1607}
1608
1609static int
1610FutureIter_traverse(futureiterobject *it, visitproc visit, void *arg)
1611{
1612 Py_VISIT(it->future);
1613 return 0;
1614}
1615
1616static PyMethodDef FutureIter_methods[] = {
1617 {"send", (PyCFunction)FutureIter_send, METH_O, NULL},
1618 {"throw", (PyCFunction)FutureIter_throw, METH_VARARGS, NULL},
1619 {"close", (PyCFunction)FutureIter_close, METH_NOARGS, NULL},
1620 {NULL, NULL} /* Sentinel */
1621};
1622
1623static PyTypeObject FutureIterType = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02001624 PyVarObject_HEAD_INIT(NULL, 0)
INADA Naoki9f2ce252016-10-15 15:39:19 +09001625 "_asyncio.FutureIter",
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001626 .tp_basicsize = sizeof(futureiterobject),
1627 .tp_itemsize = 0,
1628 .tp_dealloc = (destructor)FutureIter_dealloc,
1629 .tp_getattro = PyObject_GenericGetAttr,
1630 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
1631 .tp_traverse = (traverseproc)FutureIter_traverse,
1632 .tp_iter = PyObject_SelfIter,
1633 .tp_iternext = (iternextfunc)FutureIter_iternext,
1634 .tp_methods = FutureIter_methods,
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001635};
1636
1637static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001638future_new_iter(PyObject *fut)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001639{
1640 futureiterobject *it;
1641
1642 if (!PyObject_TypeCheck(fut, &FutureType)) {
1643 PyErr_BadInternalCall();
1644 return NULL;
1645 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001646
1647 ENSURE_FUTURE_ALIVE(fut)
1648
1649 if (fi_freelist_len) {
1650 fi_freelist_len--;
1651 it = fi_freelist;
1652 fi_freelist = (futureiterobject*) it->future;
1653 it->future = NULL;
1654 _Py_NewReference((PyObject*) it);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001655 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001656 else {
1657 it = PyObject_GC_New(futureiterobject, &FutureIterType);
1658 if (it == NULL) {
1659 return NULL;
1660 }
1661 }
1662
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001663 Py_INCREF(fut);
1664 it->future = (FutureObj*)fut;
INADA Naoki1be427b2016-10-11 02:12:34 +09001665 PyObject_GC_Track(it);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001666 return (PyObject*)it;
1667}
1668
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001669
1670/*********************** Task **************************/
1671
1672
1673/*[clinic input]
1674class _asyncio.Task "TaskObj *" "&Task_Type"
1675[clinic start generated code]*/
1676/*[clinic end generated code: output=da39a3ee5e6b4b0d input=719dcef0fcc03b37]*/
1677
1678static int task_call_step_soon(TaskObj *, PyObject *);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001679static PyObject * task_wakeup(TaskObj *, PyObject *);
1680static PyObject * task_step(TaskObj *, PyObject *);
1681
1682/* ----- Task._step wrapper */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001683
INADA Naokic411a7d2016-10-18 11:48:14 +09001684static int
Serhiy Storchakabca49392017-09-03 08:10:14 +03001685TaskStepMethWrapper_clear(TaskStepMethWrapper *o)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001686{
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001687 Py_CLEAR(o->sw_task);
1688 Py_CLEAR(o->sw_arg);
1689 return 0;
1690}
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001691
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001692static void
Serhiy Storchakabca49392017-09-03 08:10:14 +03001693TaskStepMethWrapper_dealloc(TaskStepMethWrapper *o)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001694{
1695 PyObject_GC_UnTrack(o);
Serhiy Storchakabca49392017-09-03 08:10:14 +03001696 (void)TaskStepMethWrapper_clear(o);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001697 Py_TYPE(o)->tp_free(o);
1698}
1699
1700static PyObject *
Serhiy Storchakabca49392017-09-03 08:10:14 +03001701TaskStepMethWrapper_call(TaskStepMethWrapper *o,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001702 PyObject *args, PyObject *kwds)
1703{
Serhiy Storchakabca49392017-09-03 08:10:14 +03001704 if (kwds != NULL && PyDict_GET_SIZE(kwds) != 0) {
1705 PyErr_SetString(PyExc_TypeError, "function takes no keyword arguments");
1706 return NULL;
1707 }
1708 if (args != NULL && PyTuple_GET_SIZE(args) != 0) {
1709 PyErr_SetString(PyExc_TypeError, "function takes no positional arguments");
1710 return NULL;
1711 }
Yury Selivanov22feeb82018-01-24 11:31:01 -05001712 return task_step(o->sw_task, o->sw_arg);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001713}
1714
1715static int
Serhiy Storchakabca49392017-09-03 08:10:14 +03001716TaskStepMethWrapper_traverse(TaskStepMethWrapper *o,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001717 visitproc visit, void *arg)
1718{
1719 Py_VISIT(o->sw_task);
1720 Py_VISIT(o->sw_arg);
1721 return 0;
1722}
1723
1724static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001725TaskStepMethWrapper_get___self__(TaskStepMethWrapper *o, void *Py_UNUSED(ignored))
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001726{
1727 if (o->sw_task) {
1728 Py_INCREF(o->sw_task);
1729 return (PyObject*)o->sw_task;
1730 }
1731 Py_RETURN_NONE;
1732}
1733
Serhiy Storchakabca49392017-09-03 08:10:14 +03001734static PyGetSetDef TaskStepMethWrapper_getsetlist[] = {
1735 {"__self__", (getter)TaskStepMethWrapper_get___self__, NULL, NULL},
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001736 {NULL} /* Sentinel */
1737};
1738
Benjamin Peterson3c8aae92018-07-05 22:39:34 -07001739static PyTypeObject TaskStepMethWrapper_Type = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02001740 PyVarObject_HEAD_INIT(NULL, 0)
Serhiy Storchakabca49392017-09-03 08:10:14 +03001741 "TaskStepMethWrapper",
1742 .tp_basicsize = sizeof(TaskStepMethWrapper),
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001743 .tp_itemsize = 0,
Serhiy Storchakabca49392017-09-03 08:10:14 +03001744 .tp_getset = TaskStepMethWrapper_getsetlist,
1745 .tp_dealloc = (destructor)TaskStepMethWrapper_dealloc,
1746 .tp_call = (ternaryfunc)TaskStepMethWrapper_call,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001747 .tp_getattro = PyObject_GenericGetAttr,
1748 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
Serhiy Storchakabca49392017-09-03 08:10:14 +03001749 .tp_traverse = (traverseproc)TaskStepMethWrapper_traverse,
1750 .tp_clear = (inquiry)TaskStepMethWrapper_clear,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001751};
1752
1753static PyObject *
Serhiy Storchakabca49392017-09-03 08:10:14 +03001754TaskStepMethWrapper_new(TaskObj *task, PyObject *arg)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001755{
Serhiy Storchakabca49392017-09-03 08:10:14 +03001756 TaskStepMethWrapper *o;
1757 o = PyObject_GC_New(TaskStepMethWrapper, &TaskStepMethWrapper_Type);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001758 if (o == NULL) {
1759 return NULL;
1760 }
1761
1762 Py_INCREF(task);
1763 o->sw_task = task;
1764
1765 Py_XINCREF(arg);
1766 o->sw_arg = arg;
1767
1768 PyObject_GC_Track(o);
1769 return (PyObject*) o;
1770}
1771
1772/* ----- Task._wakeup wrapper */
1773
1774static PyObject *
1775TaskWakeupMethWrapper_call(TaskWakeupMethWrapper *o,
1776 PyObject *args, PyObject *kwds)
1777{
1778 PyObject *fut;
1779
Serhiy Storchakabca49392017-09-03 08:10:14 +03001780 if (kwds != NULL && PyDict_GET_SIZE(kwds) != 0) {
1781 PyErr_SetString(PyExc_TypeError, "function takes no keyword arguments");
1782 return NULL;
1783 }
1784 if (!PyArg_ParseTuple(args, "O", &fut)) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001785 return NULL;
1786 }
1787
Yury Selivanov22feeb82018-01-24 11:31:01 -05001788 return task_wakeup(o->ww_task, fut);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001789}
1790
1791static int
1792TaskWakeupMethWrapper_clear(TaskWakeupMethWrapper *o)
1793{
1794 Py_CLEAR(o->ww_task);
1795 return 0;
1796}
1797
1798static int
1799TaskWakeupMethWrapper_traverse(TaskWakeupMethWrapper *o,
1800 visitproc visit, void *arg)
1801{
1802 Py_VISIT(o->ww_task);
1803 return 0;
1804}
1805
1806static void
1807TaskWakeupMethWrapper_dealloc(TaskWakeupMethWrapper *o)
1808{
1809 PyObject_GC_UnTrack(o);
1810 (void)TaskWakeupMethWrapper_clear(o);
1811 Py_TYPE(o)->tp_free(o);
1812}
1813
Benjamin Peterson3c8aae92018-07-05 22:39:34 -07001814static PyTypeObject TaskWakeupMethWrapper_Type = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02001815 PyVarObject_HEAD_INIT(NULL, 0)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001816 "TaskWakeupMethWrapper",
1817 .tp_basicsize = sizeof(TaskWakeupMethWrapper),
1818 .tp_itemsize = 0,
1819 .tp_dealloc = (destructor)TaskWakeupMethWrapper_dealloc,
1820 .tp_call = (ternaryfunc)TaskWakeupMethWrapper_call,
1821 .tp_getattro = PyObject_GenericGetAttr,
1822 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
1823 .tp_traverse = (traverseproc)TaskWakeupMethWrapper_traverse,
1824 .tp_clear = (inquiry)TaskWakeupMethWrapper_clear,
1825};
1826
1827static PyObject *
1828TaskWakeupMethWrapper_new(TaskObj *task)
1829{
1830 TaskWakeupMethWrapper *o;
1831 o = PyObject_GC_New(TaskWakeupMethWrapper, &TaskWakeupMethWrapper_Type);
1832 if (o == NULL) {
1833 return NULL;
1834 }
1835
1836 Py_INCREF(task);
1837 o->ww_task = task;
1838
1839 PyObject_GC_Track(o);
1840 return (PyObject*) o;
1841}
1842
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001843/* ----- Task introspection helpers */
1844
1845static int
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001846register_task(PyObject *task)
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001847{
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001848 _Py_IDENTIFIER(add);
1849
1850 PyObject *res = _PyObject_CallMethodIdObjArgs(
1851 all_tasks, &PyId_add, task, NULL);
1852 if (res == NULL) {
1853 return -1;
1854 }
1855 Py_DECREF(res);
1856 return 0;
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001857}
1858
1859
1860static int
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001861unregister_task(PyObject *task)
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001862{
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001863 _Py_IDENTIFIER(discard);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001864
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001865 PyObject *res = _PyObject_CallMethodIdObjArgs(
1866 all_tasks, &PyId_discard, task, NULL);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001867 if (res == NULL) {
1868 return -1;
1869 }
1870 Py_DECREF(res);
1871 return 0;
1872}
1873
1874
1875static int
1876enter_task(PyObject *loop, PyObject *task)
1877{
1878 PyObject *item;
1879 Py_hash_t hash;
1880 hash = PyObject_Hash(loop);
1881 if (hash == -1) {
1882 return -1;
1883 }
1884 item = _PyDict_GetItem_KnownHash(current_tasks, loop, hash);
1885 if (item != NULL) {
Serhiy Storchaka66553542018-05-20 16:30:31 +03001886 Py_INCREF(item);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001887 PyErr_Format(
1888 PyExc_RuntimeError,
1889 "Cannot enter into task %R while another " \
1890 "task %R is being executed.",
1891 task, item, NULL);
Serhiy Storchaka66553542018-05-20 16:30:31 +03001892 Py_DECREF(item);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001893 return -1;
1894 }
Serhiy Storchaka66553542018-05-20 16:30:31 +03001895 if (PyErr_Occurred()) {
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001896 return -1;
1897 }
Serhiy Storchaka66553542018-05-20 16:30:31 +03001898 return _PyDict_SetItem_KnownHash(current_tasks, loop, task, hash);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001899}
1900
1901
1902static int
1903leave_task(PyObject *loop, PyObject *task)
1904/*[clinic end generated code: output=0ebf6db4b858fb41 input=51296a46313d1ad8]*/
1905{
1906 PyObject *item;
1907 Py_hash_t hash;
1908 hash = PyObject_Hash(loop);
1909 if (hash == -1) {
1910 return -1;
1911 }
1912 item = _PyDict_GetItem_KnownHash(current_tasks, loop, hash);
1913 if (item != task) {
1914 if (item == NULL) {
1915 /* Not entered, replace with None */
1916 item = Py_None;
1917 }
1918 PyErr_Format(
1919 PyExc_RuntimeError,
1920 "Leaving task %R does not match the current task %R.",
1921 task, item, NULL);
1922 return -1;
1923 }
1924 return _PyDict_DelItem_KnownHash(current_tasks, loop, hash);
1925}
1926
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001927/* ----- Task */
1928
1929/*[clinic input]
1930_asyncio.Task.__init__
1931
Serhiy Storchakabca49392017-09-03 08:10:14 +03001932 coro: object
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001933 *
Serhiy Storchakabca49392017-09-03 08:10:14 +03001934 loop: object = None
Alex Grönholmcca4eec2018-08-09 00:06:47 +03001935 name: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001936
1937A coroutine wrapped in a Future.
1938[clinic start generated code]*/
1939
1940static int
Alex Grönholmcca4eec2018-08-09 00:06:47 +03001941_asyncio_Task___init___impl(TaskObj *self, PyObject *coro, PyObject *loop,
1942 PyObject *name)
1943/*[clinic end generated code: output=88b12b83d570df50 input=352a3137fe60091d]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001944{
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001945 if (future_init((FutureObj*)self, loop)) {
INADA Naokic411a7d2016-10-18 11:48:14 +09001946 return -1;
1947 }
INADA Naokic411a7d2016-10-18 11:48:14 +09001948
Yury Selivanova9d7e552017-12-19 07:18:45 -05001949 int is_coro = is_coroutine(coro);
1950 if (is_coro == -1) {
1951 return -1;
1952 }
1953 if (is_coro == 0) {
1954 self->task_log_destroy_pending = 0;
1955 PyErr_Format(PyExc_TypeError,
1956 "a coroutine was expected, got %R",
1957 coro, NULL);
1958 return -1;
Andrew Svetlovf74ef452017-12-15 07:04:38 +02001959 }
1960
Oren Milmand019bc82018-02-13 12:28:33 +02001961 Py_XSETREF(self->task_context, PyContext_CopyCurrent());
Yury Selivanovf23746a2018-01-22 19:11:18 -05001962 if (self->task_context == NULL) {
1963 return -1;
1964 }
1965
Oren Milmand019bc82018-02-13 12:28:33 +02001966 Py_CLEAR(self->task_fut_waiter);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001967 self->task_must_cancel = 0;
1968 self->task_log_destroy_pending = 1;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001969 Py_INCREF(coro);
Oren Milmand019bc82018-02-13 12:28:33 +02001970 Py_XSETREF(self->task_coro, coro);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001971
Alex Grönholmcca4eec2018-08-09 00:06:47 +03001972 if (name == Py_None) {
1973 name = PyUnicode_FromFormat("Task-%" PRIu64, ++task_name_counter);
Alex Grönholma7548232018-08-09 23:49:49 +03001974 } else if (!PyUnicode_CheckExact(name)) {
Alex Grönholmcca4eec2018-08-09 00:06:47 +03001975 name = PyObject_Str(name);
1976 } else {
1977 Py_INCREF(name);
1978 }
1979 Py_XSETREF(self->task_name, name);
1980 if (self->task_name == NULL) {
1981 return -1;
1982 }
1983
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001984 if (task_call_step_soon(self, NULL)) {
1985 return -1;
INADA Naokic411a7d2016-10-18 11:48:14 +09001986 }
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001987 return register_task((PyObject*)self);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001988}
1989
1990static int
1991TaskObj_clear(TaskObj *task)
1992{
1993 (void)FutureObj_clear((FutureObj*) task);
Yury Selivanovf23746a2018-01-22 19:11:18 -05001994 Py_CLEAR(task->task_context);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001995 Py_CLEAR(task->task_coro);
Alex Grönholmcca4eec2018-08-09 00:06:47 +03001996 Py_CLEAR(task->task_name);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001997 Py_CLEAR(task->task_fut_waiter);
1998 return 0;
1999}
2000
2001static int
2002TaskObj_traverse(TaskObj *task, visitproc visit, void *arg)
2003{
Yury Selivanovf23746a2018-01-22 19:11:18 -05002004 Py_VISIT(task->task_context);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002005 Py_VISIT(task->task_coro);
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002006 Py_VISIT(task->task_name);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002007 Py_VISIT(task->task_fut_waiter);
2008 (void)FutureObj_traverse((FutureObj*) task, visit, arg);
2009 return 0;
2010}
2011
2012static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02002013TaskObj_get_log_destroy_pending(TaskObj *task, void *Py_UNUSED(ignored))
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002014{
2015 if (task->task_log_destroy_pending) {
2016 Py_RETURN_TRUE;
2017 }
2018 else {
2019 Py_RETURN_FALSE;
2020 }
2021}
2022
2023static int
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02002024TaskObj_set_log_destroy_pending(TaskObj *task, PyObject *val, void *Py_UNUSED(ignored))
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002025{
Zackery Spytz842acaa2018-12-17 07:52:45 -07002026 if (val == NULL) {
2027 PyErr_SetString(PyExc_AttributeError, "cannot delete attribute");
2028 return -1;
2029 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002030 int is_true = PyObject_IsTrue(val);
2031 if (is_true < 0) {
2032 return -1;
2033 }
2034 task->task_log_destroy_pending = is_true;
2035 return 0;
2036}
2037
2038static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02002039TaskObj_get_must_cancel(TaskObj *task, void *Py_UNUSED(ignored))
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002040{
2041 if (task->task_must_cancel) {
2042 Py_RETURN_TRUE;
2043 }
2044 else {
2045 Py_RETURN_FALSE;
2046 }
2047}
2048
2049static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02002050TaskObj_get_coro(TaskObj *task, void *Py_UNUSED(ignored))
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002051{
2052 if (task->task_coro) {
2053 Py_INCREF(task->task_coro);
2054 return task->task_coro;
2055 }
2056
2057 Py_RETURN_NONE;
2058}
2059
2060static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02002061TaskObj_get_fut_waiter(TaskObj *task, void *Py_UNUSED(ignored))
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002062{
2063 if (task->task_fut_waiter) {
2064 Py_INCREF(task->task_fut_waiter);
2065 return task->task_fut_waiter;
2066 }
2067
2068 Py_RETURN_NONE;
2069}
2070
2071/*[clinic input]
2072@classmethod
2073_asyncio.Task.current_task
2074
Serhiy Storchakabca49392017-09-03 08:10:14 +03002075 loop: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002076
2077Return the currently running task in an event loop or None.
2078
2079By default the current task for the current event loop is returned.
2080
2081None is returned when called not in the context of a Task.
2082[clinic start generated code]*/
2083
2084static PyObject *
2085_asyncio_Task_current_task_impl(PyTypeObject *type, PyObject *loop)
Serhiy Storchakabca49392017-09-03 08:10:14 +03002086/*[clinic end generated code: output=99fbe7332c516e03 input=cd14770c5b79c7eb]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002087{
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002088 PyObject *ret;
2089 PyObject *current_task_func;
2090
Inada Naokic5c6cda2019-03-22 20:07:32 +09002091 if (PyErr_WarnEx(PyExc_DeprecationWarning,
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002092 "Task.current_task() is deprecated, " \
2093 "use asyncio.current_task() instead",
2094 1) < 0) {
2095 return NULL;
2096 }
2097
2098 current_task_func = _PyObject_GetAttrId(asyncio_mod, &PyId_current_task);
2099 if (current_task_func == NULL) {
2100 return NULL;
2101 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002102
Yury Selivanov8d26aa92017-03-02 22:16:33 -05002103 if (loop == Py_None) {
Yury Selivanova70232f2017-12-13 14:49:42 -05002104 loop = get_event_loop();
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002105 if (loop == NULL) {
Serhiy Storchaka66553542018-05-20 16:30:31 +03002106 Py_DECREF(current_task_func);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002107 return NULL;
2108 }
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002109 ret = PyObject_CallFunctionObjArgs(current_task_func, loop, NULL);
2110 Py_DECREF(current_task_func);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002111 Py_DECREF(loop);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002112 return ret;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002113 }
2114 else {
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002115 ret = PyObject_CallFunctionObjArgs(current_task_func, loop, NULL);
2116 Py_DECREF(current_task_func);
2117 return ret;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002118 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002119}
2120
2121/*[clinic input]
2122@classmethod
2123_asyncio.Task.all_tasks
2124
Serhiy Storchakabca49392017-09-03 08:10:14 +03002125 loop: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002126
2127Return a set of all tasks for an event loop.
2128
2129By default all tasks for the current event loop are returned.
2130[clinic start generated code]*/
2131
2132static PyObject *
2133_asyncio_Task_all_tasks_impl(PyTypeObject *type, PyObject *loop)
Serhiy Storchakabca49392017-09-03 08:10:14 +03002134/*[clinic end generated code: output=11f9b20749ccca5d input=497f80bc9ce726b5]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002135{
2136 PyObject *res;
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002137 PyObject *all_tasks_func;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002138
Inada Naokic5c6cda2019-03-22 20:07:32 +09002139 if (PyErr_WarnEx(PyExc_DeprecationWarning,
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002140 "Task.all_tasks() is deprecated, " \
2141 "use asyncio.all_tasks() instead",
2142 1) < 0) {
2143 return NULL;
2144 }
2145
Yury Selivanov416c1eb2018-05-28 17:54:02 -04002146 all_tasks_func = _PyObject_GetAttrId(asyncio_mod, &PyId__all_tasks_compat);
Serhiy Storchaka66553542018-05-20 16:30:31 +03002147 if (all_tasks_func == NULL) {
2148 return NULL;
2149 }
2150
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002151 res = PyObject_CallFunctionObjArgs(all_tasks_func, loop, NULL);
2152 Py_DECREF(all_tasks_func);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002153 return res;
2154}
2155
2156/*[clinic input]
2157_asyncio.Task._repr_info
2158[clinic start generated code]*/
2159
2160static PyObject *
2161_asyncio_Task__repr_info_impl(TaskObj *self)
2162/*[clinic end generated code: output=6a490eb66d5ba34b input=3c6d051ed3ddec8b]*/
2163{
Victor Stinnerde4ae3d2016-12-04 22:59:09 +01002164 return PyObject_CallFunctionObjArgs(
2165 asyncio_task_repr_info_func, self, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002166}
2167
2168/*[clinic input]
2169_asyncio.Task.cancel
2170
2171Request that this task cancel itself.
2172
2173This arranges for a CancelledError to be thrown into the
2174wrapped coroutine on the next cycle through the event loop.
2175The coroutine then has a chance to clean up or even deny
2176the request using try/except/finally.
2177
2178Unlike Future.cancel, this does not guarantee that the
2179task will be cancelled: the exception might be caught and
2180acted upon, delaying cancellation of the task or preventing
2181cancellation completely. The task may also return a value or
2182raise a different exception.
2183
2184Immediately after this method is called, Task.cancelled() will
2185not return True (unless the task was already cancelled). A
2186task will be marked as cancelled when the wrapped coroutine
2187terminates with a CancelledError exception (even if cancel()
2188was not called).
2189[clinic start generated code]*/
2190
2191static PyObject *
2192_asyncio_Task_cancel_impl(TaskObj *self)
2193/*[clinic end generated code: output=6bfc0479da9d5757 input=13f9bf496695cb52]*/
2194{
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +00002195 self->task_log_tb = 0;
2196
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002197 if (self->task_state != STATE_PENDING) {
2198 Py_RETURN_FALSE;
2199 }
2200
2201 if (self->task_fut_waiter) {
2202 PyObject *res;
2203 int is_true;
2204
2205 res = _PyObject_CallMethodId(
2206 self->task_fut_waiter, &PyId_cancel, NULL);
2207 if (res == NULL) {
2208 return NULL;
2209 }
2210
2211 is_true = PyObject_IsTrue(res);
2212 Py_DECREF(res);
2213 if (is_true < 0) {
2214 return NULL;
2215 }
2216
2217 if (is_true) {
2218 Py_RETURN_TRUE;
2219 }
2220 }
2221
2222 self->task_must_cancel = 1;
2223 Py_RETURN_TRUE;
2224}
2225
2226/*[clinic input]
2227_asyncio.Task.get_stack
2228
2229 *
Serhiy Storchakabca49392017-09-03 08:10:14 +03002230 limit: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002231
2232Return the list of stack frames for this task's coroutine.
2233
2234If the coroutine is not done, this returns the stack where it is
2235suspended. If the coroutine has completed successfully or was
2236cancelled, this returns an empty list. If the coroutine was
2237terminated by an exception, this returns the list of traceback
2238frames.
2239
2240The frames are always ordered from oldest to newest.
2241
2242The optional limit gives the maximum number of frames to
2243return; by default all available frames are returned. Its
2244meaning differs depending on whether a stack or a traceback is
2245returned: the newest frames of a stack are returned, but the
2246oldest frames of a traceback are returned. (This matches the
2247behavior of the traceback module.)
2248
2249For reasons beyond our control, only one stack frame is
2250returned for a suspended coroutine.
2251[clinic start generated code]*/
2252
2253static PyObject *
2254_asyncio_Task_get_stack_impl(TaskObj *self, PyObject *limit)
Serhiy Storchakabca49392017-09-03 08:10:14 +03002255/*[clinic end generated code: output=c9aeeeebd1e18118 input=05b323d42b809b90]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002256{
2257 return PyObject_CallFunctionObjArgs(
2258 asyncio_task_get_stack_func, self, limit, NULL);
2259}
2260
2261/*[clinic input]
2262_asyncio.Task.print_stack
2263
2264 *
Serhiy Storchakabca49392017-09-03 08:10:14 +03002265 limit: object = None
2266 file: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002267
2268Print the stack or traceback for this task's coroutine.
2269
2270This produces output similar to that of the traceback module,
2271for the frames retrieved by get_stack(). The limit argument
2272is passed to get_stack(). The file argument is an I/O stream
2273to which the output is written; by default output is written
2274to sys.stderr.
2275[clinic start generated code]*/
2276
2277static PyObject *
2278_asyncio_Task_print_stack_impl(TaskObj *self, PyObject *limit,
2279 PyObject *file)
Serhiy Storchakabca49392017-09-03 08:10:14 +03002280/*[clinic end generated code: output=7339e10314cd3f4d input=1a0352913b7fcd92]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002281{
2282 return PyObject_CallFunctionObjArgs(
2283 asyncio_task_print_stack_func, self, limit, file, NULL);
2284}
2285
2286/*[clinic input]
Yury Selivanov0cf16f92017-12-25 10:48:15 -05002287_asyncio.Task.set_result
2288
2289 result: object
2290 /
2291[clinic start generated code]*/
2292
2293static PyObject *
2294_asyncio_Task_set_result(TaskObj *self, PyObject *result)
2295/*[clinic end generated code: output=1dcae308bfcba318 input=9d1a00c07be41bab]*/
2296{
2297 PyErr_SetString(PyExc_RuntimeError,
2298 "Task does not support set_result operation");
2299 return NULL;
2300}
2301
2302/*[clinic input]
2303_asyncio.Task.set_exception
2304
2305 exception: object
2306 /
2307[clinic start generated code]*/
2308
2309static PyObject *
2310_asyncio_Task_set_exception(TaskObj *self, PyObject *exception)
2311/*[clinic end generated code: output=bc377fc28067303d input=9a8f65c83dcf893a]*/
2312{
2313 PyErr_SetString(PyExc_RuntimeError,
Andrew Svetlovfc359322017-12-30 15:40:27 +02002314 "Task does not support set_exception operation");
Yury Selivanov0cf16f92017-12-25 10:48:15 -05002315 return NULL;
2316}
2317
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002318/*[clinic input]
Alex Grönholm98ef9202019-05-30 18:30:09 +03002319_asyncio.Task.get_coro
2320[clinic start generated code]*/
2321
2322static PyObject *
2323_asyncio_Task_get_coro_impl(TaskObj *self)
2324/*[clinic end generated code: output=bcac27c8cc6c8073 input=d2e8606c42a7b403]*/
2325{
2326 Py_INCREF(self->task_coro);
2327 return self->task_coro;
2328}
2329
2330/*[clinic input]
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002331_asyncio.Task.get_name
2332[clinic start generated code]*/
2333
2334static PyObject *
2335_asyncio_Task_get_name_impl(TaskObj *self)
2336/*[clinic end generated code: output=0ecf1570c3b37a8f input=a4a6595d12f4f0f8]*/
2337{
2338 if (self->task_name) {
2339 Py_INCREF(self->task_name);
2340 return self->task_name;
2341 }
2342
2343 Py_RETURN_NONE;
2344}
2345
2346/*[clinic input]
2347_asyncio.Task.set_name
2348
2349 value: object
2350 /
2351[clinic start generated code]*/
2352
2353static PyObject *
2354_asyncio_Task_set_name(TaskObj *self, PyObject *value)
2355/*[clinic end generated code: output=138a8d51e32057d6 input=a8359b6e65f8fd31]*/
2356{
Alex Grönholma7548232018-08-09 23:49:49 +03002357 if (!PyUnicode_CheckExact(value)) {
2358 value = PyObject_Str(value);
2359 if (value == NULL) {
2360 return NULL;
2361 }
2362 } else {
2363 Py_INCREF(value);
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002364 }
2365
Alex Grönholma7548232018-08-09 23:49:49 +03002366 Py_XSETREF(self->task_name, value);
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002367 Py_RETURN_NONE;
2368}
Yury Selivanov0cf16f92017-12-25 10:48:15 -05002369
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002370static void
2371TaskObj_finalize(TaskObj *task)
2372{
2373 _Py_IDENTIFIER(call_exception_handler);
2374 _Py_IDENTIFIER(task);
2375 _Py_IDENTIFIER(message);
2376 _Py_IDENTIFIER(source_traceback);
2377
Serhiy Storchakabca49392017-09-03 08:10:14 +03002378 PyObject *context;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002379 PyObject *message = NULL;
Serhiy Storchakabca49392017-09-03 08:10:14 +03002380 PyObject *func;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002381 PyObject *error_type, *error_value, *error_traceback;
2382
2383 if (task->task_state != STATE_PENDING || !task->task_log_destroy_pending) {
2384 goto done;
2385 }
2386
2387 /* Save the current exception, if any. */
2388 PyErr_Fetch(&error_type, &error_value, &error_traceback);
2389
2390 context = PyDict_New();
2391 if (context == NULL) {
2392 goto finally;
2393 }
2394
2395 message = PyUnicode_FromString("Task was destroyed but it is pending!");
2396 if (message == NULL) {
2397 goto finally;
2398 }
2399
2400 if (_PyDict_SetItemId(context, &PyId_message, message) < 0 ||
2401 _PyDict_SetItemId(context, &PyId_task, (PyObject*)task) < 0)
2402 {
2403 goto finally;
2404 }
2405
2406 if (task->task_source_tb != NULL) {
2407 if (_PyDict_SetItemId(context, &PyId_source_traceback,
2408 task->task_source_tb) < 0)
2409 {
2410 goto finally;
2411 }
2412 }
2413
2414 func = _PyObject_GetAttrId(task->task_loop, &PyId_call_exception_handler);
2415 if (func != NULL) {
Serhiy Storchakabca49392017-09-03 08:10:14 +03002416 PyObject *res = PyObject_CallFunctionObjArgs(func, context, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002417 if (res == NULL) {
2418 PyErr_WriteUnraisable(func);
2419 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03002420 else {
2421 Py_DECREF(res);
2422 }
2423 Py_DECREF(func);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002424 }
2425
2426finally:
Serhiy Storchakabca49392017-09-03 08:10:14 +03002427 Py_XDECREF(context);
2428 Py_XDECREF(message);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002429
2430 /* Restore the saved exception. */
2431 PyErr_Restore(error_type, error_value, error_traceback);
2432
2433done:
2434 FutureObj_finalize((FutureObj*)task);
2435}
2436
2437static void TaskObj_dealloc(PyObject *); /* Needs Task_CheckExact */
2438
2439static PyMethodDef TaskType_methods[] = {
2440 _ASYNCIO_FUTURE_RESULT_METHODDEF
2441 _ASYNCIO_FUTURE_EXCEPTION_METHODDEF
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002442 _ASYNCIO_FUTURE_ADD_DONE_CALLBACK_METHODDEF
2443 _ASYNCIO_FUTURE_REMOVE_DONE_CALLBACK_METHODDEF
2444 _ASYNCIO_FUTURE_CANCELLED_METHODDEF
2445 _ASYNCIO_FUTURE_DONE_METHODDEF
Yury Selivanov0cf16f92017-12-25 10:48:15 -05002446 _ASYNCIO_TASK_SET_RESULT_METHODDEF
2447 _ASYNCIO_TASK_SET_EXCEPTION_METHODDEF
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002448 _ASYNCIO_TASK_CURRENT_TASK_METHODDEF
2449 _ASYNCIO_TASK_ALL_TASKS_METHODDEF
2450 _ASYNCIO_TASK_CANCEL_METHODDEF
2451 _ASYNCIO_TASK_GET_STACK_METHODDEF
2452 _ASYNCIO_TASK_PRINT_STACK_METHODDEF
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002453 _ASYNCIO_TASK__REPR_INFO_METHODDEF
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002454 _ASYNCIO_TASK_GET_NAME_METHODDEF
2455 _ASYNCIO_TASK_SET_NAME_METHODDEF
Alex Grönholm98ef9202019-05-30 18:30:09 +03002456 _ASYNCIO_TASK_GET_CORO_METHODDEF
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002457 {NULL, NULL} /* Sentinel */
2458};
2459
2460static PyGetSetDef TaskType_getsetlist[] = {
2461 FUTURE_COMMON_GETSETLIST
2462 {"_log_destroy_pending", (getter)TaskObj_get_log_destroy_pending,
2463 (setter)TaskObj_set_log_destroy_pending, NULL},
2464 {"_must_cancel", (getter)TaskObj_get_must_cancel, NULL, NULL},
2465 {"_coro", (getter)TaskObj_get_coro, NULL, NULL},
2466 {"_fut_waiter", (getter)TaskObj_get_fut_waiter, NULL, NULL},
2467 {NULL} /* Sentinel */
2468};
2469
2470static PyTypeObject TaskType = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02002471 PyVarObject_HEAD_INIT(NULL, 0)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002472 "_asyncio.Task",
2473 sizeof(TaskObj), /* tp_basicsize */
2474 .tp_base = &FutureType,
2475 .tp_dealloc = TaskObj_dealloc,
2476 .tp_as_async = &FutureType_as_async,
2477 .tp_repr = (reprfunc)FutureObj_repr,
Antoine Pitrouada319b2019-05-29 22:12:38 +02002478 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002479 .tp_doc = _asyncio_Task___init____doc__,
2480 .tp_traverse = (traverseproc)TaskObj_traverse,
2481 .tp_clear = (inquiry)TaskObj_clear,
2482 .tp_weaklistoffset = offsetof(TaskObj, task_weakreflist),
2483 .tp_iter = (getiterfunc)future_new_iter,
2484 .tp_methods = TaskType_methods,
2485 .tp_getset = TaskType_getsetlist,
2486 .tp_dictoffset = offsetof(TaskObj, dict),
2487 .tp_init = (initproc)_asyncio_Task___init__,
2488 .tp_new = PyType_GenericNew,
2489 .tp_finalize = (destructor)TaskObj_finalize,
2490};
2491
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002492static void
2493TaskObj_dealloc(PyObject *self)
2494{
2495 TaskObj *task = (TaskObj *)self;
2496
2497 if (Task_CheckExact(self)) {
2498 /* When fut is subclass of Task, finalizer is called from
2499 * subtype_dealloc.
2500 */
2501 if (PyObject_CallFinalizerFromDealloc(self) < 0) {
2502 // resurrected.
2503 return;
2504 }
2505 }
2506
Alexander Mohrde34cbe2017-08-01 23:31:07 -07002507 PyObject_GC_UnTrack(self);
2508
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002509 if (task->task_weakreflist != NULL) {
2510 PyObject_ClearWeakRefs(self);
2511 }
2512
2513 (void)TaskObj_clear(task);
2514 Py_TYPE(task)->tp_free(task);
2515}
2516
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002517static int
2518task_call_step_soon(TaskObj *task, PyObject *arg)
2519{
Serhiy Storchakabca49392017-09-03 08:10:14 +03002520 PyObject *cb = TaskStepMethWrapper_new(task, arg);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002521 if (cb == NULL) {
2522 return -1;
2523 }
2524
Yury Selivanovf23746a2018-01-22 19:11:18 -05002525 int ret = call_soon(task->task_loop, cb, NULL, task->task_context);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002526 Py_DECREF(cb);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05002527 return ret;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002528}
2529
2530static PyObject *
2531task_set_error_soon(TaskObj *task, PyObject *et, const char *format, ...)
2532{
2533 PyObject* msg;
2534
2535 va_list vargs;
2536#ifdef HAVE_STDARG_PROTOTYPES
2537 va_start(vargs, format);
2538#else
2539 va_start(vargs);
2540#endif
2541 msg = PyUnicode_FromFormatV(format, vargs);
2542 va_end(vargs);
2543
2544 if (msg == NULL) {
2545 return NULL;
2546 }
2547
Victor Stinnerde4ae3d2016-12-04 22:59:09 +01002548 PyObject *e = PyObject_CallFunctionObjArgs(et, msg, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002549 Py_DECREF(msg);
2550 if (e == NULL) {
2551 return NULL;
2552 }
2553
2554 if (task_call_step_soon(task, e) == -1) {
2555 Py_DECREF(e);
2556 return NULL;
2557 }
2558
2559 Py_DECREF(e);
2560 Py_RETURN_NONE;
2561}
2562
2563static PyObject *
2564task_step_impl(TaskObj *task, PyObject *exc)
2565{
2566 int res;
2567 int clear_exc = 0;
2568 PyObject *result = NULL;
Serhiy Storchakabca49392017-09-03 08:10:14 +03002569 PyObject *coro;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002570 PyObject *o;
2571
2572 if (task->task_state != STATE_PENDING) {
Yury Selivanov0cf16f92017-12-25 10:48:15 -05002573 PyErr_Format(asyncio_InvalidStateError,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002574 "_step(): already done: %R %R",
2575 task,
2576 exc ? exc : Py_None);
INADA Naokic411a7d2016-10-18 11:48:14 +09002577 goto fail;
2578 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09002579
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002580 if (task->task_must_cancel) {
2581 assert(exc != Py_None);
2582
2583 if (exc) {
2584 /* Check if exc is a CancelledError */
2585 res = PyObject_IsInstance(exc, asyncio_CancelledError);
2586 if (res == -1) {
2587 /* An error occurred, abort */
2588 goto fail;
2589 }
2590 if (res == 0) {
2591 /* exc is not CancelledError; reset it to NULL */
2592 exc = NULL;
2593 }
2594 }
2595
2596 if (!exc) {
2597 /* exc was not a CancelledError */
Victor Stinnerf17c3de2016-12-06 18:46:19 +01002598 exc = _PyObject_CallNoArg(asyncio_CancelledError);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002599 if (!exc) {
2600 goto fail;
2601 }
2602 clear_exc = 1;
2603 }
2604
2605 task->task_must_cancel = 0;
2606 }
2607
2608 Py_CLEAR(task->task_fut_waiter);
2609
Serhiy Storchakabca49392017-09-03 08:10:14 +03002610 coro = task->task_coro;
2611 if (coro == NULL) {
2612 PyErr_SetString(PyExc_RuntimeError, "uninitialized Task object");
2613 return NULL;
2614 }
2615
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002616 if (exc == NULL) {
2617 if (PyGen_CheckExact(coro) || PyCoro_CheckExact(coro)) {
2618 result = _PyGen_Send((PyGenObject*)coro, Py_None);
2619 }
2620 else {
Victor Stinnerb6ed57d2016-12-09 14:24:02 +01002621 result = _PyObject_CallMethodIdObjArgs(coro, &PyId_send,
2622 Py_None, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002623 }
2624 }
2625 else {
Victor Stinnerb6ed57d2016-12-09 14:24:02 +01002626 result = _PyObject_CallMethodIdObjArgs(coro, &PyId_throw,
2627 exc, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002628 if (clear_exc) {
2629 /* We created 'exc' during this call */
Serhiy Storchakabca49392017-09-03 08:10:14 +03002630 Py_DECREF(exc);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002631 }
2632 }
2633
2634 if (result == NULL) {
2635 PyObject *et, *ev, *tb;
2636
2637 if (_PyGen_FetchStopIterationValue(&o) == 0) {
2638 /* The error is StopIteration and that means that
2639 the underlying coroutine has resolved */
Miss Islington (bot)16cec132019-09-25 04:48:52 -07002640
2641 PyObject *res;
INADA Naoki991adca2017-05-11 21:18:38 +09002642 if (task->task_must_cancel) {
2643 // Task is cancelled right before coro stops.
INADA Naoki991adca2017-05-11 21:18:38 +09002644 task->task_must_cancel = 0;
Miss Islington (bot)16cec132019-09-25 04:48:52 -07002645 res = future_cancel((FutureObj*)task);
INADA Naoki991adca2017-05-11 21:18:38 +09002646 }
Miss Islington (bot)16cec132019-09-25 04:48:52 -07002647 else {
2648 res = future_set_result((FutureObj*)task, o);
2649 }
2650
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002651 Py_DECREF(o);
Miss Islington (bot)16cec132019-09-25 04:48:52 -07002652
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002653 if (res == NULL) {
2654 return NULL;
2655 }
2656 Py_DECREF(res);
2657 Py_RETURN_NONE;
2658 }
2659
2660 if (PyErr_ExceptionMatches(asyncio_CancelledError)) {
2661 /* CancelledError */
2662 PyErr_Clear();
2663 return future_cancel((FutureObj*)task);
2664 }
2665
2666 /* Some other exception; pop it and call Task.set_exception() */
2667 PyErr_Fetch(&et, &ev, &tb);
INADA Naoki991adca2017-05-11 21:18:38 +09002668
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002669 assert(et);
2670 if (!ev || !PyObject_TypeCheck(ev, (PyTypeObject *) et)) {
2671 PyErr_NormalizeException(&et, &ev, &tb);
2672 }
Yury Selivanovedfe8862016-12-01 11:37:47 -05002673 if (tb != NULL) {
2674 PyException_SetTraceback(ev, tb);
2675 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002676 o = future_set_exception((FutureObj*)task, ev);
2677 if (!o) {
2678 /* An exception in Task.set_exception() */
Serhiy Storchakabca49392017-09-03 08:10:14 +03002679 Py_DECREF(et);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002680 Py_XDECREF(tb);
2681 Py_XDECREF(ev);
2682 goto fail;
2683 }
2684 assert(o == Py_None);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002685 Py_DECREF(o);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002686
Yury Selivanov431b5402019-05-27 14:45:12 +02002687 if (PyErr_GivenExceptionMatches(et, PyExc_KeyboardInterrupt) ||
2688 PyErr_GivenExceptionMatches(et, PyExc_SystemExit))
2689 {
2690 /* We've got a KeyboardInterrupt or a SystemError; re-raise it */
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002691 PyErr_Restore(et, ev, tb);
2692 goto fail;
2693 }
2694
Serhiy Storchakabca49392017-09-03 08:10:14 +03002695 Py_DECREF(et);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002696 Py_XDECREF(tb);
2697 Py_XDECREF(ev);
2698
2699 Py_RETURN_NONE;
2700 }
2701
2702 if (result == (PyObject*)task) {
2703 /* We have a task that wants to await on itself */
2704 goto self_await;
2705 }
2706
2707 /* Check if `result` is FutureObj or TaskObj (and not a subclass) */
2708 if (Future_CheckExact(result) || Task_CheckExact(result)) {
2709 PyObject *wrapper;
2710 PyObject *res;
2711 FutureObj *fut = (FutureObj*)result;
2712
2713 /* Check if `result` future is attached to a different loop */
2714 if (fut->fut_loop != task->task_loop) {
2715 goto different_loop;
2716 }
2717
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002718 if (!fut->fut_blocking) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002719 goto yield_insteadof_yf;
2720 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002721
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002722 fut->fut_blocking = 0;
2723
2724 /* result.add_done_callback(task._wakeup) */
2725 wrapper = TaskWakeupMethWrapper_new(task);
2726 if (wrapper == NULL) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002727 goto fail;
2728 }
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002729 res = future_add_done_callback(
2730 (FutureObj*)result, wrapper, task->task_context);
2731 Py_DECREF(wrapper);
2732 if (res == NULL) {
2733 goto fail;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002734 }
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002735 Py_DECREF(res);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002736
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002737 /* task._fut_waiter = result */
2738 task->task_fut_waiter = result; /* no incref is necessary */
2739
2740 if (task->task_must_cancel) {
2741 PyObject *r;
Elvis Pranskevichus0c797a62018-10-03 10:30:31 -04002742 int is_true;
Serhiy Storchakaaddf8af2018-10-05 21:20:02 +03002743 r = _PyObject_CallMethodId(result, &PyId_cancel, NULL);
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002744 if (r == NULL) {
2745 return NULL;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002746 }
Elvis Pranskevichus0c797a62018-10-03 10:30:31 -04002747 is_true = PyObject_IsTrue(r);
2748 Py_DECREF(r);
2749 if (is_true < 0) {
2750 return NULL;
2751 }
2752 else if (is_true) {
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002753 task->task_must_cancel = 0;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002754 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002755 }
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002756
2757 Py_RETURN_NONE;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002758 }
2759
2760 /* Check if `result` is None */
2761 if (result == Py_None) {
2762 /* Bare yield relinquishes control for one event loop iteration. */
2763 if (task_call_step_soon(task, NULL)) {
2764 goto fail;
2765 }
2766 return result;
2767 }
2768
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002769 /* Check if `result` is a Future-compatible object */
2770 if (_PyObject_LookupAttrId(result, &PyId__asyncio_future_blocking, &o) < 0) {
2771 goto fail;
2772 }
2773 if (o != NULL && o != Py_None) {
2774 /* `result` is a Future-compatible object */
2775 PyObject *wrapper;
2776 PyObject *res;
2777
2778 int blocking = PyObject_IsTrue(o);
2779 Py_DECREF(o);
2780 if (blocking < 0) {
2781 goto fail;
2782 }
2783
2784 /* Check if `result` future is attached to a different loop */
2785 PyObject *oloop = get_future_loop(result);
2786 if (oloop == NULL) {
2787 goto fail;
2788 }
2789 if (oloop != task->task_loop) {
2790 Py_DECREF(oloop);
2791 goto different_loop;
2792 }
2793 Py_DECREF(oloop);
2794
2795 if (!blocking) {
2796 goto yield_insteadof_yf;
2797 }
2798
2799 /* result._asyncio_future_blocking = False */
2800 if (_PyObject_SetAttrId(
2801 result, &PyId__asyncio_future_blocking, Py_False) == -1) {
2802 goto fail;
2803 }
2804
2805 wrapper = TaskWakeupMethWrapper_new(task);
2806 if (wrapper == NULL) {
2807 goto fail;
2808 }
2809
2810 /* result.add_done_callback(task._wakeup) */
2811 PyObject *add_cb = _PyObject_GetAttrId(
2812 result, &PyId_add_done_callback);
2813 if (add_cb == NULL) {
2814 Py_DECREF(wrapper);
2815 goto fail;
2816 }
2817 PyObject *stack[2];
2818 stack[0] = wrapper;
2819 stack[1] = (PyObject *)task->task_context;
Jeroen Demeyeraacc77f2019-05-29 20:31:52 +02002820 res = _PyObject_Vectorcall(add_cb, stack, 1, context_kwname);
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002821 Py_DECREF(add_cb);
2822 Py_DECREF(wrapper);
2823 if (res == NULL) {
2824 goto fail;
2825 }
2826 Py_DECREF(res);
2827
2828 /* task._fut_waiter = result */
2829 task->task_fut_waiter = result; /* no incref is necessary */
2830
2831 if (task->task_must_cancel) {
2832 PyObject *r;
2833 int is_true;
2834 r = _PyObject_CallMethodId(result, &PyId_cancel, NULL);
2835 if (r == NULL) {
2836 return NULL;
2837 }
2838 is_true = PyObject_IsTrue(r);
2839 Py_DECREF(r);
2840 if (is_true < 0) {
2841 return NULL;
2842 }
2843 else if (is_true) {
2844 task->task_must_cancel = 0;
2845 }
2846 }
2847
2848 Py_RETURN_NONE;
2849 }
2850
2851 Py_XDECREF(o);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002852 /* Check if `result` is a generator */
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002853 res = PyObject_IsInstance(result, (PyObject*)&PyGen_Type);
2854 if (res < 0) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002855 goto fail;
2856 }
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002857 if (res) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002858 /* `result` is a generator */
Serhiy Storchaka66553542018-05-20 16:30:31 +03002859 o = task_set_error_soon(
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002860 task, PyExc_RuntimeError,
2861 "yield was used instead of yield from for "
Serhiy Storchaka66553542018-05-20 16:30:31 +03002862 "generator in task %R with %R", task, result);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002863 Py_DECREF(result);
Serhiy Storchaka66553542018-05-20 16:30:31 +03002864 return o;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002865 }
2866
2867 /* The `result` is none of the above */
Serhiy Storchaka66553542018-05-20 16:30:31 +03002868 o = task_set_error_soon(
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002869 task, PyExc_RuntimeError, "Task got bad yield: %R", result);
Serhiy Storchaka66553542018-05-20 16:30:31 +03002870 Py_DECREF(result);
2871 return o;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002872
2873self_await:
2874 o = task_set_error_soon(
2875 task, PyExc_RuntimeError,
2876 "Task cannot await on itself: %R", task);
2877 Py_DECREF(result);
2878 return o;
2879
2880yield_insteadof_yf:
2881 o = task_set_error_soon(
2882 task, PyExc_RuntimeError,
2883 "yield was used instead of yield from "
2884 "in task %R with %R",
2885 task, result);
2886 Py_DECREF(result);
2887 return o;
2888
2889different_loop:
2890 o = task_set_error_soon(
2891 task, PyExc_RuntimeError,
2892 "Task %R got Future %R attached to a different loop",
2893 task, result);
2894 Py_DECREF(result);
2895 return o;
2896
2897fail:
2898 Py_XDECREF(result);
2899 return NULL;
2900}
2901
2902static PyObject *
2903task_step(TaskObj *task, PyObject *exc)
2904{
2905 PyObject *res;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002906
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002907 if (enter_task(task->task_loop, (PyObject*)task) < 0) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002908 return NULL;
2909 }
2910
2911 res = task_step_impl(task, exc);
2912
2913 if (res == NULL) {
2914 PyObject *et, *ev, *tb;
2915 PyErr_Fetch(&et, &ev, &tb);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002916 leave_task(task->task_loop, (PyObject*)task);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002917 _PyErr_ChainExceptions(et, ev, tb);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002918 return NULL;
2919 }
2920 else {
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002921 if (leave_task(task->task_loop, (PyObject*)task) < 0) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002922 Py_DECREF(res);
2923 return NULL;
2924 }
2925 else {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002926 return res;
2927 }
2928 }
2929}
2930
2931static PyObject *
2932task_wakeup(TaskObj *task, PyObject *o)
2933{
Serhiy Storchakabca49392017-09-03 08:10:14 +03002934 PyObject *et, *ev, *tb;
2935 PyObject *result;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002936 assert(o);
2937
2938 if (Future_CheckExact(o) || Task_CheckExact(o)) {
2939 PyObject *fut_result = NULL;
2940 int res = future_get_result((FutureObj*)o, &fut_result);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002941
2942 switch(res) {
2943 case -1:
2944 assert(fut_result == NULL);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002945 break; /* exception raised */
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002946 case 0:
2947 Py_DECREF(fut_result);
Yury Selivanov22feeb82018-01-24 11:31:01 -05002948 return task_step(task, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002949 default:
2950 assert(res == 1);
Yury Selivanov22feeb82018-01-24 11:31:01 -05002951 result = task_step(task, fut_result);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002952 Py_DECREF(fut_result);
2953 return result;
2954 }
2955 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002956 else {
Serhiy Storchakabca49392017-09-03 08:10:14 +03002957 PyObject *fut_result = PyObject_CallMethod(o, "result", NULL);
2958 if (fut_result != NULL) {
2959 Py_DECREF(fut_result);
Yury Selivanov22feeb82018-01-24 11:31:01 -05002960 return task_step(task, NULL);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002961 }
2962 /* exception raised */
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002963 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03002964
2965 PyErr_Fetch(&et, &ev, &tb);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002966 if (!ev || !PyObject_TypeCheck(ev, (PyTypeObject *) et)) {
2967 PyErr_NormalizeException(&et, &ev, &tb);
2968 }
2969
Yury Selivanov22feeb82018-01-24 11:31:01 -05002970 result = task_step(task, ev);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002971
2972 Py_DECREF(et);
2973 Py_XDECREF(tb);
2974 Py_XDECREF(ev);
2975
2976 return result;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002977}
2978
2979
Yury Selivanova70232f2017-12-13 14:49:42 -05002980/*********************** Functions **************************/
2981
2982
2983/*[clinic input]
2984_asyncio._get_running_loop
2985
2986Return the running event loop or None.
2987
2988This is a low-level function intended to be used by event loops.
2989This function is thread-specific.
2990
2991[clinic start generated code]*/
2992
2993static PyObject *
2994_asyncio__get_running_loop_impl(PyObject *module)
2995/*[clinic end generated code: output=b4390af721411a0a input=0a21627e25a4bd43]*/
2996{
2997 PyObject *loop;
2998 if (get_running_loop(&loop)) {
2999 return NULL;
3000 }
3001 if (loop == NULL) {
3002 /* There's no currently running event loop */
3003 Py_RETURN_NONE;
3004 }
3005 return loop;
3006}
3007
3008/*[clinic input]
3009_asyncio._set_running_loop
3010 loop: 'O'
3011 /
3012
3013Set the running event loop.
3014
3015This is a low-level function intended to be used by event loops.
3016This function is thread-specific.
3017[clinic start generated code]*/
3018
3019static PyObject *
3020_asyncio__set_running_loop(PyObject *module, PyObject *loop)
3021/*[clinic end generated code: output=ae56bf7a28ca189a input=4c9720233d606604]*/
3022{
3023 if (set_running_loop(loop)) {
3024 return NULL;
3025 }
3026 Py_RETURN_NONE;
3027}
3028
3029/*[clinic input]
3030_asyncio.get_event_loop
3031
3032Return an asyncio event loop.
3033
3034When called from a coroutine or a callback (e.g. scheduled with
3035call_soon or similar API), this function will always return the
3036running event loop.
3037
3038If there is no running event loop set, the function will return
3039the result of `get_event_loop_policy().get_event_loop()` call.
3040[clinic start generated code]*/
3041
3042static PyObject *
3043_asyncio_get_event_loop_impl(PyObject *module)
3044/*[clinic end generated code: output=2a2d8b2f824c648b input=9364bf2916c8655d]*/
3045{
3046 return get_event_loop();
3047}
3048
3049/*[clinic input]
3050_asyncio.get_running_loop
3051
3052Return the running event loop. Raise a RuntimeError if there is none.
3053
3054This function is thread-specific.
3055[clinic start generated code]*/
3056
3057static PyObject *
3058_asyncio_get_running_loop_impl(PyObject *module)
3059/*[clinic end generated code: output=c247b5f9e529530e input=2a3bf02ba39f173d]*/
3060{
3061 PyObject *loop;
3062 if (get_running_loop(&loop)) {
3063 return NULL;
3064 }
3065 if (loop == NULL) {
3066 /* There's no currently running event loop */
3067 PyErr_SetString(
3068 PyExc_RuntimeError, "no running event loop");
3069 }
3070 return loop;
3071}
3072
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003073/*[clinic input]
3074_asyncio._register_task
3075
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003076 task: object
3077
3078Register a new task in asyncio as executed by loop.
3079
3080Returns None.
3081[clinic start generated code]*/
3082
3083static PyObject *
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003084_asyncio__register_task_impl(PyObject *module, PyObject *task)
3085/*[clinic end generated code: output=8672dadd69a7d4e2 input=21075aaea14dfbad]*/
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003086{
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003087 if (register_task(task) < 0) {
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003088 return NULL;
3089 }
3090 Py_RETURN_NONE;
3091}
3092
3093
3094/*[clinic input]
3095_asyncio._unregister_task
3096
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003097 task: object
3098
3099Unregister a task.
3100
3101Returns None.
3102[clinic start generated code]*/
3103
3104static PyObject *
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003105_asyncio__unregister_task_impl(PyObject *module, PyObject *task)
3106/*[clinic end generated code: output=6e5585706d568a46 input=28fb98c3975f7bdc]*/
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003107{
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003108 if (unregister_task(task) < 0) {
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003109 return NULL;
3110 }
3111 Py_RETURN_NONE;
3112}
3113
3114
3115/*[clinic input]
3116_asyncio._enter_task
3117
3118 loop: object
3119 task: object
3120
3121Enter into task execution or resume suspended task.
3122
3123Task belongs to loop.
3124
3125Returns None.
3126[clinic start generated code]*/
3127
3128static PyObject *
3129_asyncio__enter_task_impl(PyObject *module, PyObject *loop, PyObject *task)
3130/*[clinic end generated code: output=a22611c858035b73 input=de1b06dca70d8737]*/
3131{
3132 if (enter_task(loop, task) < 0) {
3133 return NULL;
3134 }
3135 Py_RETURN_NONE;
3136}
3137
3138
3139/*[clinic input]
3140_asyncio._leave_task
3141
3142 loop: object
3143 task: object
3144
3145Leave task execution or suspend a task.
3146
3147Task belongs to loop.
3148
3149Returns None.
3150[clinic start generated code]*/
3151
3152static PyObject *
3153_asyncio__leave_task_impl(PyObject *module, PyObject *loop, PyObject *task)
3154/*[clinic end generated code: output=0ebf6db4b858fb41 input=51296a46313d1ad8]*/
3155{
3156 if (leave_task(loop, task) < 0) {
3157 return NULL;
3158 }
3159 Py_RETURN_NONE;
3160}
3161
Yury Selivanova70232f2017-12-13 14:49:42 -05003162
Yury Selivanov9d411c12018-01-23 15:10:03 -05003163/*********************** PyRunningLoopHolder ********************/
3164
3165
3166static PyRunningLoopHolder *
3167new_running_loop_holder(PyObject *loop)
3168{
3169 PyRunningLoopHolder *rl = PyObject_New(
3170 PyRunningLoopHolder, &PyRunningLoopHolder_Type);
3171 if (rl == NULL) {
3172 return NULL;
3173 }
3174
3175#if defined(HAVE_GETPID) && !defined(MS_WINDOWS)
3176 rl->rl_pid = getpid();
3177#endif
3178
3179 Py_INCREF(loop);
3180 rl->rl_loop = loop;
3181
3182 return rl;
3183}
3184
3185
3186static void
3187PyRunningLoopHolder_tp_dealloc(PyRunningLoopHolder *rl)
3188{
3189 Py_CLEAR(rl->rl_loop);
3190 PyObject_Free(rl);
3191}
3192
3193
3194static PyTypeObject PyRunningLoopHolder_Type = {
3195 PyVarObject_HEAD_INIT(NULL, 0)
3196 "_RunningLoopHolder",
3197 sizeof(PyRunningLoopHolder),
3198 .tp_getattro = PyObject_GenericGetAttr,
3199 .tp_flags = Py_TPFLAGS_DEFAULT,
3200 .tp_dealloc = (destructor)PyRunningLoopHolder_tp_dealloc,
3201};
3202
3203
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003204/*********************** Module **************************/
3205
3206
3207static void
Zackery Spytze40ad792017-12-19 11:48:13 -07003208module_free_freelists(void)
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05003209{
3210 PyObject *next;
3211 PyObject *current;
3212
3213 next = (PyObject*) fi_freelist;
3214 while (next != NULL) {
3215 assert(fi_freelist_len > 0);
3216 fi_freelist_len--;
3217
3218 current = next;
3219 next = (PyObject*) ((futureiterobject*) current)->future;
3220 PyObject_GC_Del(current);
3221 }
3222 assert(fi_freelist_len == 0);
3223 fi_freelist = NULL;
3224}
3225
3226
3227static void
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003228module_free(void *m)
3229{
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003230 Py_CLEAR(asyncio_mod);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003231 Py_CLEAR(traceback_extract_stack);
3232 Py_CLEAR(asyncio_future_repr_info_func);
3233 Py_CLEAR(asyncio_get_event_loop_policy);
3234 Py_CLEAR(asyncio_iscoroutine_func);
3235 Py_CLEAR(asyncio_task_get_stack_func);
3236 Py_CLEAR(asyncio_task_print_stack_func);
3237 Py_CLEAR(asyncio_task_repr_info_func);
3238 Py_CLEAR(asyncio_InvalidStateError);
3239 Py_CLEAR(asyncio_CancelledError);
3240
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003241 Py_CLEAR(all_tasks);
Yury Selivanova9d7e552017-12-19 07:18:45 -05003242 Py_CLEAR(current_tasks);
3243 Py_CLEAR(iscoroutine_typecache);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05003244
Yury Selivanovf23746a2018-01-22 19:11:18 -05003245 Py_CLEAR(context_kwname);
3246
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05003247 module_free_freelists();
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003248}
3249
3250static int
3251module_init(void)
3252{
3253 PyObject *module = NULL;
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003254
3255 asyncio_mod = PyImport_ImportModule("asyncio");
3256 if (asyncio_mod == NULL) {
3257 goto fail;
3258 }
Miss Islington (bot)13915a32019-10-07 09:38:00 -07003259 if (module_initialized != 0) {
3260 return 0;
3261 }
3262 else {
3263 module_initialized = 1;
3264 }
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003265
3266 current_tasks = PyDict_New();
3267 if (current_tasks == NULL) {
3268 goto fail;
3269 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003270
Yury Selivanova9d7e552017-12-19 07:18:45 -05003271 iscoroutine_typecache = PySet_New(NULL);
3272 if (iscoroutine_typecache == NULL) {
3273 goto fail;
3274 }
3275
Yury Selivanovf23746a2018-01-22 19:11:18 -05003276
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03003277 context_kwname = Py_BuildValue("(s)", "context");
Yury Selivanovf23746a2018-01-22 19:11:18 -05003278 if (context_kwname == NULL) {
3279 goto fail;
3280 }
Yury Selivanovf23746a2018-01-22 19:11:18 -05003281
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003282#define WITH_MOD(NAME) \
3283 Py_CLEAR(module); \
3284 module = PyImport_ImportModule(NAME); \
3285 if (module == NULL) { \
Serhiy Storchakabca49392017-09-03 08:10:14 +03003286 goto fail; \
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003287 }
3288
3289#define GET_MOD_ATTR(VAR, NAME) \
3290 VAR = PyObject_GetAttrString(module, NAME); \
3291 if (VAR == NULL) { \
3292 goto fail; \
3293 }
3294
3295 WITH_MOD("asyncio.events")
Yury Selivanova70232f2017-12-13 14:49:42 -05003296 GET_MOD_ATTR(asyncio_get_event_loop_policy, "get_event_loop_policy")
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003297
3298 WITH_MOD("asyncio.base_futures")
3299 GET_MOD_ATTR(asyncio_future_repr_info_func, "_future_repr_info")
Andrew Svetlov0baa72f2018-09-11 10:13:04 -07003300
3301 WITH_MOD("asyncio.exceptions")
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003302 GET_MOD_ATTR(asyncio_InvalidStateError, "InvalidStateError")
3303 GET_MOD_ATTR(asyncio_CancelledError, "CancelledError")
3304
3305 WITH_MOD("asyncio.base_tasks")
3306 GET_MOD_ATTR(asyncio_task_repr_info_func, "_task_repr_info")
3307 GET_MOD_ATTR(asyncio_task_get_stack_func, "_task_get_stack")
3308 GET_MOD_ATTR(asyncio_task_print_stack_func, "_task_print_stack")
3309
Andrew Svetlovf74ef452017-12-15 07:04:38 +02003310 WITH_MOD("asyncio.coroutines")
3311 GET_MOD_ATTR(asyncio_iscoroutine_func, "iscoroutine")
3312
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003313 WITH_MOD("traceback")
3314 GET_MOD_ATTR(traceback_extract_stack, "extract_stack")
3315
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003316 PyObject *weak_set;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003317 WITH_MOD("weakref")
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003318 GET_MOD_ATTR(weak_set, "WeakSet");
3319 all_tasks = _PyObject_CallNoArg(weak_set);
3320 Py_CLEAR(weak_set);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003321 if (all_tasks == NULL) {
INADA Naokic411a7d2016-10-18 11:48:14 +09003322 goto fail;
3323 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003324
Serhiy Storchakabca49392017-09-03 08:10:14 +03003325 Py_DECREF(module);
INADA Naokic411a7d2016-10-18 11:48:14 +09003326 return 0;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003327
INADA Naokic411a7d2016-10-18 11:48:14 +09003328fail:
INADA Naokic411a7d2016-10-18 11:48:14 +09003329 Py_CLEAR(module);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003330 module_free(NULL);
INADA Naokic411a7d2016-10-18 11:48:14 +09003331 return -1;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003332
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003333#undef WITH_MOD
3334#undef GET_MOD_ATTR
3335}
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003336
INADA Naokic411a7d2016-10-18 11:48:14 +09003337PyDoc_STRVAR(module_doc, "Accelerator module for asyncio");
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003338
Yury Selivanova70232f2017-12-13 14:49:42 -05003339static PyMethodDef asyncio_methods[] = {
3340 _ASYNCIO_GET_EVENT_LOOP_METHODDEF
3341 _ASYNCIO_GET_RUNNING_LOOP_METHODDEF
3342 _ASYNCIO__GET_RUNNING_LOOP_METHODDEF
3343 _ASYNCIO__SET_RUNNING_LOOP_METHODDEF
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003344 _ASYNCIO__REGISTER_TASK_METHODDEF
3345 _ASYNCIO__UNREGISTER_TASK_METHODDEF
3346 _ASYNCIO__ENTER_TASK_METHODDEF
3347 _ASYNCIO__LEAVE_TASK_METHODDEF
Yury Selivanova70232f2017-12-13 14:49:42 -05003348 {NULL, NULL}
3349};
3350
INADA Naoki9f2ce252016-10-15 15:39:19 +09003351static struct PyModuleDef _asynciomodule = {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003352 PyModuleDef_HEAD_INIT, /* m_base */
INADA Naoki9f2ce252016-10-15 15:39:19 +09003353 "_asyncio", /* m_name */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003354 module_doc, /* m_doc */
3355 -1, /* m_size */
Yury Selivanova70232f2017-12-13 14:49:42 -05003356 asyncio_methods, /* m_methods */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003357 NULL, /* m_slots */
3358 NULL, /* m_traverse */
3359 NULL, /* m_clear */
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003360 (freefunc)module_free /* m_free */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003361};
3362
3363
3364PyMODINIT_FUNC
INADA Naoki9f2ce252016-10-15 15:39:19 +09003365PyInit__asyncio(void)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003366{
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003367 if (module_init() < 0) {
INADA Naokic411a7d2016-10-18 11:48:14 +09003368 return NULL;
3369 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003370 if (PyType_Ready(&FutureType) < 0) {
3371 return NULL;
3372 }
3373 if (PyType_Ready(&FutureIterType) < 0) {
3374 return NULL;
3375 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03003376 if (PyType_Ready(&TaskStepMethWrapper_Type) < 0) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003377 return NULL;
3378 }
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03003379 if (PyType_Ready(&TaskWakeupMethWrapper_Type) < 0) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003380 return NULL;
3381 }
3382 if (PyType_Ready(&TaskType) < 0) {
3383 return NULL;
3384 }
Yury Selivanov9d411c12018-01-23 15:10:03 -05003385 if (PyType_Ready(&PyRunningLoopHolder_Type) < 0) {
3386 return NULL;
3387 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003388
INADA Naoki9f2ce252016-10-15 15:39:19 +09003389 PyObject *m = PyModule_Create(&_asynciomodule);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003390 if (m == NULL) {
3391 return NULL;
3392 }
3393
3394 Py_INCREF(&FutureType);
3395 if (PyModule_AddObject(m, "Future", (PyObject *)&FutureType) < 0) {
3396 Py_DECREF(&FutureType);
3397 return NULL;
3398 }
3399
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003400 Py_INCREF(&TaskType);
3401 if (PyModule_AddObject(m, "Task", (PyObject *)&TaskType) < 0) {
3402 Py_DECREF(&TaskType);
3403 return NULL;
3404 }
3405
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003406 Py_INCREF(all_tasks);
3407 if (PyModule_AddObject(m, "_all_tasks", all_tasks) < 0) {
3408 Py_DECREF(all_tasks);
3409 return NULL;
3410 }
3411
3412 Py_INCREF(current_tasks);
3413 if (PyModule_AddObject(m, "_current_tasks", current_tasks) < 0) {
3414 Py_DECREF(current_tasks);
3415 return NULL;
3416 }
3417
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003418 return m;
3419}