blob: 4caf3a466469eb3abaef3bfe31c6ac331b5c7e59 [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;
Andrew Svetlov44d1a592017-12-16 21:58:38 +020036
Yury Selivanov9d411c12018-01-23 15:10:03 -050037static PyObject *cached_running_holder;
38static volatile uint64_t cached_running_holder_tsid;
39
Alex Grönholmcca4eec2018-08-09 00:06:47 +030040/* Counter for autogenerated Task names */
41static uint64_t task_name_counter = 0;
Andrew Svetlov44d1a592017-12-16 21:58:38 +020042
Yury Selivanovca9b36c2017-12-23 15:04:15 -050043/* WeakSet containing all alive tasks. */
44static PyObject *all_tasks;
Andrew Svetlov44d1a592017-12-16 21:58:38 +020045
46/* Dictionary containing tasks that are currently active in
47 all running event loops. {EventLoop: Task} */
Yury Selivanovca9b36c2017-12-23 15:04:15 -050048static PyObject *current_tasks;
INADA Naoki9e4e38e2016-10-09 14:44:47 +090049
Yury Selivanova9d7e552017-12-19 07:18:45 -050050/* An isinstance type cache for the 'is_coroutine()' function. */
51static PyObject *iscoroutine_typecache;
52
INADA Naoki9e4e38e2016-10-09 14:44:47 +090053
INADA Naoki9e4e38e2016-10-09 14:44:47 +090054typedef enum {
55 STATE_PENDING,
56 STATE_CANCELLED,
57 STATE_FINISHED
58} fut_state;
59
Yury Selivanova0c1ba62016-10-28 12:52:37 -040060#define FutureObj_HEAD(prefix) \
61 PyObject_HEAD \
62 PyObject *prefix##_loop; \
Yury Selivanov1b7c11f2017-12-17 20:19:47 -050063 PyObject *prefix##_callback0; \
Yury Selivanov994269c2018-09-27 14:55:55 -040064 PyObject *prefix##_context0; \
Yury Selivanova0c1ba62016-10-28 12:52:37 -040065 PyObject *prefix##_callbacks; \
66 PyObject *prefix##_exception; \
67 PyObject *prefix##_result; \
68 PyObject *prefix##_source_tb; \
69 fut_state prefix##_state; \
70 int prefix##_log_tb; \
71 int prefix##_blocking; \
72 PyObject *dict; \
73 PyObject *prefix##_weakreflist;
74
75typedef struct {
76 FutureObj_HEAD(fut)
77} FutureObj;
78
79typedef struct {
80 FutureObj_HEAD(task)
81 PyObject *task_fut_waiter;
82 PyObject *task_coro;
Alex Grönholmcca4eec2018-08-09 00:06:47 +030083 PyObject *task_name;
Yury Selivanov994269c2018-09-27 14:55:55 -040084 PyObject *task_context;
Yury Selivanova0c1ba62016-10-28 12:52:37 -040085 int task_must_cancel;
86 int task_log_destroy_pending;
87} TaskObj;
INADA Naoki9e4e38e2016-10-09 14:44:47 +090088
89typedef struct {
90 PyObject_HEAD
Yury Selivanova0c1ba62016-10-28 12:52:37 -040091 TaskObj *sw_task;
92 PyObject *sw_arg;
Serhiy Storchakabca49392017-09-03 08:10:14 +030093} TaskStepMethWrapper;
INADA Naoki9e4e38e2016-10-09 14:44:47 +090094
Yury Selivanova0c1ba62016-10-28 12:52:37 -040095typedef struct {
96 PyObject_HEAD
97 TaskObj *ww_task;
98} TaskWakeupMethWrapper;
99
Yury Selivanov9d411c12018-01-23 15:10:03 -0500100typedef struct {
101 PyObject_HEAD
102 PyObject *rl_loop;
103#if defined(HAVE_GETPID) && !defined(MS_WINDOWS)
104 pid_t rl_pid;
105#endif
106} PyRunningLoopHolder;
107
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400108
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500109static PyTypeObject FutureType;
110static PyTypeObject TaskType;
Yury Selivanov9d411c12018-01-23 15:10:03 -0500111static PyTypeObject PyRunningLoopHolder_Type;
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500112
113
114#define Future_CheckExact(obj) (Py_TYPE(obj) == &FutureType)
115#define Task_CheckExact(obj) (Py_TYPE(obj) == &TaskType)
116
117#define Future_Check(obj) PyObject_TypeCheck(obj, &FutureType)
118#define Task_Check(obj) PyObject_TypeCheck(obj, &TaskType)
119
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400120#include "clinic/_asynciomodule.c.h"
121
122
123/*[clinic input]
124class _asyncio.Future "FutureObj *" "&Future_Type"
125[clinic start generated code]*/
126/*[clinic end generated code: output=da39a3ee5e6b4b0d input=00d3e4abca711e0f]*/
127
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500128
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400129/* Get FutureIter from Future */
Yury Selivanov9d411c12018-01-23 15:10:03 -0500130static PyObject * future_new_iter(PyObject *);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900131
Yury Selivanov9d411c12018-01-23 15:10:03 -0500132static PyRunningLoopHolder * new_running_loop_holder(PyObject *);
133
Yury Selivanova70232f2017-12-13 14:49:42 -0500134
135static int
Yury Selivanova9d7e552017-12-19 07:18:45 -0500136_is_coroutine(PyObject *coro)
137{
138 /* 'coro' is not a native coroutine, call asyncio.iscoroutine()
139 to check if it's another coroutine flavour.
140
141 Do this check after 'future_init()'; in case we need to raise
142 an error, __del__ needs a properly initialized object.
143 */
144 PyObject *res = PyObject_CallFunctionObjArgs(
145 asyncio_iscoroutine_func, coro, NULL);
146 if (res == NULL) {
147 return -1;
148 }
149
150 int is_res_true = PyObject_IsTrue(res);
151 Py_DECREF(res);
152 if (is_res_true <= 0) {
153 return is_res_true;
154 }
155
Andrew Svetlov0f47fa22017-12-23 22:06:46 +0200156 if (PySet_GET_SIZE(iscoroutine_typecache) < 100) {
Yury Selivanova9d7e552017-12-19 07:18:45 -0500157 /* Just in case we don't want to cache more than 100
158 positive types. That shouldn't ever happen, unless
159 someone stressing the system on purpose.
160 */
161 if (PySet_Add(iscoroutine_typecache, (PyObject*) Py_TYPE(coro))) {
162 return -1;
163 }
164 }
165
166 return 1;
167}
168
169
170static inline int
171is_coroutine(PyObject *coro)
172{
173 if (PyCoro_CheckExact(coro)) {
174 return 1;
175 }
176
177 /* Check if `type(coro)` is in the cache.
178 Caching makes is_coroutine() function almost as fast as
179 PyCoro_CheckExact() for non-native coroutine-like objects
180 (like coroutines compiled with Cython).
181
182 asyncio.iscoroutine() has its own type caching mechanism.
183 This cache allows us to avoid the cost of even calling
184 a pure-Python function in 99.9% cases.
185 */
186 int has_it = PySet_Contains(
187 iscoroutine_typecache, (PyObject*) Py_TYPE(coro));
188 if (has_it == 0) {
189 /* type(coro) is not in iscoroutine_typecache */
190 return _is_coroutine(coro);
191 }
192
Leo Ariasc3d95082018-02-03 18:36:10 -0600193 /* either an error has occurred or
Yury Selivanova9d7e552017-12-19 07:18:45 -0500194 type(coro) is in iscoroutine_typecache
195 */
196 return has_it;
197}
198
199
Yury Selivanovca9b36c2017-12-23 15:04:15 -0500200static PyObject *
201get_future_loop(PyObject *fut)
202{
203 /* Implementation of `asyncio.futures._get_loop` */
204
205 _Py_IDENTIFIER(get_loop);
206 _Py_IDENTIFIER(_loop);
Serhiy Storchaka66553542018-05-20 16:30:31 +0300207 PyObject *getloop;
Yury Selivanovca9b36c2017-12-23 15:04:15 -0500208
209 if (Future_CheckExact(fut) || Task_CheckExact(fut)) {
210 PyObject *loop = ((FutureObj *)fut)->fut_loop;
211 Py_INCREF(loop);
212 return loop;
213 }
214
Serhiy Storchaka66553542018-05-20 16:30:31 +0300215 if (_PyObject_LookupAttrId(fut, &PyId_get_loop, &getloop) < 0) {
216 return NULL;
217 }
Yury Selivanovca9b36c2017-12-23 15:04:15 -0500218 if (getloop != NULL) {
Victor Stinner2ff58a22019-06-17 14:27:23 +0200219 PyObject *res = PyObject_CallNoArgs(getloop);
Yury Selivanovca9b36c2017-12-23 15:04:15 -0500220 Py_DECREF(getloop);
221 return res;
222 }
223
224 return _PyObject_GetAttrId(fut, &PyId__loop);
225}
226
227
Yury Selivanova9d7e552017-12-19 07:18:45 -0500228static int
Yury Selivanova70232f2017-12-13 14:49:42 -0500229get_running_loop(PyObject **loop)
230{
Yury Selivanov9d411c12018-01-23 15:10:03 -0500231 PyObject *rl;
Yury Selivanova70232f2017-12-13 14:49:42 -0500232
Yury Selivanov9d411c12018-01-23 15:10:03 -0500233 PyThreadState *ts = PyThreadState_Get();
234 if (ts->id == cached_running_holder_tsid && cached_running_holder != NULL) {
235 // Fast path, check the cache.
236 rl = cached_running_holder; // borrowed
237 }
238 else {
239 if (ts->dict == NULL) {
240 goto not_found;
241 }
242
243 rl = _PyDict_GetItemIdWithError(
244 ts->dict, &PyId___asyncio_running_event_loop__); // borrowed
245 if (rl == NULL) {
246 if (PyErr_Occurred()) {
247 goto error;
248 }
249 else {
250 goto not_found;
251 }
252 }
253
254 cached_running_holder = rl; // borrowed
255 cached_running_holder_tsid = ts->id;
Yury Selivanova70232f2017-12-13 14:49:42 -0500256 }
257
Yury Selivanov9d411c12018-01-23 15:10:03 -0500258 assert(Py_TYPE(rl) == &PyRunningLoopHolder_Type);
259 PyObject *running_loop = ((PyRunningLoopHolder *)rl)->rl_loop;
Yury Selivanova70232f2017-12-13 14:49:42 -0500260
261 if (running_loop == Py_None) {
262 goto not_found;
263 }
264
Yury Selivanov9d411c12018-01-23 15:10:03 -0500265#if defined(HAVE_GETPID) && !defined(MS_WINDOWS)
266 /* On Windows there is no getpid, but there is also no os.fork(),
267 so there is no need for this check.
268 */
269 if (getpid() != ((PyRunningLoopHolder *)rl)->rl_pid) {
270 goto not_found;
Yury Selivanova70232f2017-12-13 14:49:42 -0500271 }
Yury Selivanov9d411c12018-01-23 15:10:03 -0500272#endif
Yury Selivanova70232f2017-12-13 14:49:42 -0500273
Yury Selivanov9d411c12018-01-23 15:10:03 -0500274 Py_INCREF(running_loop);
275 *loop = running_loop;
276 return 0;
Yury Selivanova70232f2017-12-13 14:49:42 -0500277
278not_found:
279 *loop = NULL;
280 return 0;
281
Yury Selivanova70232f2017-12-13 14:49:42 -0500282error:
283 *loop = NULL;
284 return -1;
285}
286
287
288static int
289set_running_loop(PyObject *loop)
290{
Yury Selivanov9d411c12018-01-23 15:10:03 -0500291 cached_running_holder = NULL;
292 cached_running_holder_tsid = 0;
Yury Selivanova70232f2017-12-13 14:49:42 -0500293
Yury Selivanov9d411c12018-01-23 15:10:03 -0500294 PyObject *ts_dict = PyThreadState_GetDict(); // borrowed
Yury Selivanova70232f2017-12-13 14:49:42 -0500295 if (ts_dict == NULL) {
296 PyErr_SetString(
297 PyExc_RuntimeError, "thread-local storage is not available");
298 return -1;
299 }
300
Yury Selivanov9d411c12018-01-23 15:10:03 -0500301 PyRunningLoopHolder *rl = new_running_loop_holder(loop);
302 if (rl == NULL) {
Yury Selivanova70232f2017-12-13 14:49:42 -0500303 return -1;
304 }
305
Yury Selivanova70232f2017-12-13 14:49:42 -0500306 if (_PyDict_SetItemId(
Yury Selivanov9d411c12018-01-23 15:10:03 -0500307 ts_dict, &PyId___asyncio_running_event_loop__, (PyObject *)rl) < 0)
308 {
309 Py_DECREF(rl); // will cleanup loop & current_pid
Yury Selivanova70232f2017-12-13 14:49:42 -0500310 return -1;
311 }
Yury Selivanov9d411c12018-01-23 15:10:03 -0500312 Py_DECREF(rl);
Yury Selivanova70232f2017-12-13 14:49:42 -0500313
314 return 0;
315}
316
317
318static PyObject *
319get_event_loop(void)
320{
321 PyObject *loop;
322 PyObject *policy;
323
324 if (get_running_loop(&loop)) {
325 return NULL;
326 }
327 if (loop != NULL) {
328 return loop;
329 }
330
Victor Stinner2ff58a22019-06-17 14:27:23 +0200331 policy = PyObject_CallNoArgs(asyncio_get_event_loop_policy);
Yury Selivanova70232f2017-12-13 14:49:42 -0500332 if (policy == NULL) {
333 return NULL;
334 }
335
336 loop = _PyObject_CallMethodId(policy, &PyId_get_event_loop, NULL);
337 Py_DECREF(policy);
338 return loop;
339}
340
341
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900342static int
Yury Selivanov994269c2018-09-27 14:55:55 -0400343call_soon(PyObject *loop, PyObject *func, PyObject *arg, PyObject *ctx)
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500344{
345 PyObject *handle;
Yury Selivanovf23746a2018-01-22 19:11:18 -0500346 PyObject *stack[3];
347 Py_ssize_t nargs;
348
349 if (ctx == NULL) {
350 handle = _PyObject_CallMethodIdObjArgs(
351 loop, &PyId_call_soon, func, arg, NULL);
352 }
353 else {
354 /* Use FASTCALL to pass a keyword-only argument to call_soon */
355
356 PyObject *callable = _PyObject_GetAttrId(loop, &PyId_call_soon);
357 if (callable == NULL) {
358 return -1;
359 }
360
361 /* All refs in 'stack' are borrowed. */
362 nargs = 1;
363 stack[0] = func;
364 if (arg != NULL) {
365 stack[1] = arg;
366 nargs++;
367 }
368 stack[nargs] = (PyObject *)ctx;
369
Jeroen Demeyeraacc77f2019-05-29 20:31:52 +0200370 handle = _PyObject_Vectorcall(callable, stack, nargs, context_kwname);
Yury Selivanovf23746a2018-01-22 19:11:18 -0500371 Py_DECREF(callable);
372 }
373
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500374 if (handle == NULL) {
375 return -1;
376 }
377 Py_DECREF(handle);
378 return 0;
379}
380
381
382static inline int
383future_is_alive(FutureObj *fut)
384{
385 return fut->fut_loop != NULL;
386}
387
388
389static inline int
390future_ensure_alive(FutureObj *fut)
391{
392 if (!future_is_alive(fut)) {
393 PyErr_SetString(PyExc_RuntimeError,
394 "Future object is not initialized.");
395 return -1;
396 }
397 return 0;
398}
399
400
401#define ENSURE_FUTURE_ALIVE(fut) \
402 do { \
403 assert(Future_Check(fut) || Task_Check(fut)); \
404 if (future_ensure_alive((FutureObj*)fut)) { \
405 return NULL; \
406 } \
407 } while(0);
408
409
410static int
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400411future_schedule_callbacks(FutureObj *fut)
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900412{
413 Py_ssize_t len;
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500414 Py_ssize_t i;
415
416 if (fut->fut_callback0 != NULL) {
417 /* There's a 1st callback */
418
419 int ret = call_soon(
Yury Selivanovf23746a2018-01-22 19:11:18 -0500420 fut->fut_loop, fut->fut_callback0,
421 (PyObject *)fut, fut->fut_context0);
422
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500423 Py_CLEAR(fut->fut_callback0);
Yury Selivanovf23746a2018-01-22 19:11:18 -0500424 Py_CLEAR(fut->fut_context0);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500425 if (ret) {
426 /* If an error occurs in pure-Python implementation,
427 all callbacks are cleared. */
428 Py_CLEAR(fut->fut_callbacks);
429 return ret;
430 }
431
432 /* we called the first callback, now try calling
433 callbacks from the 'fut_callbacks' list. */
434 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900435
436 if (fut->fut_callbacks == NULL) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500437 /* No more callbacks, return. */
438 return 0;
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900439 }
440
441 len = PyList_GET_SIZE(fut->fut_callbacks);
442 if (len == 0) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500443 /* The list of callbacks was empty; clear it and return. */
444 Py_CLEAR(fut->fut_callbacks);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900445 return 0;
446 }
447
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900448 for (i = 0; i < len; i++) {
Yury Selivanovf23746a2018-01-22 19:11:18 -0500449 PyObject *cb_tup = PyList_GET_ITEM(fut->fut_callbacks, i);
450 PyObject *cb = PyTuple_GET_ITEM(cb_tup, 0);
451 PyObject *ctx = PyTuple_GET_ITEM(cb_tup, 1);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900452
Yury Selivanov994269c2018-09-27 14:55:55 -0400453 if (call_soon(fut->fut_loop, cb, (PyObject *)fut, ctx)) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500454 /* If an error occurs in pure-Python implementation,
455 all callbacks are cleared. */
456 Py_CLEAR(fut->fut_callbacks);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900457 return -1;
458 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900459 }
460
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500461 Py_CLEAR(fut->fut_callbacks);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900462 return 0;
463}
464
Oren Milmand019bc82018-02-13 12:28:33 +0200465
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900466static int
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400467future_init(FutureObj *fut, PyObject *loop)
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900468{
Serhiy Storchakabca49392017-09-03 08:10:14 +0300469 PyObject *res;
470 int is_true;
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900471 _Py_IDENTIFIER(get_debug);
472
Oren Milmand019bc82018-02-13 12:28:33 +0200473 // Same to FutureObj_clear() but not clearing fut->dict
474 Py_CLEAR(fut->fut_loop);
475 Py_CLEAR(fut->fut_callback0);
476 Py_CLEAR(fut->fut_context0);
477 Py_CLEAR(fut->fut_callbacks);
478 Py_CLEAR(fut->fut_result);
479 Py_CLEAR(fut->fut_exception);
480 Py_CLEAR(fut->fut_source_tb);
481
482 fut->fut_state = STATE_PENDING;
483 fut->fut_log_tb = 0;
484 fut->fut_blocking = 0;
485
Serhiy Storchakabca49392017-09-03 08:10:14 +0300486 if (loop == Py_None) {
Yury Selivanova70232f2017-12-13 14:49:42 -0500487 loop = get_event_loop();
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900488 if (loop == NULL) {
489 return -1;
490 }
491 }
492 else {
493 Py_INCREF(loop);
494 }
Oren Milmand019bc82018-02-13 12:28:33 +0200495 fut->fut_loop = loop;
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900496
Victor Stinnerf94d1ee2016-10-29 09:05:39 +0200497 res = _PyObject_CallMethodId(fut->fut_loop, &PyId_get_debug, NULL);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900498 if (res == NULL) {
499 return -1;
500 }
Serhiy Storchakabca49392017-09-03 08:10:14 +0300501 is_true = PyObject_IsTrue(res);
502 Py_DECREF(res);
503 if (is_true < 0) {
504 return -1;
505 }
Yury Selivanov35230d02018-05-28 11:11:31 -0400506 if (is_true && !_Py_IsFinalizing()) {
507 /* Only try to capture the traceback if the interpreter is not being
508 finalized. The original motivation to add a `_Py_IsFinalizing()`
509 call was to prevent SIGSEGV when a Future is created in a __del__
510 method, which is called during the interpreter shutdown and the
511 traceback module is already unloaded.
512 */
Victor Stinner2ff58a22019-06-17 14:27:23 +0200513 fut->fut_source_tb = PyObject_CallNoArgs(traceback_extract_stack);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900514 if (fut->fut_source_tb == NULL) {
515 return -1;
516 }
517 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900518
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900519 return 0;
520}
521
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900522static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400523future_set_result(FutureObj *fut, PyObject *res)
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900524{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500525 if (future_ensure_alive(fut)) {
526 return NULL;
527 }
528
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900529 if (fut->fut_state != STATE_PENDING) {
530 PyErr_SetString(asyncio_InvalidStateError, "invalid state");
531 return NULL;
532 }
533
Serhiy Storchakabca49392017-09-03 08:10:14 +0300534 assert(!fut->fut_result);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900535 Py_INCREF(res);
536 fut->fut_result = res;
537 fut->fut_state = STATE_FINISHED;
538
Yury Selivanov22feeb82018-01-24 11:31:01 -0500539 if (future_schedule_callbacks(fut) == -1) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900540 return NULL;
541 }
542 Py_RETURN_NONE;
543}
544
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900545static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400546future_set_exception(FutureObj *fut, PyObject *exc)
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900547{
548 PyObject *exc_val = NULL;
549
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900550 if (fut->fut_state != STATE_PENDING) {
551 PyErr_SetString(asyncio_InvalidStateError, "invalid state");
552 return NULL;
553 }
554
555 if (PyExceptionClass_Check(exc)) {
Victor Stinner2ff58a22019-06-17 14:27:23 +0200556 exc_val = PyObject_CallNoArgs(exc);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900557 if (exc_val == NULL) {
558 return NULL;
559 }
Serhiy Storchakabca49392017-09-03 08:10:14 +0300560 if (fut->fut_state != STATE_PENDING) {
561 Py_DECREF(exc_val);
562 PyErr_SetString(asyncio_InvalidStateError, "invalid state");
563 return NULL;
564 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900565 }
566 else {
567 exc_val = exc;
568 Py_INCREF(exc_val);
569 }
570 if (!PyExceptionInstance_Check(exc_val)) {
571 Py_DECREF(exc_val);
572 PyErr_SetString(PyExc_TypeError, "invalid exception object");
573 return NULL;
574 }
575 if ((PyObject*)Py_TYPE(exc_val) == PyExc_StopIteration) {
576 Py_DECREF(exc_val);
577 PyErr_SetString(PyExc_TypeError,
578 "StopIteration interacts badly with generators "
579 "and cannot be raised into a Future");
580 return NULL;
581 }
582
Serhiy Storchakabca49392017-09-03 08:10:14 +0300583 assert(!fut->fut_exception);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900584 fut->fut_exception = exc_val;
585 fut->fut_state = STATE_FINISHED;
586
Yury Selivanov22feeb82018-01-24 11:31:01 -0500587 if (future_schedule_callbacks(fut) == -1) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900588 return NULL;
589 }
590
591 fut->fut_log_tb = 1;
592 Py_RETURN_NONE;
593}
594
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400595static int
596future_get_result(FutureObj *fut, PyObject **result)
597{
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400598 if (fut->fut_state == STATE_CANCELLED) {
Serhiy Storchakabca49392017-09-03 08:10:14 +0300599 PyErr_SetNone(asyncio_CancelledError);
600 return -1;
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400601 }
602
603 if (fut->fut_state != STATE_FINISHED) {
Serhiy Storchakabca49392017-09-03 08:10:14 +0300604 PyErr_SetString(asyncio_InvalidStateError, "Result is not set.");
605 return -1;
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400606 }
607
608 fut->fut_log_tb = 0;
609 if (fut->fut_exception != NULL) {
610 Py_INCREF(fut->fut_exception);
611 *result = fut->fut_exception;
612 return 1;
613 }
614
615 Py_INCREF(fut->fut_result);
616 *result = fut->fut_result;
617 return 0;
618}
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900619
620static PyObject *
Yury Selivanov994269c2018-09-27 14:55:55 -0400621future_add_done_callback(FutureObj *fut, PyObject *arg, PyObject *ctx)
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900622{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500623 if (!future_is_alive(fut)) {
624 PyErr_SetString(PyExc_RuntimeError, "uninitialized Future object");
625 return NULL;
626 }
627
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900628 if (fut->fut_state != STATE_PENDING) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500629 /* The future is done/cancelled, so schedule the callback
630 right away. */
Yury Selivanovf23746a2018-01-22 19:11:18 -0500631 if (call_soon(fut->fut_loop, arg, (PyObject*) fut, ctx)) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900632 return NULL;
633 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900634 }
635 else {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500636 /* The future is pending, add a callback.
637
638 Callbacks in the future object are stored as follows:
639
640 callback0 -- a pointer to the first callback
641 callbacks -- a list of 2nd, 3rd, ... callbacks
642
643 Invariants:
644
645 * callbacks != NULL:
646 There are some callbacks in in the list. Just
647 add the new callback to it.
648
649 * callbacks == NULL and callback0 == NULL:
650 This is the first callback. Set it to callback0.
651
652 * callbacks == NULL and callback0 != NULL:
653 This is a second callback. Initialize callbacks
654 with a new list and add the new callback to it.
655 */
656
Yury Selivanovf23746a2018-01-22 19:11:18 -0500657 if (fut->fut_callbacks == NULL && fut->fut_callback0 == NULL) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500658 Py_INCREF(arg);
659 fut->fut_callback0 = arg;
Yury Selivanovf23746a2018-01-22 19:11:18 -0500660 Py_INCREF(ctx);
661 fut->fut_context0 = ctx;
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500662 }
663 else {
Yury Selivanovf23746a2018-01-22 19:11:18 -0500664 PyObject *tup = PyTuple_New(2);
665 if (tup == NULL) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500666 return NULL;
667 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500668 Py_INCREF(arg);
Yury Selivanovf23746a2018-01-22 19:11:18 -0500669 PyTuple_SET_ITEM(tup, 0, arg);
670 Py_INCREF(ctx);
671 PyTuple_SET_ITEM(tup, 1, (PyObject *)ctx);
672
673 if (fut->fut_callbacks != NULL) {
674 int err = PyList_Append(fut->fut_callbacks, tup);
675 if (err) {
676 Py_DECREF(tup);
677 return NULL;
678 }
679 Py_DECREF(tup);
680 }
681 else {
682 fut->fut_callbacks = PyList_New(1);
683 if (fut->fut_callbacks == NULL) {
684 return NULL;
685 }
686
687 PyList_SET_ITEM(fut->fut_callbacks, 0, tup); /* borrow */
688 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900689 }
690 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500691
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900692 Py_RETURN_NONE;
693}
694
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400695static PyObject *
696future_cancel(FutureObj *fut)
697{
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +0000698 fut->fut_log_tb = 0;
699
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400700 if (fut->fut_state != STATE_PENDING) {
701 Py_RETURN_FALSE;
702 }
703 fut->fut_state = STATE_CANCELLED;
704
Yury Selivanov22feeb82018-01-24 11:31:01 -0500705 if (future_schedule_callbacks(fut) == -1) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400706 return NULL;
707 }
708
709 Py_RETURN_TRUE;
710}
711
712/*[clinic input]
713_asyncio.Future.__init__
714
715 *
Serhiy Storchakabca49392017-09-03 08:10:14 +0300716 loop: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400717
718This class is *almost* compatible with concurrent.futures.Future.
719
720 Differences:
721
722 - result() and exception() do not take a timeout argument and
723 raise an exception when the future isn't done yet.
724
725 - Callbacks registered with add_done_callback() are always called
726 via the event loop's call_soon_threadsafe().
727
728 - This class is not compatible with the wait() and as_completed()
729 methods in the concurrent.futures package.
730[clinic start generated code]*/
731
732static int
733_asyncio_Future___init___impl(FutureObj *self, PyObject *loop)
Serhiy Storchakabca49392017-09-03 08:10:14 +0300734/*[clinic end generated code: output=9ed75799eaccb5d6 input=89af317082bc0bf8]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400735
736{
737 return future_init(self, loop);
738}
739
740static int
741FutureObj_clear(FutureObj *fut)
742{
743 Py_CLEAR(fut->fut_loop);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500744 Py_CLEAR(fut->fut_callback0);
Yury Selivanovf23746a2018-01-22 19:11:18 -0500745 Py_CLEAR(fut->fut_context0);
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400746 Py_CLEAR(fut->fut_callbacks);
747 Py_CLEAR(fut->fut_result);
748 Py_CLEAR(fut->fut_exception);
749 Py_CLEAR(fut->fut_source_tb);
750 Py_CLEAR(fut->dict);
751 return 0;
752}
753
754static int
755FutureObj_traverse(FutureObj *fut, visitproc visit, void *arg)
756{
757 Py_VISIT(fut->fut_loop);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500758 Py_VISIT(fut->fut_callback0);
Yury Selivanovf23746a2018-01-22 19:11:18 -0500759 Py_VISIT(fut->fut_context0);
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400760 Py_VISIT(fut->fut_callbacks);
761 Py_VISIT(fut->fut_result);
762 Py_VISIT(fut->fut_exception);
763 Py_VISIT(fut->fut_source_tb);
764 Py_VISIT(fut->dict);
765 return 0;
766}
767
768/*[clinic input]
769_asyncio.Future.result
770
771Return the result this future represents.
772
773If the future has been cancelled, raises CancelledError. If the
774future's result isn't yet available, raises InvalidStateError. If
775the future is done and has an exception set, this exception is raised.
776[clinic start generated code]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900777
778static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400779_asyncio_Future_result_impl(FutureObj *self)
780/*[clinic end generated code: output=f35f940936a4b1e5 input=49ecf9cf5ec50dc5]*/
781{
782 PyObject *result;
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500783
784 if (!future_is_alive(self)) {
785 PyErr_SetString(asyncio_InvalidStateError,
786 "Future object is not initialized.");
787 return NULL;
788 }
789
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400790 int res = future_get_result(self, &result);
791
792 if (res == -1) {
793 return NULL;
794 }
795
796 if (res == 0) {
797 return result;
798 }
799
800 assert(res == 1);
801
802 PyErr_SetObject(PyExceptionInstance_Class(result), result);
803 Py_DECREF(result);
804 return NULL;
805}
806
807/*[clinic input]
808_asyncio.Future.exception
809
810Return the exception that was set on this future.
811
812The exception (or None if no exception was set) is returned only if
813the future is done. If the future has been cancelled, raises
814CancelledError. If the future isn't done yet, raises
815InvalidStateError.
816[clinic start generated code]*/
817
818static PyObject *
819_asyncio_Future_exception_impl(FutureObj *self)
820/*[clinic end generated code: output=88b20d4f855e0710 input=733547a70c841c68]*/
821{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500822 if (!future_is_alive(self)) {
823 PyErr_SetString(asyncio_InvalidStateError,
824 "Future object is not initialized.");
825 return NULL;
826 }
827
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400828 if (self->fut_state == STATE_CANCELLED) {
Serhiy Storchakabca49392017-09-03 08:10:14 +0300829 PyErr_SetNone(asyncio_CancelledError);
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400830 return NULL;
831 }
832
833 if (self->fut_state != STATE_FINISHED) {
Serhiy Storchakabca49392017-09-03 08:10:14 +0300834 PyErr_SetString(asyncio_InvalidStateError, "Exception is not set.");
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400835 return NULL;
836 }
837
838 if (self->fut_exception != NULL) {
839 self->fut_log_tb = 0;
840 Py_INCREF(self->fut_exception);
841 return self->fut_exception;
842 }
843
844 Py_RETURN_NONE;
845}
846
847/*[clinic input]
848_asyncio.Future.set_result
849
Yury Selivanov0cf16f92017-12-25 10:48:15 -0500850 result: object
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400851 /
852
853Mark the future done and set its result.
854
855If the future is already done when this method is called, raises
856InvalidStateError.
857[clinic start generated code]*/
858
859static PyObject *
Yury Selivanov0cf16f92017-12-25 10:48:15 -0500860_asyncio_Future_set_result(FutureObj *self, PyObject *result)
861/*[clinic end generated code: output=1ec2e6bcccd6f2ce input=8b75172c2a7b05f1]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400862{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500863 ENSURE_FUTURE_ALIVE(self)
Yury Selivanov0cf16f92017-12-25 10:48:15 -0500864 return future_set_result(self, result);
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400865}
866
867/*[clinic input]
868_asyncio.Future.set_exception
869
Serhiy Storchakabca49392017-09-03 08:10:14 +0300870 exception: object
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400871 /
872
873Mark the future done and set an exception.
874
875If the future is already done when this method is called, raises
876InvalidStateError.
877[clinic start generated code]*/
878
879static PyObject *
880_asyncio_Future_set_exception(FutureObj *self, PyObject *exception)
Serhiy Storchakabca49392017-09-03 08:10:14 +0300881/*[clinic end generated code: output=f1c1b0cd321be360 input=e45b7d7aa71cc66d]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400882{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500883 ENSURE_FUTURE_ALIVE(self)
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400884 return future_set_exception(self, exception);
885}
886
887/*[clinic input]
888_asyncio.Future.add_done_callback
889
Serhiy Storchakabca49392017-09-03 08:10:14 +0300890 fn: object
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400891 /
Yury Selivanovf23746a2018-01-22 19:11:18 -0500892 *
893 context: object = NULL
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400894
895Add a callback to be run when the future becomes done.
896
897The callback is called with a single argument - the future object. If
898the future is already done when this is called, the callback is
899scheduled with call_soon.
900[clinic start generated code]*/
901
902static PyObject *
Yury Selivanovf23746a2018-01-22 19:11:18 -0500903_asyncio_Future_add_done_callback_impl(FutureObj *self, PyObject *fn,
904 PyObject *context)
905/*[clinic end generated code: output=7ce635bbc9554c1e input=15ab0693a96e9533]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400906{
Yury Selivanovf23746a2018-01-22 19:11:18 -0500907 if (context == NULL) {
Yury Selivanov994269c2018-09-27 14:55:55 -0400908 context = PyContext_CopyCurrent();
Yury Selivanovf23746a2018-01-22 19:11:18 -0500909 if (context == NULL) {
910 return NULL;
911 }
Yury Selivanov994269c2018-09-27 14:55:55 -0400912 PyObject *res = future_add_done_callback(self, fn, context);
Yury Selivanovf23746a2018-01-22 19:11:18 -0500913 Py_DECREF(context);
914 return res;
915 }
Yury Selivanov994269c2018-09-27 14:55:55 -0400916 return future_add_done_callback(self, fn, context);
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400917}
918
919/*[clinic input]
920_asyncio.Future.remove_done_callback
921
Serhiy Storchakabca49392017-09-03 08:10:14 +0300922 fn: object
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400923 /
924
925Remove all instances of a callback from the "call when done" list.
926
927Returns the number of callbacks removed.
928[clinic start generated code]*/
929
930static PyObject *
931_asyncio_Future_remove_done_callback(FutureObj *self, PyObject *fn)
Serhiy Storchakabca49392017-09-03 08:10:14 +0300932/*[clinic end generated code: output=5ab1fb52b24ef31f input=0a43280a149d505b]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900933{
934 PyObject *newlist;
935 Py_ssize_t len, i, j=0;
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500936 Py_ssize_t cleared_callback0 = 0;
937
938 ENSURE_FUTURE_ALIVE(self)
939
940 if (self->fut_callback0 != NULL) {
941 int cmp = PyObject_RichCompareBool(fn, self->fut_callback0, Py_EQ);
942 if (cmp == -1) {
943 return NULL;
944 }
945 if (cmp == 1) {
946 /* callback0 == fn */
947 Py_CLEAR(self->fut_callback0);
Yury Selivanovf23746a2018-01-22 19:11:18 -0500948 Py_CLEAR(self->fut_context0);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500949 cleared_callback0 = 1;
950 }
951 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900952
Serhiy Storchakabca49392017-09-03 08:10:14 +0300953 if (self->fut_callbacks == NULL) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500954 return PyLong_FromSsize_t(cleared_callback0);
Serhiy Storchakabca49392017-09-03 08:10:14 +0300955 }
956
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400957 len = PyList_GET_SIZE(self->fut_callbacks);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900958 if (len == 0) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500959 Py_CLEAR(self->fut_callbacks);
960 return PyLong_FromSsize_t(cleared_callback0);
961 }
962
963 if (len == 1) {
Yury Selivanovf23746a2018-01-22 19:11:18 -0500964 PyObject *cb_tup = PyList_GET_ITEM(self->fut_callbacks, 0);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500965 int cmp = PyObject_RichCompareBool(
Yury Selivanovf23746a2018-01-22 19:11:18 -0500966 fn, PyTuple_GET_ITEM(cb_tup, 0), Py_EQ);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500967 if (cmp == -1) {
968 return NULL;
969 }
970 if (cmp == 1) {
971 /* callbacks[0] == fn */
972 Py_CLEAR(self->fut_callbacks);
973 return PyLong_FromSsize_t(1 + cleared_callback0);
974 }
975 /* callbacks[0] != fn and len(callbacks) == 1 */
976 return PyLong_FromSsize_t(cleared_callback0);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900977 }
978
979 newlist = PyList_New(len);
980 if (newlist == NULL) {
981 return NULL;
982 }
983
Yury Selivanov84af9032017-03-02 23:46:56 -0500984 for (i = 0; i < PyList_GET_SIZE(self->fut_callbacks); i++) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900985 int ret;
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400986 PyObject *item = PyList_GET_ITEM(self->fut_callbacks, i);
Serhiy Storchakabca49392017-09-03 08:10:14 +0300987 Py_INCREF(item);
Yury Selivanovf23746a2018-01-22 19:11:18 -0500988 ret = PyObject_RichCompareBool(fn, PyTuple_GET_ITEM(item, 0), Py_EQ);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900989 if (ret == 0) {
Yury Selivanov833a3b02017-07-05 13:32:03 -0400990 if (j < len) {
Yury Selivanov833a3b02017-07-05 13:32:03 -0400991 PyList_SET_ITEM(newlist, j, item);
992 j++;
Serhiy Storchakabca49392017-09-03 08:10:14 +0300993 continue;
Yury Selivanov833a3b02017-07-05 13:32:03 -0400994 }
Serhiy Storchakabca49392017-09-03 08:10:14 +0300995 ret = PyList_Append(newlist, item);
996 }
997 Py_DECREF(item);
998 if (ret < 0) {
999 goto fail;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001000 }
1001 }
1002
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001003 if (j == 0) {
1004 Py_CLEAR(self->fut_callbacks);
1005 Py_DECREF(newlist);
1006 return PyLong_FromSsize_t(len + cleared_callback0);
1007 }
1008
Serhiy Storchakabca49392017-09-03 08:10:14 +03001009 if (j < len) {
1010 Py_SIZE(newlist) = j;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001011 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03001012 j = PyList_GET_SIZE(newlist);
1013 len = PyList_GET_SIZE(self->fut_callbacks);
1014 if (j != len) {
1015 if (PyList_SetSlice(self->fut_callbacks, 0, len, newlist) < 0) {
1016 goto fail;
1017 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001018 }
1019 Py_DECREF(newlist);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001020 return PyLong_FromSsize_t(len - j + cleared_callback0);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001021
1022fail:
1023 Py_DECREF(newlist);
1024 return NULL;
1025}
1026
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001027/*[clinic input]
1028_asyncio.Future.cancel
1029
1030Cancel the future and schedule callbacks.
1031
1032If the future is already done or cancelled, return False. Otherwise,
1033change the future's state to cancelled, schedule the callbacks and
1034return True.
1035[clinic start generated code]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001036
1037static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001038_asyncio_Future_cancel_impl(FutureObj *self)
1039/*[clinic end generated code: output=e45b932ba8bd68a1 input=515709a127995109]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001040{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001041 ENSURE_FUTURE_ALIVE(self)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001042 return future_cancel(self);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001043}
1044
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001045/*[clinic input]
1046_asyncio.Future.cancelled
1047
1048Return True if the future was cancelled.
1049[clinic start generated code]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001050
1051static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001052_asyncio_Future_cancelled_impl(FutureObj *self)
1053/*[clinic end generated code: output=145197ced586357d input=943ab8b7b7b17e45]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001054{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001055 if (future_is_alive(self) && self->fut_state == STATE_CANCELLED) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001056 Py_RETURN_TRUE;
1057 }
1058 else {
1059 Py_RETURN_FALSE;
1060 }
1061}
1062
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001063/*[clinic input]
1064_asyncio.Future.done
1065
1066Return True if the future is done.
1067
1068Done means either that a result / exception are available, or that the
1069future was cancelled.
1070[clinic start generated code]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001071
1072static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001073_asyncio_Future_done_impl(FutureObj *self)
1074/*[clinic end generated code: output=244c5ac351145096 input=28d7b23fdb65d2ac]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001075{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001076 if (!future_is_alive(self) || self->fut_state == STATE_PENDING) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001077 Py_RETURN_FALSE;
1078 }
1079 else {
1080 Py_RETURN_TRUE;
1081 }
1082}
1083
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001084/*[clinic input]
1085_asyncio.Future.get_loop
1086
1087Return the event loop the Future is bound to.
1088[clinic start generated code]*/
1089
1090static PyObject *
1091_asyncio_Future_get_loop_impl(FutureObj *self)
1092/*[clinic end generated code: output=119b6ea0c9816c3f input=cba48c2136c79d1f]*/
1093{
1094 Py_INCREF(self->fut_loop);
1095 return self->fut_loop;
1096}
1097
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001098static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001099FutureObj_get_blocking(FutureObj *fut, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001100{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001101 if (future_is_alive(fut) && fut->fut_blocking) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001102 Py_RETURN_TRUE;
1103 }
1104 else {
1105 Py_RETURN_FALSE;
1106 }
1107}
1108
1109static int
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001110FutureObj_set_blocking(FutureObj *fut, PyObject *val, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001111{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001112 if (future_ensure_alive(fut)) {
1113 return -1;
1114 }
Zackery Spytz842acaa2018-12-17 07:52:45 -07001115 if (val == NULL) {
1116 PyErr_SetString(PyExc_AttributeError, "cannot delete attribute");
1117 return -1;
1118 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001119
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001120 int is_true = PyObject_IsTrue(val);
1121 if (is_true < 0) {
1122 return -1;
1123 }
1124 fut->fut_blocking = is_true;
1125 return 0;
1126}
1127
1128static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001129FutureObj_get_log_traceback(FutureObj *fut, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001130{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001131 ENSURE_FUTURE_ALIVE(fut)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001132 if (fut->fut_log_tb) {
1133 Py_RETURN_TRUE;
1134 }
1135 else {
1136 Py_RETURN_FALSE;
1137 }
1138}
1139
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +00001140static int
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001141FutureObj_set_log_traceback(FutureObj *fut, PyObject *val, void *Py_UNUSED(ignored))
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +00001142{
Zackery Spytz842acaa2018-12-17 07:52:45 -07001143 if (val == NULL) {
1144 PyErr_SetString(PyExc_AttributeError, "cannot delete attribute");
1145 return -1;
1146 }
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +00001147 int is_true = PyObject_IsTrue(val);
1148 if (is_true < 0) {
1149 return -1;
1150 }
Yury Selivanove0aef4f2017-12-25 16:16:10 -05001151 if (is_true) {
1152 PyErr_SetString(PyExc_ValueError,
1153 "_log_traceback can only be set to False");
1154 return -1;
1155 }
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +00001156 fut->fut_log_tb = is_true;
1157 return 0;
1158}
1159
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001160static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001161FutureObj_get_loop(FutureObj *fut, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001162{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001163 if (!future_is_alive(fut)) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001164 Py_RETURN_NONE;
1165 }
1166 Py_INCREF(fut->fut_loop);
1167 return fut->fut_loop;
1168}
1169
1170static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001171FutureObj_get_callbacks(FutureObj *fut, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001172{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001173 Py_ssize_t i;
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001174
1175 ENSURE_FUTURE_ALIVE(fut)
1176
Yury Selivanovf23746a2018-01-22 19:11:18 -05001177 if (fut->fut_callback0 == NULL) {
1178 if (fut->fut_callbacks == NULL) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001179 Py_RETURN_NONE;
1180 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001181
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001182 Py_INCREF(fut->fut_callbacks);
1183 return fut->fut_callbacks;
1184 }
1185
Yury Selivanovf23746a2018-01-22 19:11:18 -05001186 Py_ssize_t len = 1;
1187 if (fut->fut_callbacks != NULL) {
1188 len += PyList_GET_SIZE(fut->fut_callbacks);
1189 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001190
Yury Selivanovf23746a2018-01-22 19:11:18 -05001191
1192 PyObject *new_list = PyList_New(len);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001193 if (new_list == NULL) {
1194 return NULL;
1195 }
1196
Yury Selivanovf23746a2018-01-22 19:11:18 -05001197 PyObject *tup0 = PyTuple_New(2);
1198 if (tup0 == NULL) {
1199 Py_DECREF(new_list);
1200 return NULL;
1201 }
1202
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001203 Py_INCREF(fut->fut_callback0);
Yury Selivanovf23746a2018-01-22 19:11:18 -05001204 PyTuple_SET_ITEM(tup0, 0, fut->fut_callback0);
1205 assert(fut->fut_context0 != NULL);
1206 Py_INCREF(fut->fut_context0);
1207 PyTuple_SET_ITEM(tup0, 1, (PyObject *)fut->fut_context0);
1208
1209 PyList_SET_ITEM(new_list, 0, tup0);
1210
1211 if (fut->fut_callbacks != NULL) {
1212 for (i = 0; i < PyList_GET_SIZE(fut->fut_callbacks); i++) {
1213 PyObject *cb = PyList_GET_ITEM(fut->fut_callbacks, i);
1214 Py_INCREF(cb);
1215 PyList_SET_ITEM(new_list, i + 1, cb);
1216 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001217 }
1218
1219 return new_list;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001220}
1221
1222static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001223FutureObj_get_result(FutureObj *fut, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001224{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001225 ENSURE_FUTURE_ALIVE(fut)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001226 if (fut->fut_result == NULL) {
1227 Py_RETURN_NONE;
1228 }
1229 Py_INCREF(fut->fut_result);
1230 return fut->fut_result;
1231}
1232
1233static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001234FutureObj_get_exception(FutureObj *fut, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001235{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001236 ENSURE_FUTURE_ALIVE(fut)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001237 if (fut->fut_exception == NULL) {
1238 Py_RETURN_NONE;
1239 }
1240 Py_INCREF(fut->fut_exception);
1241 return fut->fut_exception;
1242}
1243
1244static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001245FutureObj_get_source_traceback(FutureObj *fut, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001246{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001247 if (!future_is_alive(fut) || fut->fut_source_tb == NULL) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001248 Py_RETURN_NONE;
1249 }
1250 Py_INCREF(fut->fut_source_tb);
1251 return fut->fut_source_tb;
1252}
1253
1254static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001255FutureObj_get_state(FutureObj *fut, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001256{
1257 _Py_IDENTIFIER(PENDING);
1258 _Py_IDENTIFIER(CANCELLED);
1259 _Py_IDENTIFIER(FINISHED);
1260 PyObject *ret = NULL;
1261
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001262 ENSURE_FUTURE_ALIVE(fut)
1263
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001264 switch (fut->fut_state) {
1265 case STATE_PENDING:
1266 ret = _PyUnicode_FromId(&PyId_PENDING);
1267 break;
1268 case STATE_CANCELLED:
1269 ret = _PyUnicode_FromId(&PyId_CANCELLED);
1270 break;
1271 case STATE_FINISHED:
1272 ret = _PyUnicode_FromId(&PyId_FINISHED);
1273 break;
1274 default:
1275 assert (0);
1276 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03001277 Py_XINCREF(ret);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001278 return ret;
1279}
1280
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001281/*[clinic input]
1282_asyncio.Future._repr_info
1283[clinic start generated code]*/
1284
1285static PyObject *
1286_asyncio_Future__repr_info_impl(FutureObj *self)
1287/*[clinic end generated code: output=fa69e901bd176cfb input=f21504d8e2ae1ca2]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001288{
Victor Stinnerde4ae3d2016-12-04 22:59:09 +01001289 return PyObject_CallFunctionObjArgs(
1290 asyncio_future_repr_info_func, self, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001291}
1292
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001293static PyObject *
1294FutureObj_repr(FutureObj *fut)
1295{
1296 _Py_IDENTIFIER(_repr_info);
1297
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001298 ENSURE_FUTURE_ALIVE(fut)
1299
Serhiy Storchakabca49392017-09-03 08:10:14 +03001300 PyObject *rinfo = _PyObject_CallMethodIdObjArgs((PyObject*)fut,
1301 &PyId__repr_info,
1302 NULL);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001303 if (rinfo == NULL) {
1304 return NULL;
1305 }
1306
Serhiy Storchakabca49392017-09-03 08:10:14 +03001307 PyObject *rinfo_s = PyUnicode_Join(NULL, rinfo);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001308 Py_DECREF(rinfo);
1309 if (rinfo_s == NULL) {
1310 return NULL;
1311 }
1312
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03001313 PyObject *rstr = PyUnicode_FromFormat("<%s %U>",
1314 _PyType_Name(Py_TYPE(fut)), rinfo_s);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001315 Py_DECREF(rinfo_s);
1316 return rstr;
1317}
1318
1319static void
1320FutureObj_finalize(FutureObj *fut)
1321{
1322 _Py_IDENTIFIER(call_exception_handler);
1323 _Py_IDENTIFIER(message);
1324 _Py_IDENTIFIER(exception);
1325 _Py_IDENTIFIER(future);
1326 _Py_IDENTIFIER(source_traceback);
1327
Serhiy Storchakabca49392017-09-03 08:10:14 +03001328 PyObject *error_type, *error_value, *error_traceback;
1329 PyObject *context;
Serhiy Storchakabca49392017-09-03 08:10:14 +03001330 PyObject *message = NULL;
1331 PyObject *func;
1332
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001333 if (!fut->fut_log_tb) {
1334 return;
1335 }
1336 assert(fut->fut_exception != NULL);
Serhiy Storchakabca49392017-09-03 08:10:14 +03001337 fut->fut_log_tb = 0;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001338
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001339 /* Save the current exception, if any. */
1340 PyErr_Fetch(&error_type, &error_value, &error_traceback);
1341
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001342 context = PyDict_New();
1343 if (context == NULL) {
1344 goto finally;
1345 }
1346
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001347 message = PyUnicode_FromFormat(
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03001348 "%s exception was never retrieved", _PyType_Name(Py_TYPE(fut)));
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001349 if (message == NULL) {
1350 goto finally;
1351 }
1352
1353 if (_PyDict_SetItemId(context, &PyId_message, message) < 0 ||
1354 _PyDict_SetItemId(context, &PyId_exception, fut->fut_exception) < 0 ||
1355 _PyDict_SetItemId(context, &PyId_future, (PyObject*)fut) < 0) {
1356 goto finally;
1357 }
1358 if (fut->fut_source_tb != NULL) {
1359 if (_PyDict_SetItemId(context, &PyId_source_traceback,
1360 fut->fut_source_tb) < 0) {
1361 goto finally;
1362 }
1363 }
1364
1365 func = _PyObject_GetAttrId(fut->fut_loop, &PyId_call_exception_handler);
1366 if (func != NULL) {
Serhiy Storchakabca49392017-09-03 08:10:14 +03001367 PyObject *res = PyObject_CallFunctionObjArgs(func, context, NULL);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001368 if (res == NULL) {
1369 PyErr_WriteUnraisable(func);
1370 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03001371 else {
1372 Py_DECREF(res);
1373 }
1374 Py_DECREF(func);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001375 }
1376
1377finally:
Serhiy Storchakabca49392017-09-03 08:10:14 +03001378 Py_XDECREF(context);
1379 Py_XDECREF(message);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001380
1381 /* Restore the saved exception. */
1382 PyErr_Restore(error_type, error_value, error_traceback);
1383}
1384
1385
1386static PyAsyncMethods FutureType_as_async = {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001387 (unaryfunc)future_new_iter, /* am_await */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001388 0, /* am_aiter */
1389 0 /* am_anext */
1390};
1391
1392static PyMethodDef FutureType_methods[] = {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001393 _ASYNCIO_FUTURE_RESULT_METHODDEF
1394 _ASYNCIO_FUTURE_EXCEPTION_METHODDEF
1395 _ASYNCIO_FUTURE_SET_RESULT_METHODDEF
1396 _ASYNCIO_FUTURE_SET_EXCEPTION_METHODDEF
1397 _ASYNCIO_FUTURE_ADD_DONE_CALLBACK_METHODDEF
1398 _ASYNCIO_FUTURE_REMOVE_DONE_CALLBACK_METHODDEF
1399 _ASYNCIO_FUTURE_CANCEL_METHODDEF
1400 _ASYNCIO_FUTURE_CANCELLED_METHODDEF
1401 _ASYNCIO_FUTURE_DONE_METHODDEF
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001402 _ASYNCIO_FUTURE_GET_LOOP_METHODDEF
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001403 _ASYNCIO_FUTURE__REPR_INFO_METHODDEF
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001404 {NULL, NULL} /* Sentinel */
1405};
1406
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001407#define FUTURE_COMMON_GETSETLIST \
1408 {"_state", (getter)FutureObj_get_state, NULL, NULL}, \
1409 {"_asyncio_future_blocking", (getter)FutureObj_get_blocking, \
1410 (setter)FutureObj_set_blocking, NULL}, \
1411 {"_loop", (getter)FutureObj_get_loop, NULL, NULL}, \
1412 {"_callbacks", (getter)FutureObj_get_callbacks, NULL, NULL}, \
1413 {"_result", (getter)FutureObj_get_result, NULL, NULL}, \
1414 {"_exception", (getter)FutureObj_get_exception, NULL, NULL}, \
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +00001415 {"_log_traceback", (getter)FutureObj_get_log_traceback, \
1416 (setter)FutureObj_set_log_traceback, NULL}, \
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001417 {"_source_traceback", (getter)FutureObj_get_source_traceback, NULL, NULL},
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001418
1419static PyGetSetDef FutureType_getsetlist[] = {
1420 FUTURE_COMMON_GETSETLIST
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001421 {NULL} /* Sentinel */
1422};
1423
1424static void FutureObj_dealloc(PyObject *self);
1425
1426static PyTypeObject FutureType = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02001427 PyVarObject_HEAD_INIT(NULL, 0)
INADA Naoki9f2ce252016-10-15 15:39:19 +09001428 "_asyncio.Future",
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001429 sizeof(FutureObj), /* tp_basicsize */
1430 .tp_dealloc = FutureObj_dealloc,
1431 .tp_as_async = &FutureType_as_async,
1432 .tp_repr = (reprfunc)FutureObj_repr,
Antoine Pitrouada319b2019-05-29 22:12:38 +02001433 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001434 .tp_doc = _asyncio_Future___init____doc__,
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001435 .tp_traverse = (traverseproc)FutureObj_traverse,
1436 .tp_clear = (inquiry)FutureObj_clear,
1437 .tp_weaklistoffset = offsetof(FutureObj, fut_weakreflist),
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001438 .tp_iter = (getiterfunc)future_new_iter,
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001439 .tp_methods = FutureType_methods,
1440 .tp_getset = FutureType_getsetlist,
1441 .tp_dictoffset = offsetof(FutureObj, dict),
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001442 .tp_init = (initproc)_asyncio_Future___init__,
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001443 .tp_new = PyType_GenericNew,
1444 .tp_finalize = (destructor)FutureObj_finalize,
1445};
1446
1447static void
1448FutureObj_dealloc(PyObject *self)
1449{
1450 FutureObj *fut = (FutureObj *)self;
1451
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001452 if (Future_CheckExact(fut)) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001453 /* When fut is subclass of Future, finalizer is called from
1454 * subtype_dealloc.
1455 */
1456 if (PyObject_CallFinalizerFromDealloc(self) < 0) {
1457 // resurrected.
1458 return;
1459 }
1460 }
1461
Alexander Mohrde34cbe2017-08-01 23:31:07 -07001462 PyObject_GC_UnTrack(self);
1463
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001464 if (fut->fut_weakreflist != NULL) {
1465 PyObject_ClearWeakRefs(self);
1466 }
1467
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001468 (void)FutureObj_clear(fut);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001469 Py_TYPE(fut)->tp_free(fut);
1470}
1471
1472
1473/*********************** Future Iterator **************************/
1474
1475typedef struct {
1476 PyObject_HEAD
1477 FutureObj *future;
1478} futureiterobject;
1479
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001480
1481#define FI_FREELIST_MAXLEN 255
1482static futureiterobject *fi_freelist = NULL;
1483static Py_ssize_t fi_freelist_len = 0;
1484
1485
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001486static void
1487FutureIter_dealloc(futureiterobject *it)
1488{
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001489 PyObject_GC_UnTrack(it);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001490 Py_CLEAR(it->future);
1491
1492 if (fi_freelist_len < FI_FREELIST_MAXLEN) {
1493 fi_freelist_len++;
1494 it->future = (FutureObj*) fi_freelist;
1495 fi_freelist = it;
1496 }
1497 else {
1498 PyObject_GC_Del(it);
1499 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001500}
1501
1502static PyObject *
1503FutureIter_iternext(futureiterobject *it)
1504{
1505 PyObject *res;
1506 FutureObj *fut = it->future;
1507
1508 if (fut == NULL) {
1509 return NULL;
1510 }
1511
1512 if (fut->fut_state == STATE_PENDING) {
1513 if (!fut->fut_blocking) {
1514 fut->fut_blocking = 1;
1515 Py_INCREF(fut);
1516 return (PyObject *)fut;
1517 }
Yury Selivanov0cf16f92017-12-25 10:48:15 -05001518 PyErr_SetString(PyExc_RuntimeError,
1519 "await wasn't used with future");
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001520 return NULL;
1521 }
1522
Serhiy Storchakabca49392017-09-03 08:10:14 +03001523 it->future = NULL;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001524 res = _asyncio_Future_result_impl(fut);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001525 if (res != NULL) {
Serhiy Storchaka60e49aa2016-11-06 18:47:03 +02001526 /* The result of the Future is not an exception. */
Serhiy Storchakabca49392017-09-03 08:10:14 +03001527 (void)_PyGen_SetStopIterationValue(res);
Serhiy Storchaka60e49aa2016-11-06 18:47:03 +02001528 Py_DECREF(res);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001529 }
1530
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001531 Py_DECREF(fut);
1532 return NULL;
1533}
1534
1535static PyObject *
INADA Naoki74c17532016-10-25 19:00:45 +09001536FutureIter_send(futureiterobject *self, PyObject *unused)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001537{
INADA Naoki74c17532016-10-25 19:00:45 +09001538 /* Future.__iter__ doesn't care about values that are pushed to the
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03001539 * generator, it just returns self.result().
INADA Naoki74c17532016-10-25 19:00:45 +09001540 */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001541 return FutureIter_iternext(self);
1542}
1543
1544static PyObject *
1545FutureIter_throw(futureiterobject *self, PyObject *args)
1546{
Serhiy Storchakabca49392017-09-03 08:10:14 +03001547 PyObject *type, *val = NULL, *tb = NULL;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001548 if (!PyArg_ParseTuple(args, "O|OO", &type, &val, &tb))
1549 return NULL;
1550
1551 if (val == Py_None) {
1552 val = NULL;
1553 }
1554 if (tb == Py_None) {
1555 tb = NULL;
Benjamin Peterson996fc1f2016-11-14 00:15:44 -08001556 } else if (tb != NULL && !PyTraceBack_Check(tb)) {
1557 PyErr_SetString(PyExc_TypeError, "throw() third argument must be a traceback");
1558 return NULL;
1559 }
1560
1561 Py_INCREF(type);
1562 Py_XINCREF(val);
1563 Py_XINCREF(tb);
1564
1565 if (PyExceptionClass_Check(type)) {
1566 PyErr_NormalizeException(&type, &val, &tb);
Yury Selivanovedfe8862016-12-01 11:37:47 -05001567 /* No need to call PyException_SetTraceback since we'll be calling
1568 PyErr_Restore for `type`, `val`, and `tb`. */
Benjamin Peterson996fc1f2016-11-14 00:15:44 -08001569 } else if (PyExceptionInstance_Check(type)) {
1570 if (val) {
1571 PyErr_SetString(PyExc_TypeError,
1572 "instance exception may not have a separate value");
1573 goto fail;
1574 }
1575 val = type;
1576 type = PyExceptionInstance_Class(type);
1577 Py_INCREF(type);
1578 if (tb == NULL)
1579 tb = PyException_GetTraceback(val);
1580 } else {
1581 PyErr_SetString(PyExc_TypeError,
1582 "exceptions must be classes deriving BaseException or "
1583 "instances of such a class");
1584 goto fail;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001585 }
1586
1587 Py_CLEAR(self->future);
1588
Benjamin Peterson996fc1f2016-11-14 00:15:44 -08001589 PyErr_Restore(type, val, tb);
1590
Serhiy Storchakabca49392017-09-03 08:10:14 +03001591 return NULL;
Benjamin Peterson996fc1f2016-11-14 00:15:44 -08001592
1593 fail:
1594 Py_DECREF(type);
1595 Py_XDECREF(val);
1596 Py_XDECREF(tb);
1597 return NULL;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001598}
1599
1600static PyObject *
1601FutureIter_close(futureiterobject *self, PyObject *arg)
1602{
1603 Py_CLEAR(self->future);
1604 Py_RETURN_NONE;
1605}
1606
1607static int
1608FutureIter_traverse(futureiterobject *it, visitproc visit, void *arg)
1609{
1610 Py_VISIT(it->future);
1611 return 0;
1612}
1613
1614static PyMethodDef FutureIter_methods[] = {
1615 {"send", (PyCFunction)FutureIter_send, METH_O, NULL},
1616 {"throw", (PyCFunction)FutureIter_throw, METH_VARARGS, NULL},
1617 {"close", (PyCFunction)FutureIter_close, METH_NOARGS, NULL},
1618 {NULL, NULL} /* Sentinel */
1619};
1620
1621static PyTypeObject FutureIterType = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02001622 PyVarObject_HEAD_INIT(NULL, 0)
INADA Naoki9f2ce252016-10-15 15:39:19 +09001623 "_asyncio.FutureIter",
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001624 .tp_basicsize = sizeof(futureiterobject),
1625 .tp_itemsize = 0,
1626 .tp_dealloc = (destructor)FutureIter_dealloc,
1627 .tp_getattro = PyObject_GenericGetAttr,
1628 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
1629 .tp_traverse = (traverseproc)FutureIter_traverse,
1630 .tp_iter = PyObject_SelfIter,
1631 .tp_iternext = (iternextfunc)FutureIter_iternext,
1632 .tp_methods = FutureIter_methods,
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001633};
1634
1635static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001636future_new_iter(PyObject *fut)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001637{
1638 futureiterobject *it;
1639
1640 if (!PyObject_TypeCheck(fut, &FutureType)) {
1641 PyErr_BadInternalCall();
1642 return NULL;
1643 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001644
1645 ENSURE_FUTURE_ALIVE(fut)
1646
1647 if (fi_freelist_len) {
1648 fi_freelist_len--;
1649 it = fi_freelist;
1650 fi_freelist = (futureiterobject*) it->future;
1651 it->future = NULL;
1652 _Py_NewReference((PyObject*) it);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001653 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001654 else {
1655 it = PyObject_GC_New(futureiterobject, &FutureIterType);
1656 if (it == NULL) {
1657 return NULL;
1658 }
1659 }
1660
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001661 Py_INCREF(fut);
1662 it->future = (FutureObj*)fut;
INADA Naoki1be427b2016-10-11 02:12:34 +09001663 PyObject_GC_Track(it);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001664 return (PyObject*)it;
1665}
1666
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001667
1668/*********************** Task **************************/
1669
1670
1671/*[clinic input]
1672class _asyncio.Task "TaskObj *" "&Task_Type"
1673[clinic start generated code]*/
1674/*[clinic end generated code: output=da39a3ee5e6b4b0d input=719dcef0fcc03b37]*/
1675
1676static int task_call_step_soon(TaskObj *, PyObject *);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001677static PyObject * task_wakeup(TaskObj *, PyObject *);
1678static PyObject * task_step(TaskObj *, PyObject *);
1679
1680/* ----- Task._step wrapper */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001681
INADA Naokic411a7d2016-10-18 11:48:14 +09001682static int
Serhiy Storchakabca49392017-09-03 08:10:14 +03001683TaskStepMethWrapper_clear(TaskStepMethWrapper *o)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001684{
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001685 Py_CLEAR(o->sw_task);
1686 Py_CLEAR(o->sw_arg);
1687 return 0;
1688}
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001689
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001690static void
Serhiy Storchakabca49392017-09-03 08:10:14 +03001691TaskStepMethWrapper_dealloc(TaskStepMethWrapper *o)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001692{
1693 PyObject_GC_UnTrack(o);
Serhiy Storchakabca49392017-09-03 08:10:14 +03001694 (void)TaskStepMethWrapper_clear(o);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001695 Py_TYPE(o)->tp_free(o);
1696}
1697
1698static PyObject *
Serhiy Storchakabca49392017-09-03 08:10:14 +03001699TaskStepMethWrapper_call(TaskStepMethWrapper *o,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001700 PyObject *args, PyObject *kwds)
1701{
Serhiy Storchakabca49392017-09-03 08:10:14 +03001702 if (kwds != NULL && PyDict_GET_SIZE(kwds) != 0) {
1703 PyErr_SetString(PyExc_TypeError, "function takes no keyword arguments");
1704 return NULL;
1705 }
1706 if (args != NULL && PyTuple_GET_SIZE(args) != 0) {
1707 PyErr_SetString(PyExc_TypeError, "function takes no positional arguments");
1708 return NULL;
1709 }
Yury Selivanov22feeb82018-01-24 11:31:01 -05001710 return task_step(o->sw_task, o->sw_arg);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001711}
1712
1713static int
Serhiy Storchakabca49392017-09-03 08:10:14 +03001714TaskStepMethWrapper_traverse(TaskStepMethWrapper *o,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001715 visitproc visit, void *arg)
1716{
1717 Py_VISIT(o->sw_task);
1718 Py_VISIT(o->sw_arg);
1719 return 0;
1720}
1721
1722static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001723TaskStepMethWrapper_get___self__(TaskStepMethWrapper *o, void *Py_UNUSED(ignored))
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001724{
1725 if (o->sw_task) {
1726 Py_INCREF(o->sw_task);
1727 return (PyObject*)o->sw_task;
1728 }
1729 Py_RETURN_NONE;
1730}
1731
Serhiy Storchakabca49392017-09-03 08:10:14 +03001732static PyGetSetDef TaskStepMethWrapper_getsetlist[] = {
1733 {"__self__", (getter)TaskStepMethWrapper_get___self__, NULL, NULL},
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001734 {NULL} /* Sentinel */
1735};
1736
Benjamin Peterson3c8aae92018-07-05 22:39:34 -07001737static PyTypeObject TaskStepMethWrapper_Type = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02001738 PyVarObject_HEAD_INIT(NULL, 0)
Serhiy Storchakabca49392017-09-03 08:10:14 +03001739 "TaskStepMethWrapper",
1740 .tp_basicsize = sizeof(TaskStepMethWrapper),
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001741 .tp_itemsize = 0,
Serhiy Storchakabca49392017-09-03 08:10:14 +03001742 .tp_getset = TaskStepMethWrapper_getsetlist,
1743 .tp_dealloc = (destructor)TaskStepMethWrapper_dealloc,
1744 .tp_call = (ternaryfunc)TaskStepMethWrapper_call,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001745 .tp_getattro = PyObject_GenericGetAttr,
1746 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
Serhiy Storchakabca49392017-09-03 08:10:14 +03001747 .tp_traverse = (traverseproc)TaskStepMethWrapper_traverse,
1748 .tp_clear = (inquiry)TaskStepMethWrapper_clear,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001749};
1750
1751static PyObject *
Serhiy Storchakabca49392017-09-03 08:10:14 +03001752TaskStepMethWrapper_new(TaskObj *task, PyObject *arg)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001753{
Serhiy Storchakabca49392017-09-03 08:10:14 +03001754 TaskStepMethWrapper *o;
1755 o = PyObject_GC_New(TaskStepMethWrapper, &TaskStepMethWrapper_Type);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001756 if (o == NULL) {
1757 return NULL;
1758 }
1759
1760 Py_INCREF(task);
1761 o->sw_task = task;
1762
1763 Py_XINCREF(arg);
1764 o->sw_arg = arg;
1765
1766 PyObject_GC_Track(o);
1767 return (PyObject*) o;
1768}
1769
1770/* ----- Task._wakeup wrapper */
1771
1772static PyObject *
1773TaskWakeupMethWrapper_call(TaskWakeupMethWrapper *o,
1774 PyObject *args, PyObject *kwds)
1775{
1776 PyObject *fut;
1777
Serhiy Storchakabca49392017-09-03 08:10:14 +03001778 if (kwds != NULL && PyDict_GET_SIZE(kwds) != 0) {
1779 PyErr_SetString(PyExc_TypeError, "function takes no keyword arguments");
1780 return NULL;
1781 }
1782 if (!PyArg_ParseTuple(args, "O", &fut)) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001783 return NULL;
1784 }
1785
Yury Selivanov22feeb82018-01-24 11:31:01 -05001786 return task_wakeup(o->ww_task, fut);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001787}
1788
1789static int
1790TaskWakeupMethWrapper_clear(TaskWakeupMethWrapper *o)
1791{
1792 Py_CLEAR(o->ww_task);
1793 return 0;
1794}
1795
1796static int
1797TaskWakeupMethWrapper_traverse(TaskWakeupMethWrapper *o,
1798 visitproc visit, void *arg)
1799{
1800 Py_VISIT(o->ww_task);
1801 return 0;
1802}
1803
1804static void
1805TaskWakeupMethWrapper_dealloc(TaskWakeupMethWrapper *o)
1806{
1807 PyObject_GC_UnTrack(o);
1808 (void)TaskWakeupMethWrapper_clear(o);
1809 Py_TYPE(o)->tp_free(o);
1810}
1811
Benjamin Peterson3c8aae92018-07-05 22:39:34 -07001812static PyTypeObject TaskWakeupMethWrapper_Type = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02001813 PyVarObject_HEAD_INIT(NULL, 0)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001814 "TaskWakeupMethWrapper",
1815 .tp_basicsize = sizeof(TaskWakeupMethWrapper),
1816 .tp_itemsize = 0,
1817 .tp_dealloc = (destructor)TaskWakeupMethWrapper_dealloc,
1818 .tp_call = (ternaryfunc)TaskWakeupMethWrapper_call,
1819 .tp_getattro = PyObject_GenericGetAttr,
1820 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
1821 .tp_traverse = (traverseproc)TaskWakeupMethWrapper_traverse,
1822 .tp_clear = (inquiry)TaskWakeupMethWrapper_clear,
1823};
1824
1825static PyObject *
1826TaskWakeupMethWrapper_new(TaskObj *task)
1827{
1828 TaskWakeupMethWrapper *o;
1829 o = PyObject_GC_New(TaskWakeupMethWrapper, &TaskWakeupMethWrapper_Type);
1830 if (o == NULL) {
1831 return NULL;
1832 }
1833
1834 Py_INCREF(task);
1835 o->ww_task = task;
1836
1837 PyObject_GC_Track(o);
1838 return (PyObject*) o;
1839}
1840
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001841/* ----- Task introspection helpers */
1842
1843static int
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001844register_task(PyObject *task)
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001845{
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001846 _Py_IDENTIFIER(add);
1847
1848 PyObject *res = _PyObject_CallMethodIdObjArgs(
1849 all_tasks, &PyId_add, task, NULL);
1850 if (res == NULL) {
1851 return -1;
1852 }
1853 Py_DECREF(res);
1854 return 0;
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001855}
1856
1857
1858static int
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001859unregister_task(PyObject *task)
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001860{
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001861 _Py_IDENTIFIER(discard);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001862
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001863 PyObject *res = _PyObject_CallMethodIdObjArgs(
1864 all_tasks, &PyId_discard, task, NULL);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001865 if (res == NULL) {
1866 return -1;
1867 }
1868 Py_DECREF(res);
1869 return 0;
1870}
1871
1872
1873static int
1874enter_task(PyObject *loop, PyObject *task)
1875{
1876 PyObject *item;
1877 Py_hash_t hash;
1878 hash = PyObject_Hash(loop);
1879 if (hash == -1) {
1880 return -1;
1881 }
1882 item = _PyDict_GetItem_KnownHash(current_tasks, loop, hash);
1883 if (item != NULL) {
Serhiy Storchaka66553542018-05-20 16:30:31 +03001884 Py_INCREF(item);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001885 PyErr_Format(
1886 PyExc_RuntimeError,
1887 "Cannot enter into task %R while another " \
1888 "task %R is being executed.",
1889 task, item, NULL);
Serhiy Storchaka66553542018-05-20 16:30:31 +03001890 Py_DECREF(item);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001891 return -1;
1892 }
Serhiy Storchaka66553542018-05-20 16:30:31 +03001893 if (PyErr_Occurred()) {
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001894 return -1;
1895 }
Serhiy Storchaka66553542018-05-20 16:30:31 +03001896 return _PyDict_SetItem_KnownHash(current_tasks, loop, task, hash);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001897}
1898
1899
1900static int
1901leave_task(PyObject *loop, PyObject *task)
1902/*[clinic end generated code: output=0ebf6db4b858fb41 input=51296a46313d1ad8]*/
1903{
1904 PyObject *item;
1905 Py_hash_t hash;
1906 hash = PyObject_Hash(loop);
1907 if (hash == -1) {
1908 return -1;
1909 }
1910 item = _PyDict_GetItem_KnownHash(current_tasks, loop, hash);
1911 if (item != task) {
1912 if (item == NULL) {
1913 /* Not entered, replace with None */
1914 item = Py_None;
1915 }
1916 PyErr_Format(
1917 PyExc_RuntimeError,
1918 "Leaving task %R does not match the current task %R.",
1919 task, item, NULL);
1920 return -1;
1921 }
1922 return _PyDict_DelItem_KnownHash(current_tasks, loop, hash);
1923}
1924
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001925/* ----- Task */
1926
1927/*[clinic input]
1928_asyncio.Task.__init__
1929
Serhiy Storchakabca49392017-09-03 08:10:14 +03001930 coro: object
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001931 *
Serhiy Storchakabca49392017-09-03 08:10:14 +03001932 loop: object = None
Alex Grönholmcca4eec2018-08-09 00:06:47 +03001933 name: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001934
1935A coroutine wrapped in a Future.
1936[clinic start generated code]*/
1937
1938static int
Alex Grönholmcca4eec2018-08-09 00:06:47 +03001939_asyncio_Task___init___impl(TaskObj *self, PyObject *coro, PyObject *loop,
1940 PyObject *name)
1941/*[clinic end generated code: output=88b12b83d570df50 input=352a3137fe60091d]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001942{
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001943 if (future_init((FutureObj*)self, loop)) {
INADA Naokic411a7d2016-10-18 11:48:14 +09001944 return -1;
1945 }
INADA Naokic411a7d2016-10-18 11:48:14 +09001946
Yury Selivanova9d7e552017-12-19 07:18:45 -05001947 int is_coro = is_coroutine(coro);
1948 if (is_coro == -1) {
1949 return -1;
1950 }
1951 if (is_coro == 0) {
1952 self->task_log_destroy_pending = 0;
1953 PyErr_Format(PyExc_TypeError,
1954 "a coroutine was expected, got %R",
1955 coro, NULL);
1956 return -1;
Andrew Svetlovf74ef452017-12-15 07:04:38 +02001957 }
1958
Oren Milmand019bc82018-02-13 12:28:33 +02001959 Py_XSETREF(self->task_context, PyContext_CopyCurrent());
Yury Selivanovf23746a2018-01-22 19:11:18 -05001960 if (self->task_context == NULL) {
1961 return -1;
1962 }
1963
Oren Milmand019bc82018-02-13 12:28:33 +02001964 Py_CLEAR(self->task_fut_waiter);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001965 self->task_must_cancel = 0;
1966 self->task_log_destroy_pending = 1;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001967 Py_INCREF(coro);
Oren Milmand019bc82018-02-13 12:28:33 +02001968 Py_XSETREF(self->task_coro, coro);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001969
Alex Grönholmcca4eec2018-08-09 00:06:47 +03001970 if (name == Py_None) {
1971 name = PyUnicode_FromFormat("Task-%" PRIu64, ++task_name_counter);
Alex Grönholma7548232018-08-09 23:49:49 +03001972 } else if (!PyUnicode_CheckExact(name)) {
Alex Grönholmcca4eec2018-08-09 00:06:47 +03001973 name = PyObject_Str(name);
1974 } else {
1975 Py_INCREF(name);
1976 }
1977 Py_XSETREF(self->task_name, name);
1978 if (self->task_name == NULL) {
1979 return -1;
1980 }
1981
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001982 if (task_call_step_soon(self, NULL)) {
1983 return -1;
INADA Naokic411a7d2016-10-18 11:48:14 +09001984 }
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001985 return register_task((PyObject*)self);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001986}
1987
1988static int
1989TaskObj_clear(TaskObj *task)
1990{
1991 (void)FutureObj_clear((FutureObj*) task);
Yury Selivanovf23746a2018-01-22 19:11:18 -05001992 Py_CLEAR(task->task_context);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001993 Py_CLEAR(task->task_coro);
Alex Grönholmcca4eec2018-08-09 00:06:47 +03001994 Py_CLEAR(task->task_name);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001995 Py_CLEAR(task->task_fut_waiter);
1996 return 0;
1997}
1998
1999static int
2000TaskObj_traverse(TaskObj *task, visitproc visit, void *arg)
2001{
Yury Selivanovf23746a2018-01-22 19:11:18 -05002002 Py_VISIT(task->task_context);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002003 Py_VISIT(task->task_coro);
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002004 Py_VISIT(task->task_name);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002005 Py_VISIT(task->task_fut_waiter);
2006 (void)FutureObj_traverse((FutureObj*) task, visit, arg);
2007 return 0;
2008}
2009
2010static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02002011TaskObj_get_log_destroy_pending(TaskObj *task, void *Py_UNUSED(ignored))
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002012{
2013 if (task->task_log_destroy_pending) {
2014 Py_RETURN_TRUE;
2015 }
2016 else {
2017 Py_RETURN_FALSE;
2018 }
2019}
2020
2021static int
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02002022TaskObj_set_log_destroy_pending(TaskObj *task, PyObject *val, void *Py_UNUSED(ignored))
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002023{
Zackery Spytz842acaa2018-12-17 07:52:45 -07002024 if (val == NULL) {
2025 PyErr_SetString(PyExc_AttributeError, "cannot delete attribute");
2026 return -1;
2027 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002028 int is_true = PyObject_IsTrue(val);
2029 if (is_true < 0) {
2030 return -1;
2031 }
2032 task->task_log_destroy_pending = is_true;
2033 return 0;
2034}
2035
2036static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02002037TaskObj_get_must_cancel(TaskObj *task, void *Py_UNUSED(ignored))
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002038{
2039 if (task->task_must_cancel) {
2040 Py_RETURN_TRUE;
2041 }
2042 else {
2043 Py_RETURN_FALSE;
2044 }
2045}
2046
2047static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02002048TaskObj_get_coro(TaskObj *task, void *Py_UNUSED(ignored))
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002049{
2050 if (task->task_coro) {
2051 Py_INCREF(task->task_coro);
2052 return task->task_coro;
2053 }
2054
2055 Py_RETURN_NONE;
2056}
2057
2058static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02002059TaskObj_get_fut_waiter(TaskObj *task, void *Py_UNUSED(ignored))
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002060{
2061 if (task->task_fut_waiter) {
2062 Py_INCREF(task->task_fut_waiter);
2063 return task->task_fut_waiter;
2064 }
2065
2066 Py_RETURN_NONE;
2067}
2068
2069/*[clinic input]
2070@classmethod
2071_asyncio.Task.current_task
2072
Serhiy Storchakabca49392017-09-03 08:10:14 +03002073 loop: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002074
2075Return the currently running task in an event loop or None.
2076
2077By default the current task for the current event loop is returned.
2078
2079None is returned when called not in the context of a Task.
2080[clinic start generated code]*/
2081
2082static PyObject *
2083_asyncio_Task_current_task_impl(PyTypeObject *type, PyObject *loop)
Serhiy Storchakabca49392017-09-03 08:10:14 +03002084/*[clinic end generated code: output=99fbe7332c516e03 input=cd14770c5b79c7eb]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002085{
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002086 PyObject *ret;
2087 PyObject *current_task_func;
2088
Inada Naokic5c6cda2019-03-22 20:07:32 +09002089 if (PyErr_WarnEx(PyExc_DeprecationWarning,
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002090 "Task.current_task() is deprecated, " \
2091 "use asyncio.current_task() instead",
2092 1) < 0) {
2093 return NULL;
2094 }
2095
2096 current_task_func = _PyObject_GetAttrId(asyncio_mod, &PyId_current_task);
2097 if (current_task_func == NULL) {
2098 return NULL;
2099 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002100
Yury Selivanov8d26aa92017-03-02 22:16:33 -05002101 if (loop == Py_None) {
Yury Selivanova70232f2017-12-13 14:49:42 -05002102 loop = get_event_loop();
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002103 if (loop == NULL) {
Serhiy Storchaka66553542018-05-20 16:30:31 +03002104 Py_DECREF(current_task_func);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002105 return NULL;
2106 }
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002107 ret = PyObject_CallFunctionObjArgs(current_task_func, loop, NULL);
2108 Py_DECREF(current_task_func);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002109 Py_DECREF(loop);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002110 return ret;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002111 }
2112 else {
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002113 ret = PyObject_CallFunctionObjArgs(current_task_func, loop, NULL);
2114 Py_DECREF(current_task_func);
2115 return ret;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002116 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002117}
2118
2119/*[clinic input]
2120@classmethod
2121_asyncio.Task.all_tasks
2122
Serhiy Storchakabca49392017-09-03 08:10:14 +03002123 loop: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002124
2125Return a set of all tasks for an event loop.
2126
2127By default all tasks for the current event loop are returned.
2128[clinic start generated code]*/
2129
2130static PyObject *
2131_asyncio_Task_all_tasks_impl(PyTypeObject *type, PyObject *loop)
Serhiy Storchakabca49392017-09-03 08:10:14 +03002132/*[clinic end generated code: output=11f9b20749ccca5d input=497f80bc9ce726b5]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002133{
2134 PyObject *res;
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002135 PyObject *all_tasks_func;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002136
Inada Naokic5c6cda2019-03-22 20:07:32 +09002137 if (PyErr_WarnEx(PyExc_DeprecationWarning,
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002138 "Task.all_tasks() is deprecated, " \
2139 "use asyncio.all_tasks() instead",
2140 1) < 0) {
2141 return NULL;
2142 }
2143
Yury Selivanov416c1eb2018-05-28 17:54:02 -04002144 all_tasks_func = _PyObject_GetAttrId(asyncio_mod, &PyId__all_tasks_compat);
Serhiy Storchaka66553542018-05-20 16:30:31 +03002145 if (all_tasks_func == NULL) {
2146 return NULL;
2147 }
2148
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002149 res = PyObject_CallFunctionObjArgs(all_tasks_func, loop, NULL);
2150 Py_DECREF(all_tasks_func);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002151 return res;
2152}
2153
2154/*[clinic input]
2155_asyncio.Task._repr_info
2156[clinic start generated code]*/
2157
2158static PyObject *
2159_asyncio_Task__repr_info_impl(TaskObj *self)
2160/*[clinic end generated code: output=6a490eb66d5ba34b input=3c6d051ed3ddec8b]*/
2161{
Victor Stinnerde4ae3d2016-12-04 22:59:09 +01002162 return PyObject_CallFunctionObjArgs(
2163 asyncio_task_repr_info_func, self, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002164}
2165
2166/*[clinic input]
2167_asyncio.Task.cancel
2168
2169Request that this task cancel itself.
2170
2171This arranges for a CancelledError to be thrown into the
2172wrapped coroutine on the next cycle through the event loop.
2173The coroutine then has a chance to clean up or even deny
2174the request using try/except/finally.
2175
2176Unlike Future.cancel, this does not guarantee that the
2177task will be cancelled: the exception might be caught and
2178acted upon, delaying cancellation of the task or preventing
2179cancellation completely. The task may also return a value or
2180raise a different exception.
2181
2182Immediately after this method is called, Task.cancelled() will
2183not return True (unless the task was already cancelled). A
2184task will be marked as cancelled when the wrapped coroutine
2185terminates with a CancelledError exception (even if cancel()
2186was not called).
2187[clinic start generated code]*/
2188
2189static PyObject *
2190_asyncio_Task_cancel_impl(TaskObj *self)
2191/*[clinic end generated code: output=6bfc0479da9d5757 input=13f9bf496695cb52]*/
2192{
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +00002193 self->task_log_tb = 0;
2194
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002195 if (self->task_state != STATE_PENDING) {
2196 Py_RETURN_FALSE;
2197 }
2198
2199 if (self->task_fut_waiter) {
2200 PyObject *res;
2201 int is_true;
2202
2203 res = _PyObject_CallMethodId(
2204 self->task_fut_waiter, &PyId_cancel, NULL);
2205 if (res == NULL) {
2206 return NULL;
2207 }
2208
2209 is_true = PyObject_IsTrue(res);
2210 Py_DECREF(res);
2211 if (is_true < 0) {
2212 return NULL;
2213 }
2214
2215 if (is_true) {
2216 Py_RETURN_TRUE;
2217 }
2218 }
2219
2220 self->task_must_cancel = 1;
2221 Py_RETURN_TRUE;
2222}
2223
2224/*[clinic input]
2225_asyncio.Task.get_stack
2226
2227 *
Serhiy Storchakabca49392017-09-03 08:10:14 +03002228 limit: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002229
2230Return the list of stack frames for this task's coroutine.
2231
2232If the coroutine is not done, this returns the stack where it is
2233suspended. If the coroutine has completed successfully or was
2234cancelled, this returns an empty list. If the coroutine was
2235terminated by an exception, this returns the list of traceback
2236frames.
2237
2238The frames are always ordered from oldest to newest.
2239
2240The optional limit gives the maximum number of frames to
2241return; by default all available frames are returned. Its
2242meaning differs depending on whether a stack or a traceback is
2243returned: the newest frames of a stack are returned, but the
2244oldest frames of a traceback are returned. (This matches the
2245behavior of the traceback module.)
2246
2247For reasons beyond our control, only one stack frame is
2248returned for a suspended coroutine.
2249[clinic start generated code]*/
2250
2251static PyObject *
2252_asyncio_Task_get_stack_impl(TaskObj *self, PyObject *limit)
Serhiy Storchakabca49392017-09-03 08:10:14 +03002253/*[clinic end generated code: output=c9aeeeebd1e18118 input=05b323d42b809b90]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002254{
2255 return PyObject_CallFunctionObjArgs(
2256 asyncio_task_get_stack_func, self, limit, NULL);
2257}
2258
2259/*[clinic input]
2260_asyncio.Task.print_stack
2261
2262 *
Serhiy Storchakabca49392017-09-03 08:10:14 +03002263 limit: object = None
2264 file: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002265
2266Print the stack or traceback for this task's coroutine.
2267
2268This produces output similar to that of the traceback module,
2269for the frames retrieved by get_stack(). The limit argument
2270is passed to get_stack(). The file argument is an I/O stream
2271to which the output is written; by default output is written
2272to sys.stderr.
2273[clinic start generated code]*/
2274
2275static PyObject *
2276_asyncio_Task_print_stack_impl(TaskObj *self, PyObject *limit,
2277 PyObject *file)
Serhiy Storchakabca49392017-09-03 08:10:14 +03002278/*[clinic end generated code: output=7339e10314cd3f4d input=1a0352913b7fcd92]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002279{
2280 return PyObject_CallFunctionObjArgs(
2281 asyncio_task_print_stack_func, self, limit, file, NULL);
2282}
2283
2284/*[clinic input]
Yury Selivanov0cf16f92017-12-25 10:48:15 -05002285_asyncio.Task.set_result
2286
2287 result: object
2288 /
2289[clinic start generated code]*/
2290
2291static PyObject *
2292_asyncio_Task_set_result(TaskObj *self, PyObject *result)
2293/*[clinic end generated code: output=1dcae308bfcba318 input=9d1a00c07be41bab]*/
2294{
2295 PyErr_SetString(PyExc_RuntimeError,
2296 "Task does not support set_result operation");
2297 return NULL;
2298}
2299
2300/*[clinic input]
2301_asyncio.Task.set_exception
2302
2303 exception: object
2304 /
2305[clinic start generated code]*/
2306
2307static PyObject *
2308_asyncio_Task_set_exception(TaskObj *self, PyObject *exception)
2309/*[clinic end generated code: output=bc377fc28067303d input=9a8f65c83dcf893a]*/
2310{
2311 PyErr_SetString(PyExc_RuntimeError,
Andrew Svetlovfc359322017-12-30 15:40:27 +02002312 "Task does not support set_exception operation");
Yury Selivanov0cf16f92017-12-25 10:48:15 -05002313 return NULL;
2314}
2315
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002316/*[clinic input]
Alex Grönholm98ef9202019-05-30 18:30:09 +03002317_asyncio.Task.get_coro
2318[clinic start generated code]*/
2319
2320static PyObject *
2321_asyncio_Task_get_coro_impl(TaskObj *self)
2322/*[clinic end generated code: output=bcac27c8cc6c8073 input=d2e8606c42a7b403]*/
2323{
2324 Py_INCREF(self->task_coro);
2325 return self->task_coro;
2326}
2327
2328/*[clinic input]
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002329_asyncio.Task.get_name
2330[clinic start generated code]*/
2331
2332static PyObject *
2333_asyncio_Task_get_name_impl(TaskObj *self)
2334/*[clinic end generated code: output=0ecf1570c3b37a8f input=a4a6595d12f4f0f8]*/
2335{
2336 if (self->task_name) {
2337 Py_INCREF(self->task_name);
2338 return self->task_name;
2339 }
2340
2341 Py_RETURN_NONE;
2342}
2343
2344/*[clinic input]
2345_asyncio.Task.set_name
2346
2347 value: object
2348 /
2349[clinic start generated code]*/
2350
2351static PyObject *
2352_asyncio_Task_set_name(TaskObj *self, PyObject *value)
2353/*[clinic end generated code: output=138a8d51e32057d6 input=a8359b6e65f8fd31]*/
2354{
Alex Grönholma7548232018-08-09 23:49:49 +03002355 if (!PyUnicode_CheckExact(value)) {
2356 value = PyObject_Str(value);
2357 if (value == NULL) {
2358 return NULL;
2359 }
2360 } else {
2361 Py_INCREF(value);
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002362 }
2363
Alex Grönholma7548232018-08-09 23:49:49 +03002364 Py_XSETREF(self->task_name, value);
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002365 Py_RETURN_NONE;
2366}
Yury Selivanov0cf16f92017-12-25 10:48:15 -05002367
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002368static void
2369TaskObj_finalize(TaskObj *task)
2370{
2371 _Py_IDENTIFIER(call_exception_handler);
2372 _Py_IDENTIFIER(task);
2373 _Py_IDENTIFIER(message);
2374 _Py_IDENTIFIER(source_traceback);
2375
Serhiy Storchakabca49392017-09-03 08:10:14 +03002376 PyObject *context;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002377 PyObject *message = NULL;
Serhiy Storchakabca49392017-09-03 08:10:14 +03002378 PyObject *func;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002379 PyObject *error_type, *error_value, *error_traceback;
2380
2381 if (task->task_state != STATE_PENDING || !task->task_log_destroy_pending) {
2382 goto done;
2383 }
2384
2385 /* Save the current exception, if any. */
2386 PyErr_Fetch(&error_type, &error_value, &error_traceback);
2387
2388 context = PyDict_New();
2389 if (context == NULL) {
2390 goto finally;
2391 }
2392
2393 message = PyUnicode_FromString("Task was destroyed but it is pending!");
2394 if (message == NULL) {
2395 goto finally;
2396 }
2397
2398 if (_PyDict_SetItemId(context, &PyId_message, message) < 0 ||
2399 _PyDict_SetItemId(context, &PyId_task, (PyObject*)task) < 0)
2400 {
2401 goto finally;
2402 }
2403
2404 if (task->task_source_tb != NULL) {
2405 if (_PyDict_SetItemId(context, &PyId_source_traceback,
2406 task->task_source_tb) < 0)
2407 {
2408 goto finally;
2409 }
2410 }
2411
2412 func = _PyObject_GetAttrId(task->task_loop, &PyId_call_exception_handler);
2413 if (func != NULL) {
Serhiy Storchakabca49392017-09-03 08:10:14 +03002414 PyObject *res = PyObject_CallFunctionObjArgs(func, context, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002415 if (res == NULL) {
2416 PyErr_WriteUnraisable(func);
2417 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03002418 else {
2419 Py_DECREF(res);
2420 }
2421 Py_DECREF(func);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002422 }
2423
2424finally:
Serhiy Storchakabca49392017-09-03 08:10:14 +03002425 Py_XDECREF(context);
2426 Py_XDECREF(message);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002427
2428 /* Restore the saved exception. */
2429 PyErr_Restore(error_type, error_value, error_traceback);
2430
2431done:
2432 FutureObj_finalize((FutureObj*)task);
2433}
2434
2435static void TaskObj_dealloc(PyObject *); /* Needs Task_CheckExact */
2436
2437static PyMethodDef TaskType_methods[] = {
2438 _ASYNCIO_FUTURE_RESULT_METHODDEF
2439 _ASYNCIO_FUTURE_EXCEPTION_METHODDEF
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002440 _ASYNCIO_FUTURE_ADD_DONE_CALLBACK_METHODDEF
2441 _ASYNCIO_FUTURE_REMOVE_DONE_CALLBACK_METHODDEF
2442 _ASYNCIO_FUTURE_CANCELLED_METHODDEF
2443 _ASYNCIO_FUTURE_DONE_METHODDEF
Yury Selivanov0cf16f92017-12-25 10:48:15 -05002444 _ASYNCIO_TASK_SET_RESULT_METHODDEF
2445 _ASYNCIO_TASK_SET_EXCEPTION_METHODDEF
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002446 _ASYNCIO_TASK_CURRENT_TASK_METHODDEF
2447 _ASYNCIO_TASK_ALL_TASKS_METHODDEF
2448 _ASYNCIO_TASK_CANCEL_METHODDEF
2449 _ASYNCIO_TASK_GET_STACK_METHODDEF
2450 _ASYNCIO_TASK_PRINT_STACK_METHODDEF
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002451 _ASYNCIO_TASK__REPR_INFO_METHODDEF
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002452 _ASYNCIO_TASK_GET_NAME_METHODDEF
2453 _ASYNCIO_TASK_SET_NAME_METHODDEF
Alex Grönholm98ef9202019-05-30 18:30:09 +03002454 _ASYNCIO_TASK_GET_CORO_METHODDEF
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002455 {NULL, NULL} /* Sentinel */
2456};
2457
2458static PyGetSetDef TaskType_getsetlist[] = {
2459 FUTURE_COMMON_GETSETLIST
2460 {"_log_destroy_pending", (getter)TaskObj_get_log_destroy_pending,
2461 (setter)TaskObj_set_log_destroy_pending, NULL},
2462 {"_must_cancel", (getter)TaskObj_get_must_cancel, NULL, NULL},
2463 {"_coro", (getter)TaskObj_get_coro, NULL, NULL},
2464 {"_fut_waiter", (getter)TaskObj_get_fut_waiter, NULL, NULL},
2465 {NULL} /* Sentinel */
2466};
2467
2468static PyTypeObject TaskType = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02002469 PyVarObject_HEAD_INIT(NULL, 0)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002470 "_asyncio.Task",
2471 sizeof(TaskObj), /* tp_basicsize */
2472 .tp_base = &FutureType,
2473 .tp_dealloc = TaskObj_dealloc,
2474 .tp_as_async = &FutureType_as_async,
2475 .tp_repr = (reprfunc)FutureObj_repr,
Antoine Pitrouada319b2019-05-29 22:12:38 +02002476 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002477 .tp_doc = _asyncio_Task___init____doc__,
2478 .tp_traverse = (traverseproc)TaskObj_traverse,
2479 .tp_clear = (inquiry)TaskObj_clear,
2480 .tp_weaklistoffset = offsetof(TaskObj, task_weakreflist),
2481 .tp_iter = (getiterfunc)future_new_iter,
2482 .tp_methods = TaskType_methods,
2483 .tp_getset = TaskType_getsetlist,
2484 .tp_dictoffset = offsetof(TaskObj, dict),
2485 .tp_init = (initproc)_asyncio_Task___init__,
2486 .tp_new = PyType_GenericNew,
2487 .tp_finalize = (destructor)TaskObj_finalize,
2488};
2489
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002490static void
2491TaskObj_dealloc(PyObject *self)
2492{
2493 TaskObj *task = (TaskObj *)self;
2494
2495 if (Task_CheckExact(self)) {
2496 /* When fut is subclass of Task, finalizer is called from
2497 * subtype_dealloc.
2498 */
2499 if (PyObject_CallFinalizerFromDealloc(self) < 0) {
2500 // resurrected.
2501 return;
2502 }
2503 }
2504
Alexander Mohrde34cbe2017-08-01 23:31:07 -07002505 PyObject_GC_UnTrack(self);
2506
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002507 if (task->task_weakreflist != NULL) {
2508 PyObject_ClearWeakRefs(self);
2509 }
2510
2511 (void)TaskObj_clear(task);
2512 Py_TYPE(task)->tp_free(task);
2513}
2514
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002515static int
2516task_call_step_soon(TaskObj *task, PyObject *arg)
2517{
Serhiy Storchakabca49392017-09-03 08:10:14 +03002518 PyObject *cb = TaskStepMethWrapper_new(task, arg);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002519 if (cb == NULL) {
2520 return -1;
2521 }
2522
Yury Selivanovf23746a2018-01-22 19:11:18 -05002523 int ret = call_soon(task->task_loop, cb, NULL, task->task_context);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002524 Py_DECREF(cb);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05002525 return ret;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002526}
2527
2528static PyObject *
2529task_set_error_soon(TaskObj *task, PyObject *et, const char *format, ...)
2530{
2531 PyObject* msg;
2532
2533 va_list vargs;
2534#ifdef HAVE_STDARG_PROTOTYPES
2535 va_start(vargs, format);
2536#else
2537 va_start(vargs);
2538#endif
2539 msg = PyUnicode_FromFormatV(format, vargs);
2540 va_end(vargs);
2541
2542 if (msg == NULL) {
2543 return NULL;
2544 }
2545
Victor Stinnerde4ae3d2016-12-04 22:59:09 +01002546 PyObject *e = PyObject_CallFunctionObjArgs(et, msg, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002547 Py_DECREF(msg);
2548 if (e == NULL) {
2549 return NULL;
2550 }
2551
2552 if (task_call_step_soon(task, e) == -1) {
2553 Py_DECREF(e);
2554 return NULL;
2555 }
2556
2557 Py_DECREF(e);
2558 Py_RETURN_NONE;
2559}
2560
2561static PyObject *
2562task_step_impl(TaskObj *task, PyObject *exc)
2563{
2564 int res;
2565 int clear_exc = 0;
2566 PyObject *result = NULL;
Serhiy Storchakabca49392017-09-03 08:10:14 +03002567 PyObject *coro;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002568 PyObject *o;
2569
2570 if (task->task_state != STATE_PENDING) {
Yury Selivanov0cf16f92017-12-25 10:48:15 -05002571 PyErr_Format(asyncio_InvalidStateError,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002572 "_step(): already done: %R %R",
2573 task,
2574 exc ? exc : Py_None);
INADA Naokic411a7d2016-10-18 11:48:14 +09002575 goto fail;
2576 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09002577
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002578 if (task->task_must_cancel) {
2579 assert(exc != Py_None);
2580
2581 if (exc) {
2582 /* Check if exc is a CancelledError */
2583 res = PyObject_IsInstance(exc, asyncio_CancelledError);
2584 if (res == -1) {
2585 /* An error occurred, abort */
2586 goto fail;
2587 }
2588 if (res == 0) {
2589 /* exc is not CancelledError; reset it to NULL */
2590 exc = NULL;
2591 }
2592 }
2593
2594 if (!exc) {
2595 /* exc was not a CancelledError */
Victor Stinner2ff58a22019-06-17 14:27:23 +02002596 exc = PyObject_CallNoArgs(asyncio_CancelledError);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002597 if (!exc) {
2598 goto fail;
2599 }
2600 clear_exc = 1;
2601 }
2602
2603 task->task_must_cancel = 0;
2604 }
2605
2606 Py_CLEAR(task->task_fut_waiter);
2607
Serhiy Storchakabca49392017-09-03 08:10:14 +03002608 coro = task->task_coro;
2609 if (coro == NULL) {
2610 PyErr_SetString(PyExc_RuntimeError, "uninitialized Task object");
2611 return NULL;
2612 }
2613
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002614 if (exc == NULL) {
2615 if (PyGen_CheckExact(coro) || PyCoro_CheckExact(coro)) {
2616 result = _PyGen_Send((PyGenObject*)coro, Py_None);
2617 }
2618 else {
Victor Stinnerb6ed57d2016-12-09 14:24:02 +01002619 result = _PyObject_CallMethodIdObjArgs(coro, &PyId_send,
2620 Py_None, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002621 }
2622 }
2623 else {
Victor Stinnerb6ed57d2016-12-09 14:24:02 +01002624 result = _PyObject_CallMethodIdObjArgs(coro, &PyId_throw,
2625 exc, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002626 if (clear_exc) {
2627 /* We created 'exc' during this call */
Serhiy Storchakabca49392017-09-03 08:10:14 +03002628 Py_DECREF(exc);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002629 }
2630 }
2631
2632 if (result == NULL) {
2633 PyObject *et, *ev, *tb;
2634
2635 if (_PyGen_FetchStopIterationValue(&o) == 0) {
2636 /* The error is StopIteration and that means that
2637 the underlying coroutine has resolved */
INADA Naoki991adca2017-05-11 21:18:38 +09002638 if (task->task_must_cancel) {
2639 // Task is cancelled right before coro stops.
2640 Py_DECREF(o);
2641 task->task_must_cancel = 0;
2642 et = asyncio_CancelledError;
2643 Py_INCREF(et);
2644 ev = NULL;
2645 tb = NULL;
2646 goto set_exception;
2647 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002648 PyObject *res = future_set_result((FutureObj*)task, o);
2649 Py_DECREF(o);
2650 if (res == NULL) {
2651 return NULL;
2652 }
2653 Py_DECREF(res);
2654 Py_RETURN_NONE;
2655 }
2656
2657 if (PyErr_ExceptionMatches(asyncio_CancelledError)) {
2658 /* CancelledError */
2659 PyErr_Clear();
2660 return future_cancel((FutureObj*)task);
2661 }
2662
2663 /* Some other exception; pop it and call Task.set_exception() */
2664 PyErr_Fetch(&et, &ev, &tb);
INADA Naoki991adca2017-05-11 21:18:38 +09002665
2666set_exception:
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002667 assert(et);
2668 if (!ev || !PyObject_TypeCheck(ev, (PyTypeObject *) et)) {
2669 PyErr_NormalizeException(&et, &ev, &tb);
2670 }
Yury Selivanovedfe8862016-12-01 11:37:47 -05002671 if (tb != NULL) {
2672 PyException_SetTraceback(ev, tb);
2673 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002674 o = future_set_exception((FutureObj*)task, ev);
2675 if (!o) {
2676 /* An exception in Task.set_exception() */
Serhiy Storchakabca49392017-09-03 08:10:14 +03002677 Py_DECREF(et);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002678 Py_XDECREF(tb);
2679 Py_XDECREF(ev);
2680 goto fail;
2681 }
2682 assert(o == Py_None);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002683 Py_DECREF(o);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002684
Yury Selivanov431b5402019-05-27 14:45:12 +02002685 if (PyErr_GivenExceptionMatches(et, PyExc_KeyboardInterrupt) ||
2686 PyErr_GivenExceptionMatches(et, PyExc_SystemExit))
2687 {
2688 /* We've got a KeyboardInterrupt or a SystemError; re-raise it */
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002689 PyErr_Restore(et, ev, tb);
2690 goto fail;
2691 }
2692
Serhiy Storchakabca49392017-09-03 08:10:14 +03002693 Py_DECREF(et);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002694 Py_XDECREF(tb);
2695 Py_XDECREF(ev);
2696
2697 Py_RETURN_NONE;
2698 }
2699
2700 if (result == (PyObject*)task) {
2701 /* We have a task that wants to await on itself */
2702 goto self_await;
2703 }
2704
2705 /* Check if `result` is FutureObj or TaskObj (and not a subclass) */
2706 if (Future_CheckExact(result) || Task_CheckExact(result)) {
2707 PyObject *wrapper;
2708 PyObject *res;
2709 FutureObj *fut = (FutureObj*)result;
2710
2711 /* Check if `result` future is attached to a different loop */
2712 if (fut->fut_loop != task->task_loop) {
2713 goto different_loop;
2714 }
2715
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002716 if (!fut->fut_blocking) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002717 goto yield_insteadof_yf;
2718 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002719
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002720 fut->fut_blocking = 0;
2721
2722 /* result.add_done_callback(task._wakeup) */
2723 wrapper = TaskWakeupMethWrapper_new(task);
2724 if (wrapper == NULL) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002725 goto fail;
2726 }
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002727 res = future_add_done_callback(
2728 (FutureObj*)result, wrapper, task->task_context);
2729 Py_DECREF(wrapper);
2730 if (res == NULL) {
2731 goto fail;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002732 }
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002733 Py_DECREF(res);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002734
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002735 /* task._fut_waiter = result */
2736 task->task_fut_waiter = result; /* no incref is necessary */
2737
2738 if (task->task_must_cancel) {
2739 PyObject *r;
Elvis Pranskevichus0c797a62018-10-03 10:30:31 -04002740 int is_true;
Serhiy Storchakaaddf8af2018-10-05 21:20:02 +03002741 r = _PyObject_CallMethodId(result, &PyId_cancel, NULL);
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002742 if (r == NULL) {
2743 return NULL;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002744 }
Elvis Pranskevichus0c797a62018-10-03 10:30:31 -04002745 is_true = PyObject_IsTrue(r);
2746 Py_DECREF(r);
2747 if (is_true < 0) {
2748 return NULL;
2749 }
2750 else if (is_true) {
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002751 task->task_must_cancel = 0;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002752 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002753 }
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002754
2755 Py_RETURN_NONE;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002756 }
2757
2758 /* Check if `result` is None */
2759 if (result == Py_None) {
2760 /* Bare yield relinquishes control for one event loop iteration. */
2761 if (task_call_step_soon(task, NULL)) {
2762 goto fail;
2763 }
2764 return result;
2765 }
2766
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002767 /* Check if `result` is a Future-compatible object */
2768 if (_PyObject_LookupAttrId(result, &PyId__asyncio_future_blocking, &o) < 0) {
2769 goto fail;
2770 }
2771 if (o != NULL && o != Py_None) {
2772 /* `result` is a Future-compatible object */
2773 PyObject *wrapper;
2774 PyObject *res;
2775
2776 int blocking = PyObject_IsTrue(o);
2777 Py_DECREF(o);
2778 if (blocking < 0) {
2779 goto fail;
2780 }
2781
2782 /* Check if `result` future is attached to a different loop */
2783 PyObject *oloop = get_future_loop(result);
2784 if (oloop == NULL) {
2785 goto fail;
2786 }
2787 if (oloop != task->task_loop) {
2788 Py_DECREF(oloop);
2789 goto different_loop;
2790 }
2791 Py_DECREF(oloop);
2792
2793 if (!blocking) {
2794 goto yield_insteadof_yf;
2795 }
2796
2797 /* result._asyncio_future_blocking = False */
2798 if (_PyObject_SetAttrId(
2799 result, &PyId__asyncio_future_blocking, Py_False) == -1) {
2800 goto fail;
2801 }
2802
2803 wrapper = TaskWakeupMethWrapper_new(task);
2804 if (wrapper == NULL) {
2805 goto fail;
2806 }
2807
2808 /* result.add_done_callback(task._wakeup) */
2809 PyObject *add_cb = _PyObject_GetAttrId(
2810 result, &PyId_add_done_callback);
2811 if (add_cb == NULL) {
2812 Py_DECREF(wrapper);
2813 goto fail;
2814 }
2815 PyObject *stack[2];
2816 stack[0] = wrapper;
2817 stack[1] = (PyObject *)task->task_context;
Jeroen Demeyeraacc77f2019-05-29 20:31:52 +02002818 res = _PyObject_Vectorcall(add_cb, stack, 1, context_kwname);
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002819 Py_DECREF(add_cb);
2820 Py_DECREF(wrapper);
2821 if (res == NULL) {
2822 goto fail;
2823 }
2824 Py_DECREF(res);
2825
2826 /* task._fut_waiter = result */
2827 task->task_fut_waiter = result; /* no incref is necessary */
2828
2829 if (task->task_must_cancel) {
2830 PyObject *r;
2831 int is_true;
2832 r = _PyObject_CallMethodId(result, &PyId_cancel, NULL);
2833 if (r == NULL) {
2834 return NULL;
2835 }
2836 is_true = PyObject_IsTrue(r);
2837 Py_DECREF(r);
2838 if (is_true < 0) {
2839 return NULL;
2840 }
2841 else if (is_true) {
2842 task->task_must_cancel = 0;
2843 }
2844 }
2845
2846 Py_RETURN_NONE;
2847 }
2848
2849 Py_XDECREF(o);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002850 /* Check if `result` is a generator */
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002851 res = PyObject_IsInstance(result, (PyObject*)&PyGen_Type);
2852 if (res < 0) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002853 goto fail;
2854 }
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002855 if (res) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002856 /* `result` is a generator */
Serhiy Storchaka66553542018-05-20 16:30:31 +03002857 o = task_set_error_soon(
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002858 task, PyExc_RuntimeError,
2859 "yield was used instead of yield from for "
Serhiy Storchaka66553542018-05-20 16:30:31 +03002860 "generator in task %R with %R", task, result);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002861 Py_DECREF(result);
Serhiy Storchaka66553542018-05-20 16:30:31 +03002862 return o;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002863 }
2864
2865 /* The `result` is none of the above */
Serhiy Storchaka66553542018-05-20 16:30:31 +03002866 o = task_set_error_soon(
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002867 task, PyExc_RuntimeError, "Task got bad yield: %R", result);
Serhiy Storchaka66553542018-05-20 16:30:31 +03002868 Py_DECREF(result);
2869 return o;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002870
2871self_await:
2872 o = task_set_error_soon(
2873 task, PyExc_RuntimeError,
2874 "Task cannot await on itself: %R", task);
2875 Py_DECREF(result);
2876 return o;
2877
2878yield_insteadof_yf:
2879 o = task_set_error_soon(
2880 task, PyExc_RuntimeError,
2881 "yield was used instead of yield from "
2882 "in task %R with %R",
2883 task, result);
2884 Py_DECREF(result);
2885 return o;
2886
2887different_loop:
2888 o = task_set_error_soon(
2889 task, PyExc_RuntimeError,
2890 "Task %R got Future %R attached to a different loop",
2891 task, result);
2892 Py_DECREF(result);
2893 return o;
2894
2895fail:
2896 Py_XDECREF(result);
2897 return NULL;
2898}
2899
2900static PyObject *
2901task_step(TaskObj *task, PyObject *exc)
2902{
2903 PyObject *res;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002904
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002905 if (enter_task(task->task_loop, (PyObject*)task) < 0) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002906 return NULL;
2907 }
2908
2909 res = task_step_impl(task, exc);
2910
2911 if (res == NULL) {
2912 PyObject *et, *ev, *tb;
2913 PyErr_Fetch(&et, &ev, &tb);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002914 leave_task(task->task_loop, (PyObject*)task);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002915 _PyErr_ChainExceptions(et, ev, tb);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002916 return NULL;
2917 }
2918 else {
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002919 if (leave_task(task->task_loop, (PyObject*)task) < 0) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002920 Py_DECREF(res);
2921 return NULL;
2922 }
2923 else {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002924 return res;
2925 }
2926 }
2927}
2928
2929static PyObject *
2930task_wakeup(TaskObj *task, PyObject *o)
2931{
Serhiy Storchakabca49392017-09-03 08:10:14 +03002932 PyObject *et, *ev, *tb;
2933 PyObject *result;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002934 assert(o);
2935
2936 if (Future_CheckExact(o) || Task_CheckExact(o)) {
2937 PyObject *fut_result = NULL;
2938 int res = future_get_result((FutureObj*)o, &fut_result);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002939
2940 switch(res) {
2941 case -1:
2942 assert(fut_result == NULL);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002943 break; /* exception raised */
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002944 case 0:
2945 Py_DECREF(fut_result);
Yury Selivanov22feeb82018-01-24 11:31:01 -05002946 return task_step(task, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002947 default:
2948 assert(res == 1);
Yury Selivanov22feeb82018-01-24 11:31:01 -05002949 result = task_step(task, fut_result);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002950 Py_DECREF(fut_result);
2951 return result;
2952 }
2953 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002954 else {
Serhiy Storchakabca49392017-09-03 08:10:14 +03002955 PyObject *fut_result = PyObject_CallMethod(o, "result", NULL);
2956 if (fut_result != NULL) {
2957 Py_DECREF(fut_result);
Yury Selivanov22feeb82018-01-24 11:31:01 -05002958 return task_step(task, NULL);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002959 }
2960 /* exception raised */
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002961 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03002962
2963 PyErr_Fetch(&et, &ev, &tb);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002964 if (!ev || !PyObject_TypeCheck(ev, (PyTypeObject *) et)) {
2965 PyErr_NormalizeException(&et, &ev, &tb);
2966 }
2967
Yury Selivanov22feeb82018-01-24 11:31:01 -05002968 result = task_step(task, ev);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002969
2970 Py_DECREF(et);
2971 Py_XDECREF(tb);
2972 Py_XDECREF(ev);
2973
2974 return result;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002975}
2976
2977
Yury Selivanova70232f2017-12-13 14:49:42 -05002978/*********************** Functions **************************/
2979
2980
2981/*[clinic input]
2982_asyncio._get_running_loop
2983
2984Return the running event loop or None.
2985
2986This is a low-level function intended to be used by event loops.
2987This function is thread-specific.
2988
2989[clinic start generated code]*/
2990
2991static PyObject *
2992_asyncio__get_running_loop_impl(PyObject *module)
2993/*[clinic end generated code: output=b4390af721411a0a input=0a21627e25a4bd43]*/
2994{
2995 PyObject *loop;
2996 if (get_running_loop(&loop)) {
2997 return NULL;
2998 }
2999 if (loop == NULL) {
3000 /* There's no currently running event loop */
3001 Py_RETURN_NONE;
3002 }
3003 return loop;
3004}
3005
3006/*[clinic input]
3007_asyncio._set_running_loop
3008 loop: 'O'
3009 /
3010
3011Set the running event loop.
3012
3013This is a low-level function intended to be used by event loops.
3014This function is thread-specific.
3015[clinic start generated code]*/
3016
3017static PyObject *
3018_asyncio__set_running_loop(PyObject *module, PyObject *loop)
3019/*[clinic end generated code: output=ae56bf7a28ca189a input=4c9720233d606604]*/
3020{
3021 if (set_running_loop(loop)) {
3022 return NULL;
3023 }
3024 Py_RETURN_NONE;
3025}
3026
3027/*[clinic input]
3028_asyncio.get_event_loop
3029
3030Return an asyncio event loop.
3031
3032When called from a coroutine or a callback (e.g. scheduled with
3033call_soon or similar API), this function will always return the
3034running event loop.
3035
3036If there is no running event loop set, the function will return
3037the result of `get_event_loop_policy().get_event_loop()` call.
3038[clinic start generated code]*/
3039
3040static PyObject *
3041_asyncio_get_event_loop_impl(PyObject *module)
3042/*[clinic end generated code: output=2a2d8b2f824c648b input=9364bf2916c8655d]*/
3043{
3044 return get_event_loop();
3045}
3046
3047/*[clinic input]
3048_asyncio.get_running_loop
3049
3050Return the running event loop. Raise a RuntimeError if there is none.
3051
3052This function is thread-specific.
3053[clinic start generated code]*/
3054
3055static PyObject *
3056_asyncio_get_running_loop_impl(PyObject *module)
3057/*[clinic end generated code: output=c247b5f9e529530e input=2a3bf02ba39f173d]*/
3058{
3059 PyObject *loop;
3060 if (get_running_loop(&loop)) {
3061 return NULL;
3062 }
3063 if (loop == NULL) {
3064 /* There's no currently running event loop */
3065 PyErr_SetString(
3066 PyExc_RuntimeError, "no running event loop");
3067 }
3068 return loop;
3069}
3070
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003071/*[clinic input]
3072_asyncio._register_task
3073
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003074 task: object
3075
3076Register a new task in asyncio as executed by loop.
3077
3078Returns None.
3079[clinic start generated code]*/
3080
3081static PyObject *
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003082_asyncio__register_task_impl(PyObject *module, PyObject *task)
3083/*[clinic end generated code: output=8672dadd69a7d4e2 input=21075aaea14dfbad]*/
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003084{
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003085 if (register_task(task) < 0) {
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003086 return NULL;
3087 }
3088 Py_RETURN_NONE;
3089}
3090
3091
3092/*[clinic input]
3093_asyncio._unregister_task
3094
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003095 task: object
3096
3097Unregister a task.
3098
3099Returns None.
3100[clinic start generated code]*/
3101
3102static PyObject *
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003103_asyncio__unregister_task_impl(PyObject *module, PyObject *task)
3104/*[clinic end generated code: output=6e5585706d568a46 input=28fb98c3975f7bdc]*/
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003105{
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003106 if (unregister_task(task) < 0) {
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003107 return NULL;
3108 }
3109 Py_RETURN_NONE;
3110}
3111
3112
3113/*[clinic input]
3114_asyncio._enter_task
3115
3116 loop: object
3117 task: object
3118
3119Enter into task execution or resume suspended task.
3120
3121Task belongs to loop.
3122
3123Returns None.
3124[clinic start generated code]*/
3125
3126static PyObject *
3127_asyncio__enter_task_impl(PyObject *module, PyObject *loop, PyObject *task)
3128/*[clinic end generated code: output=a22611c858035b73 input=de1b06dca70d8737]*/
3129{
3130 if (enter_task(loop, task) < 0) {
3131 return NULL;
3132 }
3133 Py_RETURN_NONE;
3134}
3135
3136
3137/*[clinic input]
3138_asyncio._leave_task
3139
3140 loop: object
3141 task: object
3142
3143Leave task execution or suspend a task.
3144
3145Task belongs to loop.
3146
3147Returns None.
3148[clinic start generated code]*/
3149
3150static PyObject *
3151_asyncio__leave_task_impl(PyObject *module, PyObject *loop, PyObject *task)
3152/*[clinic end generated code: output=0ebf6db4b858fb41 input=51296a46313d1ad8]*/
3153{
3154 if (leave_task(loop, task) < 0) {
3155 return NULL;
3156 }
3157 Py_RETURN_NONE;
3158}
3159
Yury Selivanova70232f2017-12-13 14:49:42 -05003160
Yury Selivanov9d411c12018-01-23 15:10:03 -05003161/*********************** PyRunningLoopHolder ********************/
3162
3163
3164static PyRunningLoopHolder *
3165new_running_loop_holder(PyObject *loop)
3166{
3167 PyRunningLoopHolder *rl = PyObject_New(
3168 PyRunningLoopHolder, &PyRunningLoopHolder_Type);
3169 if (rl == NULL) {
3170 return NULL;
3171 }
3172
3173#if defined(HAVE_GETPID) && !defined(MS_WINDOWS)
3174 rl->rl_pid = getpid();
3175#endif
3176
3177 Py_INCREF(loop);
3178 rl->rl_loop = loop;
3179
3180 return rl;
3181}
3182
3183
3184static void
3185PyRunningLoopHolder_tp_dealloc(PyRunningLoopHolder *rl)
3186{
3187 Py_CLEAR(rl->rl_loop);
3188 PyObject_Free(rl);
3189}
3190
3191
3192static PyTypeObject PyRunningLoopHolder_Type = {
3193 PyVarObject_HEAD_INIT(NULL, 0)
3194 "_RunningLoopHolder",
3195 sizeof(PyRunningLoopHolder),
3196 .tp_getattro = PyObject_GenericGetAttr,
3197 .tp_flags = Py_TPFLAGS_DEFAULT,
3198 .tp_dealloc = (destructor)PyRunningLoopHolder_tp_dealloc,
3199};
3200
3201
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003202/*********************** Module **************************/
3203
3204
3205static void
Zackery Spytze40ad792017-12-19 11:48:13 -07003206module_free_freelists(void)
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05003207{
3208 PyObject *next;
3209 PyObject *current;
3210
3211 next = (PyObject*) fi_freelist;
3212 while (next != NULL) {
3213 assert(fi_freelist_len > 0);
3214 fi_freelist_len--;
3215
3216 current = next;
3217 next = (PyObject*) ((futureiterobject*) current)->future;
3218 PyObject_GC_Del(current);
3219 }
3220 assert(fi_freelist_len == 0);
3221 fi_freelist = NULL;
3222}
3223
3224
3225static void
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003226module_free(void *m)
3227{
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003228 Py_CLEAR(asyncio_mod);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003229 Py_CLEAR(traceback_extract_stack);
3230 Py_CLEAR(asyncio_future_repr_info_func);
3231 Py_CLEAR(asyncio_get_event_loop_policy);
3232 Py_CLEAR(asyncio_iscoroutine_func);
3233 Py_CLEAR(asyncio_task_get_stack_func);
3234 Py_CLEAR(asyncio_task_print_stack_func);
3235 Py_CLEAR(asyncio_task_repr_info_func);
3236 Py_CLEAR(asyncio_InvalidStateError);
3237 Py_CLEAR(asyncio_CancelledError);
3238
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003239 Py_CLEAR(all_tasks);
Yury Selivanova9d7e552017-12-19 07:18:45 -05003240 Py_CLEAR(current_tasks);
3241 Py_CLEAR(iscoroutine_typecache);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05003242
Yury Selivanovf23746a2018-01-22 19:11:18 -05003243 Py_CLEAR(context_kwname);
3244
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05003245 module_free_freelists();
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003246}
3247
3248static int
3249module_init(void)
3250{
3251 PyObject *module = NULL;
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003252
3253 asyncio_mod = PyImport_ImportModule("asyncio");
3254 if (asyncio_mod == NULL) {
3255 goto fail;
3256 }
3257
3258 current_tasks = PyDict_New();
3259 if (current_tasks == NULL) {
3260 goto fail;
3261 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003262
Yury Selivanova9d7e552017-12-19 07:18:45 -05003263 iscoroutine_typecache = PySet_New(NULL);
3264 if (iscoroutine_typecache == NULL) {
3265 goto fail;
3266 }
3267
Yury Selivanovf23746a2018-01-22 19:11:18 -05003268
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03003269 context_kwname = Py_BuildValue("(s)", "context");
Yury Selivanovf23746a2018-01-22 19:11:18 -05003270 if (context_kwname == NULL) {
3271 goto fail;
3272 }
Yury Selivanovf23746a2018-01-22 19:11:18 -05003273
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003274#define WITH_MOD(NAME) \
3275 Py_CLEAR(module); \
3276 module = PyImport_ImportModule(NAME); \
3277 if (module == NULL) { \
Serhiy Storchakabca49392017-09-03 08:10:14 +03003278 goto fail; \
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003279 }
3280
3281#define GET_MOD_ATTR(VAR, NAME) \
3282 VAR = PyObject_GetAttrString(module, NAME); \
3283 if (VAR == NULL) { \
3284 goto fail; \
3285 }
3286
3287 WITH_MOD("asyncio.events")
Yury Selivanova70232f2017-12-13 14:49:42 -05003288 GET_MOD_ATTR(asyncio_get_event_loop_policy, "get_event_loop_policy")
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003289
3290 WITH_MOD("asyncio.base_futures")
3291 GET_MOD_ATTR(asyncio_future_repr_info_func, "_future_repr_info")
Andrew Svetlov0baa72f2018-09-11 10:13:04 -07003292
3293 WITH_MOD("asyncio.exceptions")
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003294 GET_MOD_ATTR(asyncio_InvalidStateError, "InvalidStateError")
3295 GET_MOD_ATTR(asyncio_CancelledError, "CancelledError")
3296
3297 WITH_MOD("asyncio.base_tasks")
3298 GET_MOD_ATTR(asyncio_task_repr_info_func, "_task_repr_info")
3299 GET_MOD_ATTR(asyncio_task_get_stack_func, "_task_get_stack")
3300 GET_MOD_ATTR(asyncio_task_print_stack_func, "_task_print_stack")
3301
Andrew Svetlovf74ef452017-12-15 07:04:38 +02003302 WITH_MOD("asyncio.coroutines")
3303 GET_MOD_ATTR(asyncio_iscoroutine_func, "iscoroutine")
3304
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003305 WITH_MOD("traceback")
3306 GET_MOD_ATTR(traceback_extract_stack, "extract_stack")
3307
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003308 PyObject *weak_set;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003309 WITH_MOD("weakref")
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003310 GET_MOD_ATTR(weak_set, "WeakSet");
Victor Stinner2ff58a22019-06-17 14:27:23 +02003311 all_tasks = PyObject_CallNoArgs(weak_set);
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003312 Py_CLEAR(weak_set);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003313 if (all_tasks == NULL) {
INADA Naokic411a7d2016-10-18 11:48:14 +09003314 goto fail;
3315 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003316
Serhiy Storchakabca49392017-09-03 08:10:14 +03003317 Py_DECREF(module);
INADA Naokic411a7d2016-10-18 11:48:14 +09003318 return 0;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003319
INADA Naokic411a7d2016-10-18 11:48:14 +09003320fail:
INADA Naokic411a7d2016-10-18 11:48:14 +09003321 Py_CLEAR(module);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003322 module_free(NULL);
INADA Naokic411a7d2016-10-18 11:48:14 +09003323 return -1;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003324
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003325#undef WITH_MOD
3326#undef GET_MOD_ATTR
3327}
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003328
INADA Naokic411a7d2016-10-18 11:48:14 +09003329PyDoc_STRVAR(module_doc, "Accelerator module for asyncio");
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003330
Yury Selivanova70232f2017-12-13 14:49:42 -05003331static PyMethodDef asyncio_methods[] = {
3332 _ASYNCIO_GET_EVENT_LOOP_METHODDEF
3333 _ASYNCIO_GET_RUNNING_LOOP_METHODDEF
3334 _ASYNCIO__GET_RUNNING_LOOP_METHODDEF
3335 _ASYNCIO__SET_RUNNING_LOOP_METHODDEF
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003336 _ASYNCIO__REGISTER_TASK_METHODDEF
3337 _ASYNCIO__UNREGISTER_TASK_METHODDEF
3338 _ASYNCIO__ENTER_TASK_METHODDEF
3339 _ASYNCIO__LEAVE_TASK_METHODDEF
Yury Selivanova70232f2017-12-13 14:49:42 -05003340 {NULL, NULL}
3341};
3342
INADA Naoki9f2ce252016-10-15 15:39:19 +09003343static struct PyModuleDef _asynciomodule = {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003344 PyModuleDef_HEAD_INIT, /* m_base */
INADA Naoki9f2ce252016-10-15 15:39:19 +09003345 "_asyncio", /* m_name */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003346 module_doc, /* m_doc */
3347 -1, /* m_size */
Yury Selivanova70232f2017-12-13 14:49:42 -05003348 asyncio_methods, /* m_methods */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003349 NULL, /* m_slots */
3350 NULL, /* m_traverse */
3351 NULL, /* m_clear */
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003352 (freefunc)module_free /* m_free */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003353};
3354
3355
3356PyMODINIT_FUNC
INADA Naoki9f2ce252016-10-15 15:39:19 +09003357PyInit__asyncio(void)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003358{
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003359 if (module_init() < 0) {
INADA Naokic411a7d2016-10-18 11:48:14 +09003360 return NULL;
3361 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003362 if (PyType_Ready(&FutureType) < 0) {
3363 return NULL;
3364 }
3365 if (PyType_Ready(&FutureIterType) < 0) {
3366 return NULL;
3367 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03003368 if (PyType_Ready(&TaskStepMethWrapper_Type) < 0) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003369 return NULL;
3370 }
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03003371 if (PyType_Ready(&TaskWakeupMethWrapper_Type) < 0) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003372 return NULL;
3373 }
3374 if (PyType_Ready(&TaskType) < 0) {
3375 return NULL;
3376 }
Yury Selivanov9d411c12018-01-23 15:10:03 -05003377 if (PyType_Ready(&PyRunningLoopHolder_Type) < 0) {
3378 return NULL;
3379 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003380
INADA Naoki9f2ce252016-10-15 15:39:19 +09003381 PyObject *m = PyModule_Create(&_asynciomodule);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003382 if (m == NULL) {
3383 return NULL;
3384 }
3385
3386 Py_INCREF(&FutureType);
3387 if (PyModule_AddObject(m, "Future", (PyObject *)&FutureType) < 0) {
3388 Py_DECREF(&FutureType);
3389 return NULL;
3390 }
3391
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003392 Py_INCREF(&TaskType);
3393 if (PyModule_AddObject(m, "Task", (PyObject *)&TaskType) < 0) {
3394 Py_DECREF(&TaskType);
3395 return NULL;
3396 }
3397
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003398 Py_INCREF(all_tasks);
3399 if (PyModule_AddObject(m, "_all_tasks", all_tasks) < 0) {
3400 Py_DECREF(all_tasks);
3401 return NULL;
3402 }
3403
3404 Py_INCREF(current_tasks);
3405 if (PyModule_AddObject(m, "_current_tasks", current_tasks) < 0) {
3406 Py_DECREF(current_tasks);
3407 return NULL;
3408 }
3409
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003410 return m;
3411}