blob: d8b631b7c7a2923d72db5c1dc76b23d1ae06775a [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) {
219 PyObject *res = _PyObject_CallNoArg(getloop);
220 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
331 policy = _PyObject_CallNoArg(asyncio_get_event_loop_policy);
332 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 */
Oren Milmand019bc82018-02-13 12:28:33 +0200513 fut->fut_source_tb = _PyObject_CallNoArg(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 Stinnera5ed5f02016-12-06 18:45:50 +0100556 exc_val = _PyObject_CallNoArg(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]
2317_asyncio.Task.get_name
2318[clinic start generated code]*/
2319
2320static PyObject *
2321_asyncio_Task_get_name_impl(TaskObj *self)
2322/*[clinic end generated code: output=0ecf1570c3b37a8f input=a4a6595d12f4f0f8]*/
2323{
2324 if (self->task_name) {
2325 Py_INCREF(self->task_name);
2326 return self->task_name;
2327 }
2328
2329 Py_RETURN_NONE;
2330}
2331
2332/*[clinic input]
2333_asyncio.Task.set_name
2334
2335 value: object
2336 /
2337[clinic start generated code]*/
2338
2339static PyObject *
2340_asyncio_Task_set_name(TaskObj *self, PyObject *value)
2341/*[clinic end generated code: output=138a8d51e32057d6 input=a8359b6e65f8fd31]*/
2342{
Alex Grönholma7548232018-08-09 23:49:49 +03002343 if (!PyUnicode_CheckExact(value)) {
2344 value = PyObject_Str(value);
2345 if (value == NULL) {
2346 return NULL;
2347 }
2348 } else {
2349 Py_INCREF(value);
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002350 }
2351
Alex Grönholma7548232018-08-09 23:49:49 +03002352 Py_XSETREF(self->task_name, value);
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002353 Py_RETURN_NONE;
2354}
Yury Selivanov0cf16f92017-12-25 10:48:15 -05002355
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002356static void
2357TaskObj_finalize(TaskObj *task)
2358{
2359 _Py_IDENTIFIER(call_exception_handler);
2360 _Py_IDENTIFIER(task);
2361 _Py_IDENTIFIER(message);
2362 _Py_IDENTIFIER(source_traceback);
2363
Serhiy Storchakabca49392017-09-03 08:10:14 +03002364 PyObject *context;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002365 PyObject *message = NULL;
Serhiy Storchakabca49392017-09-03 08:10:14 +03002366 PyObject *func;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002367 PyObject *error_type, *error_value, *error_traceback;
2368
2369 if (task->task_state != STATE_PENDING || !task->task_log_destroy_pending) {
2370 goto done;
2371 }
2372
2373 /* Save the current exception, if any. */
2374 PyErr_Fetch(&error_type, &error_value, &error_traceback);
2375
2376 context = PyDict_New();
2377 if (context == NULL) {
2378 goto finally;
2379 }
2380
2381 message = PyUnicode_FromString("Task was destroyed but it is pending!");
2382 if (message == NULL) {
2383 goto finally;
2384 }
2385
2386 if (_PyDict_SetItemId(context, &PyId_message, message) < 0 ||
2387 _PyDict_SetItemId(context, &PyId_task, (PyObject*)task) < 0)
2388 {
2389 goto finally;
2390 }
2391
2392 if (task->task_source_tb != NULL) {
2393 if (_PyDict_SetItemId(context, &PyId_source_traceback,
2394 task->task_source_tb) < 0)
2395 {
2396 goto finally;
2397 }
2398 }
2399
2400 func = _PyObject_GetAttrId(task->task_loop, &PyId_call_exception_handler);
2401 if (func != NULL) {
Serhiy Storchakabca49392017-09-03 08:10:14 +03002402 PyObject *res = PyObject_CallFunctionObjArgs(func, context, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002403 if (res == NULL) {
2404 PyErr_WriteUnraisable(func);
2405 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03002406 else {
2407 Py_DECREF(res);
2408 }
2409 Py_DECREF(func);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002410 }
2411
2412finally:
Serhiy Storchakabca49392017-09-03 08:10:14 +03002413 Py_XDECREF(context);
2414 Py_XDECREF(message);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002415
2416 /* Restore the saved exception. */
2417 PyErr_Restore(error_type, error_value, error_traceback);
2418
2419done:
2420 FutureObj_finalize((FutureObj*)task);
2421}
2422
2423static void TaskObj_dealloc(PyObject *); /* Needs Task_CheckExact */
2424
2425static PyMethodDef TaskType_methods[] = {
2426 _ASYNCIO_FUTURE_RESULT_METHODDEF
2427 _ASYNCIO_FUTURE_EXCEPTION_METHODDEF
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002428 _ASYNCIO_FUTURE_ADD_DONE_CALLBACK_METHODDEF
2429 _ASYNCIO_FUTURE_REMOVE_DONE_CALLBACK_METHODDEF
2430 _ASYNCIO_FUTURE_CANCELLED_METHODDEF
2431 _ASYNCIO_FUTURE_DONE_METHODDEF
Yury Selivanov0cf16f92017-12-25 10:48:15 -05002432 _ASYNCIO_TASK_SET_RESULT_METHODDEF
2433 _ASYNCIO_TASK_SET_EXCEPTION_METHODDEF
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002434 _ASYNCIO_TASK_CURRENT_TASK_METHODDEF
2435 _ASYNCIO_TASK_ALL_TASKS_METHODDEF
2436 _ASYNCIO_TASK_CANCEL_METHODDEF
2437 _ASYNCIO_TASK_GET_STACK_METHODDEF
2438 _ASYNCIO_TASK_PRINT_STACK_METHODDEF
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002439 _ASYNCIO_TASK__REPR_INFO_METHODDEF
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002440 _ASYNCIO_TASK_GET_NAME_METHODDEF
2441 _ASYNCIO_TASK_SET_NAME_METHODDEF
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002442 {NULL, NULL} /* Sentinel */
2443};
2444
2445static PyGetSetDef TaskType_getsetlist[] = {
2446 FUTURE_COMMON_GETSETLIST
2447 {"_log_destroy_pending", (getter)TaskObj_get_log_destroy_pending,
2448 (setter)TaskObj_set_log_destroy_pending, NULL},
2449 {"_must_cancel", (getter)TaskObj_get_must_cancel, NULL, NULL},
2450 {"_coro", (getter)TaskObj_get_coro, NULL, NULL},
2451 {"_fut_waiter", (getter)TaskObj_get_fut_waiter, NULL, NULL},
2452 {NULL} /* Sentinel */
2453};
2454
2455static PyTypeObject TaskType = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02002456 PyVarObject_HEAD_INIT(NULL, 0)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002457 "_asyncio.Task",
2458 sizeof(TaskObj), /* tp_basicsize */
2459 .tp_base = &FutureType,
2460 .tp_dealloc = TaskObj_dealloc,
2461 .tp_as_async = &FutureType_as_async,
2462 .tp_repr = (reprfunc)FutureObj_repr,
Antoine Pitrouada319b2019-05-29 22:12:38 +02002463 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002464 .tp_doc = _asyncio_Task___init____doc__,
2465 .tp_traverse = (traverseproc)TaskObj_traverse,
2466 .tp_clear = (inquiry)TaskObj_clear,
2467 .tp_weaklistoffset = offsetof(TaskObj, task_weakreflist),
2468 .tp_iter = (getiterfunc)future_new_iter,
2469 .tp_methods = TaskType_methods,
2470 .tp_getset = TaskType_getsetlist,
2471 .tp_dictoffset = offsetof(TaskObj, dict),
2472 .tp_init = (initproc)_asyncio_Task___init__,
2473 .tp_new = PyType_GenericNew,
2474 .tp_finalize = (destructor)TaskObj_finalize,
2475};
2476
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002477static void
2478TaskObj_dealloc(PyObject *self)
2479{
2480 TaskObj *task = (TaskObj *)self;
2481
2482 if (Task_CheckExact(self)) {
2483 /* When fut is subclass of Task, finalizer is called from
2484 * subtype_dealloc.
2485 */
2486 if (PyObject_CallFinalizerFromDealloc(self) < 0) {
2487 // resurrected.
2488 return;
2489 }
2490 }
2491
Alexander Mohrde34cbe2017-08-01 23:31:07 -07002492 PyObject_GC_UnTrack(self);
2493
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002494 if (task->task_weakreflist != NULL) {
2495 PyObject_ClearWeakRefs(self);
2496 }
2497
2498 (void)TaskObj_clear(task);
2499 Py_TYPE(task)->tp_free(task);
2500}
2501
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002502static int
2503task_call_step_soon(TaskObj *task, PyObject *arg)
2504{
Serhiy Storchakabca49392017-09-03 08:10:14 +03002505 PyObject *cb = TaskStepMethWrapper_new(task, arg);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002506 if (cb == NULL) {
2507 return -1;
2508 }
2509
Yury Selivanovf23746a2018-01-22 19:11:18 -05002510 int ret = call_soon(task->task_loop, cb, NULL, task->task_context);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002511 Py_DECREF(cb);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05002512 return ret;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002513}
2514
2515static PyObject *
2516task_set_error_soon(TaskObj *task, PyObject *et, const char *format, ...)
2517{
2518 PyObject* msg;
2519
2520 va_list vargs;
2521#ifdef HAVE_STDARG_PROTOTYPES
2522 va_start(vargs, format);
2523#else
2524 va_start(vargs);
2525#endif
2526 msg = PyUnicode_FromFormatV(format, vargs);
2527 va_end(vargs);
2528
2529 if (msg == NULL) {
2530 return NULL;
2531 }
2532
Victor Stinnerde4ae3d2016-12-04 22:59:09 +01002533 PyObject *e = PyObject_CallFunctionObjArgs(et, msg, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002534 Py_DECREF(msg);
2535 if (e == NULL) {
2536 return NULL;
2537 }
2538
2539 if (task_call_step_soon(task, e) == -1) {
2540 Py_DECREF(e);
2541 return NULL;
2542 }
2543
2544 Py_DECREF(e);
2545 Py_RETURN_NONE;
2546}
2547
2548static PyObject *
2549task_step_impl(TaskObj *task, PyObject *exc)
2550{
2551 int res;
2552 int clear_exc = 0;
2553 PyObject *result = NULL;
Serhiy Storchakabca49392017-09-03 08:10:14 +03002554 PyObject *coro;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002555 PyObject *o;
2556
2557 if (task->task_state != STATE_PENDING) {
Yury Selivanov0cf16f92017-12-25 10:48:15 -05002558 PyErr_Format(asyncio_InvalidStateError,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002559 "_step(): already done: %R %R",
2560 task,
2561 exc ? exc : Py_None);
INADA Naokic411a7d2016-10-18 11:48:14 +09002562 goto fail;
2563 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09002564
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002565 if (task->task_must_cancel) {
2566 assert(exc != Py_None);
2567
2568 if (exc) {
2569 /* Check if exc is a CancelledError */
2570 res = PyObject_IsInstance(exc, asyncio_CancelledError);
2571 if (res == -1) {
2572 /* An error occurred, abort */
2573 goto fail;
2574 }
2575 if (res == 0) {
2576 /* exc is not CancelledError; reset it to NULL */
2577 exc = NULL;
2578 }
2579 }
2580
2581 if (!exc) {
2582 /* exc was not a CancelledError */
Victor Stinnerf17c3de2016-12-06 18:46:19 +01002583 exc = _PyObject_CallNoArg(asyncio_CancelledError);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002584 if (!exc) {
2585 goto fail;
2586 }
2587 clear_exc = 1;
2588 }
2589
2590 task->task_must_cancel = 0;
2591 }
2592
2593 Py_CLEAR(task->task_fut_waiter);
2594
Serhiy Storchakabca49392017-09-03 08:10:14 +03002595 coro = task->task_coro;
2596 if (coro == NULL) {
2597 PyErr_SetString(PyExc_RuntimeError, "uninitialized Task object");
2598 return NULL;
2599 }
2600
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002601 if (exc == NULL) {
2602 if (PyGen_CheckExact(coro) || PyCoro_CheckExact(coro)) {
2603 result = _PyGen_Send((PyGenObject*)coro, Py_None);
2604 }
2605 else {
Victor Stinnerb6ed57d2016-12-09 14:24:02 +01002606 result = _PyObject_CallMethodIdObjArgs(coro, &PyId_send,
2607 Py_None, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002608 }
2609 }
2610 else {
Victor Stinnerb6ed57d2016-12-09 14:24:02 +01002611 result = _PyObject_CallMethodIdObjArgs(coro, &PyId_throw,
2612 exc, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002613 if (clear_exc) {
2614 /* We created 'exc' during this call */
Serhiy Storchakabca49392017-09-03 08:10:14 +03002615 Py_DECREF(exc);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002616 }
2617 }
2618
2619 if (result == NULL) {
2620 PyObject *et, *ev, *tb;
2621
2622 if (_PyGen_FetchStopIterationValue(&o) == 0) {
2623 /* The error is StopIteration and that means that
2624 the underlying coroutine has resolved */
INADA Naoki991adca2017-05-11 21:18:38 +09002625 if (task->task_must_cancel) {
2626 // Task is cancelled right before coro stops.
2627 Py_DECREF(o);
2628 task->task_must_cancel = 0;
2629 et = asyncio_CancelledError;
2630 Py_INCREF(et);
2631 ev = NULL;
2632 tb = NULL;
2633 goto set_exception;
2634 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002635 PyObject *res = future_set_result((FutureObj*)task, o);
2636 Py_DECREF(o);
2637 if (res == NULL) {
2638 return NULL;
2639 }
2640 Py_DECREF(res);
2641 Py_RETURN_NONE;
2642 }
2643
2644 if (PyErr_ExceptionMatches(asyncio_CancelledError)) {
2645 /* CancelledError */
2646 PyErr_Clear();
2647 return future_cancel((FutureObj*)task);
2648 }
2649
2650 /* Some other exception; pop it and call Task.set_exception() */
2651 PyErr_Fetch(&et, &ev, &tb);
INADA Naoki991adca2017-05-11 21:18:38 +09002652
2653set_exception:
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002654 assert(et);
2655 if (!ev || !PyObject_TypeCheck(ev, (PyTypeObject *) et)) {
2656 PyErr_NormalizeException(&et, &ev, &tb);
2657 }
Yury Selivanovedfe8862016-12-01 11:37:47 -05002658 if (tb != NULL) {
2659 PyException_SetTraceback(ev, tb);
2660 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002661 o = future_set_exception((FutureObj*)task, ev);
2662 if (!o) {
2663 /* An exception in Task.set_exception() */
Serhiy Storchakabca49392017-09-03 08:10:14 +03002664 Py_DECREF(et);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002665 Py_XDECREF(tb);
2666 Py_XDECREF(ev);
2667 goto fail;
2668 }
2669 assert(o == Py_None);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002670 Py_DECREF(o);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002671
Yury Selivanov431b5402019-05-27 14:45:12 +02002672 if (PyErr_GivenExceptionMatches(et, PyExc_KeyboardInterrupt) ||
2673 PyErr_GivenExceptionMatches(et, PyExc_SystemExit))
2674 {
2675 /* We've got a KeyboardInterrupt or a SystemError; re-raise it */
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002676 PyErr_Restore(et, ev, tb);
2677 goto fail;
2678 }
2679
Serhiy Storchakabca49392017-09-03 08:10:14 +03002680 Py_DECREF(et);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002681 Py_XDECREF(tb);
2682 Py_XDECREF(ev);
2683
2684 Py_RETURN_NONE;
2685 }
2686
2687 if (result == (PyObject*)task) {
2688 /* We have a task that wants to await on itself */
2689 goto self_await;
2690 }
2691
2692 /* Check if `result` is FutureObj or TaskObj (and not a subclass) */
2693 if (Future_CheckExact(result) || Task_CheckExact(result)) {
2694 PyObject *wrapper;
2695 PyObject *res;
2696 FutureObj *fut = (FutureObj*)result;
2697
2698 /* Check if `result` future is attached to a different loop */
2699 if (fut->fut_loop != task->task_loop) {
2700 goto different_loop;
2701 }
2702
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002703 if (!fut->fut_blocking) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002704 goto yield_insteadof_yf;
2705 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002706
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002707 fut->fut_blocking = 0;
2708
2709 /* result.add_done_callback(task._wakeup) */
2710 wrapper = TaskWakeupMethWrapper_new(task);
2711 if (wrapper == NULL) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002712 goto fail;
2713 }
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002714 res = future_add_done_callback(
2715 (FutureObj*)result, wrapper, task->task_context);
2716 Py_DECREF(wrapper);
2717 if (res == NULL) {
2718 goto fail;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002719 }
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002720 Py_DECREF(res);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002721
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002722 /* task._fut_waiter = result */
2723 task->task_fut_waiter = result; /* no incref is necessary */
2724
2725 if (task->task_must_cancel) {
2726 PyObject *r;
Elvis Pranskevichus0c797a62018-10-03 10:30:31 -04002727 int is_true;
Serhiy Storchakaaddf8af2018-10-05 21:20:02 +03002728 r = _PyObject_CallMethodId(result, &PyId_cancel, NULL);
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002729 if (r == NULL) {
2730 return NULL;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002731 }
Elvis Pranskevichus0c797a62018-10-03 10:30:31 -04002732 is_true = PyObject_IsTrue(r);
2733 Py_DECREF(r);
2734 if (is_true < 0) {
2735 return NULL;
2736 }
2737 else if (is_true) {
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002738 task->task_must_cancel = 0;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002739 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002740 }
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002741
2742 Py_RETURN_NONE;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002743 }
2744
2745 /* Check if `result` is None */
2746 if (result == Py_None) {
2747 /* Bare yield relinquishes control for one event loop iteration. */
2748 if (task_call_step_soon(task, NULL)) {
2749 goto fail;
2750 }
2751 return result;
2752 }
2753
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002754 /* Check if `result` is a Future-compatible object */
2755 if (_PyObject_LookupAttrId(result, &PyId__asyncio_future_blocking, &o) < 0) {
2756 goto fail;
2757 }
2758 if (o != NULL && o != Py_None) {
2759 /* `result` is a Future-compatible object */
2760 PyObject *wrapper;
2761 PyObject *res;
2762
2763 int blocking = PyObject_IsTrue(o);
2764 Py_DECREF(o);
2765 if (blocking < 0) {
2766 goto fail;
2767 }
2768
2769 /* Check if `result` future is attached to a different loop */
2770 PyObject *oloop = get_future_loop(result);
2771 if (oloop == NULL) {
2772 goto fail;
2773 }
2774 if (oloop != task->task_loop) {
2775 Py_DECREF(oloop);
2776 goto different_loop;
2777 }
2778 Py_DECREF(oloop);
2779
2780 if (!blocking) {
2781 goto yield_insteadof_yf;
2782 }
2783
2784 /* result._asyncio_future_blocking = False */
2785 if (_PyObject_SetAttrId(
2786 result, &PyId__asyncio_future_blocking, Py_False) == -1) {
2787 goto fail;
2788 }
2789
2790 wrapper = TaskWakeupMethWrapper_new(task);
2791 if (wrapper == NULL) {
2792 goto fail;
2793 }
2794
2795 /* result.add_done_callback(task._wakeup) */
2796 PyObject *add_cb = _PyObject_GetAttrId(
2797 result, &PyId_add_done_callback);
2798 if (add_cb == NULL) {
2799 Py_DECREF(wrapper);
2800 goto fail;
2801 }
2802 PyObject *stack[2];
2803 stack[0] = wrapper;
2804 stack[1] = (PyObject *)task->task_context;
Jeroen Demeyeraacc77f2019-05-29 20:31:52 +02002805 res = _PyObject_Vectorcall(add_cb, stack, 1, context_kwname);
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002806 Py_DECREF(add_cb);
2807 Py_DECREF(wrapper);
2808 if (res == NULL) {
2809 goto fail;
2810 }
2811 Py_DECREF(res);
2812
2813 /* task._fut_waiter = result */
2814 task->task_fut_waiter = result; /* no incref is necessary */
2815
2816 if (task->task_must_cancel) {
2817 PyObject *r;
2818 int is_true;
2819 r = _PyObject_CallMethodId(result, &PyId_cancel, NULL);
2820 if (r == NULL) {
2821 return NULL;
2822 }
2823 is_true = PyObject_IsTrue(r);
2824 Py_DECREF(r);
2825 if (is_true < 0) {
2826 return NULL;
2827 }
2828 else if (is_true) {
2829 task->task_must_cancel = 0;
2830 }
2831 }
2832
2833 Py_RETURN_NONE;
2834 }
2835
2836 Py_XDECREF(o);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002837 /* Check if `result` is a generator */
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002838 res = PyObject_IsInstance(result, (PyObject*)&PyGen_Type);
2839 if (res < 0) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002840 goto fail;
2841 }
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002842 if (res) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002843 /* `result` is a generator */
Serhiy Storchaka66553542018-05-20 16:30:31 +03002844 o = task_set_error_soon(
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002845 task, PyExc_RuntimeError,
2846 "yield was used instead of yield from for "
Serhiy Storchaka66553542018-05-20 16:30:31 +03002847 "generator in task %R with %R", task, result);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002848 Py_DECREF(result);
Serhiy Storchaka66553542018-05-20 16:30:31 +03002849 return o;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002850 }
2851
2852 /* The `result` is none of the above */
Serhiy Storchaka66553542018-05-20 16:30:31 +03002853 o = task_set_error_soon(
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002854 task, PyExc_RuntimeError, "Task got bad yield: %R", result);
Serhiy Storchaka66553542018-05-20 16:30:31 +03002855 Py_DECREF(result);
2856 return o;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002857
2858self_await:
2859 o = task_set_error_soon(
2860 task, PyExc_RuntimeError,
2861 "Task cannot await on itself: %R", task);
2862 Py_DECREF(result);
2863 return o;
2864
2865yield_insteadof_yf:
2866 o = task_set_error_soon(
2867 task, PyExc_RuntimeError,
2868 "yield was used instead of yield from "
2869 "in task %R with %R",
2870 task, result);
2871 Py_DECREF(result);
2872 return o;
2873
2874different_loop:
2875 o = task_set_error_soon(
2876 task, PyExc_RuntimeError,
2877 "Task %R got Future %R attached to a different loop",
2878 task, result);
2879 Py_DECREF(result);
2880 return o;
2881
2882fail:
2883 Py_XDECREF(result);
2884 return NULL;
2885}
2886
2887static PyObject *
2888task_step(TaskObj *task, PyObject *exc)
2889{
2890 PyObject *res;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002891
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002892 if (enter_task(task->task_loop, (PyObject*)task) < 0) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002893 return NULL;
2894 }
2895
2896 res = task_step_impl(task, exc);
2897
2898 if (res == NULL) {
2899 PyObject *et, *ev, *tb;
2900 PyErr_Fetch(&et, &ev, &tb);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002901 leave_task(task->task_loop, (PyObject*)task);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002902 _PyErr_ChainExceptions(et, ev, tb);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002903 return NULL;
2904 }
2905 else {
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002906 if (leave_task(task->task_loop, (PyObject*)task) < 0) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002907 Py_DECREF(res);
2908 return NULL;
2909 }
2910 else {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002911 return res;
2912 }
2913 }
2914}
2915
2916static PyObject *
2917task_wakeup(TaskObj *task, PyObject *o)
2918{
Serhiy Storchakabca49392017-09-03 08:10:14 +03002919 PyObject *et, *ev, *tb;
2920 PyObject *result;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002921 assert(o);
2922
2923 if (Future_CheckExact(o) || Task_CheckExact(o)) {
2924 PyObject *fut_result = NULL;
2925 int res = future_get_result((FutureObj*)o, &fut_result);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002926
2927 switch(res) {
2928 case -1:
2929 assert(fut_result == NULL);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002930 break; /* exception raised */
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002931 case 0:
2932 Py_DECREF(fut_result);
Yury Selivanov22feeb82018-01-24 11:31:01 -05002933 return task_step(task, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002934 default:
2935 assert(res == 1);
Yury Selivanov22feeb82018-01-24 11:31:01 -05002936 result = task_step(task, fut_result);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002937 Py_DECREF(fut_result);
2938 return result;
2939 }
2940 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002941 else {
Serhiy Storchakabca49392017-09-03 08:10:14 +03002942 PyObject *fut_result = PyObject_CallMethod(o, "result", NULL);
2943 if (fut_result != NULL) {
2944 Py_DECREF(fut_result);
Yury Selivanov22feeb82018-01-24 11:31:01 -05002945 return task_step(task, NULL);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002946 }
2947 /* exception raised */
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002948 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03002949
2950 PyErr_Fetch(&et, &ev, &tb);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002951 if (!ev || !PyObject_TypeCheck(ev, (PyTypeObject *) et)) {
2952 PyErr_NormalizeException(&et, &ev, &tb);
2953 }
2954
Yury Selivanov22feeb82018-01-24 11:31:01 -05002955 result = task_step(task, ev);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002956
2957 Py_DECREF(et);
2958 Py_XDECREF(tb);
2959 Py_XDECREF(ev);
2960
2961 return result;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002962}
2963
2964
Yury Selivanova70232f2017-12-13 14:49:42 -05002965/*********************** Functions **************************/
2966
2967
2968/*[clinic input]
2969_asyncio._get_running_loop
2970
2971Return the running event loop or None.
2972
2973This is a low-level function intended to be used by event loops.
2974This function is thread-specific.
2975
2976[clinic start generated code]*/
2977
2978static PyObject *
2979_asyncio__get_running_loop_impl(PyObject *module)
2980/*[clinic end generated code: output=b4390af721411a0a input=0a21627e25a4bd43]*/
2981{
2982 PyObject *loop;
2983 if (get_running_loop(&loop)) {
2984 return NULL;
2985 }
2986 if (loop == NULL) {
2987 /* There's no currently running event loop */
2988 Py_RETURN_NONE;
2989 }
2990 return loop;
2991}
2992
2993/*[clinic input]
2994_asyncio._set_running_loop
2995 loop: 'O'
2996 /
2997
2998Set the running event loop.
2999
3000This is a low-level function intended to be used by event loops.
3001This function is thread-specific.
3002[clinic start generated code]*/
3003
3004static PyObject *
3005_asyncio__set_running_loop(PyObject *module, PyObject *loop)
3006/*[clinic end generated code: output=ae56bf7a28ca189a input=4c9720233d606604]*/
3007{
3008 if (set_running_loop(loop)) {
3009 return NULL;
3010 }
3011 Py_RETURN_NONE;
3012}
3013
3014/*[clinic input]
3015_asyncio.get_event_loop
3016
3017Return an asyncio event loop.
3018
3019When called from a coroutine or a callback (e.g. scheduled with
3020call_soon or similar API), this function will always return the
3021running event loop.
3022
3023If there is no running event loop set, the function will return
3024the result of `get_event_loop_policy().get_event_loop()` call.
3025[clinic start generated code]*/
3026
3027static PyObject *
3028_asyncio_get_event_loop_impl(PyObject *module)
3029/*[clinic end generated code: output=2a2d8b2f824c648b input=9364bf2916c8655d]*/
3030{
3031 return get_event_loop();
3032}
3033
3034/*[clinic input]
3035_asyncio.get_running_loop
3036
3037Return the running event loop. Raise a RuntimeError if there is none.
3038
3039This function is thread-specific.
3040[clinic start generated code]*/
3041
3042static PyObject *
3043_asyncio_get_running_loop_impl(PyObject *module)
3044/*[clinic end generated code: output=c247b5f9e529530e input=2a3bf02ba39f173d]*/
3045{
3046 PyObject *loop;
3047 if (get_running_loop(&loop)) {
3048 return NULL;
3049 }
3050 if (loop == NULL) {
3051 /* There's no currently running event loop */
3052 PyErr_SetString(
3053 PyExc_RuntimeError, "no running event loop");
3054 }
3055 return loop;
3056}
3057
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003058/*[clinic input]
3059_asyncio._register_task
3060
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003061 task: object
3062
3063Register a new task in asyncio as executed by loop.
3064
3065Returns None.
3066[clinic start generated code]*/
3067
3068static PyObject *
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003069_asyncio__register_task_impl(PyObject *module, PyObject *task)
3070/*[clinic end generated code: output=8672dadd69a7d4e2 input=21075aaea14dfbad]*/
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003071{
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003072 if (register_task(task) < 0) {
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003073 return NULL;
3074 }
3075 Py_RETURN_NONE;
3076}
3077
3078
3079/*[clinic input]
3080_asyncio._unregister_task
3081
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003082 task: object
3083
3084Unregister a task.
3085
3086Returns None.
3087[clinic start generated code]*/
3088
3089static PyObject *
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003090_asyncio__unregister_task_impl(PyObject *module, PyObject *task)
3091/*[clinic end generated code: output=6e5585706d568a46 input=28fb98c3975f7bdc]*/
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003092{
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003093 if (unregister_task(task) < 0) {
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003094 return NULL;
3095 }
3096 Py_RETURN_NONE;
3097}
3098
3099
3100/*[clinic input]
3101_asyncio._enter_task
3102
3103 loop: object
3104 task: object
3105
3106Enter into task execution or resume suspended task.
3107
3108Task belongs to loop.
3109
3110Returns None.
3111[clinic start generated code]*/
3112
3113static PyObject *
3114_asyncio__enter_task_impl(PyObject *module, PyObject *loop, PyObject *task)
3115/*[clinic end generated code: output=a22611c858035b73 input=de1b06dca70d8737]*/
3116{
3117 if (enter_task(loop, task) < 0) {
3118 return NULL;
3119 }
3120 Py_RETURN_NONE;
3121}
3122
3123
3124/*[clinic input]
3125_asyncio._leave_task
3126
3127 loop: object
3128 task: object
3129
3130Leave task execution or suspend a task.
3131
3132Task belongs to loop.
3133
3134Returns None.
3135[clinic start generated code]*/
3136
3137static PyObject *
3138_asyncio__leave_task_impl(PyObject *module, PyObject *loop, PyObject *task)
3139/*[clinic end generated code: output=0ebf6db4b858fb41 input=51296a46313d1ad8]*/
3140{
3141 if (leave_task(loop, task) < 0) {
3142 return NULL;
3143 }
3144 Py_RETURN_NONE;
3145}
3146
Yury Selivanova70232f2017-12-13 14:49:42 -05003147
Yury Selivanov9d411c12018-01-23 15:10:03 -05003148/*********************** PyRunningLoopHolder ********************/
3149
3150
3151static PyRunningLoopHolder *
3152new_running_loop_holder(PyObject *loop)
3153{
3154 PyRunningLoopHolder *rl = PyObject_New(
3155 PyRunningLoopHolder, &PyRunningLoopHolder_Type);
3156 if (rl == NULL) {
3157 return NULL;
3158 }
3159
3160#if defined(HAVE_GETPID) && !defined(MS_WINDOWS)
3161 rl->rl_pid = getpid();
3162#endif
3163
3164 Py_INCREF(loop);
3165 rl->rl_loop = loop;
3166
3167 return rl;
3168}
3169
3170
3171static void
3172PyRunningLoopHolder_tp_dealloc(PyRunningLoopHolder *rl)
3173{
3174 Py_CLEAR(rl->rl_loop);
3175 PyObject_Free(rl);
3176}
3177
3178
3179static PyTypeObject PyRunningLoopHolder_Type = {
3180 PyVarObject_HEAD_INIT(NULL, 0)
3181 "_RunningLoopHolder",
3182 sizeof(PyRunningLoopHolder),
3183 .tp_getattro = PyObject_GenericGetAttr,
3184 .tp_flags = Py_TPFLAGS_DEFAULT,
3185 .tp_dealloc = (destructor)PyRunningLoopHolder_tp_dealloc,
3186};
3187
3188
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003189/*********************** Module **************************/
3190
3191
3192static void
Zackery Spytze40ad792017-12-19 11:48:13 -07003193module_free_freelists(void)
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05003194{
3195 PyObject *next;
3196 PyObject *current;
3197
3198 next = (PyObject*) fi_freelist;
3199 while (next != NULL) {
3200 assert(fi_freelist_len > 0);
3201 fi_freelist_len--;
3202
3203 current = next;
3204 next = (PyObject*) ((futureiterobject*) current)->future;
3205 PyObject_GC_Del(current);
3206 }
3207 assert(fi_freelist_len == 0);
3208 fi_freelist = NULL;
3209}
3210
3211
3212static void
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003213module_free(void *m)
3214{
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003215 Py_CLEAR(asyncio_mod);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003216 Py_CLEAR(traceback_extract_stack);
3217 Py_CLEAR(asyncio_future_repr_info_func);
3218 Py_CLEAR(asyncio_get_event_loop_policy);
3219 Py_CLEAR(asyncio_iscoroutine_func);
3220 Py_CLEAR(asyncio_task_get_stack_func);
3221 Py_CLEAR(asyncio_task_print_stack_func);
3222 Py_CLEAR(asyncio_task_repr_info_func);
3223 Py_CLEAR(asyncio_InvalidStateError);
3224 Py_CLEAR(asyncio_CancelledError);
3225
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003226 Py_CLEAR(all_tasks);
Yury Selivanova9d7e552017-12-19 07:18:45 -05003227 Py_CLEAR(current_tasks);
3228 Py_CLEAR(iscoroutine_typecache);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05003229
Yury Selivanovf23746a2018-01-22 19:11:18 -05003230 Py_CLEAR(context_kwname);
3231
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05003232 module_free_freelists();
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003233}
3234
3235static int
3236module_init(void)
3237{
3238 PyObject *module = NULL;
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003239
3240 asyncio_mod = PyImport_ImportModule("asyncio");
3241 if (asyncio_mod == NULL) {
3242 goto fail;
3243 }
3244
3245 current_tasks = PyDict_New();
3246 if (current_tasks == NULL) {
3247 goto fail;
3248 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003249
Yury Selivanova9d7e552017-12-19 07:18:45 -05003250 iscoroutine_typecache = PySet_New(NULL);
3251 if (iscoroutine_typecache == NULL) {
3252 goto fail;
3253 }
3254
Yury Selivanovf23746a2018-01-22 19:11:18 -05003255
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03003256 context_kwname = Py_BuildValue("(s)", "context");
Yury Selivanovf23746a2018-01-22 19:11:18 -05003257 if (context_kwname == NULL) {
3258 goto fail;
3259 }
Yury Selivanovf23746a2018-01-22 19:11:18 -05003260
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003261#define WITH_MOD(NAME) \
3262 Py_CLEAR(module); \
3263 module = PyImport_ImportModule(NAME); \
3264 if (module == NULL) { \
Serhiy Storchakabca49392017-09-03 08:10:14 +03003265 goto fail; \
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003266 }
3267
3268#define GET_MOD_ATTR(VAR, NAME) \
3269 VAR = PyObject_GetAttrString(module, NAME); \
3270 if (VAR == NULL) { \
3271 goto fail; \
3272 }
3273
3274 WITH_MOD("asyncio.events")
Yury Selivanova70232f2017-12-13 14:49:42 -05003275 GET_MOD_ATTR(asyncio_get_event_loop_policy, "get_event_loop_policy")
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003276
3277 WITH_MOD("asyncio.base_futures")
3278 GET_MOD_ATTR(asyncio_future_repr_info_func, "_future_repr_info")
Andrew Svetlov0baa72f2018-09-11 10:13:04 -07003279
3280 WITH_MOD("asyncio.exceptions")
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003281 GET_MOD_ATTR(asyncio_InvalidStateError, "InvalidStateError")
3282 GET_MOD_ATTR(asyncio_CancelledError, "CancelledError")
3283
3284 WITH_MOD("asyncio.base_tasks")
3285 GET_MOD_ATTR(asyncio_task_repr_info_func, "_task_repr_info")
3286 GET_MOD_ATTR(asyncio_task_get_stack_func, "_task_get_stack")
3287 GET_MOD_ATTR(asyncio_task_print_stack_func, "_task_print_stack")
3288
Andrew Svetlovf74ef452017-12-15 07:04:38 +02003289 WITH_MOD("asyncio.coroutines")
3290 GET_MOD_ATTR(asyncio_iscoroutine_func, "iscoroutine")
3291
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003292 WITH_MOD("traceback")
3293 GET_MOD_ATTR(traceback_extract_stack, "extract_stack")
3294
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003295 PyObject *weak_set;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003296 WITH_MOD("weakref")
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003297 GET_MOD_ATTR(weak_set, "WeakSet");
3298 all_tasks = _PyObject_CallNoArg(weak_set);
3299 Py_CLEAR(weak_set);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003300 if (all_tasks == NULL) {
INADA Naokic411a7d2016-10-18 11:48:14 +09003301 goto fail;
3302 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003303
Serhiy Storchakabca49392017-09-03 08:10:14 +03003304 Py_DECREF(module);
INADA Naokic411a7d2016-10-18 11:48:14 +09003305 return 0;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003306
INADA Naokic411a7d2016-10-18 11:48:14 +09003307fail:
INADA Naokic411a7d2016-10-18 11:48:14 +09003308 Py_CLEAR(module);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003309 module_free(NULL);
INADA Naokic411a7d2016-10-18 11:48:14 +09003310 return -1;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003311
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003312#undef WITH_MOD
3313#undef GET_MOD_ATTR
3314}
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003315
INADA Naokic411a7d2016-10-18 11:48:14 +09003316PyDoc_STRVAR(module_doc, "Accelerator module for asyncio");
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003317
Yury Selivanova70232f2017-12-13 14:49:42 -05003318static PyMethodDef asyncio_methods[] = {
3319 _ASYNCIO_GET_EVENT_LOOP_METHODDEF
3320 _ASYNCIO_GET_RUNNING_LOOP_METHODDEF
3321 _ASYNCIO__GET_RUNNING_LOOP_METHODDEF
3322 _ASYNCIO__SET_RUNNING_LOOP_METHODDEF
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003323 _ASYNCIO__REGISTER_TASK_METHODDEF
3324 _ASYNCIO__UNREGISTER_TASK_METHODDEF
3325 _ASYNCIO__ENTER_TASK_METHODDEF
3326 _ASYNCIO__LEAVE_TASK_METHODDEF
Yury Selivanova70232f2017-12-13 14:49:42 -05003327 {NULL, NULL}
3328};
3329
INADA Naoki9f2ce252016-10-15 15:39:19 +09003330static struct PyModuleDef _asynciomodule = {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003331 PyModuleDef_HEAD_INIT, /* m_base */
INADA Naoki9f2ce252016-10-15 15:39:19 +09003332 "_asyncio", /* m_name */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003333 module_doc, /* m_doc */
3334 -1, /* m_size */
Yury Selivanova70232f2017-12-13 14:49:42 -05003335 asyncio_methods, /* m_methods */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003336 NULL, /* m_slots */
3337 NULL, /* m_traverse */
3338 NULL, /* m_clear */
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003339 (freefunc)module_free /* m_free */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003340};
3341
3342
3343PyMODINIT_FUNC
INADA Naoki9f2ce252016-10-15 15:39:19 +09003344PyInit__asyncio(void)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003345{
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003346 if (module_init() < 0) {
INADA Naokic411a7d2016-10-18 11:48:14 +09003347 return NULL;
3348 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003349 if (PyType_Ready(&FutureType) < 0) {
3350 return NULL;
3351 }
3352 if (PyType_Ready(&FutureIterType) < 0) {
3353 return NULL;
3354 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03003355 if (PyType_Ready(&TaskStepMethWrapper_Type) < 0) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003356 return NULL;
3357 }
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03003358 if (PyType_Ready(&TaskWakeupMethWrapper_Type) < 0) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003359 return NULL;
3360 }
3361 if (PyType_Ready(&TaskType) < 0) {
3362 return NULL;
3363 }
Yury Selivanov9d411c12018-01-23 15:10:03 -05003364 if (PyType_Ready(&PyRunningLoopHolder_Type) < 0) {
3365 return NULL;
3366 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003367
INADA Naoki9f2ce252016-10-15 15:39:19 +09003368 PyObject *m = PyModule_Create(&_asynciomodule);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003369 if (m == NULL) {
3370 return NULL;
3371 }
3372
3373 Py_INCREF(&FutureType);
3374 if (PyModule_AddObject(m, "Future", (PyObject *)&FutureType) < 0) {
3375 Py_DECREF(&FutureType);
3376 return NULL;
3377 }
3378
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003379 Py_INCREF(&TaskType);
3380 if (PyModule_AddObject(m, "Task", (PyObject *)&TaskType) < 0) {
3381 Py_DECREF(&TaskType);
3382 return NULL;
3383 }
3384
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003385 Py_INCREF(all_tasks);
3386 if (PyModule_AddObject(m, "_all_tasks", all_tasks) < 0) {
3387 Py_DECREF(all_tasks);
3388 return NULL;
3389 }
3390
3391 Py_INCREF(current_tasks);
3392 if (PyModule_AddObject(m, "_current_tasks", current_tasks) < 0) {
3393 Py_DECREF(current_tasks);
3394 return NULL;
3395 }
3396
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003397 return m;
3398}