blob: d626127699a2b5da100cf1f807901127632ab3f9 [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
206 return _PyObject_GetAttrId(fut, &PyId__loop);
207}
208
209
Yury Selivanova9d7e552017-12-19 07:18:45 -0500210static int
Yury Selivanova70232f2017-12-13 14:49:42 -0500211get_running_loop(PyObject **loop)
212{
213 PyObject *ts_dict;
214 PyObject *running_tuple;
215 PyObject *running_loop;
216 PyObject *running_loop_pid;
217 PyObject *current_pid;
218 int same_pid;
219
220 ts_dict = PyThreadState_GetDict(); // borrowed
221 if (ts_dict == NULL) {
222 PyErr_SetString(
223 PyExc_RuntimeError, "thread-local storage is not available");
224 goto error;
225 }
226
227 running_tuple = _PyDict_GetItemId(
228 ts_dict, &PyId___asyncio_running_event_loop__); // borrowed
229 if (running_tuple == NULL) {
230 /* _PyDict_GetItemId doesn't set an error if key is not found */
231 goto not_found;
232 }
233
234 assert(PyTuple_CheckExact(running_tuple));
235 assert(PyTuple_Size(running_tuple) == 2);
236 running_loop = PyTuple_GET_ITEM(running_tuple, 0); // borrowed
237 running_loop_pid = PyTuple_GET_ITEM(running_tuple, 1); // borrowed
238
239 if (running_loop == Py_None) {
240 goto not_found;
241 }
242
243 current_pid = _PyObject_CallNoArg(os_getpid);
244 if (current_pid == NULL) {
245 goto error;
246 }
247 same_pid = PyObject_RichCompareBool(current_pid, running_loop_pid, Py_EQ);
248 Py_DECREF(current_pid);
249 if (same_pid == -1) {
250 goto error;
251 }
252
253 if (same_pid) {
254 // current_pid == running_loop_pid
255 goto found;
256 }
257
258not_found:
259 *loop = NULL;
260 return 0;
261
262found:
263 Py_INCREF(running_loop);
264 *loop = running_loop;
265 return 0;
266
267error:
268 *loop = NULL;
269 return -1;
270}
271
272
273static int
274set_running_loop(PyObject *loop)
275{
276 PyObject *ts_dict;
277 PyObject *running_tuple;
278 PyObject *current_pid;
279
280 ts_dict = PyThreadState_GetDict(); // borrowed
281 if (ts_dict == NULL) {
282 PyErr_SetString(
283 PyExc_RuntimeError, "thread-local storage is not available");
284 return -1;
285 }
286
287 current_pid = _PyObject_CallNoArg(os_getpid);
288 if (current_pid == NULL) {
289 return -1;
290 }
291
292 running_tuple = PyTuple_New(2);
293 if (running_tuple == NULL) {
294 Py_DECREF(current_pid);
295 return -1;
296 }
297
298 Py_INCREF(loop);
299 PyTuple_SET_ITEM(running_tuple, 0, loop);
300 PyTuple_SET_ITEM(running_tuple, 1, current_pid); // borrowed
301
302 if (_PyDict_SetItemId(
303 ts_dict, &PyId___asyncio_running_event_loop__, running_tuple)) {
304 Py_DECREF(running_tuple); // will cleanup loop & current_pid
305 return -1;
306 }
307 Py_DECREF(running_tuple);
308
309 return 0;
310}
311
312
313static PyObject *
314get_event_loop(void)
315{
316 PyObject *loop;
317 PyObject *policy;
318
319 if (get_running_loop(&loop)) {
320 return NULL;
321 }
322 if (loop != NULL) {
323 return loop;
324 }
325
326 policy = _PyObject_CallNoArg(asyncio_get_event_loop_policy);
327 if (policy == NULL) {
328 return NULL;
329 }
330
331 loop = _PyObject_CallMethodId(policy, &PyId_get_event_loop, NULL);
332 Py_DECREF(policy);
333 return loop;
334}
335
336
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900337static int
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500338call_soon(PyObject *loop, PyObject *func, PyObject *arg)
339{
340 PyObject *handle;
341 handle = _PyObject_CallMethodIdObjArgs(
342 loop, &PyId_call_soon, func, arg, NULL);
343 if (handle == NULL) {
344 return -1;
345 }
346 Py_DECREF(handle);
347 return 0;
348}
349
350
351static inline int
352future_is_alive(FutureObj *fut)
353{
354 return fut->fut_loop != NULL;
355}
356
357
358static inline int
359future_ensure_alive(FutureObj *fut)
360{
361 if (!future_is_alive(fut)) {
362 PyErr_SetString(PyExc_RuntimeError,
363 "Future object is not initialized.");
364 return -1;
365 }
366 return 0;
367}
368
369
370#define ENSURE_FUTURE_ALIVE(fut) \
371 do { \
372 assert(Future_Check(fut) || Task_Check(fut)); \
373 if (future_ensure_alive((FutureObj*)fut)) { \
374 return NULL; \
375 } \
376 } while(0);
377
378
379static int
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400380future_schedule_callbacks(FutureObj *fut)
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900381{
382 Py_ssize_t len;
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500383 Py_ssize_t i;
384
385 if (fut->fut_callback0 != NULL) {
386 /* There's a 1st callback */
387
388 int ret = call_soon(
389 fut->fut_loop, fut->fut_callback0, (PyObject *)fut);
390 Py_CLEAR(fut->fut_callback0);
391 if (ret) {
392 /* If an error occurs in pure-Python implementation,
393 all callbacks are cleared. */
394 Py_CLEAR(fut->fut_callbacks);
395 return ret;
396 }
397
398 /* we called the first callback, now try calling
399 callbacks from the 'fut_callbacks' list. */
400 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900401
402 if (fut->fut_callbacks == NULL) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500403 /* No more callbacks, return. */
404 return 0;
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900405 }
406
407 len = PyList_GET_SIZE(fut->fut_callbacks);
408 if (len == 0) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500409 /* The list of callbacks was empty; clear it and return. */
410 Py_CLEAR(fut->fut_callbacks);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900411 return 0;
412 }
413
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900414 for (i = 0; i < len; i++) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500415 PyObject *cb = PyList_GET_ITEM(fut->fut_callbacks, i);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900416
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500417 if (call_soon(fut->fut_loop, cb, (PyObject *)fut)) {
418 /* If an error occurs in pure-Python implementation,
419 all callbacks are cleared. */
420 Py_CLEAR(fut->fut_callbacks);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900421 return -1;
422 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900423 }
424
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500425 Py_CLEAR(fut->fut_callbacks);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900426 return 0;
427}
428
429static int
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400430future_init(FutureObj *fut, PyObject *loop)
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900431{
Serhiy Storchakabca49392017-09-03 08:10:14 +0300432 PyObject *res;
433 int is_true;
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900434 _Py_IDENTIFIER(get_debug);
435
Serhiy Storchakabca49392017-09-03 08:10:14 +0300436 if (loop == Py_None) {
Yury Selivanova70232f2017-12-13 14:49:42 -0500437 loop = get_event_loop();
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900438 if (loop == NULL) {
439 return -1;
440 }
441 }
442 else {
443 Py_INCREF(loop);
444 }
Serhiy Storchakabca49392017-09-03 08:10:14 +0300445 Py_XSETREF(fut->fut_loop, loop);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900446
Victor Stinnerf94d1ee2016-10-29 09:05:39 +0200447 res = _PyObject_CallMethodId(fut->fut_loop, &PyId_get_debug, NULL);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900448 if (res == NULL) {
449 return -1;
450 }
Serhiy Storchakabca49392017-09-03 08:10:14 +0300451 is_true = PyObject_IsTrue(res);
452 Py_DECREF(res);
453 if (is_true < 0) {
454 return -1;
455 }
456 if (is_true) {
457 Py_XSETREF(fut->fut_source_tb, _PyObject_CallNoArg(traceback_extract_stack));
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900458 if (fut->fut_source_tb == NULL) {
459 return -1;
460 }
461 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900462
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500463 fut->fut_callback0 = NULL;
464 fut->fut_callbacks = NULL;
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400465
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900466 return 0;
467}
468
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900469static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400470future_set_result(FutureObj *fut, PyObject *res)
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900471{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500472 if (future_ensure_alive(fut)) {
473 return NULL;
474 }
475
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900476 if (fut->fut_state != STATE_PENDING) {
477 PyErr_SetString(asyncio_InvalidStateError, "invalid state");
478 return NULL;
479 }
480
Serhiy Storchakabca49392017-09-03 08:10:14 +0300481 assert(!fut->fut_result);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900482 Py_INCREF(res);
483 fut->fut_result = res;
484 fut->fut_state = STATE_FINISHED;
485
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400486 if (future_call_schedule_callbacks(fut) == -1) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900487 return NULL;
488 }
489 Py_RETURN_NONE;
490}
491
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900492static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400493future_set_exception(FutureObj *fut, PyObject *exc)
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900494{
495 PyObject *exc_val = NULL;
496
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900497 if (fut->fut_state != STATE_PENDING) {
498 PyErr_SetString(asyncio_InvalidStateError, "invalid state");
499 return NULL;
500 }
501
502 if (PyExceptionClass_Check(exc)) {
Victor Stinnera5ed5f02016-12-06 18:45:50 +0100503 exc_val = _PyObject_CallNoArg(exc);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900504 if (exc_val == NULL) {
505 return NULL;
506 }
Serhiy Storchakabca49392017-09-03 08:10:14 +0300507 if (fut->fut_state != STATE_PENDING) {
508 Py_DECREF(exc_val);
509 PyErr_SetString(asyncio_InvalidStateError, "invalid state");
510 return NULL;
511 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900512 }
513 else {
514 exc_val = exc;
515 Py_INCREF(exc_val);
516 }
517 if (!PyExceptionInstance_Check(exc_val)) {
518 Py_DECREF(exc_val);
519 PyErr_SetString(PyExc_TypeError, "invalid exception object");
520 return NULL;
521 }
522 if ((PyObject*)Py_TYPE(exc_val) == PyExc_StopIteration) {
523 Py_DECREF(exc_val);
524 PyErr_SetString(PyExc_TypeError,
525 "StopIteration interacts badly with generators "
526 "and cannot be raised into a Future");
527 return NULL;
528 }
529
Serhiy Storchakabca49392017-09-03 08:10:14 +0300530 assert(!fut->fut_exception);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900531 fut->fut_exception = exc_val;
532 fut->fut_state = STATE_FINISHED;
533
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400534 if (future_call_schedule_callbacks(fut) == -1) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900535 return NULL;
536 }
537
538 fut->fut_log_tb = 1;
539 Py_RETURN_NONE;
540}
541
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400542static int
543future_get_result(FutureObj *fut, PyObject **result)
544{
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400545 if (fut->fut_state == STATE_CANCELLED) {
Serhiy Storchakabca49392017-09-03 08:10:14 +0300546 PyErr_SetNone(asyncio_CancelledError);
547 return -1;
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400548 }
549
550 if (fut->fut_state != STATE_FINISHED) {
Serhiy Storchakabca49392017-09-03 08:10:14 +0300551 PyErr_SetString(asyncio_InvalidStateError, "Result is not set.");
552 return -1;
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400553 }
554
555 fut->fut_log_tb = 0;
556 if (fut->fut_exception != NULL) {
557 Py_INCREF(fut->fut_exception);
558 *result = fut->fut_exception;
559 return 1;
560 }
561
562 Py_INCREF(fut->fut_result);
563 *result = fut->fut_result;
564 return 0;
565}
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900566
567static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400568future_add_done_callback(FutureObj *fut, PyObject *arg)
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900569{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500570 if (!future_is_alive(fut)) {
571 PyErr_SetString(PyExc_RuntimeError, "uninitialized Future object");
572 return NULL;
573 }
574
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900575 if (fut->fut_state != STATE_PENDING) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500576 /* The future is done/cancelled, so schedule the callback
577 right away. */
578 if (call_soon(fut->fut_loop, arg, (PyObject*) fut)) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900579 return NULL;
580 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900581 }
582 else {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500583 /* The future is pending, add a callback.
584
585 Callbacks in the future object are stored as follows:
586
587 callback0 -- a pointer to the first callback
588 callbacks -- a list of 2nd, 3rd, ... callbacks
589
590 Invariants:
591
592 * callbacks != NULL:
593 There are some callbacks in in the list. Just
594 add the new callback to it.
595
596 * callbacks == NULL and callback0 == NULL:
597 This is the first callback. Set it to callback0.
598
599 * callbacks == NULL and callback0 != NULL:
600 This is a second callback. Initialize callbacks
601 with a new list and add the new callback to it.
602 */
603
604 if (fut->fut_callbacks != NULL) {
605 int err = PyList_Append(fut->fut_callbacks, arg);
606 if (err != 0) {
607 return NULL;
608 }
Serhiy Storchakabca49392017-09-03 08:10:14 +0300609 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500610 else if (fut->fut_callback0 == NULL) {
611 Py_INCREF(arg);
612 fut->fut_callback0 = arg;
613 }
614 else {
615 fut->fut_callbacks = PyList_New(1);
616 if (fut->fut_callbacks == NULL) {
617 return NULL;
618 }
619
620 Py_INCREF(arg);
621 PyList_SET_ITEM(fut->fut_callbacks, 0, arg);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900622 }
623 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500624
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900625 Py_RETURN_NONE;
626}
627
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400628static PyObject *
629future_cancel(FutureObj *fut)
630{
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +0000631 fut->fut_log_tb = 0;
632
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400633 if (fut->fut_state != STATE_PENDING) {
634 Py_RETURN_FALSE;
635 }
636 fut->fut_state = STATE_CANCELLED;
637
638 if (future_call_schedule_callbacks(fut) == -1) {
639 return NULL;
640 }
641
642 Py_RETURN_TRUE;
643}
644
645/*[clinic input]
646_asyncio.Future.__init__
647
648 *
Serhiy Storchakabca49392017-09-03 08:10:14 +0300649 loop: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400650
651This class is *almost* compatible with concurrent.futures.Future.
652
653 Differences:
654
655 - result() and exception() do not take a timeout argument and
656 raise an exception when the future isn't done yet.
657
658 - Callbacks registered with add_done_callback() are always called
659 via the event loop's call_soon_threadsafe().
660
661 - This class is not compatible with the wait() and as_completed()
662 methods in the concurrent.futures package.
663[clinic start generated code]*/
664
665static int
666_asyncio_Future___init___impl(FutureObj *self, PyObject *loop)
Serhiy Storchakabca49392017-09-03 08:10:14 +0300667/*[clinic end generated code: output=9ed75799eaccb5d6 input=89af317082bc0bf8]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400668
669{
670 return future_init(self, loop);
671}
672
673static int
674FutureObj_clear(FutureObj *fut)
675{
676 Py_CLEAR(fut->fut_loop);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500677 Py_CLEAR(fut->fut_callback0);
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400678 Py_CLEAR(fut->fut_callbacks);
679 Py_CLEAR(fut->fut_result);
680 Py_CLEAR(fut->fut_exception);
681 Py_CLEAR(fut->fut_source_tb);
682 Py_CLEAR(fut->dict);
683 return 0;
684}
685
686static int
687FutureObj_traverse(FutureObj *fut, visitproc visit, void *arg)
688{
689 Py_VISIT(fut->fut_loop);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500690 Py_VISIT(fut->fut_callback0);
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400691 Py_VISIT(fut->fut_callbacks);
692 Py_VISIT(fut->fut_result);
693 Py_VISIT(fut->fut_exception);
694 Py_VISIT(fut->fut_source_tb);
695 Py_VISIT(fut->dict);
696 return 0;
697}
698
699/*[clinic input]
700_asyncio.Future.result
701
702Return the result this future represents.
703
704If the future has been cancelled, raises CancelledError. If the
705future's result isn't yet available, raises InvalidStateError. If
706the future is done and has an exception set, this exception is raised.
707[clinic start generated code]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900708
709static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400710_asyncio_Future_result_impl(FutureObj *self)
711/*[clinic end generated code: output=f35f940936a4b1e5 input=49ecf9cf5ec50dc5]*/
712{
713 PyObject *result;
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500714
715 if (!future_is_alive(self)) {
716 PyErr_SetString(asyncio_InvalidStateError,
717 "Future object is not initialized.");
718 return NULL;
719 }
720
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400721 int res = future_get_result(self, &result);
722
723 if (res == -1) {
724 return NULL;
725 }
726
727 if (res == 0) {
728 return result;
729 }
730
731 assert(res == 1);
732
733 PyErr_SetObject(PyExceptionInstance_Class(result), result);
734 Py_DECREF(result);
735 return NULL;
736}
737
738/*[clinic input]
739_asyncio.Future.exception
740
741Return the exception that was set on this future.
742
743The exception (or None if no exception was set) is returned only if
744the future is done. If the future has been cancelled, raises
745CancelledError. If the future isn't done yet, raises
746InvalidStateError.
747[clinic start generated code]*/
748
749static PyObject *
750_asyncio_Future_exception_impl(FutureObj *self)
751/*[clinic end generated code: output=88b20d4f855e0710 input=733547a70c841c68]*/
752{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500753 if (!future_is_alive(self)) {
754 PyErr_SetString(asyncio_InvalidStateError,
755 "Future object is not initialized.");
756 return NULL;
757 }
758
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400759 if (self->fut_state == STATE_CANCELLED) {
Serhiy Storchakabca49392017-09-03 08:10:14 +0300760 PyErr_SetNone(asyncio_CancelledError);
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400761 return NULL;
762 }
763
764 if (self->fut_state != STATE_FINISHED) {
Serhiy Storchakabca49392017-09-03 08:10:14 +0300765 PyErr_SetString(asyncio_InvalidStateError, "Exception is not set.");
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400766 return NULL;
767 }
768
769 if (self->fut_exception != NULL) {
770 self->fut_log_tb = 0;
771 Py_INCREF(self->fut_exception);
772 return self->fut_exception;
773 }
774
775 Py_RETURN_NONE;
776}
777
778/*[clinic input]
779_asyncio.Future.set_result
780
Serhiy Storchakabca49392017-09-03 08:10:14 +0300781 res: object
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400782 /
783
784Mark the future done and set its result.
785
786If the future is already done when this method is called, raises
787InvalidStateError.
788[clinic start generated code]*/
789
790static PyObject *
791_asyncio_Future_set_result(FutureObj *self, PyObject *res)
Serhiy Storchakabca49392017-09-03 08:10:14 +0300792/*[clinic end generated code: output=a620abfc2796bfb6 input=5b9dc180f1baa56d]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400793{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500794 ENSURE_FUTURE_ALIVE(self)
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400795 return future_set_result(self, res);
796}
797
798/*[clinic input]
799_asyncio.Future.set_exception
800
Serhiy Storchakabca49392017-09-03 08:10:14 +0300801 exception: object
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400802 /
803
804Mark the future done and set an exception.
805
806If the future is already done when this method is called, raises
807InvalidStateError.
808[clinic start generated code]*/
809
810static PyObject *
811_asyncio_Future_set_exception(FutureObj *self, PyObject *exception)
Serhiy Storchakabca49392017-09-03 08:10:14 +0300812/*[clinic end generated code: output=f1c1b0cd321be360 input=e45b7d7aa71cc66d]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400813{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500814 ENSURE_FUTURE_ALIVE(self)
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400815 return future_set_exception(self, exception);
816}
817
818/*[clinic input]
819_asyncio.Future.add_done_callback
820
Serhiy Storchakabca49392017-09-03 08:10:14 +0300821 fn: object
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400822 /
823
824Add a callback to be run when the future becomes done.
825
826The callback is called with a single argument - the future object. If
827the future is already done when this is called, the callback is
828scheduled with call_soon.
829[clinic start generated code]*/
830
831static PyObject *
832_asyncio_Future_add_done_callback(FutureObj *self, PyObject *fn)
Serhiy Storchakabca49392017-09-03 08:10:14 +0300833/*[clinic end generated code: output=819e09629b2ec2b5 input=8f818b39990b027d]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400834{
835 return future_add_done_callback(self, fn);
836}
837
838/*[clinic input]
839_asyncio.Future.remove_done_callback
840
Serhiy Storchakabca49392017-09-03 08:10:14 +0300841 fn: object
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400842 /
843
844Remove all instances of a callback from the "call when done" list.
845
846Returns the number of callbacks removed.
847[clinic start generated code]*/
848
849static PyObject *
850_asyncio_Future_remove_done_callback(FutureObj *self, PyObject *fn)
Serhiy Storchakabca49392017-09-03 08:10:14 +0300851/*[clinic end generated code: output=5ab1fb52b24ef31f input=0a43280a149d505b]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900852{
853 PyObject *newlist;
854 Py_ssize_t len, i, j=0;
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500855 Py_ssize_t cleared_callback0 = 0;
856
857 ENSURE_FUTURE_ALIVE(self)
858
859 if (self->fut_callback0 != NULL) {
860 int cmp = PyObject_RichCompareBool(fn, self->fut_callback0, Py_EQ);
861 if (cmp == -1) {
862 return NULL;
863 }
864 if (cmp == 1) {
865 /* callback0 == fn */
866 Py_CLEAR(self->fut_callback0);
867 cleared_callback0 = 1;
868 }
869 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900870
Serhiy Storchakabca49392017-09-03 08:10:14 +0300871 if (self->fut_callbacks == NULL) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500872 return PyLong_FromSsize_t(cleared_callback0);
Serhiy Storchakabca49392017-09-03 08:10:14 +0300873 }
874
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400875 len = PyList_GET_SIZE(self->fut_callbacks);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900876 if (len == 0) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500877 Py_CLEAR(self->fut_callbacks);
878 return PyLong_FromSsize_t(cleared_callback0);
879 }
880
881 if (len == 1) {
882 int cmp = PyObject_RichCompareBool(
883 fn, PyList_GET_ITEM(self->fut_callbacks, 0), Py_EQ);
884 if (cmp == -1) {
885 return NULL;
886 }
887 if (cmp == 1) {
888 /* callbacks[0] == fn */
889 Py_CLEAR(self->fut_callbacks);
890 return PyLong_FromSsize_t(1 + cleared_callback0);
891 }
892 /* callbacks[0] != fn and len(callbacks) == 1 */
893 return PyLong_FromSsize_t(cleared_callback0);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900894 }
895
896 newlist = PyList_New(len);
897 if (newlist == NULL) {
898 return NULL;
899 }
900
Yury Selivanov84af9032017-03-02 23:46:56 -0500901 for (i = 0; i < PyList_GET_SIZE(self->fut_callbacks); i++) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900902 int ret;
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400903 PyObject *item = PyList_GET_ITEM(self->fut_callbacks, i);
Serhiy Storchakabca49392017-09-03 08:10:14 +0300904 Py_INCREF(item);
905 ret = PyObject_RichCompareBool(fn, item, Py_EQ);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900906 if (ret == 0) {
Yury Selivanov833a3b02017-07-05 13:32:03 -0400907 if (j < len) {
Yury Selivanov833a3b02017-07-05 13:32:03 -0400908 PyList_SET_ITEM(newlist, j, item);
909 j++;
Serhiy Storchakabca49392017-09-03 08:10:14 +0300910 continue;
Yury Selivanov833a3b02017-07-05 13:32:03 -0400911 }
Serhiy Storchakabca49392017-09-03 08:10:14 +0300912 ret = PyList_Append(newlist, item);
913 }
914 Py_DECREF(item);
915 if (ret < 0) {
916 goto fail;
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900917 }
918 }
919
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500920 if (j == 0) {
921 Py_CLEAR(self->fut_callbacks);
922 Py_DECREF(newlist);
923 return PyLong_FromSsize_t(len + cleared_callback0);
924 }
925
Serhiy Storchakabca49392017-09-03 08:10:14 +0300926 if (j < len) {
927 Py_SIZE(newlist) = j;
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900928 }
Serhiy Storchakabca49392017-09-03 08:10:14 +0300929 j = PyList_GET_SIZE(newlist);
930 len = PyList_GET_SIZE(self->fut_callbacks);
931 if (j != len) {
932 if (PyList_SetSlice(self->fut_callbacks, 0, len, newlist) < 0) {
933 goto fail;
934 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900935 }
936 Py_DECREF(newlist);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500937 return PyLong_FromSsize_t(len - j + cleared_callback0);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900938
939fail:
940 Py_DECREF(newlist);
941 return NULL;
942}
943
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400944/*[clinic input]
945_asyncio.Future.cancel
946
947Cancel the future and schedule callbacks.
948
949If the future is already done or cancelled, return False. Otherwise,
950change the future's state to cancelled, schedule the callbacks and
951return True.
952[clinic start generated code]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900953
954static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400955_asyncio_Future_cancel_impl(FutureObj *self)
956/*[clinic end generated code: output=e45b932ba8bd68a1 input=515709a127995109]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900957{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500958 ENSURE_FUTURE_ALIVE(self)
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400959 return future_cancel(self);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900960}
961
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400962/*[clinic input]
963_asyncio.Future.cancelled
964
965Return True if the future was cancelled.
966[clinic start generated code]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900967
968static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400969_asyncio_Future_cancelled_impl(FutureObj *self)
970/*[clinic end generated code: output=145197ced586357d input=943ab8b7b7b17e45]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900971{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500972 if (future_is_alive(self) && self->fut_state == STATE_CANCELLED) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900973 Py_RETURN_TRUE;
974 }
975 else {
976 Py_RETURN_FALSE;
977 }
978}
979
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400980/*[clinic input]
981_asyncio.Future.done
982
983Return True if the future is done.
984
985Done means either that a result / exception are available, or that the
986future was cancelled.
987[clinic start generated code]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900988
989static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400990_asyncio_Future_done_impl(FutureObj *self)
991/*[clinic end generated code: output=244c5ac351145096 input=28d7b23fdb65d2ac]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900992{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500993 if (!future_is_alive(self) || self->fut_state == STATE_PENDING) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900994 Py_RETURN_FALSE;
995 }
996 else {
997 Py_RETURN_TRUE;
998 }
999}
1000
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001001/*[clinic input]
1002_asyncio.Future.get_loop
1003
1004Return the event loop the Future is bound to.
1005[clinic start generated code]*/
1006
1007static PyObject *
1008_asyncio_Future_get_loop_impl(FutureObj *self)
1009/*[clinic end generated code: output=119b6ea0c9816c3f input=cba48c2136c79d1f]*/
1010{
1011 Py_INCREF(self->fut_loop);
1012 return self->fut_loop;
1013}
1014
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001015static PyObject *
1016FutureObj_get_blocking(FutureObj *fut)
1017{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001018 if (future_is_alive(fut) && fut->fut_blocking) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001019 Py_RETURN_TRUE;
1020 }
1021 else {
1022 Py_RETURN_FALSE;
1023 }
1024}
1025
1026static int
1027FutureObj_set_blocking(FutureObj *fut, PyObject *val)
1028{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001029 if (future_ensure_alive(fut)) {
1030 return -1;
1031 }
1032
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001033 int is_true = PyObject_IsTrue(val);
1034 if (is_true < 0) {
1035 return -1;
1036 }
1037 fut->fut_blocking = is_true;
1038 return 0;
1039}
1040
1041static PyObject *
1042FutureObj_get_log_traceback(FutureObj *fut)
1043{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001044 ENSURE_FUTURE_ALIVE(fut)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001045 if (fut->fut_log_tb) {
1046 Py_RETURN_TRUE;
1047 }
1048 else {
1049 Py_RETURN_FALSE;
1050 }
1051}
1052
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +00001053static int
1054FutureObj_set_log_traceback(FutureObj *fut, PyObject *val)
1055{
1056 int is_true = PyObject_IsTrue(val);
1057 if (is_true < 0) {
1058 return -1;
1059 }
1060 fut->fut_log_tb = is_true;
1061 return 0;
1062}
1063
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001064static PyObject *
1065FutureObj_get_loop(FutureObj *fut)
1066{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001067 if (!future_is_alive(fut)) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001068 Py_RETURN_NONE;
1069 }
1070 Py_INCREF(fut->fut_loop);
1071 return fut->fut_loop;
1072}
1073
1074static PyObject *
1075FutureObj_get_callbacks(FutureObj *fut)
1076{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001077 Py_ssize_t i;
1078 Py_ssize_t len;
1079 PyObject *new_list;
1080
1081 ENSURE_FUTURE_ALIVE(fut)
1082
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001083 if (fut->fut_callbacks == NULL) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001084 if (fut->fut_callback0 == NULL) {
1085 Py_RETURN_NONE;
1086 }
1087 else {
1088 new_list = PyList_New(1);
1089 if (new_list == NULL) {
1090 return NULL;
1091 }
1092 Py_INCREF(fut->fut_callback0);
1093 PyList_SET_ITEM(new_list, 0, fut->fut_callback0);
1094 return new_list;
1095 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001096 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001097
1098 assert(fut->fut_callbacks != NULL);
1099
1100 if (fut->fut_callback0 == NULL) {
1101 Py_INCREF(fut->fut_callbacks);
1102 return fut->fut_callbacks;
1103 }
1104
1105 assert(fut->fut_callback0 != NULL);
1106
1107 len = PyList_GET_SIZE(fut->fut_callbacks);
1108 new_list = PyList_New(len + 1);
1109 if (new_list == NULL) {
1110 return NULL;
1111 }
1112
1113 Py_INCREF(fut->fut_callback0);
1114 PyList_SET_ITEM(new_list, 0, fut->fut_callback0);
1115 for (i = 0; i < len; i++) {
1116 PyObject *cb = PyList_GET_ITEM(fut->fut_callbacks, i);
1117 Py_INCREF(cb);
1118 PyList_SET_ITEM(new_list, i + 1, cb);
1119 }
1120
1121 return new_list;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001122}
1123
1124static PyObject *
1125FutureObj_get_result(FutureObj *fut)
1126{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001127 ENSURE_FUTURE_ALIVE(fut)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001128 if (fut->fut_result == NULL) {
1129 Py_RETURN_NONE;
1130 }
1131 Py_INCREF(fut->fut_result);
1132 return fut->fut_result;
1133}
1134
1135static PyObject *
1136FutureObj_get_exception(FutureObj *fut)
1137{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001138 ENSURE_FUTURE_ALIVE(fut)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001139 if (fut->fut_exception == NULL) {
1140 Py_RETURN_NONE;
1141 }
1142 Py_INCREF(fut->fut_exception);
1143 return fut->fut_exception;
1144}
1145
1146static PyObject *
1147FutureObj_get_source_traceback(FutureObj *fut)
1148{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001149 if (!future_is_alive(fut) || fut->fut_source_tb == NULL) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001150 Py_RETURN_NONE;
1151 }
1152 Py_INCREF(fut->fut_source_tb);
1153 return fut->fut_source_tb;
1154}
1155
1156static PyObject *
1157FutureObj_get_state(FutureObj *fut)
1158{
1159 _Py_IDENTIFIER(PENDING);
1160 _Py_IDENTIFIER(CANCELLED);
1161 _Py_IDENTIFIER(FINISHED);
1162 PyObject *ret = NULL;
1163
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001164 ENSURE_FUTURE_ALIVE(fut)
1165
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001166 switch (fut->fut_state) {
1167 case STATE_PENDING:
1168 ret = _PyUnicode_FromId(&PyId_PENDING);
1169 break;
1170 case STATE_CANCELLED:
1171 ret = _PyUnicode_FromId(&PyId_CANCELLED);
1172 break;
1173 case STATE_FINISHED:
1174 ret = _PyUnicode_FromId(&PyId_FINISHED);
1175 break;
1176 default:
1177 assert (0);
1178 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03001179 Py_XINCREF(ret);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001180 return ret;
1181}
1182
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001183/*[clinic input]
1184_asyncio.Future._repr_info
1185[clinic start generated code]*/
1186
1187static PyObject *
1188_asyncio_Future__repr_info_impl(FutureObj *self)
1189/*[clinic end generated code: output=fa69e901bd176cfb input=f21504d8e2ae1ca2]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001190{
Victor Stinnerde4ae3d2016-12-04 22:59:09 +01001191 return PyObject_CallFunctionObjArgs(
1192 asyncio_future_repr_info_func, self, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001193}
1194
1195/*[clinic input]
1196_asyncio.Future._schedule_callbacks
1197[clinic start generated code]*/
1198
1199static PyObject *
1200_asyncio_Future__schedule_callbacks_impl(FutureObj *self)
1201/*[clinic end generated code: output=5e8958d89ea1c5dc input=4f5f295f263f4a88]*/
1202{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001203 ENSURE_FUTURE_ALIVE(self)
1204
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001205 int ret = future_schedule_callbacks(self);
1206 if (ret == -1) {
1207 return NULL;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001208 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001209 Py_RETURN_NONE;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001210}
1211
1212static PyObject *
1213FutureObj_repr(FutureObj *fut)
1214{
1215 _Py_IDENTIFIER(_repr_info);
1216
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001217 ENSURE_FUTURE_ALIVE(fut)
1218
Serhiy Storchakabca49392017-09-03 08:10:14 +03001219 PyObject *rinfo = _PyObject_CallMethodIdObjArgs((PyObject*)fut,
1220 &PyId__repr_info,
1221 NULL);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001222 if (rinfo == NULL) {
1223 return NULL;
1224 }
1225
Serhiy Storchakabca49392017-09-03 08:10:14 +03001226 PyObject *rinfo_s = PyUnicode_Join(NULL, rinfo);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001227 Py_DECREF(rinfo);
1228 if (rinfo_s == NULL) {
1229 return NULL;
1230 }
1231
1232 PyObject *rstr = NULL;
1233 PyObject *type_name = PyObject_GetAttrString((PyObject*)Py_TYPE(fut),
1234 "__name__");
1235 if (type_name != NULL) {
Serhiy Storchakabca49392017-09-03 08:10:14 +03001236 rstr = PyUnicode_FromFormat("<%S %U>", type_name, rinfo_s);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001237 Py_DECREF(type_name);
1238 }
1239 Py_DECREF(rinfo_s);
1240 return rstr;
1241}
1242
1243static void
1244FutureObj_finalize(FutureObj *fut)
1245{
1246 _Py_IDENTIFIER(call_exception_handler);
1247 _Py_IDENTIFIER(message);
1248 _Py_IDENTIFIER(exception);
1249 _Py_IDENTIFIER(future);
1250 _Py_IDENTIFIER(source_traceback);
1251
Serhiy Storchakabca49392017-09-03 08:10:14 +03001252 PyObject *error_type, *error_value, *error_traceback;
1253 PyObject *context;
1254 PyObject *type_name;
1255 PyObject *message = NULL;
1256 PyObject *func;
1257
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001258 if (!fut->fut_log_tb) {
1259 return;
1260 }
1261 assert(fut->fut_exception != NULL);
Serhiy Storchakabca49392017-09-03 08:10:14 +03001262 fut->fut_log_tb = 0;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001263
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001264 /* Save the current exception, if any. */
1265 PyErr_Fetch(&error_type, &error_value, &error_traceback);
1266
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001267 context = PyDict_New();
1268 if (context == NULL) {
1269 goto finally;
1270 }
1271
1272 type_name = PyObject_GetAttrString((PyObject*)Py_TYPE(fut), "__name__");
1273 if (type_name == NULL) {
1274 goto finally;
1275 }
1276
1277 message = PyUnicode_FromFormat(
1278 "%S exception was never retrieved", type_name);
Serhiy Storchakabca49392017-09-03 08:10:14 +03001279 Py_DECREF(type_name);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001280 if (message == NULL) {
1281 goto finally;
1282 }
1283
1284 if (_PyDict_SetItemId(context, &PyId_message, message) < 0 ||
1285 _PyDict_SetItemId(context, &PyId_exception, fut->fut_exception) < 0 ||
1286 _PyDict_SetItemId(context, &PyId_future, (PyObject*)fut) < 0) {
1287 goto finally;
1288 }
1289 if (fut->fut_source_tb != NULL) {
1290 if (_PyDict_SetItemId(context, &PyId_source_traceback,
1291 fut->fut_source_tb) < 0) {
1292 goto finally;
1293 }
1294 }
1295
1296 func = _PyObject_GetAttrId(fut->fut_loop, &PyId_call_exception_handler);
1297 if (func != NULL) {
Serhiy Storchakabca49392017-09-03 08:10:14 +03001298 PyObject *res = PyObject_CallFunctionObjArgs(func, context, NULL);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001299 if (res == NULL) {
1300 PyErr_WriteUnraisable(func);
1301 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03001302 else {
1303 Py_DECREF(res);
1304 }
1305 Py_DECREF(func);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001306 }
1307
1308finally:
Serhiy Storchakabca49392017-09-03 08:10:14 +03001309 Py_XDECREF(context);
1310 Py_XDECREF(message);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001311
1312 /* Restore the saved exception. */
1313 PyErr_Restore(error_type, error_value, error_traceback);
1314}
1315
1316
1317static PyAsyncMethods FutureType_as_async = {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001318 (unaryfunc)future_new_iter, /* am_await */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001319 0, /* am_aiter */
1320 0 /* am_anext */
1321};
1322
1323static PyMethodDef FutureType_methods[] = {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001324 _ASYNCIO_FUTURE_RESULT_METHODDEF
1325 _ASYNCIO_FUTURE_EXCEPTION_METHODDEF
1326 _ASYNCIO_FUTURE_SET_RESULT_METHODDEF
1327 _ASYNCIO_FUTURE_SET_EXCEPTION_METHODDEF
1328 _ASYNCIO_FUTURE_ADD_DONE_CALLBACK_METHODDEF
1329 _ASYNCIO_FUTURE_REMOVE_DONE_CALLBACK_METHODDEF
1330 _ASYNCIO_FUTURE_CANCEL_METHODDEF
1331 _ASYNCIO_FUTURE_CANCELLED_METHODDEF
1332 _ASYNCIO_FUTURE_DONE_METHODDEF
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001333 _ASYNCIO_FUTURE_GET_LOOP_METHODDEF
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001334 _ASYNCIO_FUTURE__REPR_INFO_METHODDEF
1335 _ASYNCIO_FUTURE__SCHEDULE_CALLBACKS_METHODDEF
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001336 {NULL, NULL} /* Sentinel */
1337};
1338
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001339#define FUTURE_COMMON_GETSETLIST \
1340 {"_state", (getter)FutureObj_get_state, NULL, NULL}, \
1341 {"_asyncio_future_blocking", (getter)FutureObj_get_blocking, \
1342 (setter)FutureObj_set_blocking, NULL}, \
1343 {"_loop", (getter)FutureObj_get_loop, NULL, NULL}, \
1344 {"_callbacks", (getter)FutureObj_get_callbacks, NULL, NULL}, \
1345 {"_result", (getter)FutureObj_get_result, NULL, NULL}, \
1346 {"_exception", (getter)FutureObj_get_exception, NULL, NULL}, \
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +00001347 {"_log_traceback", (getter)FutureObj_get_log_traceback, \
1348 (setter)FutureObj_set_log_traceback, NULL}, \
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001349 {"_source_traceback", (getter)FutureObj_get_source_traceback, NULL, NULL},
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001350
1351static PyGetSetDef FutureType_getsetlist[] = {
1352 FUTURE_COMMON_GETSETLIST
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001353 {NULL} /* Sentinel */
1354};
1355
1356static void FutureObj_dealloc(PyObject *self);
1357
1358static PyTypeObject FutureType = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02001359 PyVarObject_HEAD_INIT(NULL, 0)
INADA Naoki9f2ce252016-10-15 15:39:19 +09001360 "_asyncio.Future",
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001361 sizeof(FutureObj), /* tp_basicsize */
1362 .tp_dealloc = FutureObj_dealloc,
1363 .tp_as_async = &FutureType_as_async,
1364 .tp_repr = (reprfunc)FutureObj_repr,
1365 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE
1366 | Py_TPFLAGS_HAVE_FINALIZE,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001367 .tp_doc = _asyncio_Future___init____doc__,
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001368 .tp_traverse = (traverseproc)FutureObj_traverse,
1369 .tp_clear = (inquiry)FutureObj_clear,
1370 .tp_weaklistoffset = offsetof(FutureObj, fut_weakreflist),
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001371 .tp_iter = (getiterfunc)future_new_iter,
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001372 .tp_methods = FutureType_methods,
1373 .tp_getset = FutureType_getsetlist,
1374 .tp_dictoffset = offsetof(FutureObj, dict),
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001375 .tp_init = (initproc)_asyncio_Future___init__,
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001376 .tp_new = PyType_GenericNew,
1377 .tp_finalize = (destructor)FutureObj_finalize,
1378};
1379
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001380static inline int
1381future_call_schedule_callbacks(FutureObj *fut)
1382{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001383 if (Future_CheckExact(fut) || Task_CheckExact(fut)) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001384 return future_schedule_callbacks(fut);
1385 }
1386 else {
1387 /* `fut` is a subclass of Future */
1388 PyObject *ret = _PyObject_CallMethodId(
1389 (PyObject*)fut, &PyId__schedule_callbacks, NULL);
1390 if (ret == NULL) {
1391 return -1;
1392 }
1393
1394 Py_DECREF(ret);
1395 return 0;
1396 }
1397}
1398
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001399static void
1400FutureObj_dealloc(PyObject *self)
1401{
1402 FutureObj *fut = (FutureObj *)self;
1403
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001404 if (Future_CheckExact(fut)) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001405 /* When fut is subclass of Future, finalizer is called from
1406 * subtype_dealloc.
1407 */
1408 if (PyObject_CallFinalizerFromDealloc(self) < 0) {
1409 // resurrected.
1410 return;
1411 }
1412 }
1413
Alexander Mohrde34cbe2017-08-01 23:31:07 -07001414 PyObject_GC_UnTrack(self);
1415
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001416 if (fut->fut_weakreflist != NULL) {
1417 PyObject_ClearWeakRefs(self);
1418 }
1419
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001420 (void)FutureObj_clear(fut);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001421 Py_TYPE(fut)->tp_free(fut);
1422}
1423
1424
1425/*********************** Future Iterator **************************/
1426
1427typedef struct {
1428 PyObject_HEAD
1429 FutureObj *future;
1430} futureiterobject;
1431
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001432
1433#define FI_FREELIST_MAXLEN 255
1434static futureiterobject *fi_freelist = NULL;
1435static Py_ssize_t fi_freelist_len = 0;
1436
1437
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001438static void
1439FutureIter_dealloc(futureiterobject *it)
1440{
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001441 PyObject_GC_UnTrack(it);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001442 Py_CLEAR(it->future);
1443
1444 if (fi_freelist_len < FI_FREELIST_MAXLEN) {
1445 fi_freelist_len++;
1446 it->future = (FutureObj*) fi_freelist;
1447 fi_freelist = it;
1448 }
1449 else {
1450 PyObject_GC_Del(it);
1451 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001452}
1453
1454static PyObject *
1455FutureIter_iternext(futureiterobject *it)
1456{
1457 PyObject *res;
1458 FutureObj *fut = it->future;
1459
1460 if (fut == NULL) {
1461 return NULL;
1462 }
1463
1464 if (fut->fut_state == STATE_PENDING) {
1465 if (!fut->fut_blocking) {
1466 fut->fut_blocking = 1;
1467 Py_INCREF(fut);
1468 return (PyObject *)fut;
1469 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03001470 PyErr_SetString(PyExc_AssertionError,
1471 "yield from wasn't used with future");
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001472 return NULL;
1473 }
1474
Serhiy Storchakabca49392017-09-03 08:10:14 +03001475 it->future = NULL;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001476 res = _asyncio_Future_result_impl(fut);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001477 if (res != NULL) {
Serhiy Storchaka60e49aa2016-11-06 18:47:03 +02001478 /* The result of the Future is not an exception. */
Serhiy Storchakabca49392017-09-03 08:10:14 +03001479 (void)_PyGen_SetStopIterationValue(res);
Serhiy Storchaka60e49aa2016-11-06 18:47:03 +02001480 Py_DECREF(res);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001481 }
1482
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001483 Py_DECREF(fut);
1484 return NULL;
1485}
1486
1487static PyObject *
INADA Naoki74c17532016-10-25 19:00:45 +09001488FutureIter_send(futureiterobject *self, PyObject *unused)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001489{
INADA Naoki74c17532016-10-25 19:00:45 +09001490 /* Future.__iter__ doesn't care about values that are pushed to the
1491 * generator, it just returns "self.result().
1492 */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001493 return FutureIter_iternext(self);
1494}
1495
1496static PyObject *
1497FutureIter_throw(futureiterobject *self, PyObject *args)
1498{
Serhiy Storchakabca49392017-09-03 08:10:14 +03001499 PyObject *type, *val = NULL, *tb = NULL;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001500 if (!PyArg_ParseTuple(args, "O|OO", &type, &val, &tb))
1501 return NULL;
1502
1503 if (val == Py_None) {
1504 val = NULL;
1505 }
1506 if (tb == Py_None) {
1507 tb = NULL;
Benjamin Peterson996fc1f2016-11-14 00:15:44 -08001508 } else if (tb != NULL && !PyTraceBack_Check(tb)) {
1509 PyErr_SetString(PyExc_TypeError, "throw() third argument must be a traceback");
1510 return NULL;
1511 }
1512
1513 Py_INCREF(type);
1514 Py_XINCREF(val);
1515 Py_XINCREF(tb);
1516
1517 if (PyExceptionClass_Check(type)) {
1518 PyErr_NormalizeException(&type, &val, &tb);
Yury Selivanovedfe8862016-12-01 11:37:47 -05001519 /* No need to call PyException_SetTraceback since we'll be calling
1520 PyErr_Restore for `type`, `val`, and `tb`. */
Benjamin Peterson996fc1f2016-11-14 00:15:44 -08001521 } else if (PyExceptionInstance_Check(type)) {
1522 if (val) {
1523 PyErr_SetString(PyExc_TypeError,
1524 "instance exception may not have a separate value");
1525 goto fail;
1526 }
1527 val = type;
1528 type = PyExceptionInstance_Class(type);
1529 Py_INCREF(type);
1530 if (tb == NULL)
1531 tb = PyException_GetTraceback(val);
1532 } else {
1533 PyErr_SetString(PyExc_TypeError,
1534 "exceptions must be classes deriving BaseException or "
1535 "instances of such a class");
1536 goto fail;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001537 }
1538
1539 Py_CLEAR(self->future);
1540
Benjamin Peterson996fc1f2016-11-14 00:15:44 -08001541 PyErr_Restore(type, val, tb);
1542
Serhiy Storchakabca49392017-09-03 08:10:14 +03001543 return NULL;
Benjamin Peterson996fc1f2016-11-14 00:15:44 -08001544
1545 fail:
1546 Py_DECREF(type);
1547 Py_XDECREF(val);
1548 Py_XDECREF(tb);
1549 return NULL;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001550}
1551
1552static PyObject *
1553FutureIter_close(futureiterobject *self, PyObject *arg)
1554{
1555 Py_CLEAR(self->future);
1556 Py_RETURN_NONE;
1557}
1558
1559static int
1560FutureIter_traverse(futureiterobject *it, visitproc visit, void *arg)
1561{
1562 Py_VISIT(it->future);
1563 return 0;
1564}
1565
1566static PyMethodDef FutureIter_methods[] = {
1567 {"send", (PyCFunction)FutureIter_send, METH_O, NULL},
1568 {"throw", (PyCFunction)FutureIter_throw, METH_VARARGS, NULL},
1569 {"close", (PyCFunction)FutureIter_close, METH_NOARGS, NULL},
1570 {NULL, NULL} /* Sentinel */
1571};
1572
1573static PyTypeObject FutureIterType = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02001574 PyVarObject_HEAD_INIT(NULL, 0)
INADA Naoki9f2ce252016-10-15 15:39:19 +09001575 "_asyncio.FutureIter",
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001576 .tp_basicsize = sizeof(futureiterobject),
1577 .tp_itemsize = 0,
1578 .tp_dealloc = (destructor)FutureIter_dealloc,
1579 .tp_getattro = PyObject_GenericGetAttr,
1580 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
1581 .tp_traverse = (traverseproc)FutureIter_traverse,
1582 .tp_iter = PyObject_SelfIter,
1583 .tp_iternext = (iternextfunc)FutureIter_iternext,
1584 .tp_methods = FutureIter_methods,
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001585};
1586
1587static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001588future_new_iter(PyObject *fut)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001589{
1590 futureiterobject *it;
1591
1592 if (!PyObject_TypeCheck(fut, &FutureType)) {
1593 PyErr_BadInternalCall();
1594 return NULL;
1595 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001596
1597 ENSURE_FUTURE_ALIVE(fut)
1598
1599 if (fi_freelist_len) {
1600 fi_freelist_len--;
1601 it = fi_freelist;
1602 fi_freelist = (futureiterobject*) it->future;
1603 it->future = NULL;
1604 _Py_NewReference((PyObject*) it);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001605 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001606 else {
1607 it = PyObject_GC_New(futureiterobject, &FutureIterType);
1608 if (it == NULL) {
1609 return NULL;
1610 }
1611 }
1612
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001613 Py_INCREF(fut);
1614 it->future = (FutureObj*)fut;
INADA Naoki1be427b2016-10-11 02:12:34 +09001615 PyObject_GC_Track(it);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001616 return (PyObject*)it;
1617}
1618
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001619
1620/*********************** Task **************************/
1621
1622
1623/*[clinic input]
1624class _asyncio.Task "TaskObj *" "&Task_Type"
1625[clinic start generated code]*/
1626/*[clinic end generated code: output=da39a3ee5e6b4b0d input=719dcef0fcc03b37]*/
1627
1628static int task_call_step_soon(TaskObj *, PyObject *);
1629static inline PyObject * task_call_wakeup(TaskObj *, PyObject *);
1630static inline PyObject * task_call_step(TaskObj *, PyObject *);
1631static PyObject * task_wakeup(TaskObj *, PyObject *);
1632static PyObject * task_step(TaskObj *, PyObject *);
1633
1634/* ----- Task._step wrapper */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001635
INADA Naokic411a7d2016-10-18 11:48:14 +09001636static int
Serhiy Storchakabca49392017-09-03 08:10:14 +03001637TaskStepMethWrapper_clear(TaskStepMethWrapper *o)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001638{
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001639 Py_CLEAR(o->sw_task);
1640 Py_CLEAR(o->sw_arg);
1641 return 0;
1642}
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001643
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001644static void
Serhiy Storchakabca49392017-09-03 08:10:14 +03001645TaskStepMethWrapper_dealloc(TaskStepMethWrapper *o)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001646{
1647 PyObject_GC_UnTrack(o);
Serhiy Storchakabca49392017-09-03 08:10:14 +03001648 (void)TaskStepMethWrapper_clear(o);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001649 Py_TYPE(o)->tp_free(o);
1650}
1651
1652static PyObject *
Serhiy Storchakabca49392017-09-03 08:10:14 +03001653TaskStepMethWrapper_call(TaskStepMethWrapper *o,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001654 PyObject *args, PyObject *kwds)
1655{
Serhiy Storchakabca49392017-09-03 08:10:14 +03001656 if (kwds != NULL && PyDict_GET_SIZE(kwds) != 0) {
1657 PyErr_SetString(PyExc_TypeError, "function takes no keyword arguments");
1658 return NULL;
1659 }
1660 if (args != NULL && PyTuple_GET_SIZE(args) != 0) {
1661 PyErr_SetString(PyExc_TypeError, "function takes no positional arguments");
1662 return NULL;
1663 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001664 return task_call_step(o->sw_task, o->sw_arg);
1665}
1666
1667static int
Serhiy Storchakabca49392017-09-03 08:10:14 +03001668TaskStepMethWrapper_traverse(TaskStepMethWrapper *o,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001669 visitproc visit, void *arg)
1670{
1671 Py_VISIT(o->sw_task);
1672 Py_VISIT(o->sw_arg);
1673 return 0;
1674}
1675
1676static PyObject *
Serhiy Storchakabca49392017-09-03 08:10:14 +03001677TaskStepMethWrapper_get___self__(TaskStepMethWrapper *o)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001678{
1679 if (o->sw_task) {
1680 Py_INCREF(o->sw_task);
1681 return (PyObject*)o->sw_task;
1682 }
1683 Py_RETURN_NONE;
1684}
1685
Serhiy Storchakabca49392017-09-03 08:10:14 +03001686static PyGetSetDef TaskStepMethWrapper_getsetlist[] = {
1687 {"__self__", (getter)TaskStepMethWrapper_get___self__, NULL, NULL},
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001688 {NULL} /* Sentinel */
1689};
1690
Serhiy Storchakabca49392017-09-03 08:10:14 +03001691PyTypeObject TaskStepMethWrapper_Type = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02001692 PyVarObject_HEAD_INIT(NULL, 0)
Serhiy Storchakabca49392017-09-03 08:10:14 +03001693 "TaskStepMethWrapper",
1694 .tp_basicsize = sizeof(TaskStepMethWrapper),
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001695 .tp_itemsize = 0,
Serhiy Storchakabca49392017-09-03 08:10:14 +03001696 .tp_getset = TaskStepMethWrapper_getsetlist,
1697 .tp_dealloc = (destructor)TaskStepMethWrapper_dealloc,
1698 .tp_call = (ternaryfunc)TaskStepMethWrapper_call,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001699 .tp_getattro = PyObject_GenericGetAttr,
1700 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
Serhiy Storchakabca49392017-09-03 08:10:14 +03001701 .tp_traverse = (traverseproc)TaskStepMethWrapper_traverse,
1702 .tp_clear = (inquiry)TaskStepMethWrapper_clear,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001703};
1704
1705static PyObject *
Serhiy Storchakabca49392017-09-03 08:10:14 +03001706TaskStepMethWrapper_new(TaskObj *task, PyObject *arg)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001707{
Serhiy Storchakabca49392017-09-03 08:10:14 +03001708 TaskStepMethWrapper *o;
1709 o = PyObject_GC_New(TaskStepMethWrapper, &TaskStepMethWrapper_Type);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001710 if (o == NULL) {
1711 return NULL;
1712 }
1713
1714 Py_INCREF(task);
1715 o->sw_task = task;
1716
1717 Py_XINCREF(arg);
1718 o->sw_arg = arg;
1719
1720 PyObject_GC_Track(o);
1721 return (PyObject*) o;
1722}
1723
1724/* ----- Task._wakeup wrapper */
1725
1726static PyObject *
1727TaskWakeupMethWrapper_call(TaskWakeupMethWrapper *o,
1728 PyObject *args, PyObject *kwds)
1729{
1730 PyObject *fut;
1731
Serhiy Storchakabca49392017-09-03 08:10:14 +03001732 if (kwds != NULL && PyDict_GET_SIZE(kwds) != 0) {
1733 PyErr_SetString(PyExc_TypeError, "function takes no keyword arguments");
1734 return NULL;
1735 }
1736 if (!PyArg_ParseTuple(args, "O", &fut)) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001737 return NULL;
1738 }
1739
1740 return task_call_wakeup(o->ww_task, fut);
1741}
1742
1743static int
1744TaskWakeupMethWrapper_clear(TaskWakeupMethWrapper *o)
1745{
1746 Py_CLEAR(o->ww_task);
1747 return 0;
1748}
1749
1750static int
1751TaskWakeupMethWrapper_traverse(TaskWakeupMethWrapper *o,
1752 visitproc visit, void *arg)
1753{
1754 Py_VISIT(o->ww_task);
1755 return 0;
1756}
1757
1758static void
1759TaskWakeupMethWrapper_dealloc(TaskWakeupMethWrapper *o)
1760{
1761 PyObject_GC_UnTrack(o);
1762 (void)TaskWakeupMethWrapper_clear(o);
1763 Py_TYPE(o)->tp_free(o);
1764}
1765
1766PyTypeObject TaskWakeupMethWrapper_Type = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02001767 PyVarObject_HEAD_INIT(NULL, 0)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001768 "TaskWakeupMethWrapper",
1769 .tp_basicsize = sizeof(TaskWakeupMethWrapper),
1770 .tp_itemsize = 0,
1771 .tp_dealloc = (destructor)TaskWakeupMethWrapper_dealloc,
1772 .tp_call = (ternaryfunc)TaskWakeupMethWrapper_call,
1773 .tp_getattro = PyObject_GenericGetAttr,
1774 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
1775 .tp_traverse = (traverseproc)TaskWakeupMethWrapper_traverse,
1776 .tp_clear = (inquiry)TaskWakeupMethWrapper_clear,
1777};
1778
1779static PyObject *
1780TaskWakeupMethWrapper_new(TaskObj *task)
1781{
1782 TaskWakeupMethWrapper *o;
1783 o = PyObject_GC_New(TaskWakeupMethWrapper, &TaskWakeupMethWrapper_Type);
1784 if (o == NULL) {
1785 return NULL;
1786 }
1787
1788 Py_INCREF(task);
1789 o->ww_task = task;
1790
1791 PyObject_GC_Track(o);
1792 return (PyObject*) o;
1793}
1794
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001795/* ----- Task introspection helpers */
1796
1797static int
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001798register_task(PyObject *task)
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001799{
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001800 _Py_IDENTIFIER(add);
1801
1802 PyObject *res = _PyObject_CallMethodIdObjArgs(
1803 all_tasks, &PyId_add, task, NULL);
1804 if (res == NULL) {
1805 return -1;
1806 }
1807 Py_DECREF(res);
1808 return 0;
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001809}
1810
1811
1812static int
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001813unregister_task(PyObject *task)
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001814{
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001815 _Py_IDENTIFIER(discard);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001816
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001817 PyObject *res = _PyObject_CallMethodIdObjArgs(
1818 all_tasks, &PyId_discard, task, NULL);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001819 if (res == NULL) {
1820 return -1;
1821 }
1822 Py_DECREF(res);
1823 return 0;
1824}
1825
1826
1827static int
1828enter_task(PyObject *loop, PyObject *task)
1829{
1830 PyObject *item;
1831 Py_hash_t hash;
1832 hash = PyObject_Hash(loop);
1833 if (hash == -1) {
1834 return -1;
1835 }
1836 item = _PyDict_GetItem_KnownHash(current_tasks, loop, hash);
1837 if (item != NULL) {
1838 PyErr_Format(
1839 PyExc_RuntimeError,
1840 "Cannot enter into task %R while another " \
1841 "task %R is being executed.",
1842 task, item, NULL);
1843 return -1;
1844 }
1845 if (_PyDict_SetItem_KnownHash(current_tasks, loop, task, hash) < 0) {
1846 return -1;
1847 }
1848 return 0;
1849}
1850
1851
1852static int
1853leave_task(PyObject *loop, PyObject *task)
1854/*[clinic end generated code: output=0ebf6db4b858fb41 input=51296a46313d1ad8]*/
1855{
1856 PyObject *item;
1857 Py_hash_t hash;
1858 hash = PyObject_Hash(loop);
1859 if (hash == -1) {
1860 return -1;
1861 }
1862 item = _PyDict_GetItem_KnownHash(current_tasks, loop, hash);
1863 if (item != task) {
1864 if (item == NULL) {
1865 /* Not entered, replace with None */
1866 item = Py_None;
1867 }
1868 PyErr_Format(
1869 PyExc_RuntimeError,
1870 "Leaving task %R does not match the current task %R.",
1871 task, item, NULL);
1872 return -1;
1873 }
1874 return _PyDict_DelItem_KnownHash(current_tasks, loop, hash);
1875}
1876
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001877/* ----- Task */
1878
1879/*[clinic input]
1880_asyncio.Task.__init__
1881
Serhiy Storchakabca49392017-09-03 08:10:14 +03001882 coro: object
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001883 *
Serhiy Storchakabca49392017-09-03 08:10:14 +03001884 loop: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001885
1886A coroutine wrapped in a Future.
1887[clinic start generated code]*/
1888
1889static int
1890_asyncio_Task___init___impl(TaskObj *self, PyObject *coro, PyObject *loop)
Serhiy Storchakabca49392017-09-03 08:10:14 +03001891/*[clinic end generated code: output=9f24774c2287fc2f input=8d132974b049593e]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001892{
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001893 if (future_init((FutureObj*)self, loop)) {
INADA Naokic411a7d2016-10-18 11:48:14 +09001894 return -1;
1895 }
INADA Naokic411a7d2016-10-18 11:48:14 +09001896
Yury Selivanova9d7e552017-12-19 07:18:45 -05001897 int is_coro = is_coroutine(coro);
1898 if (is_coro == -1) {
1899 return -1;
1900 }
1901 if (is_coro == 0) {
1902 self->task_log_destroy_pending = 0;
1903 PyErr_Format(PyExc_TypeError,
1904 "a coroutine was expected, got %R",
1905 coro, NULL);
1906 return -1;
Andrew Svetlovf74ef452017-12-15 07:04:38 +02001907 }
1908
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001909 self->task_fut_waiter = NULL;
1910 self->task_must_cancel = 0;
1911 self->task_log_destroy_pending = 1;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001912 Py_INCREF(coro);
1913 self->task_coro = coro;
1914
1915 if (task_call_step_soon(self, NULL)) {
1916 return -1;
INADA Naokic411a7d2016-10-18 11:48:14 +09001917 }
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001918 return register_task((PyObject*)self);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001919}
1920
1921static int
1922TaskObj_clear(TaskObj *task)
1923{
1924 (void)FutureObj_clear((FutureObj*) task);
1925 Py_CLEAR(task->task_coro);
1926 Py_CLEAR(task->task_fut_waiter);
1927 return 0;
1928}
1929
1930static int
1931TaskObj_traverse(TaskObj *task, visitproc visit, void *arg)
1932{
1933 Py_VISIT(task->task_coro);
1934 Py_VISIT(task->task_fut_waiter);
1935 (void)FutureObj_traverse((FutureObj*) task, visit, arg);
1936 return 0;
1937}
1938
1939static PyObject *
1940TaskObj_get_log_destroy_pending(TaskObj *task)
1941{
1942 if (task->task_log_destroy_pending) {
1943 Py_RETURN_TRUE;
1944 }
1945 else {
1946 Py_RETURN_FALSE;
1947 }
1948}
1949
1950static int
1951TaskObj_set_log_destroy_pending(TaskObj *task, PyObject *val)
1952{
1953 int is_true = PyObject_IsTrue(val);
1954 if (is_true < 0) {
1955 return -1;
1956 }
1957 task->task_log_destroy_pending = is_true;
1958 return 0;
1959}
1960
1961static PyObject *
1962TaskObj_get_must_cancel(TaskObj *task)
1963{
1964 if (task->task_must_cancel) {
1965 Py_RETURN_TRUE;
1966 }
1967 else {
1968 Py_RETURN_FALSE;
1969 }
1970}
1971
1972static PyObject *
1973TaskObj_get_coro(TaskObj *task)
1974{
1975 if (task->task_coro) {
1976 Py_INCREF(task->task_coro);
1977 return task->task_coro;
1978 }
1979
1980 Py_RETURN_NONE;
1981}
1982
1983static PyObject *
1984TaskObj_get_fut_waiter(TaskObj *task)
1985{
1986 if (task->task_fut_waiter) {
1987 Py_INCREF(task->task_fut_waiter);
1988 return task->task_fut_waiter;
1989 }
1990
1991 Py_RETURN_NONE;
1992}
1993
1994/*[clinic input]
1995@classmethod
1996_asyncio.Task.current_task
1997
Serhiy Storchakabca49392017-09-03 08:10:14 +03001998 loop: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001999
2000Return the currently running task in an event loop or None.
2001
2002By default the current task for the current event loop is returned.
2003
2004None is returned when called not in the context of a Task.
2005[clinic start generated code]*/
2006
2007static PyObject *
2008_asyncio_Task_current_task_impl(PyTypeObject *type, PyObject *loop)
Serhiy Storchakabca49392017-09-03 08:10:14 +03002009/*[clinic end generated code: output=99fbe7332c516e03 input=cd14770c5b79c7eb]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002010{
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002011 PyObject *ret;
2012 PyObject *current_task_func;
2013
2014 if (PyErr_WarnEx(PyExc_PendingDeprecationWarning,
2015 "Task.current_task() is deprecated, " \
2016 "use asyncio.current_task() instead",
2017 1) < 0) {
2018 return NULL;
2019 }
2020
2021 current_task_func = _PyObject_GetAttrId(asyncio_mod, &PyId_current_task);
2022 if (current_task_func == NULL) {
2023 return NULL;
2024 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002025
Yury Selivanov8d26aa92017-03-02 22:16:33 -05002026 if (loop == Py_None) {
Yury Selivanova70232f2017-12-13 14:49:42 -05002027 loop = get_event_loop();
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002028 if (loop == NULL) {
2029 return NULL;
2030 }
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002031 ret = PyObject_CallFunctionObjArgs(current_task_func, loop, NULL);
2032 Py_DECREF(current_task_func);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002033 Py_DECREF(loop);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002034 return ret;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002035 }
2036 else {
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002037 ret = PyObject_CallFunctionObjArgs(current_task_func, loop, NULL);
2038 Py_DECREF(current_task_func);
2039 return ret;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002040 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002041}
2042
2043/*[clinic input]
2044@classmethod
2045_asyncio.Task.all_tasks
2046
Serhiy Storchakabca49392017-09-03 08:10:14 +03002047 loop: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002048
2049Return a set of all tasks for an event loop.
2050
2051By default all tasks for the current event loop are returned.
2052[clinic start generated code]*/
2053
2054static PyObject *
2055_asyncio_Task_all_tasks_impl(PyTypeObject *type, PyObject *loop)
Serhiy Storchakabca49392017-09-03 08:10:14 +03002056/*[clinic end generated code: output=11f9b20749ccca5d input=497f80bc9ce726b5]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002057{
2058 PyObject *res;
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002059 PyObject *all_tasks_func;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002060
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002061 all_tasks_func = _PyObject_GetAttrId(asyncio_mod, &PyId_all_tasks);
2062 if (all_tasks_func == NULL) {
2063 return NULL;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002064 }
2065
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002066 if (PyErr_WarnEx(PyExc_PendingDeprecationWarning,
2067 "Task.all_tasks() is deprecated, " \
2068 "use asyncio.all_tasks() instead",
2069 1) < 0) {
2070 return NULL;
2071 }
2072
2073 res = PyObject_CallFunctionObjArgs(all_tasks_func, loop, NULL);
2074 Py_DECREF(all_tasks_func);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002075 return res;
2076}
2077
2078/*[clinic input]
2079_asyncio.Task._repr_info
2080[clinic start generated code]*/
2081
2082static PyObject *
2083_asyncio_Task__repr_info_impl(TaskObj *self)
2084/*[clinic end generated code: output=6a490eb66d5ba34b input=3c6d051ed3ddec8b]*/
2085{
Victor Stinnerde4ae3d2016-12-04 22:59:09 +01002086 return PyObject_CallFunctionObjArgs(
2087 asyncio_task_repr_info_func, self, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002088}
2089
2090/*[clinic input]
2091_asyncio.Task.cancel
2092
2093Request that this task cancel itself.
2094
2095This arranges for a CancelledError to be thrown into the
2096wrapped coroutine on the next cycle through the event loop.
2097The coroutine then has a chance to clean up or even deny
2098the request using try/except/finally.
2099
2100Unlike Future.cancel, this does not guarantee that the
2101task will be cancelled: the exception might be caught and
2102acted upon, delaying cancellation of the task or preventing
2103cancellation completely. The task may also return a value or
2104raise a different exception.
2105
2106Immediately after this method is called, Task.cancelled() will
2107not return True (unless the task was already cancelled). A
2108task will be marked as cancelled when the wrapped coroutine
2109terminates with a CancelledError exception (even if cancel()
2110was not called).
2111[clinic start generated code]*/
2112
2113static PyObject *
2114_asyncio_Task_cancel_impl(TaskObj *self)
2115/*[clinic end generated code: output=6bfc0479da9d5757 input=13f9bf496695cb52]*/
2116{
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +00002117 self->task_log_tb = 0;
2118
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002119 if (self->task_state != STATE_PENDING) {
2120 Py_RETURN_FALSE;
2121 }
2122
2123 if (self->task_fut_waiter) {
2124 PyObject *res;
2125 int is_true;
2126
2127 res = _PyObject_CallMethodId(
2128 self->task_fut_waiter, &PyId_cancel, NULL);
2129 if (res == NULL) {
2130 return NULL;
2131 }
2132
2133 is_true = PyObject_IsTrue(res);
2134 Py_DECREF(res);
2135 if (is_true < 0) {
2136 return NULL;
2137 }
2138
2139 if (is_true) {
2140 Py_RETURN_TRUE;
2141 }
2142 }
2143
2144 self->task_must_cancel = 1;
2145 Py_RETURN_TRUE;
2146}
2147
2148/*[clinic input]
2149_asyncio.Task.get_stack
2150
2151 *
Serhiy Storchakabca49392017-09-03 08:10:14 +03002152 limit: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002153
2154Return the list of stack frames for this task's coroutine.
2155
2156If the coroutine is not done, this returns the stack where it is
2157suspended. If the coroutine has completed successfully or was
2158cancelled, this returns an empty list. If the coroutine was
2159terminated by an exception, this returns the list of traceback
2160frames.
2161
2162The frames are always ordered from oldest to newest.
2163
2164The optional limit gives the maximum number of frames to
2165return; by default all available frames are returned. Its
2166meaning differs depending on whether a stack or a traceback is
2167returned: the newest frames of a stack are returned, but the
2168oldest frames of a traceback are returned. (This matches the
2169behavior of the traceback module.)
2170
2171For reasons beyond our control, only one stack frame is
2172returned for a suspended coroutine.
2173[clinic start generated code]*/
2174
2175static PyObject *
2176_asyncio_Task_get_stack_impl(TaskObj *self, PyObject *limit)
Serhiy Storchakabca49392017-09-03 08:10:14 +03002177/*[clinic end generated code: output=c9aeeeebd1e18118 input=05b323d42b809b90]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002178{
2179 return PyObject_CallFunctionObjArgs(
2180 asyncio_task_get_stack_func, self, limit, NULL);
2181}
2182
2183/*[clinic input]
2184_asyncio.Task.print_stack
2185
2186 *
Serhiy Storchakabca49392017-09-03 08:10:14 +03002187 limit: object = None
2188 file: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002189
2190Print the stack or traceback for this task's coroutine.
2191
2192This produces output similar to that of the traceback module,
2193for the frames retrieved by get_stack(). The limit argument
2194is passed to get_stack(). The file argument is an I/O stream
2195to which the output is written; by default output is written
2196to sys.stderr.
2197[clinic start generated code]*/
2198
2199static PyObject *
2200_asyncio_Task_print_stack_impl(TaskObj *self, PyObject *limit,
2201 PyObject *file)
Serhiy Storchakabca49392017-09-03 08:10:14 +03002202/*[clinic end generated code: output=7339e10314cd3f4d input=1a0352913b7fcd92]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002203{
2204 return PyObject_CallFunctionObjArgs(
2205 asyncio_task_print_stack_func, self, limit, file, NULL);
2206}
2207
2208/*[clinic input]
2209_asyncio.Task._step
2210
Serhiy Storchakabca49392017-09-03 08:10:14 +03002211 exc: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002212[clinic start generated code]*/
2213
2214static PyObject *
2215_asyncio_Task__step_impl(TaskObj *self, PyObject *exc)
Serhiy Storchakabca49392017-09-03 08:10:14 +03002216/*[clinic end generated code: output=7ed23f0cefd5ae42 input=1e19a985ace87ca4]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002217{
2218 return task_step(self, exc == Py_None ? NULL : exc);
2219}
2220
2221/*[clinic input]
2222_asyncio.Task._wakeup
2223
Serhiy Storchakabca49392017-09-03 08:10:14 +03002224 fut: object
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002225[clinic start generated code]*/
2226
2227static PyObject *
2228_asyncio_Task__wakeup_impl(TaskObj *self, PyObject *fut)
Serhiy Storchakabca49392017-09-03 08:10:14 +03002229/*[clinic end generated code: output=75cb341c760fd071 input=6a0616406f829a7b]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002230{
2231 return task_wakeup(self, fut);
2232}
2233
2234static void
2235TaskObj_finalize(TaskObj *task)
2236{
2237 _Py_IDENTIFIER(call_exception_handler);
2238 _Py_IDENTIFIER(task);
2239 _Py_IDENTIFIER(message);
2240 _Py_IDENTIFIER(source_traceback);
2241
Serhiy Storchakabca49392017-09-03 08:10:14 +03002242 PyObject *context;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002243 PyObject *message = NULL;
Serhiy Storchakabca49392017-09-03 08:10:14 +03002244 PyObject *func;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002245 PyObject *error_type, *error_value, *error_traceback;
2246
2247 if (task->task_state != STATE_PENDING || !task->task_log_destroy_pending) {
2248 goto done;
2249 }
2250
2251 /* Save the current exception, if any. */
2252 PyErr_Fetch(&error_type, &error_value, &error_traceback);
2253
2254 context = PyDict_New();
2255 if (context == NULL) {
2256 goto finally;
2257 }
2258
2259 message = PyUnicode_FromString("Task was destroyed but it is pending!");
2260 if (message == NULL) {
2261 goto finally;
2262 }
2263
2264 if (_PyDict_SetItemId(context, &PyId_message, message) < 0 ||
2265 _PyDict_SetItemId(context, &PyId_task, (PyObject*)task) < 0)
2266 {
2267 goto finally;
2268 }
2269
2270 if (task->task_source_tb != NULL) {
2271 if (_PyDict_SetItemId(context, &PyId_source_traceback,
2272 task->task_source_tb) < 0)
2273 {
2274 goto finally;
2275 }
2276 }
2277
2278 func = _PyObject_GetAttrId(task->task_loop, &PyId_call_exception_handler);
2279 if (func != NULL) {
Serhiy Storchakabca49392017-09-03 08:10:14 +03002280 PyObject *res = PyObject_CallFunctionObjArgs(func, context, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002281 if (res == NULL) {
2282 PyErr_WriteUnraisable(func);
2283 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03002284 else {
2285 Py_DECREF(res);
2286 }
2287 Py_DECREF(func);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002288 }
2289
2290finally:
Serhiy Storchakabca49392017-09-03 08:10:14 +03002291 Py_XDECREF(context);
2292 Py_XDECREF(message);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002293
2294 /* Restore the saved exception. */
2295 PyErr_Restore(error_type, error_value, error_traceback);
2296
2297done:
2298 FutureObj_finalize((FutureObj*)task);
2299}
2300
2301static void TaskObj_dealloc(PyObject *); /* Needs Task_CheckExact */
2302
2303static PyMethodDef TaskType_methods[] = {
2304 _ASYNCIO_FUTURE_RESULT_METHODDEF
2305 _ASYNCIO_FUTURE_EXCEPTION_METHODDEF
2306 _ASYNCIO_FUTURE_SET_RESULT_METHODDEF
2307 _ASYNCIO_FUTURE_SET_EXCEPTION_METHODDEF
2308 _ASYNCIO_FUTURE_ADD_DONE_CALLBACK_METHODDEF
2309 _ASYNCIO_FUTURE_REMOVE_DONE_CALLBACK_METHODDEF
2310 _ASYNCIO_FUTURE_CANCELLED_METHODDEF
2311 _ASYNCIO_FUTURE_DONE_METHODDEF
2312 _ASYNCIO_TASK_CURRENT_TASK_METHODDEF
2313 _ASYNCIO_TASK_ALL_TASKS_METHODDEF
2314 _ASYNCIO_TASK_CANCEL_METHODDEF
2315 _ASYNCIO_TASK_GET_STACK_METHODDEF
2316 _ASYNCIO_TASK_PRINT_STACK_METHODDEF
2317 _ASYNCIO_TASK__WAKEUP_METHODDEF
2318 _ASYNCIO_TASK__STEP_METHODDEF
2319 _ASYNCIO_TASK__REPR_INFO_METHODDEF
2320 {NULL, NULL} /* Sentinel */
2321};
2322
2323static PyGetSetDef TaskType_getsetlist[] = {
2324 FUTURE_COMMON_GETSETLIST
2325 {"_log_destroy_pending", (getter)TaskObj_get_log_destroy_pending,
2326 (setter)TaskObj_set_log_destroy_pending, NULL},
2327 {"_must_cancel", (getter)TaskObj_get_must_cancel, NULL, NULL},
2328 {"_coro", (getter)TaskObj_get_coro, NULL, NULL},
2329 {"_fut_waiter", (getter)TaskObj_get_fut_waiter, NULL, NULL},
2330 {NULL} /* Sentinel */
2331};
2332
2333static PyTypeObject TaskType = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02002334 PyVarObject_HEAD_INIT(NULL, 0)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002335 "_asyncio.Task",
2336 sizeof(TaskObj), /* tp_basicsize */
2337 .tp_base = &FutureType,
2338 .tp_dealloc = TaskObj_dealloc,
2339 .tp_as_async = &FutureType_as_async,
2340 .tp_repr = (reprfunc)FutureObj_repr,
2341 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE
2342 | Py_TPFLAGS_HAVE_FINALIZE,
2343 .tp_doc = _asyncio_Task___init____doc__,
2344 .tp_traverse = (traverseproc)TaskObj_traverse,
2345 .tp_clear = (inquiry)TaskObj_clear,
2346 .tp_weaklistoffset = offsetof(TaskObj, task_weakreflist),
2347 .tp_iter = (getiterfunc)future_new_iter,
2348 .tp_methods = TaskType_methods,
2349 .tp_getset = TaskType_getsetlist,
2350 .tp_dictoffset = offsetof(TaskObj, dict),
2351 .tp_init = (initproc)_asyncio_Task___init__,
2352 .tp_new = PyType_GenericNew,
2353 .tp_finalize = (destructor)TaskObj_finalize,
2354};
2355
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002356static void
2357TaskObj_dealloc(PyObject *self)
2358{
2359 TaskObj *task = (TaskObj *)self;
2360
2361 if (Task_CheckExact(self)) {
2362 /* When fut is subclass of Task, finalizer is called from
2363 * subtype_dealloc.
2364 */
2365 if (PyObject_CallFinalizerFromDealloc(self) < 0) {
2366 // resurrected.
2367 return;
2368 }
2369 }
2370
Alexander Mohrde34cbe2017-08-01 23:31:07 -07002371 PyObject_GC_UnTrack(self);
2372
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002373 if (task->task_weakreflist != NULL) {
2374 PyObject_ClearWeakRefs(self);
2375 }
2376
2377 (void)TaskObj_clear(task);
2378 Py_TYPE(task)->tp_free(task);
2379}
2380
2381static inline PyObject *
2382task_call_wakeup(TaskObj *task, PyObject *fut)
2383{
2384 if (Task_CheckExact(task)) {
2385 return task_wakeup(task, fut);
2386 }
2387 else {
2388 /* `task` is a subclass of Task */
Victor Stinnerb6ed57d2016-12-09 14:24:02 +01002389 return _PyObject_CallMethodIdObjArgs((PyObject*)task, &PyId__wakeup,
2390 fut, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002391 }
2392}
2393
2394static inline PyObject *
2395task_call_step(TaskObj *task, PyObject *arg)
2396{
2397 if (Task_CheckExact(task)) {
2398 return task_step(task, arg);
2399 }
2400 else {
2401 /* `task` is a subclass of Task */
Victor Stinnerb6ed57d2016-12-09 14:24:02 +01002402 return _PyObject_CallMethodIdObjArgs((PyObject*)task, &PyId__step,
2403 arg, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002404 }
2405}
2406
2407static int
2408task_call_step_soon(TaskObj *task, PyObject *arg)
2409{
Serhiy Storchakabca49392017-09-03 08:10:14 +03002410 PyObject *cb = TaskStepMethWrapper_new(task, arg);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002411 if (cb == NULL) {
2412 return -1;
2413 }
2414
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05002415 int ret = call_soon(task->task_loop, cb, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002416 Py_DECREF(cb);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05002417 return ret;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002418}
2419
2420static PyObject *
2421task_set_error_soon(TaskObj *task, PyObject *et, const char *format, ...)
2422{
2423 PyObject* msg;
2424
2425 va_list vargs;
2426#ifdef HAVE_STDARG_PROTOTYPES
2427 va_start(vargs, format);
2428#else
2429 va_start(vargs);
2430#endif
2431 msg = PyUnicode_FromFormatV(format, vargs);
2432 va_end(vargs);
2433
2434 if (msg == NULL) {
2435 return NULL;
2436 }
2437
Victor Stinnerde4ae3d2016-12-04 22:59:09 +01002438 PyObject *e = PyObject_CallFunctionObjArgs(et, msg, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002439 Py_DECREF(msg);
2440 if (e == NULL) {
2441 return NULL;
2442 }
2443
2444 if (task_call_step_soon(task, e) == -1) {
2445 Py_DECREF(e);
2446 return NULL;
2447 }
2448
2449 Py_DECREF(e);
2450 Py_RETURN_NONE;
2451}
2452
2453static PyObject *
2454task_step_impl(TaskObj *task, PyObject *exc)
2455{
2456 int res;
2457 int clear_exc = 0;
2458 PyObject *result = NULL;
Serhiy Storchakabca49392017-09-03 08:10:14 +03002459 PyObject *coro;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002460 PyObject *o;
2461
2462 if (task->task_state != STATE_PENDING) {
2463 PyErr_Format(PyExc_AssertionError,
2464 "_step(): already done: %R %R",
2465 task,
2466 exc ? exc : Py_None);
INADA Naokic411a7d2016-10-18 11:48:14 +09002467 goto fail;
2468 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09002469
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002470 if (task->task_must_cancel) {
2471 assert(exc != Py_None);
2472
2473 if (exc) {
2474 /* Check if exc is a CancelledError */
2475 res = PyObject_IsInstance(exc, asyncio_CancelledError);
2476 if (res == -1) {
2477 /* An error occurred, abort */
2478 goto fail;
2479 }
2480 if (res == 0) {
2481 /* exc is not CancelledError; reset it to NULL */
2482 exc = NULL;
2483 }
2484 }
2485
2486 if (!exc) {
2487 /* exc was not a CancelledError */
Victor Stinnerf17c3de2016-12-06 18:46:19 +01002488 exc = _PyObject_CallNoArg(asyncio_CancelledError);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002489 if (!exc) {
2490 goto fail;
2491 }
2492 clear_exc = 1;
2493 }
2494
2495 task->task_must_cancel = 0;
2496 }
2497
2498 Py_CLEAR(task->task_fut_waiter);
2499
Serhiy Storchakabca49392017-09-03 08:10:14 +03002500 coro = task->task_coro;
2501 if (coro == NULL) {
2502 PyErr_SetString(PyExc_RuntimeError, "uninitialized Task object");
2503 return NULL;
2504 }
2505
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002506 if (exc == NULL) {
2507 if (PyGen_CheckExact(coro) || PyCoro_CheckExact(coro)) {
2508 result = _PyGen_Send((PyGenObject*)coro, Py_None);
2509 }
2510 else {
Victor Stinnerb6ed57d2016-12-09 14:24:02 +01002511 result = _PyObject_CallMethodIdObjArgs(coro, &PyId_send,
2512 Py_None, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002513 }
2514 }
2515 else {
Victor Stinnerb6ed57d2016-12-09 14:24:02 +01002516 result = _PyObject_CallMethodIdObjArgs(coro, &PyId_throw,
2517 exc, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002518 if (clear_exc) {
2519 /* We created 'exc' during this call */
Serhiy Storchakabca49392017-09-03 08:10:14 +03002520 Py_DECREF(exc);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002521 }
2522 }
2523
2524 if (result == NULL) {
2525 PyObject *et, *ev, *tb;
2526
2527 if (_PyGen_FetchStopIterationValue(&o) == 0) {
2528 /* The error is StopIteration and that means that
2529 the underlying coroutine has resolved */
INADA Naoki991adca2017-05-11 21:18:38 +09002530 if (task->task_must_cancel) {
2531 // Task is cancelled right before coro stops.
2532 Py_DECREF(o);
2533 task->task_must_cancel = 0;
2534 et = asyncio_CancelledError;
2535 Py_INCREF(et);
2536 ev = NULL;
2537 tb = NULL;
2538 goto set_exception;
2539 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002540 PyObject *res = future_set_result((FutureObj*)task, o);
2541 Py_DECREF(o);
2542 if (res == NULL) {
2543 return NULL;
2544 }
2545 Py_DECREF(res);
2546 Py_RETURN_NONE;
2547 }
2548
2549 if (PyErr_ExceptionMatches(asyncio_CancelledError)) {
2550 /* CancelledError */
2551 PyErr_Clear();
2552 return future_cancel((FutureObj*)task);
2553 }
2554
2555 /* Some other exception; pop it and call Task.set_exception() */
2556 PyErr_Fetch(&et, &ev, &tb);
INADA Naoki991adca2017-05-11 21:18:38 +09002557
2558set_exception:
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002559 assert(et);
2560 if (!ev || !PyObject_TypeCheck(ev, (PyTypeObject *) et)) {
2561 PyErr_NormalizeException(&et, &ev, &tb);
2562 }
Yury Selivanovedfe8862016-12-01 11:37:47 -05002563 if (tb != NULL) {
2564 PyException_SetTraceback(ev, tb);
2565 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002566 o = future_set_exception((FutureObj*)task, ev);
2567 if (!o) {
2568 /* An exception in Task.set_exception() */
Serhiy Storchakabca49392017-09-03 08:10:14 +03002569 Py_DECREF(et);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002570 Py_XDECREF(tb);
2571 Py_XDECREF(ev);
2572 goto fail;
2573 }
2574 assert(o == Py_None);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002575 Py_DECREF(o);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002576
2577 if (!PyErr_GivenExceptionMatches(et, PyExc_Exception)) {
2578 /* We've got a BaseException; re-raise it */
2579 PyErr_Restore(et, ev, tb);
2580 goto fail;
2581 }
2582
Serhiy Storchakabca49392017-09-03 08:10:14 +03002583 Py_DECREF(et);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002584 Py_XDECREF(tb);
2585 Py_XDECREF(ev);
2586
2587 Py_RETURN_NONE;
2588 }
2589
2590 if (result == (PyObject*)task) {
2591 /* We have a task that wants to await on itself */
2592 goto self_await;
2593 }
2594
2595 /* Check if `result` is FutureObj or TaskObj (and not a subclass) */
2596 if (Future_CheckExact(result) || Task_CheckExact(result)) {
2597 PyObject *wrapper;
2598 PyObject *res;
2599 FutureObj *fut = (FutureObj*)result;
2600
2601 /* Check if `result` future is attached to a different loop */
2602 if (fut->fut_loop != task->task_loop) {
2603 goto different_loop;
2604 }
2605
2606 if (fut->fut_blocking) {
2607 fut->fut_blocking = 0;
2608
2609 /* result.add_done_callback(task._wakeup) */
2610 wrapper = TaskWakeupMethWrapper_new(task);
2611 if (wrapper == NULL) {
2612 goto fail;
2613 }
2614 res = future_add_done_callback((FutureObj*)result, wrapper);
2615 Py_DECREF(wrapper);
2616 if (res == NULL) {
2617 goto fail;
2618 }
2619 Py_DECREF(res);
2620
2621 /* task._fut_waiter = result */
2622 task->task_fut_waiter = result; /* no incref is necessary */
2623
2624 if (task->task_must_cancel) {
2625 PyObject *r;
2626 r = future_cancel(fut);
2627 if (r == NULL) {
2628 return NULL;
2629 }
2630 if (r == Py_True) {
2631 task->task_must_cancel = 0;
2632 }
2633 Py_DECREF(r);
2634 }
2635
2636 Py_RETURN_NONE;
2637 }
2638 else {
2639 goto yield_insteadof_yf;
2640 }
2641 }
2642
2643 /* Check if `result` is a Future-compatible object */
2644 o = PyObject_GetAttrString(result, "_asyncio_future_blocking");
2645 if (o == NULL) {
2646 if (PyErr_ExceptionMatches(PyExc_AttributeError)) {
2647 PyErr_Clear();
2648 }
2649 else {
2650 goto fail;
2651 }
2652 }
2653 else {
2654 if (o == Py_None) {
Serhiy Storchakabca49392017-09-03 08:10:14 +03002655 Py_DECREF(o);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002656 }
2657 else {
2658 /* `result` is a Future-compatible object */
2659 PyObject *wrapper;
2660 PyObject *res;
2661
2662 int blocking = PyObject_IsTrue(o);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002663 Py_DECREF(o);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002664 if (blocking < 0) {
2665 goto fail;
2666 }
2667
2668 /* Check if `result` future is attached to a different loop */
Yury Selivanovca9b36c2017-12-23 15:04:15 -05002669 PyObject *oloop = get_future_loop(result);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002670 if (oloop == NULL) {
2671 goto fail;
2672 }
2673 if (oloop != task->task_loop) {
2674 Py_DECREF(oloop);
2675 goto different_loop;
2676 }
2677 else {
2678 Py_DECREF(oloop);
2679 }
2680
2681 if (blocking) {
2682 /* result._asyncio_future_blocking = False */
2683 if (PyObject_SetAttrString(
2684 result, "_asyncio_future_blocking", Py_False) == -1) {
2685 goto fail;
2686 }
2687
2688 /* result.add_done_callback(task._wakeup) */
2689 wrapper = TaskWakeupMethWrapper_new(task);
2690 if (wrapper == NULL) {
2691 goto fail;
2692 }
Victor Stinnerb6ed57d2016-12-09 14:24:02 +01002693 res = _PyObject_CallMethodIdObjArgs(result,
2694 &PyId_add_done_callback,
2695 wrapper, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002696 Py_DECREF(wrapper);
2697 if (res == NULL) {
2698 goto fail;
2699 }
2700 Py_DECREF(res);
2701
2702 /* task._fut_waiter = result */
2703 task->task_fut_waiter = result; /* no incref is necessary */
2704
2705 if (task->task_must_cancel) {
2706 PyObject *r;
2707 int is_true;
2708 r = _PyObject_CallMethodId(result, &PyId_cancel, NULL);
2709 if (r == NULL) {
2710 return NULL;
2711 }
2712 is_true = PyObject_IsTrue(r);
2713 Py_DECREF(r);
2714 if (is_true < 0) {
2715 return NULL;
2716 }
2717 else if (is_true) {
2718 task->task_must_cancel = 0;
2719 }
2720 }
2721
2722 Py_RETURN_NONE;
2723 }
2724 else {
2725 goto yield_insteadof_yf;
2726 }
2727 }
2728 }
2729
2730 /* Check if `result` is None */
2731 if (result == Py_None) {
2732 /* Bare yield relinquishes control for one event loop iteration. */
2733 if (task_call_step_soon(task, NULL)) {
2734 goto fail;
2735 }
2736 return result;
2737 }
2738
2739 /* Check if `result` is a generator */
Victor Stinnerde4ae3d2016-12-04 22:59:09 +01002740 o = PyObject_CallFunctionObjArgs(inspect_isgenerator, result, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002741 if (o == NULL) {
2742 /* An exception in inspect.isgenerator */
2743 goto fail;
2744 }
2745 res = PyObject_IsTrue(o);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002746 Py_DECREF(o);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002747 if (res == -1) {
2748 /* An exception while checking if 'val' is True */
2749 goto fail;
2750 }
2751 if (res == 1) {
2752 /* `result` is a generator */
2753 PyObject *ret;
2754 ret = task_set_error_soon(
2755 task, PyExc_RuntimeError,
2756 "yield was used instead of yield from for "
2757 "generator in task %R with %S", task, result);
2758 Py_DECREF(result);
2759 return ret;
2760 }
2761
2762 /* The `result` is none of the above */
2763 Py_DECREF(result);
2764 return task_set_error_soon(
2765 task, PyExc_RuntimeError, "Task got bad yield: %R", result);
2766
2767self_await:
2768 o = task_set_error_soon(
2769 task, PyExc_RuntimeError,
2770 "Task cannot await on itself: %R", task);
2771 Py_DECREF(result);
2772 return o;
2773
2774yield_insteadof_yf:
2775 o = task_set_error_soon(
2776 task, PyExc_RuntimeError,
2777 "yield was used instead of yield from "
2778 "in task %R with %R",
2779 task, result);
2780 Py_DECREF(result);
2781 return o;
2782
2783different_loop:
2784 o = task_set_error_soon(
2785 task, PyExc_RuntimeError,
2786 "Task %R got Future %R attached to a different loop",
2787 task, result);
2788 Py_DECREF(result);
2789 return o;
2790
2791fail:
2792 Py_XDECREF(result);
2793 return NULL;
2794}
2795
2796static PyObject *
2797task_step(TaskObj *task, PyObject *exc)
2798{
2799 PyObject *res;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002800
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002801 if (enter_task(task->task_loop, (PyObject*)task) < 0) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002802 return NULL;
2803 }
2804
2805 res = task_step_impl(task, exc);
2806
2807 if (res == NULL) {
2808 PyObject *et, *ev, *tb;
2809 PyErr_Fetch(&et, &ev, &tb);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002810 leave_task(task->task_loop, (PyObject*)task);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002811 _PyErr_ChainExceptions(et, ev, tb);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002812 return NULL;
2813 }
2814 else {
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002815 if(leave_task(task->task_loop, (PyObject*)task) < 0) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002816 Py_DECREF(res);
2817 return NULL;
2818 }
2819 else {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002820 return res;
2821 }
2822 }
2823}
2824
2825static PyObject *
2826task_wakeup(TaskObj *task, PyObject *o)
2827{
Serhiy Storchakabca49392017-09-03 08:10:14 +03002828 PyObject *et, *ev, *tb;
2829 PyObject *result;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002830 assert(o);
2831
2832 if (Future_CheckExact(o) || Task_CheckExact(o)) {
2833 PyObject *fut_result = NULL;
2834 int res = future_get_result((FutureObj*)o, &fut_result);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002835
2836 switch(res) {
2837 case -1:
2838 assert(fut_result == NULL);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002839 break; /* exception raised */
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002840 case 0:
2841 Py_DECREF(fut_result);
2842 return task_call_step(task, NULL);
2843 default:
2844 assert(res == 1);
2845 result = task_call_step(task, fut_result);
2846 Py_DECREF(fut_result);
2847 return result;
2848 }
2849 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002850 else {
Serhiy Storchakabca49392017-09-03 08:10:14 +03002851 PyObject *fut_result = PyObject_CallMethod(o, "result", NULL);
2852 if (fut_result != NULL) {
2853 Py_DECREF(fut_result);
2854 return task_call_step(task, NULL);
2855 }
2856 /* exception raised */
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002857 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03002858
2859 PyErr_Fetch(&et, &ev, &tb);
2860 if (!PyErr_GivenExceptionMatches(et, PyExc_Exception)) {
2861 /* We've got a BaseException; re-raise it */
2862 PyErr_Restore(et, ev, tb);
2863 return NULL;
2864 }
2865 if (!ev || !PyObject_TypeCheck(ev, (PyTypeObject *) et)) {
2866 PyErr_NormalizeException(&et, &ev, &tb);
2867 }
2868
2869 result = task_call_step(task, ev);
2870
2871 Py_DECREF(et);
2872 Py_XDECREF(tb);
2873 Py_XDECREF(ev);
2874
2875 return result;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002876}
2877
2878
Yury Selivanova70232f2017-12-13 14:49:42 -05002879/*********************** Functions **************************/
2880
2881
2882/*[clinic input]
2883_asyncio._get_running_loop
2884
2885Return the running event loop or None.
2886
2887This is a low-level function intended to be used by event loops.
2888This function is thread-specific.
2889
2890[clinic start generated code]*/
2891
2892static PyObject *
2893_asyncio__get_running_loop_impl(PyObject *module)
2894/*[clinic end generated code: output=b4390af721411a0a input=0a21627e25a4bd43]*/
2895{
2896 PyObject *loop;
2897 if (get_running_loop(&loop)) {
2898 return NULL;
2899 }
2900 if (loop == NULL) {
2901 /* There's no currently running event loop */
2902 Py_RETURN_NONE;
2903 }
2904 return loop;
2905}
2906
2907/*[clinic input]
2908_asyncio._set_running_loop
2909 loop: 'O'
2910 /
2911
2912Set the running event loop.
2913
2914This is a low-level function intended to be used by event loops.
2915This function is thread-specific.
2916[clinic start generated code]*/
2917
2918static PyObject *
2919_asyncio__set_running_loop(PyObject *module, PyObject *loop)
2920/*[clinic end generated code: output=ae56bf7a28ca189a input=4c9720233d606604]*/
2921{
2922 if (set_running_loop(loop)) {
2923 return NULL;
2924 }
2925 Py_RETURN_NONE;
2926}
2927
2928/*[clinic input]
2929_asyncio.get_event_loop
2930
2931Return an asyncio event loop.
2932
2933When called from a coroutine or a callback (e.g. scheduled with
2934call_soon or similar API), this function will always return the
2935running event loop.
2936
2937If there is no running event loop set, the function will return
2938the result of `get_event_loop_policy().get_event_loop()` call.
2939[clinic start generated code]*/
2940
2941static PyObject *
2942_asyncio_get_event_loop_impl(PyObject *module)
2943/*[clinic end generated code: output=2a2d8b2f824c648b input=9364bf2916c8655d]*/
2944{
2945 return get_event_loop();
2946}
2947
2948/*[clinic input]
2949_asyncio.get_running_loop
2950
2951Return the running event loop. Raise a RuntimeError if there is none.
2952
2953This function is thread-specific.
2954[clinic start generated code]*/
2955
2956static PyObject *
2957_asyncio_get_running_loop_impl(PyObject *module)
2958/*[clinic end generated code: output=c247b5f9e529530e input=2a3bf02ba39f173d]*/
2959{
2960 PyObject *loop;
2961 if (get_running_loop(&loop)) {
2962 return NULL;
2963 }
2964 if (loop == NULL) {
2965 /* There's no currently running event loop */
2966 PyErr_SetString(
2967 PyExc_RuntimeError, "no running event loop");
2968 }
2969 return loop;
2970}
2971
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002972/*[clinic input]
2973_asyncio._register_task
2974
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002975 task: object
2976
2977Register a new task in asyncio as executed by loop.
2978
2979Returns None.
2980[clinic start generated code]*/
2981
2982static PyObject *
Yury Selivanovca9b36c2017-12-23 15:04:15 -05002983_asyncio__register_task_impl(PyObject *module, PyObject *task)
2984/*[clinic end generated code: output=8672dadd69a7d4e2 input=21075aaea14dfbad]*/
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002985{
Yury Selivanovca9b36c2017-12-23 15:04:15 -05002986 if (register_task(task) < 0) {
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002987 return NULL;
2988 }
2989 Py_RETURN_NONE;
2990}
2991
2992
2993/*[clinic input]
2994_asyncio._unregister_task
2995
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002996 task: object
2997
2998Unregister a task.
2999
3000Returns None.
3001[clinic start generated code]*/
3002
3003static PyObject *
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003004_asyncio__unregister_task_impl(PyObject *module, PyObject *task)
3005/*[clinic end generated code: output=6e5585706d568a46 input=28fb98c3975f7bdc]*/
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003006{
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003007 if (unregister_task(task) < 0) {
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003008 return NULL;
3009 }
3010 Py_RETURN_NONE;
3011}
3012
3013
3014/*[clinic input]
3015_asyncio._enter_task
3016
3017 loop: object
3018 task: object
3019
3020Enter into task execution or resume suspended task.
3021
3022Task belongs to loop.
3023
3024Returns None.
3025[clinic start generated code]*/
3026
3027static PyObject *
3028_asyncio__enter_task_impl(PyObject *module, PyObject *loop, PyObject *task)
3029/*[clinic end generated code: output=a22611c858035b73 input=de1b06dca70d8737]*/
3030{
3031 if (enter_task(loop, task) < 0) {
3032 return NULL;
3033 }
3034 Py_RETURN_NONE;
3035}
3036
3037
3038/*[clinic input]
3039_asyncio._leave_task
3040
3041 loop: object
3042 task: object
3043
3044Leave task execution or suspend a task.
3045
3046Task belongs to loop.
3047
3048Returns None.
3049[clinic start generated code]*/
3050
3051static PyObject *
3052_asyncio__leave_task_impl(PyObject *module, PyObject *loop, PyObject *task)
3053/*[clinic end generated code: output=0ebf6db4b858fb41 input=51296a46313d1ad8]*/
3054{
3055 if (leave_task(loop, task) < 0) {
3056 return NULL;
3057 }
3058 Py_RETURN_NONE;
3059}
3060
Yury Selivanova70232f2017-12-13 14:49:42 -05003061
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003062/*********************** Module **************************/
3063
3064
3065static void
Zackery Spytze40ad792017-12-19 11:48:13 -07003066module_free_freelists(void)
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05003067{
3068 PyObject *next;
3069 PyObject *current;
3070
3071 next = (PyObject*) fi_freelist;
3072 while (next != NULL) {
3073 assert(fi_freelist_len > 0);
3074 fi_freelist_len--;
3075
3076 current = next;
3077 next = (PyObject*) ((futureiterobject*) current)->future;
3078 PyObject_GC_Del(current);
3079 }
3080 assert(fi_freelist_len == 0);
3081 fi_freelist = NULL;
3082}
3083
3084
3085static void
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003086module_free(void *m)
3087{
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003088 Py_CLEAR(asyncio_mod);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003089 Py_CLEAR(inspect_isgenerator);
Yury Selivanova70232f2017-12-13 14:49:42 -05003090 Py_CLEAR(os_getpid);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003091 Py_CLEAR(traceback_extract_stack);
3092 Py_CLEAR(asyncio_future_repr_info_func);
3093 Py_CLEAR(asyncio_get_event_loop_policy);
3094 Py_CLEAR(asyncio_iscoroutine_func);
3095 Py_CLEAR(asyncio_task_get_stack_func);
3096 Py_CLEAR(asyncio_task_print_stack_func);
3097 Py_CLEAR(asyncio_task_repr_info_func);
3098 Py_CLEAR(asyncio_InvalidStateError);
3099 Py_CLEAR(asyncio_CancelledError);
3100
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003101 Py_CLEAR(all_tasks);
Yury Selivanova9d7e552017-12-19 07:18:45 -05003102 Py_CLEAR(current_tasks);
3103 Py_CLEAR(iscoroutine_typecache);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05003104
3105 module_free_freelists();
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003106}
3107
3108static int
3109module_init(void)
3110{
3111 PyObject *module = NULL;
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003112
3113 asyncio_mod = PyImport_ImportModule("asyncio");
3114 if (asyncio_mod == NULL) {
3115 goto fail;
3116 }
3117
3118 current_tasks = PyDict_New();
3119 if (current_tasks == NULL) {
3120 goto fail;
3121 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003122
Yury Selivanova9d7e552017-12-19 07:18:45 -05003123 iscoroutine_typecache = PySet_New(NULL);
3124 if (iscoroutine_typecache == NULL) {
3125 goto fail;
3126 }
3127
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003128#define WITH_MOD(NAME) \
3129 Py_CLEAR(module); \
3130 module = PyImport_ImportModule(NAME); \
3131 if (module == NULL) { \
Serhiy Storchakabca49392017-09-03 08:10:14 +03003132 goto fail; \
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003133 }
3134
3135#define GET_MOD_ATTR(VAR, NAME) \
3136 VAR = PyObject_GetAttrString(module, NAME); \
3137 if (VAR == NULL) { \
3138 goto fail; \
3139 }
3140
3141 WITH_MOD("asyncio.events")
Yury Selivanova70232f2017-12-13 14:49:42 -05003142 GET_MOD_ATTR(asyncio_get_event_loop_policy, "get_event_loop_policy")
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003143
3144 WITH_MOD("asyncio.base_futures")
3145 GET_MOD_ATTR(asyncio_future_repr_info_func, "_future_repr_info")
3146 GET_MOD_ATTR(asyncio_InvalidStateError, "InvalidStateError")
3147 GET_MOD_ATTR(asyncio_CancelledError, "CancelledError")
3148
3149 WITH_MOD("asyncio.base_tasks")
3150 GET_MOD_ATTR(asyncio_task_repr_info_func, "_task_repr_info")
3151 GET_MOD_ATTR(asyncio_task_get_stack_func, "_task_get_stack")
3152 GET_MOD_ATTR(asyncio_task_print_stack_func, "_task_print_stack")
3153
Andrew Svetlovf74ef452017-12-15 07:04:38 +02003154 WITH_MOD("asyncio.coroutines")
3155 GET_MOD_ATTR(asyncio_iscoroutine_func, "iscoroutine")
3156
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003157 WITH_MOD("inspect")
3158 GET_MOD_ATTR(inspect_isgenerator, "isgenerator")
3159
Yury Selivanova70232f2017-12-13 14:49:42 -05003160 WITH_MOD("os")
3161 GET_MOD_ATTR(os_getpid, "getpid")
3162
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003163 WITH_MOD("traceback")
3164 GET_MOD_ATTR(traceback_extract_stack, "extract_stack")
3165
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003166 PyObject *weak_set;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003167 WITH_MOD("weakref")
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003168 GET_MOD_ATTR(weak_set, "WeakSet");
3169 all_tasks = _PyObject_CallNoArg(weak_set);
3170 Py_CLEAR(weak_set);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003171 if (all_tasks == NULL) {
INADA Naokic411a7d2016-10-18 11:48:14 +09003172 goto fail;
3173 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003174
Serhiy Storchakabca49392017-09-03 08:10:14 +03003175 Py_DECREF(module);
INADA Naokic411a7d2016-10-18 11:48:14 +09003176 return 0;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003177
INADA Naokic411a7d2016-10-18 11:48:14 +09003178fail:
INADA Naokic411a7d2016-10-18 11:48:14 +09003179 Py_CLEAR(module);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003180 module_free(NULL);
INADA Naokic411a7d2016-10-18 11:48:14 +09003181 return -1;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003182
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003183#undef WITH_MOD
3184#undef GET_MOD_ATTR
3185}
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003186
INADA Naokic411a7d2016-10-18 11:48:14 +09003187PyDoc_STRVAR(module_doc, "Accelerator module for asyncio");
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003188
Yury Selivanova70232f2017-12-13 14:49:42 -05003189static PyMethodDef asyncio_methods[] = {
3190 _ASYNCIO_GET_EVENT_LOOP_METHODDEF
3191 _ASYNCIO_GET_RUNNING_LOOP_METHODDEF
3192 _ASYNCIO__GET_RUNNING_LOOP_METHODDEF
3193 _ASYNCIO__SET_RUNNING_LOOP_METHODDEF
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003194 _ASYNCIO__REGISTER_TASK_METHODDEF
3195 _ASYNCIO__UNREGISTER_TASK_METHODDEF
3196 _ASYNCIO__ENTER_TASK_METHODDEF
3197 _ASYNCIO__LEAVE_TASK_METHODDEF
Yury Selivanova70232f2017-12-13 14:49:42 -05003198 {NULL, NULL}
3199};
3200
INADA Naoki9f2ce252016-10-15 15:39:19 +09003201static struct PyModuleDef _asynciomodule = {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003202 PyModuleDef_HEAD_INIT, /* m_base */
INADA Naoki9f2ce252016-10-15 15:39:19 +09003203 "_asyncio", /* m_name */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003204 module_doc, /* m_doc */
3205 -1, /* m_size */
Yury Selivanova70232f2017-12-13 14:49:42 -05003206 asyncio_methods, /* m_methods */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003207 NULL, /* m_slots */
3208 NULL, /* m_traverse */
3209 NULL, /* m_clear */
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003210 (freefunc)module_free /* m_free */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003211};
3212
3213
3214PyMODINIT_FUNC
INADA Naoki9f2ce252016-10-15 15:39:19 +09003215PyInit__asyncio(void)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003216{
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003217 if (module_init() < 0) {
INADA Naokic411a7d2016-10-18 11:48:14 +09003218 return NULL;
3219 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003220 if (PyType_Ready(&FutureType) < 0) {
3221 return NULL;
3222 }
3223 if (PyType_Ready(&FutureIterType) < 0) {
3224 return NULL;
3225 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03003226 if (PyType_Ready(&TaskStepMethWrapper_Type) < 0) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003227 return NULL;
3228 }
3229 if(PyType_Ready(&TaskWakeupMethWrapper_Type) < 0) {
3230 return NULL;
3231 }
3232 if (PyType_Ready(&TaskType) < 0) {
3233 return NULL;
3234 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003235
INADA Naoki9f2ce252016-10-15 15:39:19 +09003236 PyObject *m = PyModule_Create(&_asynciomodule);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003237 if (m == NULL) {
3238 return NULL;
3239 }
3240
3241 Py_INCREF(&FutureType);
3242 if (PyModule_AddObject(m, "Future", (PyObject *)&FutureType) < 0) {
3243 Py_DECREF(&FutureType);
3244 return NULL;
3245 }
3246
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003247 Py_INCREF(&TaskType);
3248 if (PyModule_AddObject(m, "Task", (PyObject *)&TaskType) < 0) {
3249 Py_DECREF(&TaskType);
3250 return NULL;
3251 }
3252
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003253 Py_INCREF(all_tasks);
3254 if (PyModule_AddObject(m, "_all_tasks", all_tasks) < 0) {
3255 Py_DECREF(all_tasks);
3256 return NULL;
3257 }
3258
3259 Py_INCREF(current_tasks);
3260 if (PyModule_AddObject(m, "_current_tasks", current_tasks) < 0) {
3261 Py_DECREF(current_tasks);
3262 return NULL;
3263 }
3264
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003265 return m;
3266}