blob: f70e3457c379a9313266373b62567c06db7337bf [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__);
Yury Selivanova0c1ba62016-10-28 12:52:37 -040013_Py_IDENTIFIER(add_done_callback);
Andrew Svetlov44d1a592017-12-16 21:58:38 +020014_Py_IDENTIFIER(all_tasks);
INADA Naoki9e4e38e2016-10-09 14:44:47 +090015_Py_IDENTIFIER(call_soon);
Yury Selivanova0c1ba62016-10-28 12:52:37 -040016_Py_IDENTIFIER(cancel);
Andrew Svetlov44d1a592017-12-16 21:58:38 +020017_Py_IDENTIFIER(current_task);
Yury Selivanova70232f2017-12-13 14:49:42 -050018_Py_IDENTIFIER(get_event_loop);
Yury Selivanova0c1ba62016-10-28 12:52:37 -040019_Py_IDENTIFIER(send);
20_Py_IDENTIFIER(throw);
21_Py_IDENTIFIER(_step);
22_Py_IDENTIFIER(_schedule_callbacks);
23_Py_IDENTIFIER(_wakeup);
INADA Naoki9e4e38e2016-10-09 14:44:47 +090024
25
INADA Naoki9f2ce252016-10-15 15:39:19 +090026/* State of the _asyncio module */
Andrew Svetlov44d1a592017-12-16 21:58:38 +020027static PyObject *asyncio_mod;
Yury Selivanova0c1ba62016-10-28 12:52:37 -040028static PyObject *inspect_isgenerator;
Yury Selivanova70232f2017-12-13 14:49:42 -050029static PyObject *os_getpid;
Andrew Svetlov44d1a592017-12-16 21:58:38 +020030static PyObject *traceback_extract_stack;
31static PyObject *asyncio_get_event_loop_policy;
32static PyObject *asyncio_future_repr_info_func;
33static PyObject *asyncio_iscoroutine_func;
34static PyObject *asyncio_task_get_stack_func;
35static PyObject *asyncio_task_print_stack_func;
36static PyObject *asyncio_task_repr_info_func;
37static PyObject *asyncio_InvalidStateError;
38static PyObject *asyncio_CancelledError;
39
40
Yury Selivanovca9b36c2017-12-23 15:04:15 -050041/* WeakSet containing all alive tasks. */
42static PyObject *all_tasks;
Andrew Svetlov44d1a592017-12-16 21:58:38 +020043
44/* Dictionary containing tasks that are currently active in
45 all running event loops. {EventLoop: Task} */
Yury Selivanovca9b36c2017-12-23 15:04:15 -050046static PyObject *current_tasks;
INADA Naoki9e4e38e2016-10-09 14:44:47 +090047
Yury Selivanova9d7e552017-12-19 07:18:45 -050048/* An isinstance type cache for the 'is_coroutine()' function. */
49static PyObject *iscoroutine_typecache;
50
INADA Naoki9e4e38e2016-10-09 14:44:47 +090051
INADA Naoki9e4e38e2016-10-09 14:44:47 +090052typedef enum {
53 STATE_PENDING,
54 STATE_CANCELLED,
55 STATE_FINISHED
56} fut_state;
57
Yury Selivanova0c1ba62016-10-28 12:52:37 -040058#define FutureObj_HEAD(prefix) \
59 PyObject_HEAD \
60 PyObject *prefix##_loop; \
Yury Selivanov1b7c11f2017-12-17 20:19:47 -050061 PyObject *prefix##_callback0; \
Yury Selivanova0c1ba62016-10-28 12:52:37 -040062 PyObject *prefix##_callbacks; \
63 PyObject *prefix##_exception; \
64 PyObject *prefix##_result; \
65 PyObject *prefix##_source_tb; \
66 fut_state prefix##_state; \
67 int prefix##_log_tb; \
68 int prefix##_blocking; \
69 PyObject *dict; \
70 PyObject *prefix##_weakreflist;
71
72typedef struct {
73 FutureObj_HEAD(fut)
74} FutureObj;
75
76typedef struct {
77 FutureObj_HEAD(task)
78 PyObject *task_fut_waiter;
79 PyObject *task_coro;
80 int task_must_cancel;
81 int task_log_destroy_pending;
82} TaskObj;
INADA Naoki9e4e38e2016-10-09 14:44:47 +090083
84typedef struct {
85 PyObject_HEAD
Yury Selivanova0c1ba62016-10-28 12:52:37 -040086 TaskObj *sw_task;
87 PyObject *sw_arg;
Serhiy Storchakabca49392017-09-03 08:10:14 +030088} TaskStepMethWrapper;
INADA Naoki9e4e38e2016-10-09 14:44:47 +090089
Yury Selivanova0c1ba62016-10-28 12:52:37 -040090typedef struct {
91 PyObject_HEAD
92 TaskObj *ww_task;
93} TaskWakeupMethWrapper;
94
95
Yury Selivanov1b7c11f2017-12-17 20:19:47 -050096static PyTypeObject FutureType;
97static PyTypeObject TaskType;
98
99
100#define Future_CheckExact(obj) (Py_TYPE(obj) == &FutureType)
101#define Task_CheckExact(obj) (Py_TYPE(obj) == &TaskType)
102
103#define Future_Check(obj) PyObject_TypeCheck(obj, &FutureType)
104#define Task_Check(obj) PyObject_TypeCheck(obj, &TaskType)
105
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400106#include "clinic/_asynciomodule.c.h"
107
108
109/*[clinic input]
110class _asyncio.Future "FutureObj *" "&Future_Type"
111[clinic start generated code]*/
112/*[clinic end generated code: output=da39a3ee5e6b4b0d input=00d3e4abca711e0f]*/
113
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500114
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400115/* Get FutureIter from Future */
116static PyObject* future_new_iter(PyObject *);
117static inline int future_call_schedule_callbacks(FutureObj *);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900118
Yury Selivanova70232f2017-12-13 14:49:42 -0500119
120static int
Yury Selivanova9d7e552017-12-19 07:18:45 -0500121_is_coroutine(PyObject *coro)
122{
123 /* 'coro' is not a native coroutine, call asyncio.iscoroutine()
124 to check if it's another coroutine flavour.
125
126 Do this check after 'future_init()'; in case we need to raise
127 an error, __del__ needs a properly initialized object.
128 */
129 PyObject *res = PyObject_CallFunctionObjArgs(
130 asyncio_iscoroutine_func, coro, NULL);
131 if (res == NULL) {
132 return -1;
133 }
134
135 int is_res_true = PyObject_IsTrue(res);
136 Py_DECREF(res);
137 if (is_res_true <= 0) {
138 return is_res_true;
139 }
140
Andrew Svetlov0f47fa22017-12-23 22:06:46 +0200141 if (PySet_GET_SIZE(iscoroutine_typecache) < 100) {
Yury Selivanova9d7e552017-12-19 07:18:45 -0500142 /* Just in case we don't want to cache more than 100
143 positive types. That shouldn't ever happen, unless
144 someone stressing the system on purpose.
145 */
146 if (PySet_Add(iscoroutine_typecache, (PyObject*) Py_TYPE(coro))) {
147 return -1;
148 }
149 }
150
151 return 1;
152}
153
154
155static inline int
156is_coroutine(PyObject *coro)
157{
158 if (PyCoro_CheckExact(coro)) {
159 return 1;
160 }
161
162 /* Check if `type(coro)` is in the cache.
163 Caching makes is_coroutine() function almost as fast as
164 PyCoro_CheckExact() for non-native coroutine-like objects
165 (like coroutines compiled with Cython).
166
167 asyncio.iscoroutine() has its own type caching mechanism.
168 This cache allows us to avoid the cost of even calling
169 a pure-Python function in 99.9% cases.
170 */
171 int has_it = PySet_Contains(
172 iscoroutine_typecache, (PyObject*) Py_TYPE(coro));
173 if (has_it == 0) {
174 /* type(coro) is not in iscoroutine_typecache */
175 return _is_coroutine(coro);
176 }
177
178 /* either an error has occured or
179 type(coro) is in iscoroutine_typecache
180 */
181 return has_it;
182}
183
184
Yury Selivanovca9b36c2017-12-23 15:04:15 -0500185static PyObject *
186get_future_loop(PyObject *fut)
187{
188 /* Implementation of `asyncio.futures._get_loop` */
189
190 _Py_IDENTIFIER(get_loop);
191 _Py_IDENTIFIER(_loop);
192
193 if (Future_CheckExact(fut) || Task_CheckExact(fut)) {
194 PyObject *loop = ((FutureObj *)fut)->fut_loop;
195 Py_INCREF(loop);
196 return loop;
197 }
198
199 PyObject *getloop = _PyObject_GetAttrId(fut, &PyId_get_loop);
200 if (getloop != NULL) {
201 PyObject *res = _PyObject_CallNoArg(getloop);
202 Py_DECREF(getloop);
203 return res;
204 }
205
Yury Selivanov719ccbc2017-12-23 16:29:26 -0500206 PyErr_Clear();
Yury Selivanovca9b36c2017-12-23 15:04:15 -0500207 return _PyObject_GetAttrId(fut, &PyId__loop);
208}
209
210
Yury Selivanova9d7e552017-12-19 07:18:45 -0500211static int
Yury Selivanova70232f2017-12-13 14:49:42 -0500212get_running_loop(PyObject **loop)
213{
214 PyObject *ts_dict;
215 PyObject *running_tuple;
216 PyObject *running_loop;
217 PyObject *running_loop_pid;
218 PyObject *current_pid;
219 int same_pid;
220
221 ts_dict = PyThreadState_GetDict(); // borrowed
222 if (ts_dict == NULL) {
223 PyErr_SetString(
224 PyExc_RuntimeError, "thread-local storage is not available");
225 goto error;
226 }
227
228 running_tuple = _PyDict_GetItemId(
229 ts_dict, &PyId___asyncio_running_event_loop__); // borrowed
230 if (running_tuple == NULL) {
231 /* _PyDict_GetItemId doesn't set an error if key is not found */
232 goto not_found;
233 }
234
235 assert(PyTuple_CheckExact(running_tuple));
236 assert(PyTuple_Size(running_tuple) == 2);
237 running_loop = PyTuple_GET_ITEM(running_tuple, 0); // borrowed
238 running_loop_pid = PyTuple_GET_ITEM(running_tuple, 1); // borrowed
239
240 if (running_loop == Py_None) {
241 goto not_found;
242 }
243
244 current_pid = _PyObject_CallNoArg(os_getpid);
245 if (current_pid == NULL) {
246 goto error;
247 }
248 same_pid = PyObject_RichCompareBool(current_pid, running_loop_pid, Py_EQ);
249 Py_DECREF(current_pid);
250 if (same_pid == -1) {
251 goto error;
252 }
253
254 if (same_pid) {
255 // current_pid == running_loop_pid
256 goto found;
257 }
258
259not_found:
260 *loop = NULL;
261 return 0;
262
263found:
264 Py_INCREF(running_loop);
265 *loop = running_loop;
266 return 0;
267
268error:
269 *loop = NULL;
270 return -1;
271}
272
273
274static int
275set_running_loop(PyObject *loop)
276{
277 PyObject *ts_dict;
278 PyObject *running_tuple;
279 PyObject *current_pid;
280
281 ts_dict = PyThreadState_GetDict(); // borrowed
282 if (ts_dict == NULL) {
283 PyErr_SetString(
284 PyExc_RuntimeError, "thread-local storage is not available");
285 return -1;
286 }
287
288 current_pid = _PyObject_CallNoArg(os_getpid);
289 if (current_pid == NULL) {
290 return -1;
291 }
292
293 running_tuple = PyTuple_New(2);
294 if (running_tuple == NULL) {
295 Py_DECREF(current_pid);
296 return -1;
297 }
298
299 Py_INCREF(loop);
300 PyTuple_SET_ITEM(running_tuple, 0, loop);
301 PyTuple_SET_ITEM(running_tuple, 1, current_pid); // borrowed
302
303 if (_PyDict_SetItemId(
304 ts_dict, &PyId___asyncio_running_event_loop__, running_tuple)) {
305 Py_DECREF(running_tuple); // will cleanup loop & current_pid
306 return -1;
307 }
308 Py_DECREF(running_tuple);
309
310 return 0;
311}
312
313
314static PyObject *
315get_event_loop(void)
316{
317 PyObject *loop;
318 PyObject *policy;
319
320 if (get_running_loop(&loop)) {
321 return NULL;
322 }
323 if (loop != NULL) {
324 return loop;
325 }
326
327 policy = _PyObject_CallNoArg(asyncio_get_event_loop_policy);
328 if (policy == NULL) {
329 return NULL;
330 }
331
332 loop = _PyObject_CallMethodId(policy, &PyId_get_event_loop, NULL);
333 Py_DECREF(policy);
334 return loop;
335}
336
337
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900338static int
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500339call_soon(PyObject *loop, PyObject *func, PyObject *arg)
340{
341 PyObject *handle;
342 handle = _PyObject_CallMethodIdObjArgs(
343 loop, &PyId_call_soon, func, arg, NULL);
344 if (handle == NULL) {
345 return -1;
346 }
347 Py_DECREF(handle);
348 return 0;
349}
350
351
352static inline int
353future_is_alive(FutureObj *fut)
354{
355 return fut->fut_loop != NULL;
356}
357
358
359static inline int
360future_ensure_alive(FutureObj *fut)
361{
362 if (!future_is_alive(fut)) {
363 PyErr_SetString(PyExc_RuntimeError,
364 "Future object is not initialized.");
365 return -1;
366 }
367 return 0;
368}
369
370
371#define ENSURE_FUTURE_ALIVE(fut) \
372 do { \
373 assert(Future_Check(fut) || Task_Check(fut)); \
374 if (future_ensure_alive((FutureObj*)fut)) { \
375 return NULL; \
376 } \
377 } while(0);
378
379
380static int
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400381future_schedule_callbacks(FutureObj *fut)
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900382{
383 Py_ssize_t len;
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500384 Py_ssize_t i;
385
386 if (fut->fut_callback0 != NULL) {
387 /* There's a 1st callback */
388
389 int ret = call_soon(
390 fut->fut_loop, fut->fut_callback0, (PyObject *)fut);
391 Py_CLEAR(fut->fut_callback0);
392 if (ret) {
393 /* If an error occurs in pure-Python implementation,
394 all callbacks are cleared. */
395 Py_CLEAR(fut->fut_callbacks);
396 return ret;
397 }
398
399 /* we called the first callback, now try calling
400 callbacks from the 'fut_callbacks' list. */
401 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900402
403 if (fut->fut_callbacks == NULL) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500404 /* No more callbacks, return. */
405 return 0;
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900406 }
407
408 len = PyList_GET_SIZE(fut->fut_callbacks);
409 if (len == 0) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500410 /* The list of callbacks was empty; clear it and return. */
411 Py_CLEAR(fut->fut_callbacks);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900412 return 0;
413 }
414
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900415 for (i = 0; i < len; i++) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500416 PyObject *cb = PyList_GET_ITEM(fut->fut_callbacks, i);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900417
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500418 if (call_soon(fut->fut_loop, cb, (PyObject *)fut)) {
419 /* If an error occurs in pure-Python implementation,
420 all callbacks are cleared. */
421 Py_CLEAR(fut->fut_callbacks);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900422 return -1;
423 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900424 }
425
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500426 Py_CLEAR(fut->fut_callbacks);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900427 return 0;
428}
429
430static int
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400431future_init(FutureObj *fut, PyObject *loop)
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900432{
Serhiy Storchakabca49392017-09-03 08:10:14 +0300433 PyObject *res;
434 int is_true;
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900435 _Py_IDENTIFIER(get_debug);
436
Serhiy Storchakabca49392017-09-03 08:10:14 +0300437 if (loop == Py_None) {
Yury Selivanova70232f2017-12-13 14:49:42 -0500438 loop = get_event_loop();
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900439 if (loop == NULL) {
440 return -1;
441 }
442 }
443 else {
444 Py_INCREF(loop);
445 }
Serhiy Storchakabca49392017-09-03 08:10:14 +0300446 Py_XSETREF(fut->fut_loop, loop);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900447
Victor Stinnerf94d1ee2016-10-29 09:05:39 +0200448 res = _PyObject_CallMethodId(fut->fut_loop, &PyId_get_debug, NULL);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900449 if (res == NULL) {
450 return -1;
451 }
Serhiy Storchakabca49392017-09-03 08:10:14 +0300452 is_true = PyObject_IsTrue(res);
453 Py_DECREF(res);
454 if (is_true < 0) {
455 return -1;
456 }
457 if (is_true) {
458 Py_XSETREF(fut->fut_source_tb, _PyObject_CallNoArg(traceback_extract_stack));
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900459 if (fut->fut_source_tb == NULL) {
460 return -1;
461 }
462 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900463
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500464 fut->fut_callback0 = NULL;
465 fut->fut_callbacks = NULL;
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400466
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900467 return 0;
468}
469
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900470static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400471future_set_result(FutureObj *fut, PyObject *res)
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900472{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500473 if (future_ensure_alive(fut)) {
474 return NULL;
475 }
476
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900477 if (fut->fut_state != STATE_PENDING) {
478 PyErr_SetString(asyncio_InvalidStateError, "invalid state");
479 return NULL;
480 }
481
Serhiy Storchakabca49392017-09-03 08:10:14 +0300482 assert(!fut->fut_result);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900483 Py_INCREF(res);
484 fut->fut_result = res;
485 fut->fut_state = STATE_FINISHED;
486
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400487 if (future_call_schedule_callbacks(fut) == -1) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900488 return NULL;
489 }
490 Py_RETURN_NONE;
491}
492
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900493static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400494future_set_exception(FutureObj *fut, PyObject *exc)
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900495{
496 PyObject *exc_val = NULL;
497
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900498 if (fut->fut_state != STATE_PENDING) {
499 PyErr_SetString(asyncio_InvalidStateError, "invalid state");
500 return NULL;
501 }
502
503 if (PyExceptionClass_Check(exc)) {
Victor Stinnera5ed5f02016-12-06 18:45:50 +0100504 exc_val = _PyObject_CallNoArg(exc);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900505 if (exc_val == NULL) {
506 return NULL;
507 }
Serhiy Storchakabca49392017-09-03 08:10:14 +0300508 if (fut->fut_state != STATE_PENDING) {
509 Py_DECREF(exc_val);
510 PyErr_SetString(asyncio_InvalidStateError, "invalid state");
511 return NULL;
512 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900513 }
514 else {
515 exc_val = exc;
516 Py_INCREF(exc_val);
517 }
518 if (!PyExceptionInstance_Check(exc_val)) {
519 Py_DECREF(exc_val);
520 PyErr_SetString(PyExc_TypeError, "invalid exception object");
521 return NULL;
522 }
523 if ((PyObject*)Py_TYPE(exc_val) == PyExc_StopIteration) {
524 Py_DECREF(exc_val);
525 PyErr_SetString(PyExc_TypeError,
526 "StopIteration interacts badly with generators "
527 "and cannot be raised into a Future");
528 return NULL;
529 }
530
Serhiy Storchakabca49392017-09-03 08:10:14 +0300531 assert(!fut->fut_exception);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900532 fut->fut_exception = exc_val;
533 fut->fut_state = STATE_FINISHED;
534
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400535 if (future_call_schedule_callbacks(fut) == -1) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900536 return NULL;
537 }
538
539 fut->fut_log_tb = 1;
540 Py_RETURN_NONE;
541}
542
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400543static int
544future_get_result(FutureObj *fut, PyObject **result)
545{
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400546 if (fut->fut_state == STATE_CANCELLED) {
Serhiy Storchakabca49392017-09-03 08:10:14 +0300547 PyErr_SetNone(asyncio_CancelledError);
548 return -1;
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400549 }
550
551 if (fut->fut_state != STATE_FINISHED) {
Serhiy Storchakabca49392017-09-03 08:10:14 +0300552 PyErr_SetString(asyncio_InvalidStateError, "Result is not set.");
553 return -1;
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400554 }
555
556 fut->fut_log_tb = 0;
557 if (fut->fut_exception != NULL) {
558 Py_INCREF(fut->fut_exception);
559 *result = fut->fut_exception;
560 return 1;
561 }
562
563 Py_INCREF(fut->fut_result);
564 *result = fut->fut_result;
565 return 0;
566}
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900567
568static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400569future_add_done_callback(FutureObj *fut, PyObject *arg)
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900570{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500571 if (!future_is_alive(fut)) {
572 PyErr_SetString(PyExc_RuntimeError, "uninitialized Future object");
573 return NULL;
574 }
575
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900576 if (fut->fut_state != STATE_PENDING) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500577 /* The future is done/cancelled, so schedule the callback
578 right away. */
579 if (call_soon(fut->fut_loop, arg, (PyObject*) fut)) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900580 return NULL;
581 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900582 }
583 else {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500584 /* The future is pending, add a callback.
585
586 Callbacks in the future object are stored as follows:
587
588 callback0 -- a pointer to the first callback
589 callbacks -- a list of 2nd, 3rd, ... callbacks
590
591 Invariants:
592
593 * callbacks != NULL:
594 There are some callbacks in in the list. Just
595 add the new callback to it.
596
597 * callbacks == NULL and callback0 == NULL:
598 This is the first callback. Set it to callback0.
599
600 * callbacks == NULL and callback0 != NULL:
601 This is a second callback. Initialize callbacks
602 with a new list and add the new callback to it.
603 */
604
605 if (fut->fut_callbacks != NULL) {
606 int err = PyList_Append(fut->fut_callbacks, arg);
607 if (err != 0) {
608 return NULL;
609 }
Serhiy Storchakabca49392017-09-03 08:10:14 +0300610 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500611 else if (fut->fut_callback0 == NULL) {
612 Py_INCREF(arg);
613 fut->fut_callback0 = arg;
614 }
615 else {
616 fut->fut_callbacks = PyList_New(1);
617 if (fut->fut_callbacks == NULL) {
618 return NULL;
619 }
620
621 Py_INCREF(arg);
622 PyList_SET_ITEM(fut->fut_callbacks, 0, arg);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900623 }
624 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500625
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900626 Py_RETURN_NONE;
627}
628
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400629static PyObject *
630future_cancel(FutureObj *fut)
631{
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +0000632 fut->fut_log_tb = 0;
633
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400634 if (fut->fut_state != STATE_PENDING) {
635 Py_RETURN_FALSE;
636 }
637 fut->fut_state = STATE_CANCELLED;
638
639 if (future_call_schedule_callbacks(fut) == -1) {
640 return NULL;
641 }
642
643 Py_RETURN_TRUE;
644}
645
646/*[clinic input]
647_asyncio.Future.__init__
648
649 *
Serhiy Storchakabca49392017-09-03 08:10:14 +0300650 loop: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400651
652This class is *almost* compatible with concurrent.futures.Future.
653
654 Differences:
655
656 - result() and exception() do not take a timeout argument and
657 raise an exception when the future isn't done yet.
658
659 - Callbacks registered with add_done_callback() are always called
660 via the event loop's call_soon_threadsafe().
661
662 - This class is not compatible with the wait() and as_completed()
663 methods in the concurrent.futures package.
664[clinic start generated code]*/
665
666static int
667_asyncio_Future___init___impl(FutureObj *self, PyObject *loop)
Serhiy Storchakabca49392017-09-03 08:10:14 +0300668/*[clinic end generated code: output=9ed75799eaccb5d6 input=89af317082bc0bf8]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400669
670{
671 return future_init(self, loop);
672}
673
674static int
675FutureObj_clear(FutureObj *fut)
676{
677 Py_CLEAR(fut->fut_loop);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500678 Py_CLEAR(fut->fut_callback0);
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400679 Py_CLEAR(fut->fut_callbacks);
680 Py_CLEAR(fut->fut_result);
681 Py_CLEAR(fut->fut_exception);
682 Py_CLEAR(fut->fut_source_tb);
683 Py_CLEAR(fut->dict);
684 return 0;
685}
686
687static int
688FutureObj_traverse(FutureObj *fut, visitproc visit, void *arg)
689{
690 Py_VISIT(fut->fut_loop);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500691 Py_VISIT(fut->fut_callback0);
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400692 Py_VISIT(fut->fut_callbacks);
693 Py_VISIT(fut->fut_result);
694 Py_VISIT(fut->fut_exception);
695 Py_VISIT(fut->fut_source_tb);
696 Py_VISIT(fut->dict);
697 return 0;
698}
699
700/*[clinic input]
701_asyncio.Future.result
702
703Return the result this future represents.
704
705If the future has been cancelled, raises CancelledError. If the
706future's result isn't yet available, raises InvalidStateError. If
707the future is done and has an exception set, this exception is raised.
708[clinic start generated code]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900709
710static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400711_asyncio_Future_result_impl(FutureObj *self)
712/*[clinic end generated code: output=f35f940936a4b1e5 input=49ecf9cf5ec50dc5]*/
713{
714 PyObject *result;
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500715
716 if (!future_is_alive(self)) {
717 PyErr_SetString(asyncio_InvalidStateError,
718 "Future object is not initialized.");
719 return NULL;
720 }
721
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400722 int res = future_get_result(self, &result);
723
724 if (res == -1) {
725 return NULL;
726 }
727
728 if (res == 0) {
729 return result;
730 }
731
732 assert(res == 1);
733
734 PyErr_SetObject(PyExceptionInstance_Class(result), result);
735 Py_DECREF(result);
736 return NULL;
737}
738
739/*[clinic input]
740_asyncio.Future.exception
741
742Return the exception that was set on this future.
743
744The exception (or None if no exception was set) is returned only if
745the future is done. If the future has been cancelled, raises
746CancelledError. If the future isn't done yet, raises
747InvalidStateError.
748[clinic start generated code]*/
749
750static PyObject *
751_asyncio_Future_exception_impl(FutureObj *self)
752/*[clinic end generated code: output=88b20d4f855e0710 input=733547a70c841c68]*/
753{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500754 if (!future_is_alive(self)) {
755 PyErr_SetString(asyncio_InvalidStateError,
756 "Future object is not initialized.");
757 return NULL;
758 }
759
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400760 if (self->fut_state == STATE_CANCELLED) {
Serhiy Storchakabca49392017-09-03 08:10:14 +0300761 PyErr_SetNone(asyncio_CancelledError);
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400762 return NULL;
763 }
764
765 if (self->fut_state != STATE_FINISHED) {
Serhiy Storchakabca49392017-09-03 08:10:14 +0300766 PyErr_SetString(asyncio_InvalidStateError, "Exception is not set.");
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400767 return NULL;
768 }
769
770 if (self->fut_exception != NULL) {
771 self->fut_log_tb = 0;
772 Py_INCREF(self->fut_exception);
773 return self->fut_exception;
774 }
775
776 Py_RETURN_NONE;
777}
778
779/*[clinic input]
780_asyncio.Future.set_result
781
Serhiy Storchakabca49392017-09-03 08:10:14 +0300782 res: object
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400783 /
784
785Mark the future done and set its result.
786
787If the future is already done when this method is called, raises
788InvalidStateError.
789[clinic start generated code]*/
790
791static PyObject *
792_asyncio_Future_set_result(FutureObj *self, PyObject *res)
Serhiy Storchakabca49392017-09-03 08:10:14 +0300793/*[clinic end generated code: output=a620abfc2796bfb6 input=5b9dc180f1baa56d]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400794{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500795 ENSURE_FUTURE_ALIVE(self)
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400796 return future_set_result(self, res);
797}
798
799/*[clinic input]
800_asyncio.Future.set_exception
801
Serhiy Storchakabca49392017-09-03 08:10:14 +0300802 exception: object
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400803 /
804
805Mark the future done and set an exception.
806
807If the future is already done when this method is called, raises
808InvalidStateError.
809[clinic start generated code]*/
810
811static PyObject *
812_asyncio_Future_set_exception(FutureObj *self, PyObject *exception)
Serhiy Storchakabca49392017-09-03 08:10:14 +0300813/*[clinic end generated code: output=f1c1b0cd321be360 input=e45b7d7aa71cc66d]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400814{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500815 ENSURE_FUTURE_ALIVE(self)
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400816 return future_set_exception(self, exception);
817}
818
819/*[clinic input]
820_asyncio.Future.add_done_callback
821
Serhiy Storchakabca49392017-09-03 08:10:14 +0300822 fn: object
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400823 /
824
825Add a callback to be run when the future becomes done.
826
827The callback is called with a single argument - the future object. If
828the future is already done when this is called, the callback is
829scheduled with call_soon.
830[clinic start generated code]*/
831
832static PyObject *
833_asyncio_Future_add_done_callback(FutureObj *self, PyObject *fn)
Serhiy Storchakabca49392017-09-03 08:10:14 +0300834/*[clinic end generated code: output=819e09629b2ec2b5 input=8f818b39990b027d]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400835{
836 return future_add_done_callback(self, fn);
837}
838
839/*[clinic input]
840_asyncio.Future.remove_done_callback
841
Serhiy Storchakabca49392017-09-03 08:10:14 +0300842 fn: object
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400843 /
844
845Remove all instances of a callback from the "call when done" list.
846
847Returns the number of callbacks removed.
848[clinic start generated code]*/
849
850static PyObject *
851_asyncio_Future_remove_done_callback(FutureObj *self, PyObject *fn)
Serhiy Storchakabca49392017-09-03 08:10:14 +0300852/*[clinic end generated code: output=5ab1fb52b24ef31f input=0a43280a149d505b]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900853{
854 PyObject *newlist;
855 Py_ssize_t len, i, j=0;
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500856 Py_ssize_t cleared_callback0 = 0;
857
858 ENSURE_FUTURE_ALIVE(self)
859
860 if (self->fut_callback0 != NULL) {
861 int cmp = PyObject_RichCompareBool(fn, self->fut_callback0, Py_EQ);
862 if (cmp == -1) {
863 return NULL;
864 }
865 if (cmp == 1) {
866 /* callback0 == fn */
867 Py_CLEAR(self->fut_callback0);
868 cleared_callback0 = 1;
869 }
870 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900871
Serhiy Storchakabca49392017-09-03 08:10:14 +0300872 if (self->fut_callbacks == NULL) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500873 return PyLong_FromSsize_t(cleared_callback0);
Serhiy Storchakabca49392017-09-03 08:10:14 +0300874 }
875
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400876 len = PyList_GET_SIZE(self->fut_callbacks);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900877 if (len == 0) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500878 Py_CLEAR(self->fut_callbacks);
879 return PyLong_FromSsize_t(cleared_callback0);
880 }
881
882 if (len == 1) {
883 int cmp = PyObject_RichCompareBool(
884 fn, PyList_GET_ITEM(self->fut_callbacks, 0), Py_EQ);
885 if (cmp == -1) {
886 return NULL;
887 }
888 if (cmp == 1) {
889 /* callbacks[0] == fn */
890 Py_CLEAR(self->fut_callbacks);
891 return PyLong_FromSsize_t(1 + cleared_callback0);
892 }
893 /* callbacks[0] != fn and len(callbacks) == 1 */
894 return PyLong_FromSsize_t(cleared_callback0);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900895 }
896
897 newlist = PyList_New(len);
898 if (newlist == NULL) {
899 return NULL;
900 }
901
Yury Selivanov84af9032017-03-02 23:46:56 -0500902 for (i = 0; i < PyList_GET_SIZE(self->fut_callbacks); i++) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900903 int ret;
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400904 PyObject *item = PyList_GET_ITEM(self->fut_callbacks, i);
Serhiy Storchakabca49392017-09-03 08:10:14 +0300905 Py_INCREF(item);
906 ret = PyObject_RichCompareBool(fn, item, Py_EQ);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900907 if (ret == 0) {
Yury Selivanov833a3b02017-07-05 13:32:03 -0400908 if (j < len) {
Yury Selivanov833a3b02017-07-05 13:32:03 -0400909 PyList_SET_ITEM(newlist, j, item);
910 j++;
Serhiy Storchakabca49392017-09-03 08:10:14 +0300911 continue;
Yury Selivanov833a3b02017-07-05 13:32:03 -0400912 }
Serhiy Storchakabca49392017-09-03 08:10:14 +0300913 ret = PyList_Append(newlist, item);
914 }
915 Py_DECREF(item);
916 if (ret < 0) {
917 goto fail;
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900918 }
919 }
920
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500921 if (j == 0) {
922 Py_CLEAR(self->fut_callbacks);
923 Py_DECREF(newlist);
924 return PyLong_FromSsize_t(len + cleared_callback0);
925 }
926
Serhiy Storchakabca49392017-09-03 08:10:14 +0300927 if (j < len) {
928 Py_SIZE(newlist) = j;
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900929 }
Serhiy Storchakabca49392017-09-03 08:10:14 +0300930 j = PyList_GET_SIZE(newlist);
931 len = PyList_GET_SIZE(self->fut_callbacks);
932 if (j != len) {
933 if (PyList_SetSlice(self->fut_callbacks, 0, len, newlist) < 0) {
934 goto fail;
935 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900936 }
937 Py_DECREF(newlist);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500938 return PyLong_FromSsize_t(len - j + cleared_callback0);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900939
940fail:
941 Py_DECREF(newlist);
942 return NULL;
943}
944
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400945/*[clinic input]
946_asyncio.Future.cancel
947
948Cancel the future and schedule callbacks.
949
950If the future is already done or cancelled, return False. Otherwise,
951change the future's state to cancelled, schedule the callbacks and
952return True.
953[clinic start generated code]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900954
955static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400956_asyncio_Future_cancel_impl(FutureObj *self)
957/*[clinic end generated code: output=e45b932ba8bd68a1 input=515709a127995109]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900958{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500959 ENSURE_FUTURE_ALIVE(self)
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400960 return future_cancel(self);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900961}
962
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400963/*[clinic input]
964_asyncio.Future.cancelled
965
966Return True if the future was cancelled.
967[clinic start generated code]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900968
969static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400970_asyncio_Future_cancelled_impl(FutureObj *self)
971/*[clinic end generated code: output=145197ced586357d input=943ab8b7b7b17e45]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900972{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500973 if (future_is_alive(self) && self->fut_state == STATE_CANCELLED) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900974 Py_RETURN_TRUE;
975 }
976 else {
977 Py_RETURN_FALSE;
978 }
979}
980
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400981/*[clinic input]
982_asyncio.Future.done
983
984Return True if the future is done.
985
986Done means either that a result / exception are available, or that the
987future was cancelled.
988[clinic start generated code]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900989
990static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400991_asyncio_Future_done_impl(FutureObj *self)
992/*[clinic end generated code: output=244c5ac351145096 input=28d7b23fdb65d2ac]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900993{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500994 if (!future_is_alive(self) || self->fut_state == STATE_PENDING) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900995 Py_RETURN_FALSE;
996 }
997 else {
998 Py_RETURN_TRUE;
999 }
1000}
1001
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001002/*[clinic input]
1003_asyncio.Future.get_loop
1004
1005Return the event loop the Future is bound to.
1006[clinic start generated code]*/
1007
1008static PyObject *
1009_asyncio_Future_get_loop_impl(FutureObj *self)
1010/*[clinic end generated code: output=119b6ea0c9816c3f input=cba48c2136c79d1f]*/
1011{
1012 Py_INCREF(self->fut_loop);
1013 return self->fut_loop;
1014}
1015
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001016static PyObject *
1017FutureObj_get_blocking(FutureObj *fut)
1018{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001019 if (future_is_alive(fut) && fut->fut_blocking) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001020 Py_RETURN_TRUE;
1021 }
1022 else {
1023 Py_RETURN_FALSE;
1024 }
1025}
1026
1027static int
1028FutureObj_set_blocking(FutureObj *fut, PyObject *val)
1029{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001030 if (future_ensure_alive(fut)) {
1031 return -1;
1032 }
1033
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001034 int is_true = PyObject_IsTrue(val);
1035 if (is_true < 0) {
1036 return -1;
1037 }
1038 fut->fut_blocking = is_true;
1039 return 0;
1040}
1041
1042static PyObject *
1043FutureObj_get_log_traceback(FutureObj *fut)
1044{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001045 ENSURE_FUTURE_ALIVE(fut)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001046 if (fut->fut_log_tb) {
1047 Py_RETURN_TRUE;
1048 }
1049 else {
1050 Py_RETURN_FALSE;
1051 }
1052}
1053
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +00001054static int
1055FutureObj_set_log_traceback(FutureObj *fut, PyObject *val)
1056{
1057 int is_true = PyObject_IsTrue(val);
1058 if (is_true < 0) {
1059 return -1;
1060 }
1061 fut->fut_log_tb = is_true;
1062 return 0;
1063}
1064
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001065static PyObject *
1066FutureObj_get_loop(FutureObj *fut)
1067{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001068 if (!future_is_alive(fut)) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001069 Py_RETURN_NONE;
1070 }
1071 Py_INCREF(fut->fut_loop);
1072 return fut->fut_loop;
1073}
1074
1075static PyObject *
1076FutureObj_get_callbacks(FutureObj *fut)
1077{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001078 Py_ssize_t i;
1079 Py_ssize_t len;
1080 PyObject *new_list;
1081
1082 ENSURE_FUTURE_ALIVE(fut)
1083
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001084 if (fut->fut_callbacks == NULL) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001085 if (fut->fut_callback0 == NULL) {
1086 Py_RETURN_NONE;
1087 }
1088 else {
1089 new_list = PyList_New(1);
1090 if (new_list == NULL) {
1091 return NULL;
1092 }
1093 Py_INCREF(fut->fut_callback0);
1094 PyList_SET_ITEM(new_list, 0, fut->fut_callback0);
1095 return new_list;
1096 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001097 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001098
1099 assert(fut->fut_callbacks != NULL);
1100
1101 if (fut->fut_callback0 == NULL) {
1102 Py_INCREF(fut->fut_callbacks);
1103 return fut->fut_callbacks;
1104 }
1105
1106 assert(fut->fut_callback0 != NULL);
1107
1108 len = PyList_GET_SIZE(fut->fut_callbacks);
1109 new_list = PyList_New(len + 1);
1110 if (new_list == NULL) {
1111 return NULL;
1112 }
1113
1114 Py_INCREF(fut->fut_callback0);
1115 PyList_SET_ITEM(new_list, 0, fut->fut_callback0);
1116 for (i = 0; i < len; i++) {
1117 PyObject *cb = PyList_GET_ITEM(fut->fut_callbacks, i);
1118 Py_INCREF(cb);
1119 PyList_SET_ITEM(new_list, i + 1, cb);
1120 }
1121
1122 return new_list;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001123}
1124
1125static PyObject *
1126FutureObj_get_result(FutureObj *fut)
1127{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001128 ENSURE_FUTURE_ALIVE(fut)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001129 if (fut->fut_result == NULL) {
1130 Py_RETURN_NONE;
1131 }
1132 Py_INCREF(fut->fut_result);
1133 return fut->fut_result;
1134}
1135
1136static PyObject *
1137FutureObj_get_exception(FutureObj *fut)
1138{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001139 ENSURE_FUTURE_ALIVE(fut)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001140 if (fut->fut_exception == NULL) {
1141 Py_RETURN_NONE;
1142 }
1143 Py_INCREF(fut->fut_exception);
1144 return fut->fut_exception;
1145}
1146
1147static PyObject *
1148FutureObj_get_source_traceback(FutureObj *fut)
1149{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001150 if (!future_is_alive(fut) || fut->fut_source_tb == NULL) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001151 Py_RETURN_NONE;
1152 }
1153 Py_INCREF(fut->fut_source_tb);
1154 return fut->fut_source_tb;
1155}
1156
1157static PyObject *
1158FutureObj_get_state(FutureObj *fut)
1159{
1160 _Py_IDENTIFIER(PENDING);
1161 _Py_IDENTIFIER(CANCELLED);
1162 _Py_IDENTIFIER(FINISHED);
1163 PyObject *ret = NULL;
1164
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001165 ENSURE_FUTURE_ALIVE(fut)
1166
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001167 switch (fut->fut_state) {
1168 case STATE_PENDING:
1169 ret = _PyUnicode_FromId(&PyId_PENDING);
1170 break;
1171 case STATE_CANCELLED:
1172 ret = _PyUnicode_FromId(&PyId_CANCELLED);
1173 break;
1174 case STATE_FINISHED:
1175 ret = _PyUnicode_FromId(&PyId_FINISHED);
1176 break;
1177 default:
1178 assert (0);
1179 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03001180 Py_XINCREF(ret);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001181 return ret;
1182}
1183
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001184/*[clinic input]
1185_asyncio.Future._repr_info
1186[clinic start generated code]*/
1187
1188static PyObject *
1189_asyncio_Future__repr_info_impl(FutureObj *self)
1190/*[clinic end generated code: output=fa69e901bd176cfb input=f21504d8e2ae1ca2]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001191{
Victor Stinnerde4ae3d2016-12-04 22:59:09 +01001192 return PyObject_CallFunctionObjArgs(
1193 asyncio_future_repr_info_func, self, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001194}
1195
1196/*[clinic input]
1197_asyncio.Future._schedule_callbacks
1198[clinic start generated code]*/
1199
1200static PyObject *
1201_asyncio_Future__schedule_callbacks_impl(FutureObj *self)
1202/*[clinic end generated code: output=5e8958d89ea1c5dc input=4f5f295f263f4a88]*/
1203{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001204 ENSURE_FUTURE_ALIVE(self)
1205
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001206 int ret = future_schedule_callbacks(self);
1207 if (ret == -1) {
1208 return NULL;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001209 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001210 Py_RETURN_NONE;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001211}
1212
1213static PyObject *
1214FutureObj_repr(FutureObj *fut)
1215{
1216 _Py_IDENTIFIER(_repr_info);
1217
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001218 ENSURE_FUTURE_ALIVE(fut)
1219
Serhiy Storchakabca49392017-09-03 08:10:14 +03001220 PyObject *rinfo = _PyObject_CallMethodIdObjArgs((PyObject*)fut,
1221 &PyId__repr_info,
1222 NULL);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001223 if (rinfo == NULL) {
1224 return NULL;
1225 }
1226
Serhiy Storchakabca49392017-09-03 08:10:14 +03001227 PyObject *rinfo_s = PyUnicode_Join(NULL, rinfo);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001228 Py_DECREF(rinfo);
1229 if (rinfo_s == NULL) {
1230 return NULL;
1231 }
1232
1233 PyObject *rstr = NULL;
1234 PyObject *type_name = PyObject_GetAttrString((PyObject*)Py_TYPE(fut),
1235 "__name__");
1236 if (type_name != NULL) {
Serhiy Storchakabca49392017-09-03 08:10:14 +03001237 rstr = PyUnicode_FromFormat("<%S %U>", type_name, rinfo_s);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001238 Py_DECREF(type_name);
1239 }
1240 Py_DECREF(rinfo_s);
1241 return rstr;
1242}
1243
1244static void
1245FutureObj_finalize(FutureObj *fut)
1246{
1247 _Py_IDENTIFIER(call_exception_handler);
1248 _Py_IDENTIFIER(message);
1249 _Py_IDENTIFIER(exception);
1250 _Py_IDENTIFIER(future);
1251 _Py_IDENTIFIER(source_traceback);
1252
Serhiy Storchakabca49392017-09-03 08:10:14 +03001253 PyObject *error_type, *error_value, *error_traceback;
1254 PyObject *context;
1255 PyObject *type_name;
1256 PyObject *message = NULL;
1257 PyObject *func;
1258
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001259 if (!fut->fut_log_tb) {
1260 return;
1261 }
1262 assert(fut->fut_exception != NULL);
Serhiy Storchakabca49392017-09-03 08:10:14 +03001263 fut->fut_log_tb = 0;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001264
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001265 /* Save the current exception, if any. */
1266 PyErr_Fetch(&error_type, &error_value, &error_traceback);
1267
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001268 context = PyDict_New();
1269 if (context == NULL) {
1270 goto finally;
1271 }
1272
1273 type_name = PyObject_GetAttrString((PyObject*)Py_TYPE(fut), "__name__");
1274 if (type_name == NULL) {
1275 goto finally;
1276 }
1277
1278 message = PyUnicode_FromFormat(
1279 "%S exception was never retrieved", type_name);
Serhiy Storchakabca49392017-09-03 08:10:14 +03001280 Py_DECREF(type_name);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001281 if (message == NULL) {
1282 goto finally;
1283 }
1284
1285 if (_PyDict_SetItemId(context, &PyId_message, message) < 0 ||
1286 _PyDict_SetItemId(context, &PyId_exception, fut->fut_exception) < 0 ||
1287 _PyDict_SetItemId(context, &PyId_future, (PyObject*)fut) < 0) {
1288 goto finally;
1289 }
1290 if (fut->fut_source_tb != NULL) {
1291 if (_PyDict_SetItemId(context, &PyId_source_traceback,
1292 fut->fut_source_tb) < 0) {
1293 goto finally;
1294 }
1295 }
1296
1297 func = _PyObject_GetAttrId(fut->fut_loop, &PyId_call_exception_handler);
1298 if (func != NULL) {
Serhiy Storchakabca49392017-09-03 08:10:14 +03001299 PyObject *res = PyObject_CallFunctionObjArgs(func, context, NULL);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001300 if (res == NULL) {
1301 PyErr_WriteUnraisable(func);
1302 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03001303 else {
1304 Py_DECREF(res);
1305 }
1306 Py_DECREF(func);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001307 }
1308
1309finally:
Serhiy Storchakabca49392017-09-03 08:10:14 +03001310 Py_XDECREF(context);
1311 Py_XDECREF(message);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001312
1313 /* Restore the saved exception. */
1314 PyErr_Restore(error_type, error_value, error_traceback);
1315}
1316
1317
1318static PyAsyncMethods FutureType_as_async = {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001319 (unaryfunc)future_new_iter, /* am_await */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001320 0, /* am_aiter */
1321 0 /* am_anext */
1322};
1323
1324static PyMethodDef FutureType_methods[] = {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001325 _ASYNCIO_FUTURE_RESULT_METHODDEF
1326 _ASYNCIO_FUTURE_EXCEPTION_METHODDEF
1327 _ASYNCIO_FUTURE_SET_RESULT_METHODDEF
1328 _ASYNCIO_FUTURE_SET_EXCEPTION_METHODDEF
1329 _ASYNCIO_FUTURE_ADD_DONE_CALLBACK_METHODDEF
1330 _ASYNCIO_FUTURE_REMOVE_DONE_CALLBACK_METHODDEF
1331 _ASYNCIO_FUTURE_CANCEL_METHODDEF
1332 _ASYNCIO_FUTURE_CANCELLED_METHODDEF
1333 _ASYNCIO_FUTURE_DONE_METHODDEF
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001334 _ASYNCIO_FUTURE_GET_LOOP_METHODDEF
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001335 _ASYNCIO_FUTURE__REPR_INFO_METHODDEF
1336 _ASYNCIO_FUTURE__SCHEDULE_CALLBACKS_METHODDEF
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001337 {NULL, NULL} /* Sentinel */
1338};
1339
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001340#define FUTURE_COMMON_GETSETLIST \
1341 {"_state", (getter)FutureObj_get_state, NULL, NULL}, \
1342 {"_asyncio_future_blocking", (getter)FutureObj_get_blocking, \
1343 (setter)FutureObj_set_blocking, NULL}, \
1344 {"_loop", (getter)FutureObj_get_loop, NULL, NULL}, \
1345 {"_callbacks", (getter)FutureObj_get_callbacks, NULL, NULL}, \
1346 {"_result", (getter)FutureObj_get_result, NULL, NULL}, \
1347 {"_exception", (getter)FutureObj_get_exception, NULL, NULL}, \
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +00001348 {"_log_traceback", (getter)FutureObj_get_log_traceback, \
1349 (setter)FutureObj_set_log_traceback, NULL}, \
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001350 {"_source_traceback", (getter)FutureObj_get_source_traceback, NULL, NULL},
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001351
1352static PyGetSetDef FutureType_getsetlist[] = {
1353 FUTURE_COMMON_GETSETLIST
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001354 {NULL} /* Sentinel */
1355};
1356
1357static void FutureObj_dealloc(PyObject *self);
1358
1359static PyTypeObject FutureType = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02001360 PyVarObject_HEAD_INIT(NULL, 0)
INADA Naoki9f2ce252016-10-15 15:39:19 +09001361 "_asyncio.Future",
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001362 sizeof(FutureObj), /* tp_basicsize */
1363 .tp_dealloc = FutureObj_dealloc,
1364 .tp_as_async = &FutureType_as_async,
1365 .tp_repr = (reprfunc)FutureObj_repr,
1366 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE
1367 | Py_TPFLAGS_HAVE_FINALIZE,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001368 .tp_doc = _asyncio_Future___init____doc__,
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001369 .tp_traverse = (traverseproc)FutureObj_traverse,
1370 .tp_clear = (inquiry)FutureObj_clear,
1371 .tp_weaklistoffset = offsetof(FutureObj, fut_weakreflist),
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001372 .tp_iter = (getiterfunc)future_new_iter,
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001373 .tp_methods = FutureType_methods,
1374 .tp_getset = FutureType_getsetlist,
1375 .tp_dictoffset = offsetof(FutureObj, dict),
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001376 .tp_init = (initproc)_asyncio_Future___init__,
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001377 .tp_new = PyType_GenericNew,
1378 .tp_finalize = (destructor)FutureObj_finalize,
1379};
1380
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001381static inline int
1382future_call_schedule_callbacks(FutureObj *fut)
1383{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001384 if (Future_CheckExact(fut) || Task_CheckExact(fut)) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001385 return future_schedule_callbacks(fut);
1386 }
1387 else {
1388 /* `fut` is a subclass of Future */
1389 PyObject *ret = _PyObject_CallMethodId(
1390 (PyObject*)fut, &PyId__schedule_callbacks, NULL);
1391 if (ret == NULL) {
1392 return -1;
1393 }
1394
1395 Py_DECREF(ret);
1396 return 0;
1397 }
1398}
1399
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001400static void
1401FutureObj_dealloc(PyObject *self)
1402{
1403 FutureObj *fut = (FutureObj *)self;
1404
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001405 if (Future_CheckExact(fut)) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001406 /* When fut is subclass of Future, finalizer is called from
1407 * subtype_dealloc.
1408 */
1409 if (PyObject_CallFinalizerFromDealloc(self) < 0) {
1410 // resurrected.
1411 return;
1412 }
1413 }
1414
Alexander Mohrde34cbe2017-08-01 23:31:07 -07001415 PyObject_GC_UnTrack(self);
1416
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001417 if (fut->fut_weakreflist != NULL) {
1418 PyObject_ClearWeakRefs(self);
1419 }
1420
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001421 (void)FutureObj_clear(fut);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001422 Py_TYPE(fut)->tp_free(fut);
1423}
1424
1425
1426/*********************** Future Iterator **************************/
1427
1428typedef struct {
1429 PyObject_HEAD
1430 FutureObj *future;
1431} futureiterobject;
1432
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001433
1434#define FI_FREELIST_MAXLEN 255
1435static futureiterobject *fi_freelist = NULL;
1436static Py_ssize_t fi_freelist_len = 0;
1437
1438
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001439static void
1440FutureIter_dealloc(futureiterobject *it)
1441{
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001442 PyObject_GC_UnTrack(it);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001443 Py_CLEAR(it->future);
1444
1445 if (fi_freelist_len < FI_FREELIST_MAXLEN) {
1446 fi_freelist_len++;
1447 it->future = (FutureObj*) fi_freelist;
1448 fi_freelist = it;
1449 }
1450 else {
1451 PyObject_GC_Del(it);
1452 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001453}
1454
1455static PyObject *
1456FutureIter_iternext(futureiterobject *it)
1457{
1458 PyObject *res;
1459 FutureObj *fut = it->future;
1460
1461 if (fut == NULL) {
1462 return NULL;
1463 }
1464
1465 if (fut->fut_state == STATE_PENDING) {
1466 if (!fut->fut_blocking) {
1467 fut->fut_blocking = 1;
1468 Py_INCREF(fut);
1469 return (PyObject *)fut;
1470 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03001471 PyErr_SetString(PyExc_AssertionError,
1472 "yield from wasn't used with future");
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001473 return NULL;
1474 }
1475
Serhiy Storchakabca49392017-09-03 08:10:14 +03001476 it->future = NULL;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001477 res = _asyncio_Future_result_impl(fut);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001478 if (res != NULL) {
Serhiy Storchaka60e49aa2016-11-06 18:47:03 +02001479 /* The result of the Future is not an exception. */
Serhiy Storchakabca49392017-09-03 08:10:14 +03001480 (void)_PyGen_SetStopIterationValue(res);
Serhiy Storchaka60e49aa2016-11-06 18:47:03 +02001481 Py_DECREF(res);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001482 }
1483
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001484 Py_DECREF(fut);
1485 return NULL;
1486}
1487
1488static PyObject *
INADA Naoki74c17532016-10-25 19:00:45 +09001489FutureIter_send(futureiterobject *self, PyObject *unused)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001490{
INADA Naoki74c17532016-10-25 19:00:45 +09001491 /* Future.__iter__ doesn't care about values that are pushed to the
1492 * generator, it just returns "self.result().
1493 */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001494 return FutureIter_iternext(self);
1495}
1496
1497static PyObject *
1498FutureIter_throw(futureiterobject *self, PyObject *args)
1499{
Serhiy Storchakabca49392017-09-03 08:10:14 +03001500 PyObject *type, *val = NULL, *tb = NULL;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001501 if (!PyArg_ParseTuple(args, "O|OO", &type, &val, &tb))
1502 return NULL;
1503
1504 if (val == Py_None) {
1505 val = NULL;
1506 }
1507 if (tb == Py_None) {
1508 tb = NULL;
Benjamin Peterson996fc1f2016-11-14 00:15:44 -08001509 } else if (tb != NULL && !PyTraceBack_Check(tb)) {
1510 PyErr_SetString(PyExc_TypeError, "throw() third argument must be a traceback");
1511 return NULL;
1512 }
1513
1514 Py_INCREF(type);
1515 Py_XINCREF(val);
1516 Py_XINCREF(tb);
1517
1518 if (PyExceptionClass_Check(type)) {
1519 PyErr_NormalizeException(&type, &val, &tb);
Yury Selivanovedfe8862016-12-01 11:37:47 -05001520 /* No need to call PyException_SetTraceback since we'll be calling
1521 PyErr_Restore for `type`, `val`, and `tb`. */
Benjamin Peterson996fc1f2016-11-14 00:15:44 -08001522 } else if (PyExceptionInstance_Check(type)) {
1523 if (val) {
1524 PyErr_SetString(PyExc_TypeError,
1525 "instance exception may not have a separate value");
1526 goto fail;
1527 }
1528 val = type;
1529 type = PyExceptionInstance_Class(type);
1530 Py_INCREF(type);
1531 if (tb == NULL)
1532 tb = PyException_GetTraceback(val);
1533 } else {
1534 PyErr_SetString(PyExc_TypeError,
1535 "exceptions must be classes deriving BaseException or "
1536 "instances of such a class");
1537 goto fail;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001538 }
1539
1540 Py_CLEAR(self->future);
1541
Benjamin Peterson996fc1f2016-11-14 00:15:44 -08001542 PyErr_Restore(type, val, tb);
1543
Serhiy Storchakabca49392017-09-03 08:10:14 +03001544 return NULL;
Benjamin Peterson996fc1f2016-11-14 00:15:44 -08001545
1546 fail:
1547 Py_DECREF(type);
1548 Py_XDECREF(val);
1549 Py_XDECREF(tb);
1550 return NULL;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001551}
1552
1553static PyObject *
1554FutureIter_close(futureiterobject *self, PyObject *arg)
1555{
1556 Py_CLEAR(self->future);
1557 Py_RETURN_NONE;
1558}
1559
1560static int
1561FutureIter_traverse(futureiterobject *it, visitproc visit, void *arg)
1562{
1563 Py_VISIT(it->future);
1564 return 0;
1565}
1566
1567static PyMethodDef FutureIter_methods[] = {
1568 {"send", (PyCFunction)FutureIter_send, METH_O, NULL},
1569 {"throw", (PyCFunction)FutureIter_throw, METH_VARARGS, NULL},
1570 {"close", (PyCFunction)FutureIter_close, METH_NOARGS, NULL},
1571 {NULL, NULL} /* Sentinel */
1572};
1573
1574static PyTypeObject FutureIterType = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02001575 PyVarObject_HEAD_INIT(NULL, 0)
INADA Naoki9f2ce252016-10-15 15:39:19 +09001576 "_asyncio.FutureIter",
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001577 .tp_basicsize = sizeof(futureiterobject),
1578 .tp_itemsize = 0,
1579 .tp_dealloc = (destructor)FutureIter_dealloc,
1580 .tp_getattro = PyObject_GenericGetAttr,
1581 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
1582 .tp_traverse = (traverseproc)FutureIter_traverse,
1583 .tp_iter = PyObject_SelfIter,
1584 .tp_iternext = (iternextfunc)FutureIter_iternext,
1585 .tp_methods = FutureIter_methods,
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001586};
1587
1588static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001589future_new_iter(PyObject *fut)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001590{
1591 futureiterobject *it;
1592
1593 if (!PyObject_TypeCheck(fut, &FutureType)) {
1594 PyErr_BadInternalCall();
1595 return NULL;
1596 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001597
1598 ENSURE_FUTURE_ALIVE(fut)
1599
1600 if (fi_freelist_len) {
1601 fi_freelist_len--;
1602 it = fi_freelist;
1603 fi_freelist = (futureiterobject*) it->future;
1604 it->future = NULL;
1605 _Py_NewReference((PyObject*) it);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001606 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001607 else {
1608 it = PyObject_GC_New(futureiterobject, &FutureIterType);
1609 if (it == NULL) {
1610 return NULL;
1611 }
1612 }
1613
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001614 Py_INCREF(fut);
1615 it->future = (FutureObj*)fut;
INADA Naoki1be427b2016-10-11 02:12:34 +09001616 PyObject_GC_Track(it);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001617 return (PyObject*)it;
1618}
1619
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001620
1621/*********************** Task **************************/
1622
1623
1624/*[clinic input]
1625class _asyncio.Task "TaskObj *" "&Task_Type"
1626[clinic start generated code]*/
1627/*[clinic end generated code: output=da39a3ee5e6b4b0d input=719dcef0fcc03b37]*/
1628
1629static int task_call_step_soon(TaskObj *, PyObject *);
1630static inline PyObject * task_call_wakeup(TaskObj *, PyObject *);
1631static inline PyObject * task_call_step(TaskObj *, PyObject *);
1632static PyObject * task_wakeup(TaskObj *, PyObject *);
1633static PyObject * task_step(TaskObj *, PyObject *);
1634
1635/* ----- Task._step wrapper */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001636
INADA Naokic411a7d2016-10-18 11:48:14 +09001637static int
Serhiy Storchakabca49392017-09-03 08:10:14 +03001638TaskStepMethWrapper_clear(TaskStepMethWrapper *o)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001639{
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001640 Py_CLEAR(o->sw_task);
1641 Py_CLEAR(o->sw_arg);
1642 return 0;
1643}
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001644
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001645static void
Serhiy Storchakabca49392017-09-03 08:10:14 +03001646TaskStepMethWrapper_dealloc(TaskStepMethWrapper *o)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001647{
1648 PyObject_GC_UnTrack(o);
Serhiy Storchakabca49392017-09-03 08:10:14 +03001649 (void)TaskStepMethWrapper_clear(o);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001650 Py_TYPE(o)->tp_free(o);
1651}
1652
1653static PyObject *
Serhiy Storchakabca49392017-09-03 08:10:14 +03001654TaskStepMethWrapper_call(TaskStepMethWrapper *o,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001655 PyObject *args, PyObject *kwds)
1656{
Serhiy Storchakabca49392017-09-03 08:10:14 +03001657 if (kwds != NULL && PyDict_GET_SIZE(kwds) != 0) {
1658 PyErr_SetString(PyExc_TypeError, "function takes no keyword arguments");
1659 return NULL;
1660 }
1661 if (args != NULL && PyTuple_GET_SIZE(args) != 0) {
1662 PyErr_SetString(PyExc_TypeError, "function takes no positional arguments");
1663 return NULL;
1664 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001665 return task_call_step(o->sw_task, o->sw_arg);
1666}
1667
1668static int
Serhiy Storchakabca49392017-09-03 08:10:14 +03001669TaskStepMethWrapper_traverse(TaskStepMethWrapper *o,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001670 visitproc visit, void *arg)
1671{
1672 Py_VISIT(o->sw_task);
1673 Py_VISIT(o->sw_arg);
1674 return 0;
1675}
1676
1677static PyObject *
Serhiy Storchakabca49392017-09-03 08:10:14 +03001678TaskStepMethWrapper_get___self__(TaskStepMethWrapper *o)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001679{
1680 if (o->sw_task) {
1681 Py_INCREF(o->sw_task);
1682 return (PyObject*)o->sw_task;
1683 }
1684 Py_RETURN_NONE;
1685}
1686
Serhiy Storchakabca49392017-09-03 08:10:14 +03001687static PyGetSetDef TaskStepMethWrapper_getsetlist[] = {
1688 {"__self__", (getter)TaskStepMethWrapper_get___self__, NULL, NULL},
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001689 {NULL} /* Sentinel */
1690};
1691
Serhiy Storchakabca49392017-09-03 08:10:14 +03001692PyTypeObject TaskStepMethWrapper_Type = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02001693 PyVarObject_HEAD_INIT(NULL, 0)
Serhiy Storchakabca49392017-09-03 08:10:14 +03001694 "TaskStepMethWrapper",
1695 .tp_basicsize = sizeof(TaskStepMethWrapper),
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001696 .tp_itemsize = 0,
Serhiy Storchakabca49392017-09-03 08:10:14 +03001697 .tp_getset = TaskStepMethWrapper_getsetlist,
1698 .tp_dealloc = (destructor)TaskStepMethWrapper_dealloc,
1699 .tp_call = (ternaryfunc)TaskStepMethWrapper_call,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001700 .tp_getattro = PyObject_GenericGetAttr,
1701 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
Serhiy Storchakabca49392017-09-03 08:10:14 +03001702 .tp_traverse = (traverseproc)TaskStepMethWrapper_traverse,
1703 .tp_clear = (inquiry)TaskStepMethWrapper_clear,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001704};
1705
1706static PyObject *
Serhiy Storchakabca49392017-09-03 08:10:14 +03001707TaskStepMethWrapper_new(TaskObj *task, PyObject *arg)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001708{
Serhiy Storchakabca49392017-09-03 08:10:14 +03001709 TaskStepMethWrapper *o;
1710 o = PyObject_GC_New(TaskStepMethWrapper, &TaskStepMethWrapper_Type);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001711 if (o == NULL) {
1712 return NULL;
1713 }
1714
1715 Py_INCREF(task);
1716 o->sw_task = task;
1717
1718 Py_XINCREF(arg);
1719 o->sw_arg = arg;
1720
1721 PyObject_GC_Track(o);
1722 return (PyObject*) o;
1723}
1724
1725/* ----- Task._wakeup wrapper */
1726
1727static PyObject *
1728TaskWakeupMethWrapper_call(TaskWakeupMethWrapper *o,
1729 PyObject *args, PyObject *kwds)
1730{
1731 PyObject *fut;
1732
Serhiy Storchakabca49392017-09-03 08:10:14 +03001733 if (kwds != NULL && PyDict_GET_SIZE(kwds) != 0) {
1734 PyErr_SetString(PyExc_TypeError, "function takes no keyword arguments");
1735 return NULL;
1736 }
1737 if (!PyArg_ParseTuple(args, "O", &fut)) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001738 return NULL;
1739 }
1740
1741 return task_call_wakeup(o->ww_task, fut);
1742}
1743
1744static int
1745TaskWakeupMethWrapper_clear(TaskWakeupMethWrapper *o)
1746{
1747 Py_CLEAR(o->ww_task);
1748 return 0;
1749}
1750
1751static int
1752TaskWakeupMethWrapper_traverse(TaskWakeupMethWrapper *o,
1753 visitproc visit, void *arg)
1754{
1755 Py_VISIT(o->ww_task);
1756 return 0;
1757}
1758
1759static void
1760TaskWakeupMethWrapper_dealloc(TaskWakeupMethWrapper *o)
1761{
1762 PyObject_GC_UnTrack(o);
1763 (void)TaskWakeupMethWrapper_clear(o);
1764 Py_TYPE(o)->tp_free(o);
1765}
1766
1767PyTypeObject TaskWakeupMethWrapper_Type = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02001768 PyVarObject_HEAD_INIT(NULL, 0)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001769 "TaskWakeupMethWrapper",
1770 .tp_basicsize = sizeof(TaskWakeupMethWrapper),
1771 .tp_itemsize = 0,
1772 .tp_dealloc = (destructor)TaskWakeupMethWrapper_dealloc,
1773 .tp_call = (ternaryfunc)TaskWakeupMethWrapper_call,
1774 .tp_getattro = PyObject_GenericGetAttr,
1775 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
1776 .tp_traverse = (traverseproc)TaskWakeupMethWrapper_traverse,
1777 .tp_clear = (inquiry)TaskWakeupMethWrapper_clear,
1778};
1779
1780static PyObject *
1781TaskWakeupMethWrapper_new(TaskObj *task)
1782{
1783 TaskWakeupMethWrapper *o;
1784 o = PyObject_GC_New(TaskWakeupMethWrapper, &TaskWakeupMethWrapper_Type);
1785 if (o == NULL) {
1786 return NULL;
1787 }
1788
1789 Py_INCREF(task);
1790 o->ww_task = task;
1791
1792 PyObject_GC_Track(o);
1793 return (PyObject*) o;
1794}
1795
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001796/* ----- Task introspection helpers */
1797
1798static int
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001799register_task(PyObject *task)
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001800{
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001801 _Py_IDENTIFIER(add);
1802
1803 PyObject *res = _PyObject_CallMethodIdObjArgs(
1804 all_tasks, &PyId_add, task, NULL);
1805 if (res == NULL) {
1806 return -1;
1807 }
1808 Py_DECREF(res);
1809 return 0;
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001810}
1811
1812
1813static int
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001814unregister_task(PyObject *task)
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001815{
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001816 _Py_IDENTIFIER(discard);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001817
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001818 PyObject *res = _PyObject_CallMethodIdObjArgs(
1819 all_tasks, &PyId_discard, task, NULL);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001820 if (res == NULL) {
1821 return -1;
1822 }
1823 Py_DECREF(res);
1824 return 0;
1825}
1826
1827
1828static int
1829enter_task(PyObject *loop, PyObject *task)
1830{
1831 PyObject *item;
1832 Py_hash_t hash;
1833 hash = PyObject_Hash(loop);
1834 if (hash == -1) {
1835 return -1;
1836 }
1837 item = _PyDict_GetItem_KnownHash(current_tasks, loop, hash);
1838 if (item != NULL) {
1839 PyErr_Format(
1840 PyExc_RuntimeError,
1841 "Cannot enter into task %R while another " \
1842 "task %R is being executed.",
1843 task, item, NULL);
1844 return -1;
1845 }
1846 if (_PyDict_SetItem_KnownHash(current_tasks, loop, task, hash) < 0) {
1847 return -1;
1848 }
1849 return 0;
1850}
1851
1852
1853static int
1854leave_task(PyObject *loop, PyObject *task)
1855/*[clinic end generated code: output=0ebf6db4b858fb41 input=51296a46313d1ad8]*/
1856{
1857 PyObject *item;
1858 Py_hash_t hash;
1859 hash = PyObject_Hash(loop);
1860 if (hash == -1) {
1861 return -1;
1862 }
1863 item = _PyDict_GetItem_KnownHash(current_tasks, loop, hash);
1864 if (item != task) {
1865 if (item == NULL) {
1866 /* Not entered, replace with None */
1867 item = Py_None;
1868 }
1869 PyErr_Format(
1870 PyExc_RuntimeError,
1871 "Leaving task %R does not match the current task %R.",
1872 task, item, NULL);
1873 return -1;
1874 }
1875 return _PyDict_DelItem_KnownHash(current_tasks, loop, hash);
1876}
1877
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001878/* ----- Task */
1879
1880/*[clinic input]
1881_asyncio.Task.__init__
1882
Serhiy Storchakabca49392017-09-03 08:10:14 +03001883 coro: object
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001884 *
Serhiy Storchakabca49392017-09-03 08:10:14 +03001885 loop: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001886
1887A coroutine wrapped in a Future.
1888[clinic start generated code]*/
1889
1890static int
1891_asyncio_Task___init___impl(TaskObj *self, PyObject *coro, PyObject *loop)
Serhiy Storchakabca49392017-09-03 08:10:14 +03001892/*[clinic end generated code: output=9f24774c2287fc2f input=8d132974b049593e]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001893{
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001894 if (future_init((FutureObj*)self, loop)) {
INADA Naokic411a7d2016-10-18 11:48:14 +09001895 return -1;
1896 }
INADA Naokic411a7d2016-10-18 11:48:14 +09001897
Yury Selivanova9d7e552017-12-19 07:18:45 -05001898 int is_coro = is_coroutine(coro);
1899 if (is_coro == -1) {
1900 return -1;
1901 }
1902 if (is_coro == 0) {
1903 self->task_log_destroy_pending = 0;
1904 PyErr_Format(PyExc_TypeError,
1905 "a coroutine was expected, got %R",
1906 coro, NULL);
1907 return -1;
Andrew Svetlovf74ef452017-12-15 07:04:38 +02001908 }
1909
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001910 self->task_fut_waiter = NULL;
1911 self->task_must_cancel = 0;
1912 self->task_log_destroy_pending = 1;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001913 Py_INCREF(coro);
1914 self->task_coro = coro;
1915
1916 if (task_call_step_soon(self, NULL)) {
1917 return -1;
INADA Naokic411a7d2016-10-18 11:48:14 +09001918 }
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001919 return register_task((PyObject*)self);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001920}
1921
1922static int
1923TaskObj_clear(TaskObj *task)
1924{
1925 (void)FutureObj_clear((FutureObj*) task);
1926 Py_CLEAR(task->task_coro);
1927 Py_CLEAR(task->task_fut_waiter);
1928 return 0;
1929}
1930
1931static int
1932TaskObj_traverse(TaskObj *task, visitproc visit, void *arg)
1933{
1934 Py_VISIT(task->task_coro);
1935 Py_VISIT(task->task_fut_waiter);
1936 (void)FutureObj_traverse((FutureObj*) task, visit, arg);
1937 return 0;
1938}
1939
1940static PyObject *
1941TaskObj_get_log_destroy_pending(TaskObj *task)
1942{
1943 if (task->task_log_destroy_pending) {
1944 Py_RETURN_TRUE;
1945 }
1946 else {
1947 Py_RETURN_FALSE;
1948 }
1949}
1950
1951static int
1952TaskObj_set_log_destroy_pending(TaskObj *task, PyObject *val)
1953{
1954 int is_true = PyObject_IsTrue(val);
1955 if (is_true < 0) {
1956 return -1;
1957 }
1958 task->task_log_destroy_pending = is_true;
1959 return 0;
1960}
1961
1962static PyObject *
1963TaskObj_get_must_cancel(TaskObj *task)
1964{
1965 if (task->task_must_cancel) {
1966 Py_RETURN_TRUE;
1967 }
1968 else {
1969 Py_RETURN_FALSE;
1970 }
1971}
1972
1973static PyObject *
1974TaskObj_get_coro(TaskObj *task)
1975{
1976 if (task->task_coro) {
1977 Py_INCREF(task->task_coro);
1978 return task->task_coro;
1979 }
1980
1981 Py_RETURN_NONE;
1982}
1983
1984static PyObject *
1985TaskObj_get_fut_waiter(TaskObj *task)
1986{
1987 if (task->task_fut_waiter) {
1988 Py_INCREF(task->task_fut_waiter);
1989 return task->task_fut_waiter;
1990 }
1991
1992 Py_RETURN_NONE;
1993}
1994
1995/*[clinic input]
1996@classmethod
1997_asyncio.Task.current_task
1998
Serhiy Storchakabca49392017-09-03 08:10:14 +03001999 loop: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002000
2001Return the currently running task in an event loop or None.
2002
2003By default the current task for the current event loop is returned.
2004
2005None is returned when called not in the context of a Task.
2006[clinic start generated code]*/
2007
2008static PyObject *
2009_asyncio_Task_current_task_impl(PyTypeObject *type, PyObject *loop)
Serhiy Storchakabca49392017-09-03 08:10:14 +03002010/*[clinic end generated code: output=99fbe7332c516e03 input=cd14770c5b79c7eb]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002011{
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002012 PyObject *ret;
2013 PyObject *current_task_func;
2014
2015 if (PyErr_WarnEx(PyExc_PendingDeprecationWarning,
2016 "Task.current_task() is deprecated, " \
2017 "use asyncio.current_task() instead",
2018 1) < 0) {
2019 return NULL;
2020 }
2021
2022 current_task_func = _PyObject_GetAttrId(asyncio_mod, &PyId_current_task);
2023 if (current_task_func == NULL) {
2024 return NULL;
2025 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002026
Yury Selivanov8d26aa92017-03-02 22:16:33 -05002027 if (loop == Py_None) {
Yury Selivanova70232f2017-12-13 14:49:42 -05002028 loop = get_event_loop();
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002029 if (loop == NULL) {
2030 return NULL;
2031 }
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002032 ret = PyObject_CallFunctionObjArgs(current_task_func, loop, NULL);
2033 Py_DECREF(current_task_func);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002034 Py_DECREF(loop);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002035 return ret;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002036 }
2037 else {
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002038 ret = PyObject_CallFunctionObjArgs(current_task_func, loop, NULL);
2039 Py_DECREF(current_task_func);
2040 return ret;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002041 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002042}
2043
2044/*[clinic input]
2045@classmethod
2046_asyncio.Task.all_tasks
2047
Serhiy Storchakabca49392017-09-03 08:10:14 +03002048 loop: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002049
2050Return a set of all tasks for an event loop.
2051
2052By default all tasks for the current event loop are returned.
2053[clinic start generated code]*/
2054
2055static PyObject *
2056_asyncio_Task_all_tasks_impl(PyTypeObject *type, PyObject *loop)
Serhiy Storchakabca49392017-09-03 08:10:14 +03002057/*[clinic end generated code: output=11f9b20749ccca5d input=497f80bc9ce726b5]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002058{
2059 PyObject *res;
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002060 PyObject *all_tasks_func;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002061
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002062 all_tasks_func = _PyObject_GetAttrId(asyncio_mod, &PyId_all_tasks);
2063 if (all_tasks_func == NULL) {
2064 return NULL;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002065 }
2066
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002067 if (PyErr_WarnEx(PyExc_PendingDeprecationWarning,
2068 "Task.all_tasks() is deprecated, " \
2069 "use asyncio.all_tasks() instead",
2070 1) < 0) {
2071 return NULL;
2072 }
2073
2074 res = PyObject_CallFunctionObjArgs(all_tasks_func, loop, NULL);
2075 Py_DECREF(all_tasks_func);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002076 return res;
2077}
2078
2079/*[clinic input]
2080_asyncio.Task._repr_info
2081[clinic start generated code]*/
2082
2083static PyObject *
2084_asyncio_Task__repr_info_impl(TaskObj *self)
2085/*[clinic end generated code: output=6a490eb66d5ba34b input=3c6d051ed3ddec8b]*/
2086{
Victor Stinnerde4ae3d2016-12-04 22:59:09 +01002087 return PyObject_CallFunctionObjArgs(
2088 asyncio_task_repr_info_func, self, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002089}
2090
2091/*[clinic input]
2092_asyncio.Task.cancel
2093
2094Request that this task cancel itself.
2095
2096This arranges for a CancelledError to be thrown into the
2097wrapped coroutine on the next cycle through the event loop.
2098The coroutine then has a chance to clean up or even deny
2099the request using try/except/finally.
2100
2101Unlike Future.cancel, this does not guarantee that the
2102task will be cancelled: the exception might be caught and
2103acted upon, delaying cancellation of the task or preventing
2104cancellation completely. The task may also return a value or
2105raise a different exception.
2106
2107Immediately after this method is called, Task.cancelled() will
2108not return True (unless the task was already cancelled). A
2109task will be marked as cancelled when the wrapped coroutine
2110terminates with a CancelledError exception (even if cancel()
2111was not called).
2112[clinic start generated code]*/
2113
2114static PyObject *
2115_asyncio_Task_cancel_impl(TaskObj *self)
2116/*[clinic end generated code: output=6bfc0479da9d5757 input=13f9bf496695cb52]*/
2117{
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +00002118 self->task_log_tb = 0;
2119
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002120 if (self->task_state != STATE_PENDING) {
2121 Py_RETURN_FALSE;
2122 }
2123
2124 if (self->task_fut_waiter) {
2125 PyObject *res;
2126 int is_true;
2127
2128 res = _PyObject_CallMethodId(
2129 self->task_fut_waiter, &PyId_cancel, NULL);
2130 if (res == NULL) {
2131 return NULL;
2132 }
2133
2134 is_true = PyObject_IsTrue(res);
2135 Py_DECREF(res);
2136 if (is_true < 0) {
2137 return NULL;
2138 }
2139
2140 if (is_true) {
2141 Py_RETURN_TRUE;
2142 }
2143 }
2144
2145 self->task_must_cancel = 1;
2146 Py_RETURN_TRUE;
2147}
2148
2149/*[clinic input]
2150_asyncio.Task.get_stack
2151
2152 *
Serhiy Storchakabca49392017-09-03 08:10:14 +03002153 limit: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002154
2155Return the list of stack frames for this task's coroutine.
2156
2157If the coroutine is not done, this returns the stack where it is
2158suspended. If the coroutine has completed successfully or was
2159cancelled, this returns an empty list. If the coroutine was
2160terminated by an exception, this returns the list of traceback
2161frames.
2162
2163The frames are always ordered from oldest to newest.
2164
2165The optional limit gives the maximum number of frames to
2166return; by default all available frames are returned. Its
2167meaning differs depending on whether a stack or a traceback is
2168returned: the newest frames of a stack are returned, but the
2169oldest frames of a traceback are returned. (This matches the
2170behavior of the traceback module.)
2171
2172For reasons beyond our control, only one stack frame is
2173returned for a suspended coroutine.
2174[clinic start generated code]*/
2175
2176static PyObject *
2177_asyncio_Task_get_stack_impl(TaskObj *self, PyObject *limit)
Serhiy Storchakabca49392017-09-03 08:10:14 +03002178/*[clinic end generated code: output=c9aeeeebd1e18118 input=05b323d42b809b90]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002179{
2180 return PyObject_CallFunctionObjArgs(
2181 asyncio_task_get_stack_func, self, limit, NULL);
2182}
2183
2184/*[clinic input]
2185_asyncio.Task.print_stack
2186
2187 *
Serhiy Storchakabca49392017-09-03 08:10:14 +03002188 limit: object = None
2189 file: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002190
2191Print the stack or traceback for this task's coroutine.
2192
2193This produces output similar to that of the traceback module,
2194for the frames retrieved by get_stack(). The limit argument
2195is passed to get_stack(). The file argument is an I/O stream
2196to which the output is written; by default output is written
2197to sys.stderr.
2198[clinic start generated code]*/
2199
2200static PyObject *
2201_asyncio_Task_print_stack_impl(TaskObj *self, PyObject *limit,
2202 PyObject *file)
Serhiy Storchakabca49392017-09-03 08:10:14 +03002203/*[clinic end generated code: output=7339e10314cd3f4d input=1a0352913b7fcd92]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002204{
2205 return PyObject_CallFunctionObjArgs(
2206 asyncio_task_print_stack_func, self, limit, file, NULL);
2207}
2208
2209/*[clinic input]
2210_asyncio.Task._step
2211
Serhiy Storchakabca49392017-09-03 08:10:14 +03002212 exc: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002213[clinic start generated code]*/
2214
2215static PyObject *
2216_asyncio_Task__step_impl(TaskObj *self, PyObject *exc)
Serhiy Storchakabca49392017-09-03 08:10:14 +03002217/*[clinic end generated code: output=7ed23f0cefd5ae42 input=1e19a985ace87ca4]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002218{
2219 return task_step(self, exc == Py_None ? NULL : exc);
2220}
2221
2222/*[clinic input]
2223_asyncio.Task._wakeup
2224
Serhiy Storchakabca49392017-09-03 08:10:14 +03002225 fut: object
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002226[clinic start generated code]*/
2227
2228static PyObject *
2229_asyncio_Task__wakeup_impl(TaskObj *self, PyObject *fut)
Serhiy Storchakabca49392017-09-03 08:10:14 +03002230/*[clinic end generated code: output=75cb341c760fd071 input=6a0616406f829a7b]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002231{
2232 return task_wakeup(self, fut);
2233}
2234
2235static void
2236TaskObj_finalize(TaskObj *task)
2237{
2238 _Py_IDENTIFIER(call_exception_handler);
2239 _Py_IDENTIFIER(task);
2240 _Py_IDENTIFIER(message);
2241 _Py_IDENTIFIER(source_traceback);
2242
Serhiy Storchakabca49392017-09-03 08:10:14 +03002243 PyObject *context;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002244 PyObject *message = NULL;
Serhiy Storchakabca49392017-09-03 08:10:14 +03002245 PyObject *func;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002246 PyObject *error_type, *error_value, *error_traceback;
2247
2248 if (task->task_state != STATE_PENDING || !task->task_log_destroy_pending) {
2249 goto done;
2250 }
2251
2252 /* Save the current exception, if any. */
2253 PyErr_Fetch(&error_type, &error_value, &error_traceback);
2254
2255 context = PyDict_New();
2256 if (context == NULL) {
2257 goto finally;
2258 }
2259
2260 message = PyUnicode_FromString("Task was destroyed but it is pending!");
2261 if (message == NULL) {
2262 goto finally;
2263 }
2264
2265 if (_PyDict_SetItemId(context, &PyId_message, message) < 0 ||
2266 _PyDict_SetItemId(context, &PyId_task, (PyObject*)task) < 0)
2267 {
2268 goto finally;
2269 }
2270
2271 if (task->task_source_tb != NULL) {
2272 if (_PyDict_SetItemId(context, &PyId_source_traceback,
2273 task->task_source_tb) < 0)
2274 {
2275 goto finally;
2276 }
2277 }
2278
2279 func = _PyObject_GetAttrId(task->task_loop, &PyId_call_exception_handler);
2280 if (func != NULL) {
Serhiy Storchakabca49392017-09-03 08:10:14 +03002281 PyObject *res = PyObject_CallFunctionObjArgs(func, context, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002282 if (res == NULL) {
2283 PyErr_WriteUnraisable(func);
2284 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03002285 else {
2286 Py_DECREF(res);
2287 }
2288 Py_DECREF(func);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002289 }
2290
2291finally:
Serhiy Storchakabca49392017-09-03 08:10:14 +03002292 Py_XDECREF(context);
2293 Py_XDECREF(message);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002294
2295 /* Restore the saved exception. */
2296 PyErr_Restore(error_type, error_value, error_traceback);
2297
2298done:
2299 FutureObj_finalize((FutureObj*)task);
2300}
2301
2302static void TaskObj_dealloc(PyObject *); /* Needs Task_CheckExact */
2303
2304static PyMethodDef TaskType_methods[] = {
2305 _ASYNCIO_FUTURE_RESULT_METHODDEF
2306 _ASYNCIO_FUTURE_EXCEPTION_METHODDEF
2307 _ASYNCIO_FUTURE_SET_RESULT_METHODDEF
2308 _ASYNCIO_FUTURE_SET_EXCEPTION_METHODDEF
2309 _ASYNCIO_FUTURE_ADD_DONE_CALLBACK_METHODDEF
2310 _ASYNCIO_FUTURE_REMOVE_DONE_CALLBACK_METHODDEF
2311 _ASYNCIO_FUTURE_CANCELLED_METHODDEF
2312 _ASYNCIO_FUTURE_DONE_METHODDEF
2313 _ASYNCIO_TASK_CURRENT_TASK_METHODDEF
2314 _ASYNCIO_TASK_ALL_TASKS_METHODDEF
2315 _ASYNCIO_TASK_CANCEL_METHODDEF
2316 _ASYNCIO_TASK_GET_STACK_METHODDEF
2317 _ASYNCIO_TASK_PRINT_STACK_METHODDEF
2318 _ASYNCIO_TASK__WAKEUP_METHODDEF
2319 _ASYNCIO_TASK__STEP_METHODDEF
2320 _ASYNCIO_TASK__REPR_INFO_METHODDEF
2321 {NULL, NULL} /* Sentinel */
2322};
2323
2324static PyGetSetDef TaskType_getsetlist[] = {
2325 FUTURE_COMMON_GETSETLIST
2326 {"_log_destroy_pending", (getter)TaskObj_get_log_destroy_pending,
2327 (setter)TaskObj_set_log_destroy_pending, NULL},
2328 {"_must_cancel", (getter)TaskObj_get_must_cancel, NULL, NULL},
2329 {"_coro", (getter)TaskObj_get_coro, NULL, NULL},
2330 {"_fut_waiter", (getter)TaskObj_get_fut_waiter, NULL, NULL},
2331 {NULL} /* Sentinel */
2332};
2333
2334static PyTypeObject TaskType = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02002335 PyVarObject_HEAD_INIT(NULL, 0)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002336 "_asyncio.Task",
2337 sizeof(TaskObj), /* tp_basicsize */
2338 .tp_base = &FutureType,
2339 .tp_dealloc = TaskObj_dealloc,
2340 .tp_as_async = &FutureType_as_async,
2341 .tp_repr = (reprfunc)FutureObj_repr,
2342 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE
2343 | Py_TPFLAGS_HAVE_FINALIZE,
2344 .tp_doc = _asyncio_Task___init____doc__,
2345 .tp_traverse = (traverseproc)TaskObj_traverse,
2346 .tp_clear = (inquiry)TaskObj_clear,
2347 .tp_weaklistoffset = offsetof(TaskObj, task_weakreflist),
2348 .tp_iter = (getiterfunc)future_new_iter,
2349 .tp_methods = TaskType_methods,
2350 .tp_getset = TaskType_getsetlist,
2351 .tp_dictoffset = offsetof(TaskObj, dict),
2352 .tp_init = (initproc)_asyncio_Task___init__,
2353 .tp_new = PyType_GenericNew,
2354 .tp_finalize = (destructor)TaskObj_finalize,
2355};
2356
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002357static void
2358TaskObj_dealloc(PyObject *self)
2359{
2360 TaskObj *task = (TaskObj *)self;
2361
2362 if (Task_CheckExact(self)) {
2363 /* When fut is subclass of Task, finalizer is called from
2364 * subtype_dealloc.
2365 */
2366 if (PyObject_CallFinalizerFromDealloc(self) < 0) {
2367 // resurrected.
2368 return;
2369 }
2370 }
2371
Alexander Mohrde34cbe2017-08-01 23:31:07 -07002372 PyObject_GC_UnTrack(self);
2373
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002374 if (task->task_weakreflist != NULL) {
2375 PyObject_ClearWeakRefs(self);
2376 }
2377
2378 (void)TaskObj_clear(task);
2379 Py_TYPE(task)->tp_free(task);
2380}
2381
2382static inline PyObject *
2383task_call_wakeup(TaskObj *task, PyObject *fut)
2384{
2385 if (Task_CheckExact(task)) {
2386 return task_wakeup(task, fut);
2387 }
2388 else {
2389 /* `task` is a subclass of Task */
Victor Stinnerb6ed57d2016-12-09 14:24:02 +01002390 return _PyObject_CallMethodIdObjArgs((PyObject*)task, &PyId__wakeup,
2391 fut, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002392 }
2393}
2394
2395static inline PyObject *
2396task_call_step(TaskObj *task, PyObject *arg)
2397{
2398 if (Task_CheckExact(task)) {
2399 return task_step(task, arg);
2400 }
2401 else {
2402 /* `task` is a subclass of Task */
Victor Stinnerb6ed57d2016-12-09 14:24:02 +01002403 return _PyObject_CallMethodIdObjArgs((PyObject*)task, &PyId__step,
2404 arg, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002405 }
2406}
2407
2408static int
2409task_call_step_soon(TaskObj *task, PyObject *arg)
2410{
Serhiy Storchakabca49392017-09-03 08:10:14 +03002411 PyObject *cb = TaskStepMethWrapper_new(task, arg);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002412 if (cb == NULL) {
2413 return -1;
2414 }
2415
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05002416 int ret = call_soon(task->task_loop, cb, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002417 Py_DECREF(cb);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05002418 return ret;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002419}
2420
2421static PyObject *
2422task_set_error_soon(TaskObj *task, PyObject *et, const char *format, ...)
2423{
2424 PyObject* msg;
2425
2426 va_list vargs;
2427#ifdef HAVE_STDARG_PROTOTYPES
2428 va_start(vargs, format);
2429#else
2430 va_start(vargs);
2431#endif
2432 msg = PyUnicode_FromFormatV(format, vargs);
2433 va_end(vargs);
2434
2435 if (msg == NULL) {
2436 return NULL;
2437 }
2438
Victor Stinnerde4ae3d2016-12-04 22:59:09 +01002439 PyObject *e = PyObject_CallFunctionObjArgs(et, msg, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002440 Py_DECREF(msg);
2441 if (e == NULL) {
2442 return NULL;
2443 }
2444
2445 if (task_call_step_soon(task, e) == -1) {
2446 Py_DECREF(e);
2447 return NULL;
2448 }
2449
2450 Py_DECREF(e);
2451 Py_RETURN_NONE;
2452}
2453
2454static PyObject *
2455task_step_impl(TaskObj *task, PyObject *exc)
2456{
2457 int res;
2458 int clear_exc = 0;
2459 PyObject *result = NULL;
Serhiy Storchakabca49392017-09-03 08:10:14 +03002460 PyObject *coro;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002461 PyObject *o;
2462
2463 if (task->task_state != STATE_PENDING) {
2464 PyErr_Format(PyExc_AssertionError,
2465 "_step(): already done: %R %R",
2466 task,
2467 exc ? exc : Py_None);
INADA Naokic411a7d2016-10-18 11:48:14 +09002468 goto fail;
2469 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09002470
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002471 if (task->task_must_cancel) {
2472 assert(exc != Py_None);
2473
2474 if (exc) {
2475 /* Check if exc is a CancelledError */
2476 res = PyObject_IsInstance(exc, asyncio_CancelledError);
2477 if (res == -1) {
2478 /* An error occurred, abort */
2479 goto fail;
2480 }
2481 if (res == 0) {
2482 /* exc is not CancelledError; reset it to NULL */
2483 exc = NULL;
2484 }
2485 }
2486
2487 if (!exc) {
2488 /* exc was not a CancelledError */
Victor Stinnerf17c3de2016-12-06 18:46:19 +01002489 exc = _PyObject_CallNoArg(asyncio_CancelledError);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002490 if (!exc) {
2491 goto fail;
2492 }
2493 clear_exc = 1;
2494 }
2495
2496 task->task_must_cancel = 0;
2497 }
2498
2499 Py_CLEAR(task->task_fut_waiter);
2500
Serhiy Storchakabca49392017-09-03 08:10:14 +03002501 coro = task->task_coro;
2502 if (coro == NULL) {
2503 PyErr_SetString(PyExc_RuntimeError, "uninitialized Task object");
2504 return NULL;
2505 }
2506
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002507 if (exc == NULL) {
2508 if (PyGen_CheckExact(coro) || PyCoro_CheckExact(coro)) {
2509 result = _PyGen_Send((PyGenObject*)coro, Py_None);
2510 }
2511 else {
Victor Stinnerb6ed57d2016-12-09 14:24:02 +01002512 result = _PyObject_CallMethodIdObjArgs(coro, &PyId_send,
2513 Py_None, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002514 }
2515 }
2516 else {
Victor Stinnerb6ed57d2016-12-09 14:24:02 +01002517 result = _PyObject_CallMethodIdObjArgs(coro, &PyId_throw,
2518 exc, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002519 if (clear_exc) {
2520 /* We created 'exc' during this call */
Serhiy Storchakabca49392017-09-03 08:10:14 +03002521 Py_DECREF(exc);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002522 }
2523 }
2524
2525 if (result == NULL) {
2526 PyObject *et, *ev, *tb;
2527
2528 if (_PyGen_FetchStopIterationValue(&o) == 0) {
2529 /* The error is StopIteration and that means that
2530 the underlying coroutine has resolved */
INADA Naoki991adca2017-05-11 21:18:38 +09002531 if (task->task_must_cancel) {
2532 // Task is cancelled right before coro stops.
2533 Py_DECREF(o);
2534 task->task_must_cancel = 0;
2535 et = asyncio_CancelledError;
2536 Py_INCREF(et);
2537 ev = NULL;
2538 tb = NULL;
2539 goto set_exception;
2540 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002541 PyObject *res = future_set_result((FutureObj*)task, o);
2542 Py_DECREF(o);
2543 if (res == NULL) {
2544 return NULL;
2545 }
2546 Py_DECREF(res);
2547 Py_RETURN_NONE;
2548 }
2549
2550 if (PyErr_ExceptionMatches(asyncio_CancelledError)) {
2551 /* CancelledError */
2552 PyErr_Clear();
2553 return future_cancel((FutureObj*)task);
2554 }
2555
2556 /* Some other exception; pop it and call Task.set_exception() */
2557 PyErr_Fetch(&et, &ev, &tb);
INADA Naoki991adca2017-05-11 21:18:38 +09002558
2559set_exception:
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002560 assert(et);
2561 if (!ev || !PyObject_TypeCheck(ev, (PyTypeObject *) et)) {
2562 PyErr_NormalizeException(&et, &ev, &tb);
2563 }
Yury Selivanovedfe8862016-12-01 11:37:47 -05002564 if (tb != NULL) {
2565 PyException_SetTraceback(ev, tb);
2566 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002567 o = future_set_exception((FutureObj*)task, ev);
2568 if (!o) {
2569 /* An exception in Task.set_exception() */
Serhiy Storchakabca49392017-09-03 08:10:14 +03002570 Py_DECREF(et);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002571 Py_XDECREF(tb);
2572 Py_XDECREF(ev);
2573 goto fail;
2574 }
2575 assert(o == Py_None);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002576 Py_DECREF(o);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002577
2578 if (!PyErr_GivenExceptionMatches(et, PyExc_Exception)) {
2579 /* We've got a BaseException; re-raise it */
2580 PyErr_Restore(et, ev, tb);
2581 goto fail;
2582 }
2583
Serhiy Storchakabca49392017-09-03 08:10:14 +03002584 Py_DECREF(et);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002585 Py_XDECREF(tb);
2586 Py_XDECREF(ev);
2587
2588 Py_RETURN_NONE;
2589 }
2590
2591 if (result == (PyObject*)task) {
2592 /* We have a task that wants to await on itself */
2593 goto self_await;
2594 }
2595
2596 /* Check if `result` is FutureObj or TaskObj (and not a subclass) */
2597 if (Future_CheckExact(result) || Task_CheckExact(result)) {
2598 PyObject *wrapper;
2599 PyObject *res;
2600 FutureObj *fut = (FutureObj*)result;
2601
2602 /* Check if `result` future is attached to a different loop */
2603 if (fut->fut_loop != task->task_loop) {
2604 goto different_loop;
2605 }
2606
2607 if (fut->fut_blocking) {
2608 fut->fut_blocking = 0;
2609
2610 /* result.add_done_callback(task._wakeup) */
2611 wrapper = TaskWakeupMethWrapper_new(task);
2612 if (wrapper == NULL) {
2613 goto fail;
2614 }
2615 res = future_add_done_callback((FutureObj*)result, wrapper);
2616 Py_DECREF(wrapper);
2617 if (res == NULL) {
2618 goto fail;
2619 }
2620 Py_DECREF(res);
2621
2622 /* task._fut_waiter = result */
2623 task->task_fut_waiter = result; /* no incref is necessary */
2624
2625 if (task->task_must_cancel) {
2626 PyObject *r;
2627 r = future_cancel(fut);
2628 if (r == NULL) {
2629 return NULL;
2630 }
2631 if (r == Py_True) {
2632 task->task_must_cancel = 0;
2633 }
2634 Py_DECREF(r);
2635 }
2636
2637 Py_RETURN_NONE;
2638 }
2639 else {
2640 goto yield_insteadof_yf;
2641 }
2642 }
2643
2644 /* Check if `result` is a Future-compatible object */
2645 o = PyObject_GetAttrString(result, "_asyncio_future_blocking");
2646 if (o == NULL) {
2647 if (PyErr_ExceptionMatches(PyExc_AttributeError)) {
2648 PyErr_Clear();
2649 }
2650 else {
2651 goto fail;
2652 }
2653 }
2654 else {
2655 if (o == Py_None) {
Serhiy Storchakabca49392017-09-03 08:10:14 +03002656 Py_DECREF(o);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002657 }
2658 else {
2659 /* `result` is a Future-compatible object */
2660 PyObject *wrapper;
2661 PyObject *res;
2662
2663 int blocking = PyObject_IsTrue(o);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002664 Py_DECREF(o);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002665 if (blocking < 0) {
2666 goto fail;
2667 }
2668
2669 /* Check if `result` future is attached to a different loop */
Yury Selivanovca9b36c2017-12-23 15:04:15 -05002670 PyObject *oloop = get_future_loop(result);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002671 if (oloop == NULL) {
2672 goto fail;
2673 }
2674 if (oloop != task->task_loop) {
2675 Py_DECREF(oloop);
2676 goto different_loop;
2677 }
2678 else {
2679 Py_DECREF(oloop);
2680 }
2681
2682 if (blocking) {
2683 /* result._asyncio_future_blocking = False */
2684 if (PyObject_SetAttrString(
2685 result, "_asyncio_future_blocking", Py_False) == -1) {
2686 goto fail;
2687 }
2688
2689 /* result.add_done_callback(task._wakeup) */
2690 wrapper = TaskWakeupMethWrapper_new(task);
2691 if (wrapper == NULL) {
2692 goto fail;
2693 }
Victor Stinnerb6ed57d2016-12-09 14:24:02 +01002694 res = _PyObject_CallMethodIdObjArgs(result,
2695 &PyId_add_done_callback,
2696 wrapper, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002697 Py_DECREF(wrapper);
2698 if (res == NULL) {
2699 goto fail;
2700 }
2701 Py_DECREF(res);
2702
2703 /* task._fut_waiter = result */
2704 task->task_fut_waiter = result; /* no incref is necessary */
2705
2706 if (task->task_must_cancel) {
2707 PyObject *r;
2708 int is_true;
2709 r = _PyObject_CallMethodId(result, &PyId_cancel, NULL);
2710 if (r == NULL) {
2711 return NULL;
2712 }
2713 is_true = PyObject_IsTrue(r);
2714 Py_DECREF(r);
2715 if (is_true < 0) {
2716 return NULL;
2717 }
2718 else if (is_true) {
2719 task->task_must_cancel = 0;
2720 }
2721 }
2722
2723 Py_RETURN_NONE;
2724 }
2725 else {
2726 goto yield_insteadof_yf;
2727 }
2728 }
2729 }
2730
2731 /* Check if `result` is None */
2732 if (result == Py_None) {
2733 /* Bare yield relinquishes control for one event loop iteration. */
2734 if (task_call_step_soon(task, NULL)) {
2735 goto fail;
2736 }
2737 return result;
2738 }
2739
2740 /* Check if `result` is a generator */
Victor Stinnerde4ae3d2016-12-04 22:59:09 +01002741 o = PyObject_CallFunctionObjArgs(inspect_isgenerator, result, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002742 if (o == NULL) {
2743 /* An exception in inspect.isgenerator */
2744 goto fail;
2745 }
2746 res = PyObject_IsTrue(o);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002747 Py_DECREF(o);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002748 if (res == -1) {
2749 /* An exception while checking if 'val' is True */
2750 goto fail;
2751 }
2752 if (res == 1) {
2753 /* `result` is a generator */
2754 PyObject *ret;
2755 ret = task_set_error_soon(
2756 task, PyExc_RuntimeError,
2757 "yield was used instead of yield from for "
2758 "generator in task %R with %S", task, result);
2759 Py_DECREF(result);
2760 return ret;
2761 }
2762
2763 /* The `result` is none of the above */
2764 Py_DECREF(result);
2765 return task_set_error_soon(
2766 task, PyExc_RuntimeError, "Task got bad yield: %R", result);
2767
2768self_await:
2769 o = task_set_error_soon(
2770 task, PyExc_RuntimeError,
2771 "Task cannot await on itself: %R", task);
2772 Py_DECREF(result);
2773 return o;
2774
2775yield_insteadof_yf:
2776 o = task_set_error_soon(
2777 task, PyExc_RuntimeError,
2778 "yield was used instead of yield from "
2779 "in task %R with %R",
2780 task, result);
2781 Py_DECREF(result);
2782 return o;
2783
2784different_loop:
2785 o = task_set_error_soon(
2786 task, PyExc_RuntimeError,
2787 "Task %R got Future %R attached to a different loop",
2788 task, result);
2789 Py_DECREF(result);
2790 return o;
2791
2792fail:
2793 Py_XDECREF(result);
2794 return NULL;
2795}
2796
2797static PyObject *
2798task_step(TaskObj *task, PyObject *exc)
2799{
2800 PyObject *res;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002801
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002802 if (enter_task(task->task_loop, (PyObject*)task) < 0) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002803 return NULL;
2804 }
2805
2806 res = task_step_impl(task, exc);
2807
2808 if (res == NULL) {
2809 PyObject *et, *ev, *tb;
2810 PyErr_Fetch(&et, &ev, &tb);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002811 leave_task(task->task_loop, (PyObject*)task);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002812 _PyErr_ChainExceptions(et, ev, tb);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002813 return NULL;
2814 }
2815 else {
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002816 if(leave_task(task->task_loop, (PyObject*)task) < 0) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002817 Py_DECREF(res);
2818 return NULL;
2819 }
2820 else {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002821 return res;
2822 }
2823 }
2824}
2825
2826static PyObject *
2827task_wakeup(TaskObj *task, PyObject *o)
2828{
Serhiy Storchakabca49392017-09-03 08:10:14 +03002829 PyObject *et, *ev, *tb;
2830 PyObject *result;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002831 assert(o);
2832
2833 if (Future_CheckExact(o) || Task_CheckExact(o)) {
2834 PyObject *fut_result = NULL;
2835 int res = future_get_result((FutureObj*)o, &fut_result);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002836
2837 switch(res) {
2838 case -1:
2839 assert(fut_result == NULL);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002840 break; /* exception raised */
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002841 case 0:
2842 Py_DECREF(fut_result);
2843 return task_call_step(task, NULL);
2844 default:
2845 assert(res == 1);
2846 result = task_call_step(task, fut_result);
2847 Py_DECREF(fut_result);
2848 return result;
2849 }
2850 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002851 else {
Serhiy Storchakabca49392017-09-03 08:10:14 +03002852 PyObject *fut_result = PyObject_CallMethod(o, "result", NULL);
2853 if (fut_result != NULL) {
2854 Py_DECREF(fut_result);
2855 return task_call_step(task, NULL);
2856 }
2857 /* exception raised */
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002858 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03002859
2860 PyErr_Fetch(&et, &ev, &tb);
2861 if (!PyErr_GivenExceptionMatches(et, PyExc_Exception)) {
2862 /* We've got a BaseException; re-raise it */
2863 PyErr_Restore(et, ev, tb);
2864 return NULL;
2865 }
2866 if (!ev || !PyObject_TypeCheck(ev, (PyTypeObject *) et)) {
2867 PyErr_NormalizeException(&et, &ev, &tb);
2868 }
2869
2870 result = task_call_step(task, ev);
2871
2872 Py_DECREF(et);
2873 Py_XDECREF(tb);
2874 Py_XDECREF(ev);
2875
2876 return result;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002877}
2878
2879
Yury Selivanova70232f2017-12-13 14:49:42 -05002880/*********************** Functions **************************/
2881
2882
2883/*[clinic input]
2884_asyncio._get_running_loop
2885
2886Return the running event loop or None.
2887
2888This is a low-level function intended to be used by event loops.
2889This function is thread-specific.
2890
2891[clinic start generated code]*/
2892
2893static PyObject *
2894_asyncio__get_running_loop_impl(PyObject *module)
2895/*[clinic end generated code: output=b4390af721411a0a input=0a21627e25a4bd43]*/
2896{
2897 PyObject *loop;
2898 if (get_running_loop(&loop)) {
2899 return NULL;
2900 }
2901 if (loop == NULL) {
2902 /* There's no currently running event loop */
2903 Py_RETURN_NONE;
2904 }
2905 return loop;
2906}
2907
2908/*[clinic input]
2909_asyncio._set_running_loop
2910 loop: 'O'
2911 /
2912
2913Set the running event loop.
2914
2915This is a low-level function intended to be used by event loops.
2916This function is thread-specific.
2917[clinic start generated code]*/
2918
2919static PyObject *
2920_asyncio__set_running_loop(PyObject *module, PyObject *loop)
2921/*[clinic end generated code: output=ae56bf7a28ca189a input=4c9720233d606604]*/
2922{
2923 if (set_running_loop(loop)) {
2924 return NULL;
2925 }
2926 Py_RETURN_NONE;
2927}
2928
2929/*[clinic input]
2930_asyncio.get_event_loop
2931
2932Return an asyncio event loop.
2933
2934When called from a coroutine or a callback (e.g. scheduled with
2935call_soon or similar API), this function will always return the
2936running event loop.
2937
2938If there is no running event loop set, the function will return
2939the result of `get_event_loop_policy().get_event_loop()` call.
2940[clinic start generated code]*/
2941
2942static PyObject *
2943_asyncio_get_event_loop_impl(PyObject *module)
2944/*[clinic end generated code: output=2a2d8b2f824c648b input=9364bf2916c8655d]*/
2945{
2946 return get_event_loop();
2947}
2948
2949/*[clinic input]
2950_asyncio.get_running_loop
2951
2952Return the running event loop. Raise a RuntimeError if there is none.
2953
2954This function is thread-specific.
2955[clinic start generated code]*/
2956
2957static PyObject *
2958_asyncio_get_running_loop_impl(PyObject *module)
2959/*[clinic end generated code: output=c247b5f9e529530e input=2a3bf02ba39f173d]*/
2960{
2961 PyObject *loop;
2962 if (get_running_loop(&loop)) {
2963 return NULL;
2964 }
2965 if (loop == NULL) {
2966 /* There's no currently running event loop */
2967 PyErr_SetString(
2968 PyExc_RuntimeError, "no running event loop");
2969 }
2970 return loop;
2971}
2972
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002973/*[clinic input]
2974_asyncio._register_task
2975
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002976 task: object
2977
2978Register a new task in asyncio as executed by loop.
2979
2980Returns None.
2981[clinic start generated code]*/
2982
2983static PyObject *
Yury Selivanovca9b36c2017-12-23 15:04:15 -05002984_asyncio__register_task_impl(PyObject *module, PyObject *task)
2985/*[clinic end generated code: output=8672dadd69a7d4e2 input=21075aaea14dfbad]*/
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002986{
Yury Selivanovca9b36c2017-12-23 15:04:15 -05002987 if (register_task(task) < 0) {
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002988 return NULL;
2989 }
2990 Py_RETURN_NONE;
2991}
2992
2993
2994/*[clinic input]
2995_asyncio._unregister_task
2996
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002997 task: object
2998
2999Unregister a task.
3000
3001Returns None.
3002[clinic start generated code]*/
3003
3004static PyObject *
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003005_asyncio__unregister_task_impl(PyObject *module, PyObject *task)
3006/*[clinic end generated code: output=6e5585706d568a46 input=28fb98c3975f7bdc]*/
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003007{
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003008 if (unregister_task(task) < 0) {
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003009 return NULL;
3010 }
3011 Py_RETURN_NONE;
3012}
3013
3014
3015/*[clinic input]
3016_asyncio._enter_task
3017
3018 loop: object
3019 task: object
3020
3021Enter into task execution or resume suspended task.
3022
3023Task belongs to loop.
3024
3025Returns None.
3026[clinic start generated code]*/
3027
3028static PyObject *
3029_asyncio__enter_task_impl(PyObject *module, PyObject *loop, PyObject *task)
3030/*[clinic end generated code: output=a22611c858035b73 input=de1b06dca70d8737]*/
3031{
3032 if (enter_task(loop, task) < 0) {
3033 return NULL;
3034 }
3035 Py_RETURN_NONE;
3036}
3037
3038
3039/*[clinic input]
3040_asyncio._leave_task
3041
3042 loop: object
3043 task: object
3044
3045Leave task execution or suspend a task.
3046
3047Task belongs to loop.
3048
3049Returns None.
3050[clinic start generated code]*/
3051
3052static PyObject *
3053_asyncio__leave_task_impl(PyObject *module, PyObject *loop, PyObject *task)
3054/*[clinic end generated code: output=0ebf6db4b858fb41 input=51296a46313d1ad8]*/
3055{
3056 if (leave_task(loop, task) < 0) {
3057 return NULL;
3058 }
3059 Py_RETURN_NONE;
3060}
3061
Yury Selivanova70232f2017-12-13 14:49:42 -05003062
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003063/*********************** Module **************************/
3064
3065
3066static void
Zackery Spytze40ad792017-12-19 11:48:13 -07003067module_free_freelists(void)
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05003068{
3069 PyObject *next;
3070 PyObject *current;
3071
3072 next = (PyObject*) fi_freelist;
3073 while (next != NULL) {
3074 assert(fi_freelist_len > 0);
3075 fi_freelist_len--;
3076
3077 current = next;
3078 next = (PyObject*) ((futureiterobject*) current)->future;
3079 PyObject_GC_Del(current);
3080 }
3081 assert(fi_freelist_len == 0);
3082 fi_freelist = NULL;
3083}
3084
3085
3086static void
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003087module_free(void *m)
3088{
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003089 Py_CLEAR(asyncio_mod);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003090 Py_CLEAR(inspect_isgenerator);
Yury Selivanova70232f2017-12-13 14:49:42 -05003091 Py_CLEAR(os_getpid);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003092 Py_CLEAR(traceback_extract_stack);
3093 Py_CLEAR(asyncio_future_repr_info_func);
3094 Py_CLEAR(asyncio_get_event_loop_policy);
3095 Py_CLEAR(asyncio_iscoroutine_func);
3096 Py_CLEAR(asyncio_task_get_stack_func);
3097 Py_CLEAR(asyncio_task_print_stack_func);
3098 Py_CLEAR(asyncio_task_repr_info_func);
3099 Py_CLEAR(asyncio_InvalidStateError);
3100 Py_CLEAR(asyncio_CancelledError);
3101
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003102 Py_CLEAR(all_tasks);
Yury Selivanova9d7e552017-12-19 07:18:45 -05003103 Py_CLEAR(current_tasks);
3104 Py_CLEAR(iscoroutine_typecache);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05003105
3106 module_free_freelists();
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003107}
3108
3109static int
3110module_init(void)
3111{
3112 PyObject *module = NULL;
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003113
3114 asyncio_mod = PyImport_ImportModule("asyncio");
3115 if (asyncio_mod == NULL) {
3116 goto fail;
3117 }
3118
3119 current_tasks = PyDict_New();
3120 if (current_tasks == NULL) {
3121 goto fail;
3122 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003123
Yury Selivanova9d7e552017-12-19 07:18:45 -05003124 iscoroutine_typecache = PySet_New(NULL);
3125 if (iscoroutine_typecache == NULL) {
3126 goto fail;
3127 }
3128
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003129#define WITH_MOD(NAME) \
3130 Py_CLEAR(module); \
3131 module = PyImport_ImportModule(NAME); \
3132 if (module == NULL) { \
Serhiy Storchakabca49392017-09-03 08:10:14 +03003133 goto fail; \
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003134 }
3135
3136#define GET_MOD_ATTR(VAR, NAME) \
3137 VAR = PyObject_GetAttrString(module, NAME); \
3138 if (VAR == NULL) { \
3139 goto fail; \
3140 }
3141
3142 WITH_MOD("asyncio.events")
Yury Selivanova70232f2017-12-13 14:49:42 -05003143 GET_MOD_ATTR(asyncio_get_event_loop_policy, "get_event_loop_policy")
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003144
3145 WITH_MOD("asyncio.base_futures")
3146 GET_MOD_ATTR(asyncio_future_repr_info_func, "_future_repr_info")
3147 GET_MOD_ATTR(asyncio_InvalidStateError, "InvalidStateError")
3148 GET_MOD_ATTR(asyncio_CancelledError, "CancelledError")
3149
3150 WITH_MOD("asyncio.base_tasks")
3151 GET_MOD_ATTR(asyncio_task_repr_info_func, "_task_repr_info")
3152 GET_MOD_ATTR(asyncio_task_get_stack_func, "_task_get_stack")
3153 GET_MOD_ATTR(asyncio_task_print_stack_func, "_task_print_stack")
3154
Andrew Svetlovf74ef452017-12-15 07:04:38 +02003155 WITH_MOD("asyncio.coroutines")
3156 GET_MOD_ATTR(asyncio_iscoroutine_func, "iscoroutine")
3157
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003158 WITH_MOD("inspect")
3159 GET_MOD_ATTR(inspect_isgenerator, "isgenerator")
3160
Yury Selivanova70232f2017-12-13 14:49:42 -05003161 WITH_MOD("os")
3162 GET_MOD_ATTR(os_getpid, "getpid")
3163
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003164 WITH_MOD("traceback")
3165 GET_MOD_ATTR(traceback_extract_stack, "extract_stack")
3166
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003167 PyObject *weak_set;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003168 WITH_MOD("weakref")
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003169 GET_MOD_ATTR(weak_set, "WeakSet");
3170 all_tasks = _PyObject_CallNoArg(weak_set);
3171 Py_CLEAR(weak_set);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003172 if (all_tasks == NULL) {
INADA Naokic411a7d2016-10-18 11:48:14 +09003173 goto fail;
3174 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003175
Serhiy Storchakabca49392017-09-03 08:10:14 +03003176 Py_DECREF(module);
INADA Naokic411a7d2016-10-18 11:48:14 +09003177 return 0;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003178
INADA Naokic411a7d2016-10-18 11:48:14 +09003179fail:
INADA Naokic411a7d2016-10-18 11:48:14 +09003180 Py_CLEAR(module);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003181 module_free(NULL);
INADA Naokic411a7d2016-10-18 11:48:14 +09003182 return -1;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003183
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003184#undef WITH_MOD
3185#undef GET_MOD_ATTR
3186}
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003187
INADA Naokic411a7d2016-10-18 11:48:14 +09003188PyDoc_STRVAR(module_doc, "Accelerator module for asyncio");
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003189
Yury Selivanova70232f2017-12-13 14:49:42 -05003190static PyMethodDef asyncio_methods[] = {
3191 _ASYNCIO_GET_EVENT_LOOP_METHODDEF
3192 _ASYNCIO_GET_RUNNING_LOOP_METHODDEF
3193 _ASYNCIO__GET_RUNNING_LOOP_METHODDEF
3194 _ASYNCIO__SET_RUNNING_LOOP_METHODDEF
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003195 _ASYNCIO__REGISTER_TASK_METHODDEF
3196 _ASYNCIO__UNREGISTER_TASK_METHODDEF
3197 _ASYNCIO__ENTER_TASK_METHODDEF
3198 _ASYNCIO__LEAVE_TASK_METHODDEF
Yury Selivanova70232f2017-12-13 14:49:42 -05003199 {NULL, NULL}
3200};
3201
INADA Naoki9f2ce252016-10-15 15:39:19 +09003202static struct PyModuleDef _asynciomodule = {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003203 PyModuleDef_HEAD_INIT, /* m_base */
INADA Naoki9f2ce252016-10-15 15:39:19 +09003204 "_asyncio", /* m_name */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003205 module_doc, /* m_doc */
3206 -1, /* m_size */
Yury Selivanova70232f2017-12-13 14:49:42 -05003207 asyncio_methods, /* m_methods */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003208 NULL, /* m_slots */
3209 NULL, /* m_traverse */
3210 NULL, /* m_clear */
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003211 (freefunc)module_free /* m_free */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003212};
3213
3214
3215PyMODINIT_FUNC
INADA Naoki9f2ce252016-10-15 15:39:19 +09003216PyInit__asyncio(void)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003217{
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003218 if (module_init() < 0) {
INADA Naokic411a7d2016-10-18 11:48:14 +09003219 return NULL;
3220 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003221 if (PyType_Ready(&FutureType) < 0) {
3222 return NULL;
3223 }
3224 if (PyType_Ready(&FutureIterType) < 0) {
3225 return NULL;
3226 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03003227 if (PyType_Ready(&TaskStepMethWrapper_Type) < 0) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003228 return NULL;
3229 }
3230 if(PyType_Ready(&TaskWakeupMethWrapper_Type) < 0) {
3231 return NULL;
3232 }
3233 if (PyType_Ready(&TaskType) < 0) {
3234 return NULL;
3235 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003236
INADA Naoki9f2ce252016-10-15 15:39:19 +09003237 PyObject *m = PyModule_Create(&_asynciomodule);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003238 if (m == NULL) {
3239 return NULL;
3240 }
3241
3242 Py_INCREF(&FutureType);
3243 if (PyModule_AddObject(m, "Future", (PyObject *)&FutureType) < 0) {
3244 Py_DECREF(&FutureType);
3245 return NULL;
3246 }
3247
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003248 Py_INCREF(&TaskType);
3249 if (PyModule_AddObject(m, "Task", (PyObject *)&TaskType) < 0) {
3250 Py_DECREF(&TaskType);
3251 return NULL;
3252 }
3253
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003254 Py_INCREF(all_tasks);
3255 if (PyModule_AddObject(m, "_all_tasks", all_tasks) < 0) {
3256 Py_DECREF(all_tasks);
3257 return NULL;
3258 }
3259
3260 Py_INCREF(current_tasks);
3261 if (PyModule_AddObject(m, "_current_tasks", current_tasks) < 0) {
3262 Py_DECREF(current_tasks);
3263 return NULL;
3264 }
3265
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003266 return m;
3267}