blob: 5030a40b873719e5b245a0091070d462a7230c1c [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);
Andrew Svetlov44d1a592017-12-16 21:58:38 +020019_Py_IDENTIFIER(pop);
Yury Selivanova0c1ba62016-10-28 12:52:37 -040020_Py_IDENTIFIER(send);
21_Py_IDENTIFIER(throw);
22_Py_IDENTIFIER(_step);
23_Py_IDENTIFIER(_schedule_callbacks);
24_Py_IDENTIFIER(_wakeup);
INADA Naoki9e4e38e2016-10-09 14:44:47 +090025
26
INADA Naoki9f2ce252016-10-15 15:39:19 +090027/* State of the _asyncio module */
Andrew Svetlov44d1a592017-12-16 21:58:38 +020028static PyObject *asyncio_mod;
Yury Selivanova0c1ba62016-10-28 12:52:37 -040029static PyObject *inspect_isgenerator;
Yury Selivanova70232f2017-12-13 14:49:42 -050030static PyObject *os_getpid;
Andrew Svetlov44d1a592017-12-16 21:58:38 +020031static PyObject *traceback_extract_stack;
32static PyObject *asyncio_get_event_loop_policy;
33static PyObject *asyncio_future_repr_info_func;
34static PyObject *asyncio_iscoroutine_func;
35static PyObject *asyncio_task_get_stack_func;
36static PyObject *asyncio_task_print_stack_func;
37static PyObject *asyncio_task_repr_info_func;
38static PyObject *asyncio_InvalidStateError;
39static PyObject *asyncio_CancelledError;
40
41
42/* WeakKeyDictionary of {Task: EventLoop} containing all tasks alive.
43 Task should be a weak reference to remove entry on task garbage
44 collection, EventLoop is required
45 to not access to private task._loop attribute. */
46static PyObject *current_tasks;
47
48/* Dictionary containing tasks that are currently active in
49 all running event loops. {EventLoop: Task} */
50static PyObject *all_tasks;
INADA Naoki9e4e38e2016-10-09 14:44:47 +090051
52
INADA Naoki9e4e38e2016-10-09 14:44:47 +090053typedef enum {
54 STATE_PENDING,
55 STATE_CANCELLED,
56 STATE_FINISHED
57} fut_state;
58
Yury Selivanova0c1ba62016-10-28 12:52:37 -040059#define FutureObj_HEAD(prefix) \
60 PyObject_HEAD \
61 PyObject *prefix##_loop; \
Yury Selivanov1b7c11f2017-12-17 20:19:47 -050062 PyObject *prefix##_callback0; \
Yury Selivanova0c1ba62016-10-28 12:52:37 -040063 PyObject *prefix##_callbacks; \
64 PyObject *prefix##_exception; \
65 PyObject *prefix##_result; \
66 PyObject *prefix##_source_tb; \
67 fut_state prefix##_state; \
68 int prefix##_log_tb; \
69 int prefix##_blocking; \
70 PyObject *dict; \
71 PyObject *prefix##_weakreflist;
72
73typedef struct {
74 FutureObj_HEAD(fut)
75} FutureObj;
76
77typedef struct {
78 FutureObj_HEAD(task)
79 PyObject *task_fut_waiter;
80 PyObject *task_coro;
81 int task_must_cancel;
82 int task_log_destroy_pending;
83} TaskObj;
INADA Naoki9e4e38e2016-10-09 14:44:47 +090084
85typedef struct {
86 PyObject_HEAD
Yury Selivanova0c1ba62016-10-28 12:52:37 -040087 TaskObj *sw_task;
88 PyObject *sw_arg;
Serhiy Storchakabca49392017-09-03 08:10:14 +030089} TaskStepMethWrapper;
INADA Naoki9e4e38e2016-10-09 14:44:47 +090090
Yury Selivanova0c1ba62016-10-28 12:52:37 -040091typedef struct {
92 PyObject_HEAD
93 TaskObj *ww_task;
94} TaskWakeupMethWrapper;
95
96
Yury Selivanov1b7c11f2017-12-17 20:19:47 -050097static PyTypeObject FutureType;
98static PyTypeObject TaskType;
99
100
101#define Future_CheckExact(obj) (Py_TYPE(obj) == &FutureType)
102#define Task_CheckExact(obj) (Py_TYPE(obj) == &TaskType)
103
104#define Future_Check(obj) PyObject_TypeCheck(obj, &FutureType)
105#define Task_Check(obj) PyObject_TypeCheck(obj, &TaskType)
106
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400107#include "clinic/_asynciomodule.c.h"
108
109
110/*[clinic input]
111class _asyncio.Future "FutureObj *" "&Future_Type"
112[clinic start generated code]*/
113/*[clinic end generated code: output=da39a3ee5e6b4b0d input=00d3e4abca711e0f]*/
114
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500115
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400116/* Get FutureIter from Future */
117static PyObject* future_new_iter(PyObject *);
118static inline int future_call_schedule_callbacks(FutureObj *);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900119
Yury Selivanova70232f2017-12-13 14:49:42 -0500120
121static int
122get_running_loop(PyObject **loop)
123{
124 PyObject *ts_dict;
125 PyObject *running_tuple;
126 PyObject *running_loop;
127 PyObject *running_loop_pid;
128 PyObject *current_pid;
129 int same_pid;
130
131 ts_dict = PyThreadState_GetDict(); // borrowed
132 if (ts_dict == NULL) {
133 PyErr_SetString(
134 PyExc_RuntimeError, "thread-local storage is not available");
135 goto error;
136 }
137
138 running_tuple = _PyDict_GetItemId(
139 ts_dict, &PyId___asyncio_running_event_loop__); // borrowed
140 if (running_tuple == NULL) {
141 /* _PyDict_GetItemId doesn't set an error if key is not found */
142 goto not_found;
143 }
144
145 assert(PyTuple_CheckExact(running_tuple));
146 assert(PyTuple_Size(running_tuple) == 2);
147 running_loop = PyTuple_GET_ITEM(running_tuple, 0); // borrowed
148 running_loop_pid = PyTuple_GET_ITEM(running_tuple, 1); // borrowed
149
150 if (running_loop == Py_None) {
151 goto not_found;
152 }
153
154 current_pid = _PyObject_CallNoArg(os_getpid);
155 if (current_pid == NULL) {
156 goto error;
157 }
158 same_pid = PyObject_RichCompareBool(current_pid, running_loop_pid, Py_EQ);
159 Py_DECREF(current_pid);
160 if (same_pid == -1) {
161 goto error;
162 }
163
164 if (same_pid) {
165 // current_pid == running_loop_pid
166 goto found;
167 }
168
169not_found:
170 *loop = NULL;
171 return 0;
172
173found:
174 Py_INCREF(running_loop);
175 *loop = running_loop;
176 return 0;
177
178error:
179 *loop = NULL;
180 return -1;
181}
182
183
184static int
185set_running_loop(PyObject *loop)
186{
187 PyObject *ts_dict;
188 PyObject *running_tuple;
189 PyObject *current_pid;
190
191 ts_dict = PyThreadState_GetDict(); // borrowed
192 if (ts_dict == NULL) {
193 PyErr_SetString(
194 PyExc_RuntimeError, "thread-local storage is not available");
195 return -1;
196 }
197
198 current_pid = _PyObject_CallNoArg(os_getpid);
199 if (current_pid == NULL) {
200 return -1;
201 }
202
203 running_tuple = PyTuple_New(2);
204 if (running_tuple == NULL) {
205 Py_DECREF(current_pid);
206 return -1;
207 }
208
209 Py_INCREF(loop);
210 PyTuple_SET_ITEM(running_tuple, 0, loop);
211 PyTuple_SET_ITEM(running_tuple, 1, current_pid); // borrowed
212
213 if (_PyDict_SetItemId(
214 ts_dict, &PyId___asyncio_running_event_loop__, running_tuple)) {
215 Py_DECREF(running_tuple); // will cleanup loop & current_pid
216 return -1;
217 }
218 Py_DECREF(running_tuple);
219
220 return 0;
221}
222
223
224static PyObject *
225get_event_loop(void)
226{
227 PyObject *loop;
228 PyObject *policy;
229
230 if (get_running_loop(&loop)) {
231 return NULL;
232 }
233 if (loop != NULL) {
234 return loop;
235 }
236
237 policy = _PyObject_CallNoArg(asyncio_get_event_loop_policy);
238 if (policy == NULL) {
239 return NULL;
240 }
241
242 loop = _PyObject_CallMethodId(policy, &PyId_get_event_loop, NULL);
243 Py_DECREF(policy);
244 return loop;
245}
246
247
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900248static int
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500249call_soon(PyObject *loop, PyObject *func, PyObject *arg)
250{
251 PyObject *handle;
252 handle = _PyObject_CallMethodIdObjArgs(
253 loop, &PyId_call_soon, func, arg, NULL);
254 if (handle == NULL) {
255 return -1;
256 }
257 Py_DECREF(handle);
258 return 0;
259}
260
261
262static inline int
263future_is_alive(FutureObj *fut)
264{
265 return fut->fut_loop != NULL;
266}
267
268
269static inline int
270future_ensure_alive(FutureObj *fut)
271{
272 if (!future_is_alive(fut)) {
273 PyErr_SetString(PyExc_RuntimeError,
274 "Future object is not initialized.");
275 return -1;
276 }
277 return 0;
278}
279
280
281#define ENSURE_FUTURE_ALIVE(fut) \
282 do { \
283 assert(Future_Check(fut) || Task_Check(fut)); \
284 if (future_ensure_alive((FutureObj*)fut)) { \
285 return NULL; \
286 } \
287 } while(0);
288
289
290static int
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400291future_schedule_callbacks(FutureObj *fut)
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900292{
293 Py_ssize_t len;
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500294 Py_ssize_t i;
295
296 if (fut->fut_callback0 != NULL) {
297 /* There's a 1st callback */
298
299 int ret = call_soon(
300 fut->fut_loop, fut->fut_callback0, (PyObject *)fut);
301 Py_CLEAR(fut->fut_callback0);
302 if (ret) {
303 /* If an error occurs in pure-Python implementation,
304 all callbacks are cleared. */
305 Py_CLEAR(fut->fut_callbacks);
306 return ret;
307 }
308
309 /* we called the first callback, now try calling
310 callbacks from the 'fut_callbacks' list. */
311 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900312
313 if (fut->fut_callbacks == NULL) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500314 /* No more callbacks, return. */
315 return 0;
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900316 }
317
318 len = PyList_GET_SIZE(fut->fut_callbacks);
319 if (len == 0) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500320 /* The list of callbacks was empty; clear it and return. */
321 Py_CLEAR(fut->fut_callbacks);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900322 return 0;
323 }
324
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900325 for (i = 0; i < len; i++) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500326 PyObject *cb = PyList_GET_ITEM(fut->fut_callbacks, i);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900327
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500328 if (call_soon(fut->fut_loop, cb, (PyObject *)fut)) {
329 /* If an error occurs in pure-Python implementation,
330 all callbacks are cleared. */
331 Py_CLEAR(fut->fut_callbacks);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900332 return -1;
333 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900334 }
335
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500336 Py_CLEAR(fut->fut_callbacks);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900337 return 0;
338}
339
340static int
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400341future_init(FutureObj *fut, PyObject *loop)
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900342{
Serhiy Storchakabca49392017-09-03 08:10:14 +0300343 PyObject *res;
344 int is_true;
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900345 _Py_IDENTIFIER(get_debug);
346
Serhiy Storchakabca49392017-09-03 08:10:14 +0300347 if (loop == Py_None) {
Yury Selivanova70232f2017-12-13 14:49:42 -0500348 loop = get_event_loop();
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900349 if (loop == NULL) {
350 return -1;
351 }
352 }
353 else {
354 Py_INCREF(loop);
355 }
Serhiy Storchakabca49392017-09-03 08:10:14 +0300356 Py_XSETREF(fut->fut_loop, loop);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900357
Victor Stinnerf94d1ee2016-10-29 09:05:39 +0200358 res = _PyObject_CallMethodId(fut->fut_loop, &PyId_get_debug, NULL);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900359 if (res == NULL) {
360 return -1;
361 }
Serhiy Storchakabca49392017-09-03 08:10:14 +0300362 is_true = PyObject_IsTrue(res);
363 Py_DECREF(res);
364 if (is_true < 0) {
365 return -1;
366 }
367 if (is_true) {
368 Py_XSETREF(fut->fut_source_tb, _PyObject_CallNoArg(traceback_extract_stack));
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900369 if (fut->fut_source_tb == NULL) {
370 return -1;
371 }
372 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900373
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500374 fut->fut_callback0 = NULL;
375 fut->fut_callbacks = NULL;
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400376
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900377 return 0;
378}
379
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900380static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400381future_set_result(FutureObj *fut, PyObject *res)
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900382{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500383 if (future_ensure_alive(fut)) {
384 return NULL;
385 }
386
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900387 if (fut->fut_state != STATE_PENDING) {
388 PyErr_SetString(asyncio_InvalidStateError, "invalid state");
389 return NULL;
390 }
391
Serhiy Storchakabca49392017-09-03 08:10:14 +0300392 assert(!fut->fut_result);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900393 Py_INCREF(res);
394 fut->fut_result = res;
395 fut->fut_state = STATE_FINISHED;
396
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400397 if (future_call_schedule_callbacks(fut) == -1) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900398 return NULL;
399 }
400 Py_RETURN_NONE;
401}
402
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900403static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400404future_set_exception(FutureObj *fut, PyObject *exc)
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900405{
406 PyObject *exc_val = NULL;
407
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900408 if (fut->fut_state != STATE_PENDING) {
409 PyErr_SetString(asyncio_InvalidStateError, "invalid state");
410 return NULL;
411 }
412
413 if (PyExceptionClass_Check(exc)) {
Victor Stinnera5ed5f02016-12-06 18:45:50 +0100414 exc_val = _PyObject_CallNoArg(exc);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900415 if (exc_val == NULL) {
416 return NULL;
417 }
Serhiy Storchakabca49392017-09-03 08:10:14 +0300418 if (fut->fut_state != STATE_PENDING) {
419 Py_DECREF(exc_val);
420 PyErr_SetString(asyncio_InvalidStateError, "invalid state");
421 return NULL;
422 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900423 }
424 else {
425 exc_val = exc;
426 Py_INCREF(exc_val);
427 }
428 if (!PyExceptionInstance_Check(exc_val)) {
429 Py_DECREF(exc_val);
430 PyErr_SetString(PyExc_TypeError, "invalid exception object");
431 return NULL;
432 }
433 if ((PyObject*)Py_TYPE(exc_val) == PyExc_StopIteration) {
434 Py_DECREF(exc_val);
435 PyErr_SetString(PyExc_TypeError,
436 "StopIteration interacts badly with generators "
437 "and cannot be raised into a Future");
438 return NULL;
439 }
440
Serhiy Storchakabca49392017-09-03 08:10:14 +0300441 assert(!fut->fut_exception);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900442 fut->fut_exception = exc_val;
443 fut->fut_state = STATE_FINISHED;
444
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400445 if (future_call_schedule_callbacks(fut) == -1) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900446 return NULL;
447 }
448
449 fut->fut_log_tb = 1;
450 Py_RETURN_NONE;
451}
452
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400453static int
454future_get_result(FutureObj *fut, PyObject **result)
455{
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400456 if (fut->fut_state == STATE_CANCELLED) {
Serhiy Storchakabca49392017-09-03 08:10:14 +0300457 PyErr_SetNone(asyncio_CancelledError);
458 return -1;
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400459 }
460
461 if (fut->fut_state != STATE_FINISHED) {
Serhiy Storchakabca49392017-09-03 08:10:14 +0300462 PyErr_SetString(asyncio_InvalidStateError, "Result is not set.");
463 return -1;
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400464 }
465
466 fut->fut_log_tb = 0;
467 if (fut->fut_exception != NULL) {
468 Py_INCREF(fut->fut_exception);
469 *result = fut->fut_exception;
470 return 1;
471 }
472
473 Py_INCREF(fut->fut_result);
474 *result = fut->fut_result;
475 return 0;
476}
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900477
478static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400479future_add_done_callback(FutureObj *fut, PyObject *arg)
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900480{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500481 if (!future_is_alive(fut)) {
482 PyErr_SetString(PyExc_RuntimeError, "uninitialized Future object");
483 return NULL;
484 }
485
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900486 if (fut->fut_state != STATE_PENDING) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500487 /* The future is done/cancelled, so schedule the callback
488 right away. */
489 if (call_soon(fut->fut_loop, arg, (PyObject*) fut)) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900490 return NULL;
491 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900492 }
493 else {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500494 /* The future is pending, add a callback.
495
496 Callbacks in the future object are stored as follows:
497
498 callback0 -- a pointer to the first callback
499 callbacks -- a list of 2nd, 3rd, ... callbacks
500
501 Invariants:
502
503 * callbacks != NULL:
504 There are some callbacks in in the list. Just
505 add the new callback to it.
506
507 * callbacks == NULL and callback0 == NULL:
508 This is the first callback. Set it to callback0.
509
510 * callbacks == NULL and callback0 != NULL:
511 This is a second callback. Initialize callbacks
512 with a new list and add the new callback to it.
513 */
514
515 if (fut->fut_callbacks != NULL) {
516 int err = PyList_Append(fut->fut_callbacks, arg);
517 if (err != 0) {
518 return NULL;
519 }
Serhiy Storchakabca49392017-09-03 08:10:14 +0300520 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500521 else if (fut->fut_callback0 == NULL) {
522 Py_INCREF(arg);
523 fut->fut_callback0 = arg;
524 }
525 else {
526 fut->fut_callbacks = PyList_New(1);
527 if (fut->fut_callbacks == NULL) {
528 return NULL;
529 }
530
531 Py_INCREF(arg);
532 PyList_SET_ITEM(fut->fut_callbacks, 0, arg);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900533 }
534 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500535
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900536 Py_RETURN_NONE;
537}
538
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400539static PyObject *
540future_cancel(FutureObj *fut)
541{
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +0000542 fut->fut_log_tb = 0;
543
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400544 if (fut->fut_state != STATE_PENDING) {
545 Py_RETURN_FALSE;
546 }
547 fut->fut_state = STATE_CANCELLED;
548
549 if (future_call_schedule_callbacks(fut) == -1) {
550 return NULL;
551 }
552
553 Py_RETURN_TRUE;
554}
555
556/*[clinic input]
557_asyncio.Future.__init__
558
559 *
Serhiy Storchakabca49392017-09-03 08:10:14 +0300560 loop: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400561
562This class is *almost* compatible with concurrent.futures.Future.
563
564 Differences:
565
566 - result() and exception() do not take a timeout argument and
567 raise an exception when the future isn't done yet.
568
569 - Callbacks registered with add_done_callback() are always called
570 via the event loop's call_soon_threadsafe().
571
572 - This class is not compatible with the wait() and as_completed()
573 methods in the concurrent.futures package.
574[clinic start generated code]*/
575
576static int
577_asyncio_Future___init___impl(FutureObj *self, PyObject *loop)
Serhiy Storchakabca49392017-09-03 08:10:14 +0300578/*[clinic end generated code: output=9ed75799eaccb5d6 input=89af317082bc0bf8]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400579
580{
581 return future_init(self, loop);
582}
583
584static int
585FutureObj_clear(FutureObj *fut)
586{
587 Py_CLEAR(fut->fut_loop);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500588 Py_CLEAR(fut->fut_callback0);
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400589 Py_CLEAR(fut->fut_callbacks);
590 Py_CLEAR(fut->fut_result);
591 Py_CLEAR(fut->fut_exception);
592 Py_CLEAR(fut->fut_source_tb);
593 Py_CLEAR(fut->dict);
594 return 0;
595}
596
597static int
598FutureObj_traverse(FutureObj *fut, visitproc visit, void *arg)
599{
600 Py_VISIT(fut->fut_loop);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500601 Py_VISIT(fut->fut_callback0);
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400602 Py_VISIT(fut->fut_callbacks);
603 Py_VISIT(fut->fut_result);
604 Py_VISIT(fut->fut_exception);
605 Py_VISIT(fut->fut_source_tb);
606 Py_VISIT(fut->dict);
607 return 0;
608}
609
610/*[clinic input]
611_asyncio.Future.result
612
613Return the result this future represents.
614
615If the future has been cancelled, raises CancelledError. If the
616future's result isn't yet available, raises InvalidStateError. If
617the future is done and has an exception set, this exception is raised.
618[clinic start generated code]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900619
620static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400621_asyncio_Future_result_impl(FutureObj *self)
622/*[clinic end generated code: output=f35f940936a4b1e5 input=49ecf9cf5ec50dc5]*/
623{
624 PyObject *result;
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500625
626 if (!future_is_alive(self)) {
627 PyErr_SetString(asyncio_InvalidStateError,
628 "Future object is not initialized.");
629 return NULL;
630 }
631
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400632 int res = future_get_result(self, &result);
633
634 if (res == -1) {
635 return NULL;
636 }
637
638 if (res == 0) {
639 return result;
640 }
641
642 assert(res == 1);
643
644 PyErr_SetObject(PyExceptionInstance_Class(result), result);
645 Py_DECREF(result);
646 return NULL;
647}
648
649/*[clinic input]
650_asyncio.Future.exception
651
652Return the exception that was set on this future.
653
654The exception (or None if no exception was set) is returned only if
655the future is done. If the future has been cancelled, raises
656CancelledError. If the future isn't done yet, raises
657InvalidStateError.
658[clinic start generated code]*/
659
660static PyObject *
661_asyncio_Future_exception_impl(FutureObj *self)
662/*[clinic end generated code: output=88b20d4f855e0710 input=733547a70c841c68]*/
663{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500664 if (!future_is_alive(self)) {
665 PyErr_SetString(asyncio_InvalidStateError,
666 "Future object is not initialized.");
667 return NULL;
668 }
669
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400670 if (self->fut_state == STATE_CANCELLED) {
Serhiy Storchakabca49392017-09-03 08:10:14 +0300671 PyErr_SetNone(asyncio_CancelledError);
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400672 return NULL;
673 }
674
675 if (self->fut_state != STATE_FINISHED) {
Serhiy Storchakabca49392017-09-03 08:10:14 +0300676 PyErr_SetString(asyncio_InvalidStateError, "Exception is not set.");
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400677 return NULL;
678 }
679
680 if (self->fut_exception != NULL) {
681 self->fut_log_tb = 0;
682 Py_INCREF(self->fut_exception);
683 return self->fut_exception;
684 }
685
686 Py_RETURN_NONE;
687}
688
689/*[clinic input]
690_asyncio.Future.set_result
691
Serhiy Storchakabca49392017-09-03 08:10:14 +0300692 res: object
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400693 /
694
695Mark the future done and set its result.
696
697If the future is already done when this method is called, raises
698InvalidStateError.
699[clinic start generated code]*/
700
701static PyObject *
702_asyncio_Future_set_result(FutureObj *self, PyObject *res)
Serhiy Storchakabca49392017-09-03 08:10:14 +0300703/*[clinic end generated code: output=a620abfc2796bfb6 input=5b9dc180f1baa56d]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400704{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500705 ENSURE_FUTURE_ALIVE(self)
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400706 return future_set_result(self, res);
707}
708
709/*[clinic input]
710_asyncio.Future.set_exception
711
Serhiy Storchakabca49392017-09-03 08:10:14 +0300712 exception: object
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400713 /
714
715Mark the future done and set an exception.
716
717If the future is already done when this method is called, raises
718InvalidStateError.
719[clinic start generated code]*/
720
721static PyObject *
722_asyncio_Future_set_exception(FutureObj *self, PyObject *exception)
Serhiy Storchakabca49392017-09-03 08:10:14 +0300723/*[clinic end generated code: output=f1c1b0cd321be360 input=e45b7d7aa71cc66d]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400724{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500725 ENSURE_FUTURE_ALIVE(self)
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400726 return future_set_exception(self, exception);
727}
728
729/*[clinic input]
730_asyncio.Future.add_done_callback
731
Serhiy Storchakabca49392017-09-03 08:10:14 +0300732 fn: object
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400733 /
734
735Add a callback to be run when the future becomes done.
736
737The callback is called with a single argument - the future object. If
738the future is already done when this is called, the callback is
739scheduled with call_soon.
740[clinic start generated code]*/
741
742static PyObject *
743_asyncio_Future_add_done_callback(FutureObj *self, PyObject *fn)
Serhiy Storchakabca49392017-09-03 08:10:14 +0300744/*[clinic end generated code: output=819e09629b2ec2b5 input=8f818b39990b027d]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400745{
746 return future_add_done_callback(self, fn);
747}
748
749/*[clinic input]
750_asyncio.Future.remove_done_callback
751
Serhiy Storchakabca49392017-09-03 08:10:14 +0300752 fn: object
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400753 /
754
755Remove all instances of a callback from the "call when done" list.
756
757Returns the number of callbacks removed.
758[clinic start generated code]*/
759
760static PyObject *
761_asyncio_Future_remove_done_callback(FutureObj *self, PyObject *fn)
Serhiy Storchakabca49392017-09-03 08:10:14 +0300762/*[clinic end generated code: output=5ab1fb52b24ef31f input=0a43280a149d505b]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900763{
764 PyObject *newlist;
765 Py_ssize_t len, i, j=0;
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500766 Py_ssize_t cleared_callback0 = 0;
767
768 ENSURE_FUTURE_ALIVE(self)
769
770 if (self->fut_callback0 != NULL) {
771 int cmp = PyObject_RichCompareBool(fn, self->fut_callback0, Py_EQ);
772 if (cmp == -1) {
773 return NULL;
774 }
775 if (cmp == 1) {
776 /* callback0 == fn */
777 Py_CLEAR(self->fut_callback0);
778 cleared_callback0 = 1;
779 }
780 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900781
Serhiy Storchakabca49392017-09-03 08:10:14 +0300782 if (self->fut_callbacks == NULL) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500783 return PyLong_FromSsize_t(cleared_callback0);
Serhiy Storchakabca49392017-09-03 08:10:14 +0300784 }
785
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400786 len = PyList_GET_SIZE(self->fut_callbacks);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900787 if (len == 0) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500788 Py_CLEAR(self->fut_callbacks);
789 return PyLong_FromSsize_t(cleared_callback0);
790 }
791
792 if (len == 1) {
793 int cmp = PyObject_RichCompareBool(
794 fn, PyList_GET_ITEM(self->fut_callbacks, 0), Py_EQ);
795 if (cmp == -1) {
796 return NULL;
797 }
798 if (cmp == 1) {
799 /* callbacks[0] == fn */
800 Py_CLEAR(self->fut_callbacks);
801 return PyLong_FromSsize_t(1 + cleared_callback0);
802 }
803 /* callbacks[0] != fn and len(callbacks) == 1 */
804 return PyLong_FromSsize_t(cleared_callback0);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900805 }
806
807 newlist = PyList_New(len);
808 if (newlist == NULL) {
809 return NULL;
810 }
811
Yury Selivanov84af9032017-03-02 23:46:56 -0500812 for (i = 0; i < PyList_GET_SIZE(self->fut_callbacks); i++) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900813 int ret;
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400814 PyObject *item = PyList_GET_ITEM(self->fut_callbacks, i);
Serhiy Storchakabca49392017-09-03 08:10:14 +0300815 Py_INCREF(item);
816 ret = PyObject_RichCompareBool(fn, item, Py_EQ);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900817 if (ret == 0) {
Yury Selivanov833a3b02017-07-05 13:32:03 -0400818 if (j < len) {
Yury Selivanov833a3b02017-07-05 13:32:03 -0400819 PyList_SET_ITEM(newlist, j, item);
820 j++;
Serhiy Storchakabca49392017-09-03 08:10:14 +0300821 continue;
Yury Selivanov833a3b02017-07-05 13:32:03 -0400822 }
Serhiy Storchakabca49392017-09-03 08:10:14 +0300823 ret = PyList_Append(newlist, item);
824 }
825 Py_DECREF(item);
826 if (ret < 0) {
827 goto fail;
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900828 }
829 }
830
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500831 if (j == 0) {
832 Py_CLEAR(self->fut_callbacks);
833 Py_DECREF(newlist);
834 return PyLong_FromSsize_t(len + cleared_callback0);
835 }
836
Serhiy Storchakabca49392017-09-03 08:10:14 +0300837 if (j < len) {
838 Py_SIZE(newlist) = j;
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900839 }
Serhiy Storchakabca49392017-09-03 08:10:14 +0300840 j = PyList_GET_SIZE(newlist);
841 len = PyList_GET_SIZE(self->fut_callbacks);
842 if (j != len) {
843 if (PyList_SetSlice(self->fut_callbacks, 0, len, newlist) < 0) {
844 goto fail;
845 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900846 }
847 Py_DECREF(newlist);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500848 return PyLong_FromSsize_t(len - j + cleared_callback0);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900849
850fail:
851 Py_DECREF(newlist);
852 return NULL;
853}
854
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400855/*[clinic input]
856_asyncio.Future.cancel
857
858Cancel the future and schedule callbacks.
859
860If the future is already done or cancelled, return False. Otherwise,
861change the future's state to cancelled, schedule the callbacks and
862return True.
863[clinic start generated code]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900864
865static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400866_asyncio_Future_cancel_impl(FutureObj *self)
867/*[clinic end generated code: output=e45b932ba8bd68a1 input=515709a127995109]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900868{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500869 ENSURE_FUTURE_ALIVE(self)
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400870 return future_cancel(self);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900871}
872
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400873/*[clinic input]
874_asyncio.Future.cancelled
875
876Return True if the future was cancelled.
877[clinic start generated code]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900878
879static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400880_asyncio_Future_cancelled_impl(FutureObj *self)
881/*[clinic end generated code: output=145197ced586357d input=943ab8b7b7b17e45]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900882{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500883 if (future_is_alive(self) && self->fut_state == STATE_CANCELLED) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900884 Py_RETURN_TRUE;
885 }
886 else {
887 Py_RETURN_FALSE;
888 }
889}
890
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400891/*[clinic input]
892_asyncio.Future.done
893
894Return True if the future is done.
895
896Done means either that a result / exception are available, or that the
897future was cancelled.
898[clinic start generated code]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900899
900static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400901_asyncio_Future_done_impl(FutureObj *self)
902/*[clinic end generated code: output=244c5ac351145096 input=28d7b23fdb65d2ac]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900903{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500904 if (!future_is_alive(self) || self->fut_state == STATE_PENDING) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900905 Py_RETURN_FALSE;
906 }
907 else {
908 Py_RETURN_TRUE;
909 }
910}
911
912static PyObject *
913FutureObj_get_blocking(FutureObj *fut)
914{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500915 if (future_is_alive(fut) && fut->fut_blocking) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900916 Py_RETURN_TRUE;
917 }
918 else {
919 Py_RETURN_FALSE;
920 }
921}
922
923static int
924FutureObj_set_blocking(FutureObj *fut, PyObject *val)
925{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500926 if (future_ensure_alive(fut)) {
927 return -1;
928 }
929
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900930 int is_true = PyObject_IsTrue(val);
931 if (is_true < 0) {
932 return -1;
933 }
934 fut->fut_blocking = is_true;
935 return 0;
936}
937
938static PyObject *
939FutureObj_get_log_traceback(FutureObj *fut)
940{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500941 ENSURE_FUTURE_ALIVE(fut)
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900942 if (fut->fut_log_tb) {
943 Py_RETURN_TRUE;
944 }
945 else {
946 Py_RETURN_FALSE;
947 }
948}
949
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +0000950static int
951FutureObj_set_log_traceback(FutureObj *fut, PyObject *val)
952{
953 int is_true = PyObject_IsTrue(val);
954 if (is_true < 0) {
955 return -1;
956 }
957 fut->fut_log_tb = is_true;
958 return 0;
959}
960
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900961static PyObject *
962FutureObj_get_loop(FutureObj *fut)
963{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500964 if (!future_is_alive(fut)) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900965 Py_RETURN_NONE;
966 }
967 Py_INCREF(fut->fut_loop);
968 return fut->fut_loop;
969}
970
971static PyObject *
972FutureObj_get_callbacks(FutureObj *fut)
973{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500974 Py_ssize_t i;
975 Py_ssize_t len;
976 PyObject *new_list;
977
978 ENSURE_FUTURE_ALIVE(fut)
979
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900980 if (fut->fut_callbacks == NULL) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500981 if (fut->fut_callback0 == NULL) {
982 Py_RETURN_NONE;
983 }
984 else {
985 new_list = PyList_New(1);
986 if (new_list == NULL) {
987 return NULL;
988 }
989 Py_INCREF(fut->fut_callback0);
990 PyList_SET_ITEM(new_list, 0, fut->fut_callback0);
991 return new_list;
992 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900993 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500994
995 assert(fut->fut_callbacks != NULL);
996
997 if (fut->fut_callback0 == NULL) {
998 Py_INCREF(fut->fut_callbacks);
999 return fut->fut_callbacks;
1000 }
1001
1002 assert(fut->fut_callback0 != NULL);
1003
1004 len = PyList_GET_SIZE(fut->fut_callbacks);
1005 new_list = PyList_New(len + 1);
1006 if (new_list == NULL) {
1007 return NULL;
1008 }
1009
1010 Py_INCREF(fut->fut_callback0);
1011 PyList_SET_ITEM(new_list, 0, fut->fut_callback0);
1012 for (i = 0; i < len; i++) {
1013 PyObject *cb = PyList_GET_ITEM(fut->fut_callbacks, i);
1014 Py_INCREF(cb);
1015 PyList_SET_ITEM(new_list, i + 1, cb);
1016 }
1017
1018 return new_list;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001019}
1020
1021static PyObject *
1022FutureObj_get_result(FutureObj *fut)
1023{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001024 ENSURE_FUTURE_ALIVE(fut)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001025 if (fut->fut_result == NULL) {
1026 Py_RETURN_NONE;
1027 }
1028 Py_INCREF(fut->fut_result);
1029 return fut->fut_result;
1030}
1031
1032static PyObject *
1033FutureObj_get_exception(FutureObj *fut)
1034{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001035 ENSURE_FUTURE_ALIVE(fut)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001036 if (fut->fut_exception == NULL) {
1037 Py_RETURN_NONE;
1038 }
1039 Py_INCREF(fut->fut_exception);
1040 return fut->fut_exception;
1041}
1042
1043static PyObject *
1044FutureObj_get_source_traceback(FutureObj *fut)
1045{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001046 if (!future_is_alive(fut) || fut->fut_source_tb == NULL) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001047 Py_RETURN_NONE;
1048 }
1049 Py_INCREF(fut->fut_source_tb);
1050 return fut->fut_source_tb;
1051}
1052
1053static PyObject *
1054FutureObj_get_state(FutureObj *fut)
1055{
1056 _Py_IDENTIFIER(PENDING);
1057 _Py_IDENTIFIER(CANCELLED);
1058 _Py_IDENTIFIER(FINISHED);
1059 PyObject *ret = NULL;
1060
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001061 ENSURE_FUTURE_ALIVE(fut)
1062
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001063 switch (fut->fut_state) {
1064 case STATE_PENDING:
1065 ret = _PyUnicode_FromId(&PyId_PENDING);
1066 break;
1067 case STATE_CANCELLED:
1068 ret = _PyUnicode_FromId(&PyId_CANCELLED);
1069 break;
1070 case STATE_FINISHED:
1071 ret = _PyUnicode_FromId(&PyId_FINISHED);
1072 break;
1073 default:
1074 assert (0);
1075 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03001076 Py_XINCREF(ret);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001077 return ret;
1078}
1079
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001080/*[clinic input]
1081_asyncio.Future._repr_info
1082[clinic start generated code]*/
1083
1084static PyObject *
1085_asyncio_Future__repr_info_impl(FutureObj *self)
1086/*[clinic end generated code: output=fa69e901bd176cfb input=f21504d8e2ae1ca2]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001087{
Victor Stinnerde4ae3d2016-12-04 22:59:09 +01001088 return PyObject_CallFunctionObjArgs(
1089 asyncio_future_repr_info_func, self, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001090}
1091
1092/*[clinic input]
1093_asyncio.Future._schedule_callbacks
1094[clinic start generated code]*/
1095
1096static PyObject *
1097_asyncio_Future__schedule_callbacks_impl(FutureObj *self)
1098/*[clinic end generated code: output=5e8958d89ea1c5dc input=4f5f295f263f4a88]*/
1099{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001100 ENSURE_FUTURE_ALIVE(self)
1101
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001102 int ret = future_schedule_callbacks(self);
1103 if (ret == -1) {
1104 return NULL;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001105 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001106 Py_RETURN_NONE;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001107}
1108
1109static PyObject *
1110FutureObj_repr(FutureObj *fut)
1111{
1112 _Py_IDENTIFIER(_repr_info);
1113
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001114 ENSURE_FUTURE_ALIVE(fut)
1115
Serhiy Storchakabca49392017-09-03 08:10:14 +03001116 PyObject *rinfo = _PyObject_CallMethodIdObjArgs((PyObject*)fut,
1117 &PyId__repr_info,
1118 NULL);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001119 if (rinfo == NULL) {
1120 return NULL;
1121 }
1122
Serhiy Storchakabca49392017-09-03 08:10:14 +03001123 PyObject *rinfo_s = PyUnicode_Join(NULL, rinfo);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001124 Py_DECREF(rinfo);
1125 if (rinfo_s == NULL) {
1126 return NULL;
1127 }
1128
1129 PyObject *rstr = NULL;
1130 PyObject *type_name = PyObject_GetAttrString((PyObject*)Py_TYPE(fut),
1131 "__name__");
1132 if (type_name != NULL) {
Serhiy Storchakabca49392017-09-03 08:10:14 +03001133 rstr = PyUnicode_FromFormat("<%S %U>", type_name, rinfo_s);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001134 Py_DECREF(type_name);
1135 }
1136 Py_DECREF(rinfo_s);
1137 return rstr;
1138}
1139
1140static void
1141FutureObj_finalize(FutureObj *fut)
1142{
1143 _Py_IDENTIFIER(call_exception_handler);
1144 _Py_IDENTIFIER(message);
1145 _Py_IDENTIFIER(exception);
1146 _Py_IDENTIFIER(future);
1147 _Py_IDENTIFIER(source_traceback);
1148
Serhiy Storchakabca49392017-09-03 08:10:14 +03001149 PyObject *error_type, *error_value, *error_traceback;
1150 PyObject *context;
1151 PyObject *type_name;
1152 PyObject *message = NULL;
1153 PyObject *func;
1154
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001155 if (!fut->fut_log_tb) {
1156 return;
1157 }
1158 assert(fut->fut_exception != NULL);
Serhiy Storchakabca49392017-09-03 08:10:14 +03001159 fut->fut_log_tb = 0;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001160
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001161 /* Save the current exception, if any. */
1162 PyErr_Fetch(&error_type, &error_value, &error_traceback);
1163
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001164 context = PyDict_New();
1165 if (context == NULL) {
1166 goto finally;
1167 }
1168
1169 type_name = PyObject_GetAttrString((PyObject*)Py_TYPE(fut), "__name__");
1170 if (type_name == NULL) {
1171 goto finally;
1172 }
1173
1174 message = PyUnicode_FromFormat(
1175 "%S exception was never retrieved", type_name);
Serhiy Storchakabca49392017-09-03 08:10:14 +03001176 Py_DECREF(type_name);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001177 if (message == NULL) {
1178 goto finally;
1179 }
1180
1181 if (_PyDict_SetItemId(context, &PyId_message, message) < 0 ||
1182 _PyDict_SetItemId(context, &PyId_exception, fut->fut_exception) < 0 ||
1183 _PyDict_SetItemId(context, &PyId_future, (PyObject*)fut) < 0) {
1184 goto finally;
1185 }
1186 if (fut->fut_source_tb != NULL) {
1187 if (_PyDict_SetItemId(context, &PyId_source_traceback,
1188 fut->fut_source_tb) < 0) {
1189 goto finally;
1190 }
1191 }
1192
1193 func = _PyObject_GetAttrId(fut->fut_loop, &PyId_call_exception_handler);
1194 if (func != NULL) {
Serhiy Storchakabca49392017-09-03 08:10:14 +03001195 PyObject *res = PyObject_CallFunctionObjArgs(func, context, NULL);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001196 if (res == NULL) {
1197 PyErr_WriteUnraisable(func);
1198 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03001199 else {
1200 Py_DECREF(res);
1201 }
1202 Py_DECREF(func);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001203 }
1204
1205finally:
Serhiy Storchakabca49392017-09-03 08:10:14 +03001206 Py_XDECREF(context);
1207 Py_XDECREF(message);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001208
1209 /* Restore the saved exception. */
1210 PyErr_Restore(error_type, error_value, error_traceback);
1211}
1212
1213
1214static PyAsyncMethods FutureType_as_async = {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001215 (unaryfunc)future_new_iter, /* am_await */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001216 0, /* am_aiter */
1217 0 /* am_anext */
1218};
1219
1220static PyMethodDef FutureType_methods[] = {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001221 _ASYNCIO_FUTURE_RESULT_METHODDEF
1222 _ASYNCIO_FUTURE_EXCEPTION_METHODDEF
1223 _ASYNCIO_FUTURE_SET_RESULT_METHODDEF
1224 _ASYNCIO_FUTURE_SET_EXCEPTION_METHODDEF
1225 _ASYNCIO_FUTURE_ADD_DONE_CALLBACK_METHODDEF
1226 _ASYNCIO_FUTURE_REMOVE_DONE_CALLBACK_METHODDEF
1227 _ASYNCIO_FUTURE_CANCEL_METHODDEF
1228 _ASYNCIO_FUTURE_CANCELLED_METHODDEF
1229 _ASYNCIO_FUTURE_DONE_METHODDEF
1230 _ASYNCIO_FUTURE__REPR_INFO_METHODDEF
1231 _ASYNCIO_FUTURE__SCHEDULE_CALLBACKS_METHODDEF
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001232 {NULL, NULL} /* Sentinel */
1233};
1234
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001235#define FUTURE_COMMON_GETSETLIST \
1236 {"_state", (getter)FutureObj_get_state, NULL, NULL}, \
1237 {"_asyncio_future_blocking", (getter)FutureObj_get_blocking, \
1238 (setter)FutureObj_set_blocking, NULL}, \
1239 {"_loop", (getter)FutureObj_get_loop, NULL, NULL}, \
1240 {"_callbacks", (getter)FutureObj_get_callbacks, NULL, NULL}, \
1241 {"_result", (getter)FutureObj_get_result, NULL, NULL}, \
1242 {"_exception", (getter)FutureObj_get_exception, NULL, NULL}, \
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +00001243 {"_log_traceback", (getter)FutureObj_get_log_traceback, \
1244 (setter)FutureObj_set_log_traceback, NULL}, \
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001245 {"_source_traceback", (getter)FutureObj_get_source_traceback, NULL, NULL},
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001246
1247static PyGetSetDef FutureType_getsetlist[] = {
1248 FUTURE_COMMON_GETSETLIST
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001249 {NULL} /* Sentinel */
1250};
1251
1252static void FutureObj_dealloc(PyObject *self);
1253
1254static PyTypeObject FutureType = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02001255 PyVarObject_HEAD_INIT(NULL, 0)
INADA Naoki9f2ce252016-10-15 15:39:19 +09001256 "_asyncio.Future",
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001257 sizeof(FutureObj), /* tp_basicsize */
1258 .tp_dealloc = FutureObj_dealloc,
1259 .tp_as_async = &FutureType_as_async,
1260 .tp_repr = (reprfunc)FutureObj_repr,
1261 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE
1262 | Py_TPFLAGS_HAVE_FINALIZE,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001263 .tp_doc = _asyncio_Future___init____doc__,
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001264 .tp_traverse = (traverseproc)FutureObj_traverse,
1265 .tp_clear = (inquiry)FutureObj_clear,
1266 .tp_weaklistoffset = offsetof(FutureObj, fut_weakreflist),
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001267 .tp_iter = (getiterfunc)future_new_iter,
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001268 .tp_methods = FutureType_methods,
1269 .tp_getset = FutureType_getsetlist,
1270 .tp_dictoffset = offsetof(FutureObj, dict),
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001271 .tp_init = (initproc)_asyncio_Future___init__,
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001272 .tp_new = PyType_GenericNew,
1273 .tp_finalize = (destructor)FutureObj_finalize,
1274};
1275
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001276static inline int
1277future_call_schedule_callbacks(FutureObj *fut)
1278{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001279 if (Future_CheckExact(fut) || Task_CheckExact(fut)) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001280 return future_schedule_callbacks(fut);
1281 }
1282 else {
1283 /* `fut` is a subclass of Future */
1284 PyObject *ret = _PyObject_CallMethodId(
1285 (PyObject*)fut, &PyId__schedule_callbacks, NULL);
1286 if (ret == NULL) {
1287 return -1;
1288 }
1289
1290 Py_DECREF(ret);
1291 return 0;
1292 }
1293}
1294
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001295static void
1296FutureObj_dealloc(PyObject *self)
1297{
1298 FutureObj *fut = (FutureObj *)self;
1299
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001300 if (Future_CheckExact(fut)) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001301 /* When fut is subclass of Future, finalizer is called from
1302 * subtype_dealloc.
1303 */
1304 if (PyObject_CallFinalizerFromDealloc(self) < 0) {
1305 // resurrected.
1306 return;
1307 }
1308 }
1309
Alexander Mohrde34cbe2017-08-01 23:31:07 -07001310 PyObject_GC_UnTrack(self);
1311
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001312 if (fut->fut_weakreflist != NULL) {
1313 PyObject_ClearWeakRefs(self);
1314 }
1315
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001316 (void)FutureObj_clear(fut);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001317 Py_TYPE(fut)->tp_free(fut);
1318}
1319
1320
1321/*********************** Future Iterator **************************/
1322
1323typedef struct {
1324 PyObject_HEAD
1325 FutureObj *future;
1326} futureiterobject;
1327
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001328
1329#define FI_FREELIST_MAXLEN 255
1330static futureiterobject *fi_freelist = NULL;
1331static Py_ssize_t fi_freelist_len = 0;
1332
1333
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001334static void
1335FutureIter_dealloc(futureiterobject *it)
1336{
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001337 PyObject_GC_UnTrack(it);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001338 Py_CLEAR(it->future);
1339
1340 if (fi_freelist_len < FI_FREELIST_MAXLEN) {
1341 fi_freelist_len++;
1342 it->future = (FutureObj*) fi_freelist;
1343 fi_freelist = it;
1344 }
1345 else {
1346 PyObject_GC_Del(it);
1347 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001348}
1349
1350static PyObject *
1351FutureIter_iternext(futureiterobject *it)
1352{
1353 PyObject *res;
1354 FutureObj *fut = it->future;
1355
1356 if (fut == NULL) {
1357 return NULL;
1358 }
1359
1360 if (fut->fut_state == STATE_PENDING) {
1361 if (!fut->fut_blocking) {
1362 fut->fut_blocking = 1;
1363 Py_INCREF(fut);
1364 return (PyObject *)fut;
1365 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03001366 PyErr_SetString(PyExc_AssertionError,
1367 "yield from wasn't used with future");
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001368 return NULL;
1369 }
1370
Serhiy Storchakabca49392017-09-03 08:10:14 +03001371 it->future = NULL;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001372 res = _asyncio_Future_result_impl(fut);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001373 if (res != NULL) {
Serhiy Storchaka60e49aa2016-11-06 18:47:03 +02001374 /* The result of the Future is not an exception. */
Serhiy Storchakabca49392017-09-03 08:10:14 +03001375 (void)_PyGen_SetStopIterationValue(res);
Serhiy Storchaka60e49aa2016-11-06 18:47:03 +02001376 Py_DECREF(res);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001377 }
1378
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001379 Py_DECREF(fut);
1380 return NULL;
1381}
1382
1383static PyObject *
INADA Naoki74c17532016-10-25 19:00:45 +09001384FutureIter_send(futureiterobject *self, PyObject *unused)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001385{
INADA Naoki74c17532016-10-25 19:00:45 +09001386 /* Future.__iter__ doesn't care about values that are pushed to the
1387 * generator, it just returns "self.result().
1388 */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001389 return FutureIter_iternext(self);
1390}
1391
1392static PyObject *
1393FutureIter_throw(futureiterobject *self, PyObject *args)
1394{
Serhiy Storchakabca49392017-09-03 08:10:14 +03001395 PyObject *type, *val = NULL, *tb = NULL;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001396 if (!PyArg_ParseTuple(args, "O|OO", &type, &val, &tb))
1397 return NULL;
1398
1399 if (val == Py_None) {
1400 val = NULL;
1401 }
1402 if (tb == Py_None) {
1403 tb = NULL;
Benjamin Peterson996fc1f2016-11-14 00:15:44 -08001404 } else if (tb != NULL && !PyTraceBack_Check(tb)) {
1405 PyErr_SetString(PyExc_TypeError, "throw() third argument must be a traceback");
1406 return NULL;
1407 }
1408
1409 Py_INCREF(type);
1410 Py_XINCREF(val);
1411 Py_XINCREF(tb);
1412
1413 if (PyExceptionClass_Check(type)) {
1414 PyErr_NormalizeException(&type, &val, &tb);
Yury Selivanovedfe8862016-12-01 11:37:47 -05001415 /* No need to call PyException_SetTraceback since we'll be calling
1416 PyErr_Restore for `type`, `val`, and `tb`. */
Benjamin Peterson996fc1f2016-11-14 00:15:44 -08001417 } else if (PyExceptionInstance_Check(type)) {
1418 if (val) {
1419 PyErr_SetString(PyExc_TypeError,
1420 "instance exception may not have a separate value");
1421 goto fail;
1422 }
1423 val = type;
1424 type = PyExceptionInstance_Class(type);
1425 Py_INCREF(type);
1426 if (tb == NULL)
1427 tb = PyException_GetTraceback(val);
1428 } else {
1429 PyErr_SetString(PyExc_TypeError,
1430 "exceptions must be classes deriving BaseException or "
1431 "instances of such a class");
1432 goto fail;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001433 }
1434
1435 Py_CLEAR(self->future);
1436
Benjamin Peterson996fc1f2016-11-14 00:15:44 -08001437 PyErr_Restore(type, val, tb);
1438
Serhiy Storchakabca49392017-09-03 08:10:14 +03001439 return NULL;
Benjamin Peterson996fc1f2016-11-14 00:15:44 -08001440
1441 fail:
1442 Py_DECREF(type);
1443 Py_XDECREF(val);
1444 Py_XDECREF(tb);
1445 return NULL;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001446}
1447
1448static PyObject *
1449FutureIter_close(futureiterobject *self, PyObject *arg)
1450{
1451 Py_CLEAR(self->future);
1452 Py_RETURN_NONE;
1453}
1454
1455static int
1456FutureIter_traverse(futureiterobject *it, visitproc visit, void *arg)
1457{
1458 Py_VISIT(it->future);
1459 return 0;
1460}
1461
1462static PyMethodDef FutureIter_methods[] = {
1463 {"send", (PyCFunction)FutureIter_send, METH_O, NULL},
1464 {"throw", (PyCFunction)FutureIter_throw, METH_VARARGS, NULL},
1465 {"close", (PyCFunction)FutureIter_close, METH_NOARGS, NULL},
1466 {NULL, NULL} /* Sentinel */
1467};
1468
1469static PyTypeObject FutureIterType = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02001470 PyVarObject_HEAD_INIT(NULL, 0)
INADA Naoki9f2ce252016-10-15 15:39:19 +09001471 "_asyncio.FutureIter",
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001472 .tp_basicsize = sizeof(futureiterobject),
1473 .tp_itemsize = 0,
1474 .tp_dealloc = (destructor)FutureIter_dealloc,
1475 .tp_getattro = PyObject_GenericGetAttr,
1476 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
1477 .tp_traverse = (traverseproc)FutureIter_traverse,
1478 .tp_iter = PyObject_SelfIter,
1479 .tp_iternext = (iternextfunc)FutureIter_iternext,
1480 .tp_methods = FutureIter_methods,
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001481};
1482
1483static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001484future_new_iter(PyObject *fut)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001485{
1486 futureiterobject *it;
1487
1488 if (!PyObject_TypeCheck(fut, &FutureType)) {
1489 PyErr_BadInternalCall();
1490 return NULL;
1491 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001492
1493 ENSURE_FUTURE_ALIVE(fut)
1494
1495 if (fi_freelist_len) {
1496 fi_freelist_len--;
1497 it = fi_freelist;
1498 fi_freelist = (futureiterobject*) it->future;
1499 it->future = NULL;
1500 _Py_NewReference((PyObject*) it);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001501 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001502 else {
1503 it = PyObject_GC_New(futureiterobject, &FutureIterType);
1504 if (it == NULL) {
1505 return NULL;
1506 }
1507 }
1508
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001509 Py_INCREF(fut);
1510 it->future = (FutureObj*)fut;
INADA Naoki1be427b2016-10-11 02:12:34 +09001511 PyObject_GC_Track(it);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001512 return (PyObject*)it;
1513}
1514
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001515
1516/*********************** Task **************************/
1517
1518
1519/*[clinic input]
1520class _asyncio.Task "TaskObj *" "&Task_Type"
1521[clinic start generated code]*/
1522/*[clinic end generated code: output=da39a3ee5e6b4b0d input=719dcef0fcc03b37]*/
1523
1524static int task_call_step_soon(TaskObj *, PyObject *);
1525static inline PyObject * task_call_wakeup(TaskObj *, PyObject *);
1526static inline PyObject * task_call_step(TaskObj *, PyObject *);
1527static PyObject * task_wakeup(TaskObj *, PyObject *);
1528static PyObject * task_step(TaskObj *, PyObject *);
1529
1530/* ----- Task._step wrapper */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001531
INADA Naokic411a7d2016-10-18 11:48:14 +09001532static int
Serhiy Storchakabca49392017-09-03 08:10:14 +03001533TaskStepMethWrapper_clear(TaskStepMethWrapper *o)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001534{
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001535 Py_CLEAR(o->sw_task);
1536 Py_CLEAR(o->sw_arg);
1537 return 0;
1538}
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001539
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001540static void
Serhiy Storchakabca49392017-09-03 08:10:14 +03001541TaskStepMethWrapper_dealloc(TaskStepMethWrapper *o)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001542{
1543 PyObject_GC_UnTrack(o);
Serhiy Storchakabca49392017-09-03 08:10:14 +03001544 (void)TaskStepMethWrapper_clear(o);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001545 Py_TYPE(o)->tp_free(o);
1546}
1547
1548static PyObject *
Serhiy Storchakabca49392017-09-03 08:10:14 +03001549TaskStepMethWrapper_call(TaskStepMethWrapper *o,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001550 PyObject *args, PyObject *kwds)
1551{
Serhiy Storchakabca49392017-09-03 08:10:14 +03001552 if (kwds != NULL && PyDict_GET_SIZE(kwds) != 0) {
1553 PyErr_SetString(PyExc_TypeError, "function takes no keyword arguments");
1554 return NULL;
1555 }
1556 if (args != NULL && PyTuple_GET_SIZE(args) != 0) {
1557 PyErr_SetString(PyExc_TypeError, "function takes no positional arguments");
1558 return NULL;
1559 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001560 return task_call_step(o->sw_task, o->sw_arg);
1561}
1562
1563static int
Serhiy Storchakabca49392017-09-03 08:10:14 +03001564TaskStepMethWrapper_traverse(TaskStepMethWrapper *o,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001565 visitproc visit, void *arg)
1566{
1567 Py_VISIT(o->sw_task);
1568 Py_VISIT(o->sw_arg);
1569 return 0;
1570}
1571
1572static PyObject *
Serhiy Storchakabca49392017-09-03 08:10:14 +03001573TaskStepMethWrapper_get___self__(TaskStepMethWrapper *o)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001574{
1575 if (o->sw_task) {
1576 Py_INCREF(o->sw_task);
1577 return (PyObject*)o->sw_task;
1578 }
1579 Py_RETURN_NONE;
1580}
1581
Serhiy Storchakabca49392017-09-03 08:10:14 +03001582static PyGetSetDef TaskStepMethWrapper_getsetlist[] = {
1583 {"__self__", (getter)TaskStepMethWrapper_get___self__, NULL, NULL},
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001584 {NULL} /* Sentinel */
1585};
1586
Serhiy Storchakabca49392017-09-03 08:10:14 +03001587PyTypeObject TaskStepMethWrapper_Type = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02001588 PyVarObject_HEAD_INIT(NULL, 0)
Serhiy Storchakabca49392017-09-03 08:10:14 +03001589 "TaskStepMethWrapper",
1590 .tp_basicsize = sizeof(TaskStepMethWrapper),
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001591 .tp_itemsize = 0,
Serhiy Storchakabca49392017-09-03 08:10:14 +03001592 .tp_getset = TaskStepMethWrapper_getsetlist,
1593 .tp_dealloc = (destructor)TaskStepMethWrapper_dealloc,
1594 .tp_call = (ternaryfunc)TaskStepMethWrapper_call,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001595 .tp_getattro = PyObject_GenericGetAttr,
1596 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
Serhiy Storchakabca49392017-09-03 08:10:14 +03001597 .tp_traverse = (traverseproc)TaskStepMethWrapper_traverse,
1598 .tp_clear = (inquiry)TaskStepMethWrapper_clear,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001599};
1600
1601static PyObject *
Serhiy Storchakabca49392017-09-03 08:10:14 +03001602TaskStepMethWrapper_new(TaskObj *task, PyObject *arg)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001603{
Serhiy Storchakabca49392017-09-03 08:10:14 +03001604 TaskStepMethWrapper *o;
1605 o = PyObject_GC_New(TaskStepMethWrapper, &TaskStepMethWrapper_Type);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001606 if (o == NULL) {
1607 return NULL;
1608 }
1609
1610 Py_INCREF(task);
1611 o->sw_task = task;
1612
1613 Py_XINCREF(arg);
1614 o->sw_arg = arg;
1615
1616 PyObject_GC_Track(o);
1617 return (PyObject*) o;
1618}
1619
1620/* ----- Task._wakeup wrapper */
1621
1622static PyObject *
1623TaskWakeupMethWrapper_call(TaskWakeupMethWrapper *o,
1624 PyObject *args, PyObject *kwds)
1625{
1626 PyObject *fut;
1627
Serhiy Storchakabca49392017-09-03 08:10:14 +03001628 if (kwds != NULL && PyDict_GET_SIZE(kwds) != 0) {
1629 PyErr_SetString(PyExc_TypeError, "function takes no keyword arguments");
1630 return NULL;
1631 }
1632 if (!PyArg_ParseTuple(args, "O", &fut)) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001633 return NULL;
1634 }
1635
1636 return task_call_wakeup(o->ww_task, fut);
1637}
1638
1639static int
1640TaskWakeupMethWrapper_clear(TaskWakeupMethWrapper *o)
1641{
1642 Py_CLEAR(o->ww_task);
1643 return 0;
1644}
1645
1646static int
1647TaskWakeupMethWrapper_traverse(TaskWakeupMethWrapper *o,
1648 visitproc visit, void *arg)
1649{
1650 Py_VISIT(o->ww_task);
1651 return 0;
1652}
1653
1654static void
1655TaskWakeupMethWrapper_dealloc(TaskWakeupMethWrapper *o)
1656{
1657 PyObject_GC_UnTrack(o);
1658 (void)TaskWakeupMethWrapper_clear(o);
1659 Py_TYPE(o)->tp_free(o);
1660}
1661
1662PyTypeObject TaskWakeupMethWrapper_Type = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02001663 PyVarObject_HEAD_INIT(NULL, 0)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001664 "TaskWakeupMethWrapper",
1665 .tp_basicsize = sizeof(TaskWakeupMethWrapper),
1666 .tp_itemsize = 0,
1667 .tp_dealloc = (destructor)TaskWakeupMethWrapper_dealloc,
1668 .tp_call = (ternaryfunc)TaskWakeupMethWrapper_call,
1669 .tp_getattro = PyObject_GenericGetAttr,
1670 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
1671 .tp_traverse = (traverseproc)TaskWakeupMethWrapper_traverse,
1672 .tp_clear = (inquiry)TaskWakeupMethWrapper_clear,
1673};
1674
1675static PyObject *
1676TaskWakeupMethWrapper_new(TaskObj *task)
1677{
1678 TaskWakeupMethWrapper *o;
1679 o = PyObject_GC_New(TaskWakeupMethWrapper, &TaskWakeupMethWrapper_Type);
1680 if (o == NULL) {
1681 return NULL;
1682 }
1683
1684 Py_INCREF(task);
1685 o->ww_task = task;
1686
1687 PyObject_GC_Track(o);
1688 return (PyObject*) o;
1689}
1690
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001691/* ----- Task introspection helpers */
1692
1693static int
1694register_task(PyObject *loop, PyObject *task)
1695{
1696 return PyObject_SetItem(all_tasks, task, loop);
1697}
1698
1699
1700static int
1701unregister_task(PyObject *loop, PyObject *task)
1702{
1703 PyObject *res;
1704
1705 res = _PyObject_CallMethodIdObjArgs(all_tasks, &PyId_pop,
1706 task, Py_None, NULL);
1707 if (res == NULL) {
1708 return -1;
1709 }
1710 Py_DECREF(res);
1711 return 0;
1712}
1713
1714
1715static int
1716enter_task(PyObject *loop, PyObject *task)
1717{
1718 PyObject *item;
1719 Py_hash_t hash;
1720 hash = PyObject_Hash(loop);
1721 if (hash == -1) {
1722 return -1;
1723 }
1724 item = _PyDict_GetItem_KnownHash(current_tasks, loop, hash);
1725 if (item != NULL) {
1726 PyErr_Format(
1727 PyExc_RuntimeError,
1728 "Cannot enter into task %R while another " \
1729 "task %R is being executed.",
1730 task, item, NULL);
1731 return -1;
1732 }
1733 if (_PyDict_SetItem_KnownHash(current_tasks, loop, task, hash) < 0) {
1734 return -1;
1735 }
1736 return 0;
1737}
1738
1739
1740static int
1741leave_task(PyObject *loop, PyObject *task)
1742/*[clinic end generated code: output=0ebf6db4b858fb41 input=51296a46313d1ad8]*/
1743{
1744 PyObject *item;
1745 Py_hash_t hash;
1746 hash = PyObject_Hash(loop);
1747 if (hash == -1) {
1748 return -1;
1749 }
1750 item = _PyDict_GetItem_KnownHash(current_tasks, loop, hash);
1751 if (item != task) {
1752 if (item == NULL) {
1753 /* Not entered, replace with None */
1754 item = Py_None;
1755 }
1756 PyErr_Format(
1757 PyExc_RuntimeError,
1758 "Leaving task %R does not match the current task %R.",
1759 task, item, NULL);
1760 return -1;
1761 }
1762 return _PyDict_DelItem_KnownHash(current_tasks, loop, hash);
1763}
1764
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001765/* ----- Task */
1766
1767/*[clinic input]
1768_asyncio.Task.__init__
1769
Serhiy Storchakabca49392017-09-03 08:10:14 +03001770 coro: object
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001771 *
Serhiy Storchakabca49392017-09-03 08:10:14 +03001772 loop: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001773
1774A coroutine wrapped in a Future.
1775[clinic start generated code]*/
1776
1777static int
1778_asyncio_Task___init___impl(TaskObj *self, PyObject *coro, PyObject *loop)
Serhiy Storchakabca49392017-09-03 08:10:14 +03001779/*[clinic end generated code: output=9f24774c2287fc2f input=8d132974b049593e]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001780{
1781 PyObject *res;
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001782
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001783 if (future_init((FutureObj*)self, loop)) {
INADA Naokic411a7d2016-10-18 11:48:14 +09001784 return -1;
1785 }
INADA Naokic411a7d2016-10-18 11:48:14 +09001786
Andrew Svetlovf74ef452017-12-15 07:04:38 +02001787 if (!PyCoro_CheckExact(coro)) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001788 /* 'coro' is not a native coroutine, call asyncio.iscoroutine()
1789 to check if it's another coroutine flavour.
1790
1791 Do this check after 'future_init()'; in case we need to raise
1792 an error, __del__ needs a properly initialized object.
1793 */
1794 res = PyObject_CallFunctionObjArgs(
1795 asyncio_iscoroutine_func, coro, NULL);
Andrew Svetlovf74ef452017-12-15 07:04:38 +02001796 if (res == NULL) {
1797 return -1;
1798 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001799
1800 int tmp = PyObject_Not(res);
Andrew Svetlovf74ef452017-12-15 07:04:38 +02001801 Py_DECREF(res);
1802 if (tmp < 0) {
1803 return -1;
1804 }
1805 if (tmp) {
1806 self->task_log_destroy_pending = 0;
1807 PyErr_Format(PyExc_TypeError,
1808 "a coroutine was expected, got %R",
1809 coro, NULL);
1810 return -1;
1811 }
1812 }
1813
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001814 self->task_fut_waiter = NULL;
1815 self->task_must_cancel = 0;
1816 self->task_log_destroy_pending = 1;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001817 Py_INCREF(coro);
1818 self->task_coro = coro;
1819
1820 if (task_call_step_soon(self, NULL)) {
1821 return -1;
INADA Naokic411a7d2016-10-18 11:48:14 +09001822 }
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001823 return register_task(self->task_loop, (PyObject*)self);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001824}
1825
1826static int
1827TaskObj_clear(TaskObj *task)
1828{
1829 (void)FutureObj_clear((FutureObj*) task);
1830 Py_CLEAR(task->task_coro);
1831 Py_CLEAR(task->task_fut_waiter);
1832 return 0;
1833}
1834
1835static int
1836TaskObj_traverse(TaskObj *task, visitproc visit, void *arg)
1837{
1838 Py_VISIT(task->task_coro);
1839 Py_VISIT(task->task_fut_waiter);
1840 (void)FutureObj_traverse((FutureObj*) task, visit, arg);
1841 return 0;
1842}
1843
1844static PyObject *
1845TaskObj_get_log_destroy_pending(TaskObj *task)
1846{
1847 if (task->task_log_destroy_pending) {
1848 Py_RETURN_TRUE;
1849 }
1850 else {
1851 Py_RETURN_FALSE;
1852 }
1853}
1854
1855static int
1856TaskObj_set_log_destroy_pending(TaskObj *task, PyObject *val)
1857{
1858 int is_true = PyObject_IsTrue(val);
1859 if (is_true < 0) {
1860 return -1;
1861 }
1862 task->task_log_destroy_pending = is_true;
1863 return 0;
1864}
1865
1866static PyObject *
1867TaskObj_get_must_cancel(TaskObj *task)
1868{
1869 if (task->task_must_cancel) {
1870 Py_RETURN_TRUE;
1871 }
1872 else {
1873 Py_RETURN_FALSE;
1874 }
1875}
1876
1877static PyObject *
1878TaskObj_get_coro(TaskObj *task)
1879{
1880 if (task->task_coro) {
1881 Py_INCREF(task->task_coro);
1882 return task->task_coro;
1883 }
1884
1885 Py_RETURN_NONE;
1886}
1887
1888static PyObject *
1889TaskObj_get_fut_waiter(TaskObj *task)
1890{
1891 if (task->task_fut_waiter) {
1892 Py_INCREF(task->task_fut_waiter);
1893 return task->task_fut_waiter;
1894 }
1895
1896 Py_RETURN_NONE;
1897}
1898
1899/*[clinic input]
1900@classmethod
1901_asyncio.Task.current_task
1902
Serhiy Storchakabca49392017-09-03 08:10:14 +03001903 loop: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001904
1905Return the currently running task in an event loop or None.
1906
1907By default the current task for the current event loop is returned.
1908
1909None is returned when called not in the context of a Task.
1910[clinic start generated code]*/
1911
1912static PyObject *
1913_asyncio_Task_current_task_impl(PyTypeObject *type, PyObject *loop)
Serhiy Storchakabca49392017-09-03 08:10:14 +03001914/*[clinic end generated code: output=99fbe7332c516e03 input=cd14770c5b79c7eb]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001915{
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001916 PyObject *ret;
1917 PyObject *current_task_func;
1918
1919 if (PyErr_WarnEx(PyExc_PendingDeprecationWarning,
1920 "Task.current_task() is deprecated, " \
1921 "use asyncio.current_task() instead",
1922 1) < 0) {
1923 return NULL;
1924 }
1925
1926 current_task_func = _PyObject_GetAttrId(asyncio_mod, &PyId_current_task);
1927 if (current_task_func == NULL) {
1928 return NULL;
1929 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001930
Yury Selivanov8d26aa92017-03-02 22:16:33 -05001931 if (loop == Py_None) {
Yury Selivanova70232f2017-12-13 14:49:42 -05001932 loop = get_event_loop();
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001933 if (loop == NULL) {
1934 return NULL;
1935 }
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001936 ret = PyObject_CallFunctionObjArgs(current_task_func, loop, NULL);
1937 Py_DECREF(current_task_func);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001938 Py_DECREF(loop);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001939 return ret;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001940 }
1941 else {
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001942 ret = PyObject_CallFunctionObjArgs(current_task_func, loop, NULL);
1943 Py_DECREF(current_task_func);
1944 return ret;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001945 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001946}
1947
1948/*[clinic input]
1949@classmethod
1950_asyncio.Task.all_tasks
1951
Serhiy Storchakabca49392017-09-03 08:10:14 +03001952 loop: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001953
1954Return a set of all tasks for an event loop.
1955
1956By default all tasks for the current event loop are returned.
1957[clinic start generated code]*/
1958
1959static PyObject *
1960_asyncio_Task_all_tasks_impl(PyTypeObject *type, PyObject *loop)
Serhiy Storchakabca49392017-09-03 08:10:14 +03001961/*[clinic end generated code: output=11f9b20749ccca5d input=497f80bc9ce726b5]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001962{
1963 PyObject *res;
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001964 PyObject *all_tasks_func;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001965
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001966 all_tasks_func = _PyObject_GetAttrId(asyncio_mod, &PyId_all_tasks);
1967 if (all_tasks_func == NULL) {
1968 return NULL;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001969 }
1970
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001971 if (PyErr_WarnEx(PyExc_PendingDeprecationWarning,
1972 "Task.all_tasks() is deprecated, " \
1973 "use asyncio.all_tasks() instead",
1974 1) < 0) {
1975 return NULL;
1976 }
1977
1978 res = PyObject_CallFunctionObjArgs(all_tasks_func, loop, NULL);
1979 Py_DECREF(all_tasks_func);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001980 return res;
1981}
1982
1983/*[clinic input]
1984_asyncio.Task._repr_info
1985[clinic start generated code]*/
1986
1987static PyObject *
1988_asyncio_Task__repr_info_impl(TaskObj *self)
1989/*[clinic end generated code: output=6a490eb66d5ba34b input=3c6d051ed3ddec8b]*/
1990{
Victor Stinnerde4ae3d2016-12-04 22:59:09 +01001991 return PyObject_CallFunctionObjArgs(
1992 asyncio_task_repr_info_func, self, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001993}
1994
1995/*[clinic input]
1996_asyncio.Task.cancel
1997
1998Request that this task cancel itself.
1999
2000This arranges for a CancelledError to be thrown into the
2001wrapped coroutine on the next cycle through the event loop.
2002The coroutine then has a chance to clean up or even deny
2003the request using try/except/finally.
2004
2005Unlike Future.cancel, this does not guarantee that the
2006task will be cancelled: the exception might be caught and
2007acted upon, delaying cancellation of the task or preventing
2008cancellation completely. The task may also return a value or
2009raise a different exception.
2010
2011Immediately after this method is called, Task.cancelled() will
2012not return True (unless the task was already cancelled). A
2013task will be marked as cancelled when the wrapped coroutine
2014terminates with a CancelledError exception (even if cancel()
2015was not called).
2016[clinic start generated code]*/
2017
2018static PyObject *
2019_asyncio_Task_cancel_impl(TaskObj *self)
2020/*[clinic end generated code: output=6bfc0479da9d5757 input=13f9bf496695cb52]*/
2021{
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +00002022 self->task_log_tb = 0;
2023
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002024 if (self->task_state != STATE_PENDING) {
2025 Py_RETURN_FALSE;
2026 }
2027
2028 if (self->task_fut_waiter) {
2029 PyObject *res;
2030 int is_true;
2031
2032 res = _PyObject_CallMethodId(
2033 self->task_fut_waiter, &PyId_cancel, NULL);
2034 if (res == NULL) {
2035 return NULL;
2036 }
2037
2038 is_true = PyObject_IsTrue(res);
2039 Py_DECREF(res);
2040 if (is_true < 0) {
2041 return NULL;
2042 }
2043
2044 if (is_true) {
2045 Py_RETURN_TRUE;
2046 }
2047 }
2048
2049 self->task_must_cancel = 1;
2050 Py_RETURN_TRUE;
2051}
2052
2053/*[clinic input]
2054_asyncio.Task.get_stack
2055
2056 *
Serhiy Storchakabca49392017-09-03 08:10:14 +03002057 limit: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002058
2059Return the list of stack frames for this task's coroutine.
2060
2061If the coroutine is not done, this returns the stack where it is
2062suspended. If the coroutine has completed successfully or was
2063cancelled, this returns an empty list. If the coroutine was
2064terminated by an exception, this returns the list of traceback
2065frames.
2066
2067The frames are always ordered from oldest to newest.
2068
2069The optional limit gives the maximum number of frames to
2070return; by default all available frames are returned. Its
2071meaning differs depending on whether a stack or a traceback is
2072returned: the newest frames of a stack are returned, but the
2073oldest frames of a traceback are returned. (This matches the
2074behavior of the traceback module.)
2075
2076For reasons beyond our control, only one stack frame is
2077returned for a suspended coroutine.
2078[clinic start generated code]*/
2079
2080static PyObject *
2081_asyncio_Task_get_stack_impl(TaskObj *self, PyObject *limit)
Serhiy Storchakabca49392017-09-03 08:10:14 +03002082/*[clinic end generated code: output=c9aeeeebd1e18118 input=05b323d42b809b90]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002083{
2084 return PyObject_CallFunctionObjArgs(
2085 asyncio_task_get_stack_func, self, limit, NULL);
2086}
2087
2088/*[clinic input]
2089_asyncio.Task.print_stack
2090
2091 *
Serhiy Storchakabca49392017-09-03 08:10:14 +03002092 limit: object = None
2093 file: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002094
2095Print the stack or traceback for this task's coroutine.
2096
2097This produces output similar to that of the traceback module,
2098for the frames retrieved by get_stack(). The limit argument
2099is passed to get_stack(). The file argument is an I/O stream
2100to which the output is written; by default output is written
2101to sys.stderr.
2102[clinic start generated code]*/
2103
2104static PyObject *
2105_asyncio_Task_print_stack_impl(TaskObj *self, PyObject *limit,
2106 PyObject *file)
Serhiy Storchakabca49392017-09-03 08:10:14 +03002107/*[clinic end generated code: output=7339e10314cd3f4d input=1a0352913b7fcd92]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002108{
2109 return PyObject_CallFunctionObjArgs(
2110 asyncio_task_print_stack_func, self, limit, file, NULL);
2111}
2112
2113/*[clinic input]
2114_asyncio.Task._step
2115
Serhiy Storchakabca49392017-09-03 08:10:14 +03002116 exc: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002117[clinic start generated code]*/
2118
2119static PyObject *
2120_asyncio_Task__step_impl(TaskObj *self, PyObject *exc)
Serhiy Storchakabca49392017-09-03 08:10:14 +03002121/*[clinic end generated code: output=7ed23f0cefd5ae42 input=1e19a985ace87ca4]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002122{
2123 return task_step(self, exc == Py_None ? NULL : exc);
2124}
2125
2126/*[clinic input]
2127_asyncio.Task._wakeup
2128
Serhiy Storchakabca49392017-09-03 08:10:14 +03002129 fut: object
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002130[clinic start generated code]*/
2131
2132static PyObject *
2133_asyncio_Task__wakeup_impl(TaskObj *self, PyObject *fut)
Serhiy Storchakabca49392017-09-03 08:10:14 +03002134/*[clinic end generated code: output=75cb341c760fd071 input=6a0616406f829a7b]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002135{
2136 return task_wakeup(self, fut);
2137}
2138
2139static void
2140TaskObj_finalize(TaskObj *task)
2141{
2142 _Py_IDENTIFIER(call_exception_handler);
2143 _Py_IDENTIFIER(task);
2144 _Py_IDENTIFIER(message);
2145 _Py_IDENTIFIER(source_traceback);
2146
Serhiy Storchakabca49392017-09-03 08:10:14 +03002147 PyObject *context;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002148 PyObject *message = NULL;
Serhiy Storchakabca49392017-09-03 08:10:14 +03002149 PyObject *func;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002150 PyObject *error_type, *error_value, *error_traceback;
2151
2152 if (task->task_state != STATE_PENDING || !task->task_log_destroy_pending) {
2153 goto done;
2154 }
2155
2156 /* Save the current exception, if any. */
2157 PyErr_Fetch(&error_type, &error_value, &error_traceback);
2158
2159 context = PyDict_New();
2160 if (context == NULL) {
2161 goto finally;
2162 }
2163
2164 message = PyUnicode_FromString("Task was destroyed but it is pending!");
2165 if (message == NULL) {
2166 goto finally;
2167 }
2168
2169 if (_PyDict_SetItemId(context, &PyId_message, message) < 0 ||
2170 _PyDict_SetItemId(context, &PyId_task, (PyObject*)task) < 0)
2171 {
2172 goto finally;
2173 }
2174
2175 if (task->task_source_tb != NULL) {
2176 if (_PyDict_SetItemId(context, &PyId_source_traceback,
2177 task->task_source_tb) < 0)
2178 {
2179 goto finally;
2180 }
2181 }
2182
2183 func = _PyObject_GetAttrId(task->task_loop, &PyId_call_exception_handler);
2184 if (func != NULL) {
Serhiy Storchakabca49392017-09-03 08:10:14 +03002185 PyObject *res = PyObject_CallFunctionObjArgs(func, context, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002186 if (res == NULL) {
2187 PyErr_WriteUnraisable(func);
2188 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03002189 else {
2190 Py_DECREF(res);
2191 }
2192 Py_DECREF(func);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002193 }
2194
2195finally:
Serhiy Storchakabca49392017-09-03 08:10:14 +03002196 Py_XDECREF(context);
2197 Py_XDECREF(message);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002198
2199 /* Restore the saved exception. */
2200 PyErr_Restore(error_type, error_value, error_traceback);
2201
2202done:
2203 FutureObj_finalize((FutureObj*)task);
2204}
2205
2206static void TaskObj_dealloc(PyObject *); /* Needs Task_CheckExact */
2207
2208static PyMethodDef TaskType_methods[] = {
2209 _ASYNCIO_FUTURE_RESULT_METHODDEF
2210 _ASYNCIO_FUTURE_EXCEPTION_METHODDEF
2211 _ASYNCIO_FUTURE_SET_RESULT_METHODDEF
2212 _ASYNCIO_FUTURE_SET_EXCEPTION_METHODDEF
2213 _ASYNCIO_FUTURE_ADD_DONE_CALLBACK_METHODDEF
2214 _ASYNCIO_FUTURE_REMOVE_DONE_CALLBACK_METHODDEF
2215 _ASYNCIO_FUTURE_CANCELLED_METHODDEF
2216 _ASYNCIO_FUTURE_DONE_METHODDEF
2217 _ASYNCIO_TASK_CURRENT_TASK_METHODDEF
2218 _ASYNCIO_TASK_ALL_TASKS_METHODDEF
2219 _ASYNCIO_TASK_CANCEL_METHODDEF
2220 _ASYNCIO_TASK_GET_STACK_METHODDEF
2221 _ASYNCIO_TASK_PRINT_STACK_METHODDEF
2222 _ASYNCIO_TASK__WAKEUP_METHODDEF
2223 _ASYNCIO_TASK__STEP_METHODDEF
2224 _ASYNCIO_TASK__REPR_INFO_METHODDEF
2225 {NULL, NULL} /* Sentinel */
2226};
2227
2228static PyGetSetDef TaskType_getsetlist[] = {
2229 FUTURE_COMMON_GETSETLIST
2230 {"_log_destroy_pending", (getter)TaskObj_get_log_destroy_pending,
2231 (setter)TaskObj_set_log_destroy_pending, NULL},
2232 {"_must_cancel", (getter)TaskObj_get_must_cancel, NULL, NULL},
2233 {"_coro", (getter)TaskObj_get_coro, NULL, NULL},
2234 {"_fut_waiter", (getter)TaskObj_get_fut_waiter, NULL, NULL},
2235 {NULL} /* Sentinel */
2236};
2237
2238static PyTypeObject TaskType = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02002239 PyVarObject_HEAD_INIT(NULL, 0)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002240 "_asyncio.Task",
2241 sizeof(TaskObj), /* tp_basicsize */
2242 .tp_base = &FutureType,
2243 .tp_dealloc = TaskObj_dealloc,
2244 .tp_as_async = &FutureType_as_async,
2245 .tp_repr = (reprfunc)FutureObj_repr,
2246 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE
2247 | Py_TPFLAGS_HAVE_FINALIZE,
2248 .tp_doc = _asyncio_Task___init____doc__,
2249 .tp_traverse = (traverseproc)TaskObj_traverse,
2250 .tp_clear = (inquiry)TaskObj_clear,
2251 .tp_weaklistoffset = offsetof(TaskObj, task_weakreflist),
2252 .tp_iter = (getiterfunc)future_new_iter,
2253 .tp_methods = TaskType_methods,
2254 .tp_getset = TaskType_getsetlist,
2255 .tp_dictoffset = offsetof(TaskObj, dict),
2256 .tp_init = (initproc)_asyncio_Task___init__,
2257 .tp_new = PyType_GenericNew,
2258 .tp_finalize = (destructor)TaskObj_finalize,
2259};
2260
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002261static void
2262TaskObj_dealloc(PyObject *self)
2263{
2264 TaskObj *task = (TaskObj *)self;
2265
2266 if (Task_CheckExact(self)) {
2267 /* When fut is subclass of Task, finalizer is called from
2268 * subtype_dealloc.
2269 */
2270 if (PyObject_CallFinalizerFromDealloc(self) < 0) {
2271 // resurrected.
2272 return;
2273 }
2274 }
2275
Alexander Mohrde34cbe2017-08-01 23:31:07 -07002276 PyObject_GC_UnTrack(self);
2277
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002278 if (task->task_weakreflist != NULL) {
2279 PyObject_ClearWeakRefs(self);
2280 }
2281
2282 (void)TaskObj_clear(task);
2283 Py_TYPE(task)->tp_free(task);
2284}
2285
2286static inline PyObject *
2287task_call_wakeup(TaskObj *task, PyObject *fut)
2288{
2289 if (Task_CheckExact(task)) {
2290 return task_wakeup(task, fut);
2291 }
2292 else {
2293 /* `task` is a subclass of Task */
Victor Stinnerb6ed57d2016-12-09 14:24:02 +01002294 return _PyObject_CallMethodIdObjArgs((PyObject*)task, &PyId__wakeup,
2295 fut, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002296 }
2297}
2298
2299static inline PyObject *
2300task_call_step(TaskObj *task, PyObject *arg)
2301{
2302 if (Task_CheckExact(task)) {
2303 return task_step(task, arg);
2304 }
2305 else {
2306 /* `task` is a subclass of Task */
Victor Stinnerb6ed57d2016-12-09 14:24:02 +01002307 return _PyObject_CallMethodIdObjArgs((PyObject*)task, &PyId__step,
2308 arg, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002309 }
2310}
2311
2312static int
2313task_call_step_soon(TaskObj *task, PyObject *arg)
2314{
Serhiy Storchakabca49392017-09-03 08:10:14 +03002315 PyObject *cb = TaskStepMethWrapper_new(task, arg);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002316 if (cb == NULL) {
2317 return -1;
2318 }
2319
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05002320 int ret = call_soon(task->task_loop, cb, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002321 Py_DECREF(cb);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05002322 return ret;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002323}
2324
2325static PyObject *
2326task_set_error_soon(TaskObj *task, PyObject *et, const char *format, ...)
2327{
2328 PyObject* msg;
2329
2330 va_list vargs;
2331#ifdef HAVE_STDARG_PROTOTYPES
2332 va_start(vargs, format);
2333#else
2334 va_start(vargs);
2335#endif
2336 msg = PyUnicode_FromFormatV(format, vargs);
2337 va_end(vargs);
2338
2339 if (msg == NULL) {
2340 return NULL;
2341 }
2342
Victor Stinnerde4ae3d2016-12-04 22:59:09 +01002343 PyObject *e = PyObject_CallFunctionObjArgs(et, msg, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002344 Py_DECREF(msg);
2345 if (e == NULL) {
2346 return NULL;
2347 }
2348
2349 if (task_call_step_soon(task, e) == -1) {
2350 Py_DECREF(e);
2351 return NULL;
2352 }
2353
2354 Py_DECREF(e);
2355 Py_RETURN_NONE;
2356}
2357
2358static PyObject *
2359task_step_impl(TaskObj *task, PyObject *exc)
2360{
2361 int res;
2362 int clear_exc = 0;
2363 PyObject *result = NULL;
Serhiy Storchakabca49392017-09-03 08:10:14 +03002364 PyObject *coro;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002365 PyObject *o;
2366
2367 if (task->task_state != STATE_PENDING) {
2368 PyErr_Format(PyExc_AssertionError,
2369 "_step(): already done: %R %R",
2370 task,
2371 exc ? exc : Py_None);
INADA Naokic411a7d2016-10-18 11:48:14 +09002372 goto fail;
2373 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09002374
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002375 if (task->task_must_cancel) {
2376 assert(exc != Py_None);
2377
2378 if (exc) {
2379 /* Check if exc is a CancelledError */
2380 res = PyObject_IsInstance(exc, asyncio_CancelledError);
2381 if (res == -1) {
2382 /* An error occurred, abort */
2383 goto fail;
2384 }
2385 if (res == 0) {
2386 /* exc is not CancelledError; reset it to NULL */
2387 exc = NULL;
2388 }
2389 }
2390
2391 if (!exc) {
2392 /* exc was not a CancelledError */
Victor Stinnerf17c3de2016-12-06 18:46:19 +01002393 exc = _PyObject_CallNoArg(asyncio_CancelledError);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002394 if (!exc) {
2395 goto fail;
2396 }
2397 clear_exc = 1;
2398 }
2399
2400 task->task_must_cancel = 0;
2401 }
2402
2403 Py_CLEAR(task->task_fut_waiter);
2404
Serhiy Storchakabca49392017-09-03 08:10:14 +03002405 coro = task->task_coro;
2406 if (coro == NULL) {
2407 PyErr_SetString(PyExc_RuntimeError, "uninitialized Task object");
2408 return NULL;
2409 }
2410
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002411 if (exc == NULL) {
2412 if (PyGen_CheckExact(coro) || PyCoro_CheckExact(coro)) {
2413 result = _PyGen_Send((PyGenObject*)coro, Py_None);
2414 }
2415 else {
Victor Stinnerb6ed57d2016-12-09 14:24:02 +01002416 result = _PyObject_CallMethodIdObjArgs(coro, &PyId_send,
2417 Py_None, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002418 }
2419 }
2420 else {
Victor Stinnerb6ed57d2016-12-09 14:24:02 +01002421 result = _PyObject_CallMethodIdObjArgs(coro, &PyId_throw,
2422 exc, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002423 if (clear_exc) {
2424 /* We created 'exc' during this call */
Serhiy Storchakabca49392017-09-03 08:10:14 +03002425 Py_DECREF(exc);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002426 }
2427 }
2428
2429 if (result == NULL) {
2430 PyObject *et, *ev, *tb;
2431
2432 if (_PyGen_FetchStopIterationValue(&o) == 0) {
2433 /* The error is StopIteration and that means that
2434 the underlying coroutine has resolved */
INADA Naoki991adca2017-05-11 21:18:38 +09002435 if (task->task_must_cancel) {
2436 // Task is cancelled right before coro stops.
2437 Py_DECREF(o);
2438 task->task_must_cancel = 0;
2439 et = asyncio_CancelledError;
2440 Py_INCREF(et);
2441 ev = NULL;
2442 tb = NULL;
2443 goto set_exception;
2444 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002445 PyObject *res = future_set_result((FutureObj*)task, o);
2446 Py_DECREF(o);
2447 if (res == NULL) {
2448 return NULL;
2449 }
2450 Py_DECREF(res);
2451 Py_RETURN_NONE;
2452 }
2453
2454 if (PyErr_ExceptionMatches(asyncio_CancelledError)) {
2455 /* CancelledError */
2456 PyErr_Clear();
2457 return future_cancel((FutureObj*)task);
2458 }
2459
2460 /* Some other exception; pop it and call Task.set_exception() */
2461 PyErr_Fetch(&et, &ev, &tb);
INADA Naoki991adca2017-05-11 21:18:38 +09002462
2463set_exception:
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002464 assert(et);
2465 if (!ev || !PyObject_TypeCheck(ev, (PyTypeObject *) et)) {
2466 PyErr_NormalizeException(&et, &ev, &tb);
2467 }
Yury Selivanovedfe8862016-12-01 11:37:47 -05002468 if (tb != NULL) {
2469 PyException_SetTraceback(ev, tb);
2470 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002471 o = future_set_exception((FutureObj*)task, ev);
2472 if (!o) {
2473 /* An exception in Task.set_exception() */
Serhiy Storchakabca49392017-09-03 08:10:14 +03002474 Py_DECREF(et);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002475 Py_XDECREF(tb);
2476 Py_XDECREF(ev);
2477 goto fail;
2478 }
2479 assert(o == Py_None);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002480 Py_DECREF(o);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002481
2482 if (!PyErr_GivenExceptionMatches(et, PyExc_Exception)) {
2483 /* We've got a BaseException; re-raise it */
2484 PyErr_Restore(et, ev, tb);
2485 goto fail;
2486 }
2487
Serhiy Storchakabca49392017-09-03 08:10:14 +03002488 Py_DECREF(et);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002489 Py_XDECREF(tb);
2490 Py_XDECREF(ev);
2491
2492 Py_RETURN_NONE;
2493 }
2494
2495 if (result == (PyObject*)task) {
2496 /* We have a task that wants to await on itself */
2497 goto self_await;
2498 }
2499
2500 /* Check if `result` is FutureObj or TaskObj (and not a subclass) */
2501 if (Future_CheckExact(result) || Task_CheckExact(result)) {
2502 PyObject *wrapper;
2503 PyObject *res;
2504 FutureObj *fut = (FutureObj*)result;
2505
2506 /* Check if `result` future is attached to a different loop */
2507 if (fut->fut_loop != task->task_loop) {
2508 goto different_loop;
2509 }
2510
2511 if (fut->fut_blocking) {
2512 fut->fut_blocking = 0;
2513
2514 /* result.add_done_callback(task._wakeup) */
2515 wrapper = TaskWakeupMethWrapper_new(task);
2516 if (wrapper == NULL) {
2517 goto fail;
2518 }
2519 res = future_add_done_callback((FutureObj*)result, wrapper);
2520 Py_DECREF(wrapper);
2521 if (res == NULL) {
2522 goto fail;
2523 }
2524 Py_DECREF(res);
2525
2526 /* task._fut_waiter = result */
2527 task->task_fut_waiter = result; /* no incref is necessary */
2528
2529 if (task->task_must_cancel) {
2530 PyObject *r;
2531 r = future_cancel(fut);
2532 if (r == NULL) {
2533 return NULL;
2534 }
2535 if (r == Py_True) {
2536 task->task_must_cancel = 0;
2537 }
2538 Py_DECREF(r);
2539 }
2540
2541 Py_RETURN_NONE;
2542 }
2543 else {
2544 goto yield_insteadof_yf;
2545 }
2546 }
2547
2548 /* Check if `result` is a Future-compatible object */
2549 o = PyObject_GetAttrString(result, "_asyncio_future_blocking");
2550 if (o == NULL) {
2551 if (PyErr_ExceptionMatches(PyExc_AttributeError)) {
2552 PyErr_Clear();
2553 }
2554 else {
2555 goto fail;
2556 }
2557 }
2558 else {
2559 if (o == Py_None) {
Serhiy Storchakabca49392017-09-03 08:10:14 +03002560 Py_DECREF(o);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002561 }
2562 else {
2563 /* `result` is a Future-compatible object */
2564 PyObject *wrapper;
2565 PyObject *res;
2566
2567 int blocking = PyObject_IsTrue(o);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002568 Py_DECREF(o);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002569 if (blocking < 0) {
2570 goto fail;
2571 }
2572
2573 /* Check if `result` future is attached to a different loop */
2574 PyObject *oloop = PyObject_GetAttrString(result, "_loop");
2575 if (oloop == NULL) {
2576 goto fail;
2577 }
2578 if (oloop != task->task_loop) {
2579 Py_DECREF(oloop);
2580 goto different_loop;
2581 }
2582 else {
2583 Py_DECREF(oloop);
2584 }
2585
2586 if (blocking) {
2587 /* result._asyncio_future_blocking = False */
2588 if (PyObject_SetAttrString(
2589 result, "_asyncio_future_blocking", Py_False) == -1) {
2590 goto fail;
2591 }
2592
2593 /* result.add_done_callback(task._wakeup) */
2594 wrapper = TaskWakeupMethWrapper_new(task);
2595 if (wrapper == NULL) {
2596 goto fail;
2597 }
Victor Stinnerb6ed57d2016-12-09 14:24:02 +01002598 res = _PyObject_CallMethodIdObjArgs(result,
2599 &PyId_add_done_callback,
2600 wrapper, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002601 Py_DECREF(wrapper);
2602 if (res == NULL) {
2603 goto fail;
2604 }
2605 Py_DECREF(res);
2606
2607 /* task._fut_waiter = result */
2608 task->task_fut_waiter = result; /* no incref is necessary */
2609
2610 if (task->task_must_cancel) {
2611 PyObject *r;
2612 int is_true;
2613 r = _PyObject_CallMethodId(result, &PyId_cancel, NULL);
2614 if (r == NULL) {
2615 return NULL;
2616 }
2617 is_true = PyObject_IsTrue(r);
2618 Py_DECREF(r);
2619 if (is_true < 0) {
2620 return NULL;
2621 }
2622 else if (is_true) {
2623 task->task_must_cancel = 0;
2624 }
2625 }
2626
2627 Py_RETURN_NONE;
2628 }
2629 else {
2630 goto yield_insteadof_yf;
2631 }
2632 }
2633 }
2634
2635 /* Check if `result` is None */
2636 if (result == Py_None) {
2637 /* Bare yield relinquishes control for one event loop iteration. */
2638 if (task_call_step_soon(task, NULL)) {
2639 goto fail;
2640 }
2641 return result;
2642 }
2643
2644 /* Check if `result` is a generator */
Victor Stinnerde4ae3d2016-12-04 22:59:09 +01002645 o = PyObject_CallFunctionObjArgs(inspect_isgenerator, result, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002646 if (o == NULL) {
2647 /* An exception in inspect.isgenerator */
2648 goto fail;
2649 }
2650 res = PyObject_IsTrue(o);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002651 Py_DECREF(o);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002652 if (res == -1) {
2653 /* An exception while checking if 'val' is True */
2654 goto fail;
2655 }
2656 if (res == 1) {
2657 /* `result` is a generator */
2658 PyObject *ret;
2659 ret = task_set_error_soon(
2660 task, PyExc_RuntimeError,
2661 "yield was used instead of yield from for "
2662 "generator in task %R with %S", task, result);
2663 Py_DECREF(result);
2664 return ret;
2665 }
2666
2667 /* The `result` is none of the above */
2668 Py_DECREF(result);
2669 return task_set_error_soon(
2670 task, PyExc_RuntimeError, "Task got bad yield: %R", result);
2671
2672self_await:
2673 o = task_set_error_soon(
2674 task, PyExc_RuntimeError,
2675 "Task cannot await on itself: %R", task);
2676 Py_DECREF(result);
2677 return o;
2678
2679yield_insteadof_yf:
2680 o = task_set_error_soon(
2681 task, PyExc_RuntimeError,
2682 "yield was used instead of yield from "
2683 "in task %R with %R",
2684 task, result);
2685 Py_DECREF(result);
2686 return o;
2687
2688different_loop:
2689 o = task_set_error_soon(
2690 task, PyExc_RuntimeError,
2691 "Task %R got Future %R attached to a different loop",
2692 task, result);
2693 Py_DECREF(result);
2694 return o;
2695
2696fail:
2697 Py_XDECREF(result);
2698 return NULL;
2699}
2700
2701static PyObject *
2702task_step(TaskObj *task, PyObject *exc)
2703{
2704 PyObject *res;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002705
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002706 if (enter_task(task->task_loop, (PyObject*)task) < 0) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002707 return NULL;
2708 }
2709
2710 res = task_step_impl(task, exc);
2711
2712 if (res == NULL) {
2713 PyObject *et, *ev, *tb;
2714 PyErr_Fetch(&et, &ev, &tb);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002715 leave_task(task->task_loop, (PyObject*)task);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002716 _PyErr_ChainExceptions(et, ev, tb);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002717 return NULL;
2718 }
2719 else {
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002720 if(leave_task(task->task_loop, (PyObject*)task) < 0) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002721 Py_DECREF(res);
2722 return NULL;
2723 }
2724 else {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002725 return res;
2726 }
2727 }
2728}
2729
2730static PyObject *
2731task_wakeup(TaskObj *task, PyObject *o)
2732{
Serhiy Storchakabca49392017-09-03 08:10:14 +03002733 PyObject *et, *ev, *tb;
2734 PyObject *result;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002735 assert(o);
2736
2737 if (Future_CheckExact(o) || Task_CheckExact(o)) {
2738 PyObject *fut_result = NULL;
2739 int res = future_get_result((FutureObj*)o, &fut_result);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002740
2741 switch(res) {
2742 case -1:
2743 assert(fut_result == NULL);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002744 break; /* exception raised */
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002745 case 0:
2746 Py_DECREF(fut_result);
2747 return task_call_step(task, NULL);
2748 default:
2749 assert(res == 1);
2750 result = task_call_step(task, fut_result);
2751 Py_DECREF(fut_result);
2752 return result;
2753 }
2754 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002755 else {
Serhiy Storchakabca49392017-09-03 08:10:14 +03002756 PyObject *fut_result = PyObject_CallMethod(o, "result", NULL);
2757 if (fut_result != NULL) {
2758 Py_DECREF(fut_result);
2759 return task_call_step(task, NULL);
2760 }
2761 /* exception raised */
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002762 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03002763
2764 PyErr_Fetch(&et, &ev, &tb);
2765 if (!PyErr_GivenExceptionMatches(et, PyExc_Exception)) {
2766 /* We've got a BaseException; re-raise it */
2767 PyErr_Restore(et, ev, tb);
2768 return NULL;
2769 }
2770 if (!ev || !PyObject_TypeCheck(ev, (PyTypeObject *) et)) {
2771 PyErr_NormalizeException(&et, &ev, &tb);
2772 }
2773
2774 result = task_call_step(task, ev);
2775
2776 Py_DECREF(et);
2777 Py_XDECREF(tb);
2778 Py_XDECREF(ev);
2779
2780 return result;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002781}
2782
2783
Yury Selivanova70232f2017-12-13 14:49:42 -05002784/*********************** Functions **************************/
2785
2786
2787/*[clinic input]
2788_asyncio._get_running_loop
2789
2790Return the running event loop or None.
2791
2792This is a low-level function intended to be used by event loops.
2793This function is thread-specific.
2794
2795[clinic start generated code]*/
2796
2797static PyObject *
2798_asyncio__get_running_loop_impl(PyObject *module)
2799/*[clinic end generated code: output=b4390af721411a0a input=0a21627e25a4bd43]*/
2800{
2801 PyObject *loop;
2802 if (get_running_loop(&loop)) {
2803 return NULL;
2804 }
2805 if (loop == NULL) {
2806 /* There's no currently running event loop */
2807 Py_RETURN_NONE;
2808 }
2809 return loop;
2810}
2811
2812/*[clinic input]
2813_asyncio._set_running_loop
2814 loop: 'O'
2815 /
2816
2817Set the running event loop.
2818
2819This is a low-level function intended to be used by event loops.
2820This function is thread-specific.
2821[clinic start generated code]*/
2822
2823static PyObject *
2824_asyncio__set_running_loop(PyObject *module, PyObject *loop)
2825/*[clinic end generated code: output=ae56bf7a28ca189a input=4c9720233d606604]*/
2826{
2827 if (set_running_loop(loop)) {
2828 return NULL;
2829 }
2830 Py_RETURN_NONE;
2831}
2832
2833/*[clinic input]
2834_asyncio.get_event_loop
2835
2836Return an asyncio event loop.
2837
2838When called from a coroutine or a callback (e.g. scheduled with
2839call_soon or similar API), this function will always return the
2840running event loop.
2841
2842If there is no running event loop set, the function will return
2843the result of `get_event_loop_policy().get_event_loop()` call.
2844[clinic start generated code]*/
2845
2846static PyObject *
2847_asyncio_get_event_loop_impl(PyObject *module)
2848/*[clinic end generated code: output=2a2d8b2f824c648b input=9364bf2916c8655d]*/
2849{
2850 return get_event_loop();
2851}
2852
2853/*[clinic input]
2854_asyncio.get_running_loop
2855
2856Return the running event loop. Raise a RuntimeError if there is none.
2857
2858This function is thread-specific.
2859[clinic start generated code]*/
2860
2861static PyObject *
2862_asyncio_get_running_loop_impl(PyObject *module)
2863/*[clinic end generated code: output=c247b5f9e529530e input=2a3bf02ba39f173d]*/
2864{
2865 PyObject *loop;
2866 if (get_running_loop(&loop)) {
2867 return NULL;
2868 }
2869 if (loop == NULL) {
2870 /* There's no currently running event loop */
2871 PyErr_SetString(
2872 PyExc_RuntimeError, "no running event loop");
2873 }
2874 return loop;
2875}
2876
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002877/*[clinic input]
2878_asyncio._register_task
2879
2880 loop: object
2881 task: object
2882
2883Register a new task in asyncio as executed by loop.
2884
2885Returns None.
2886[clinic start generated code]*/
2887
2888static PyObject *
2889_asyncio__register_task_impl(PyObject *module, PyObject *loop,
2890 PyObject *task)
2891/*[clinic end generated code: output=54c5cb733dbe0f38 input=9b5fee38fcb2c288]*/
2892{
2893 if (register_task(loop, task) < 0) {
2894 return NULL;
2895 }
2896 Py_RETURN_NONE;
2897}
2898
2899
2900/*[clinic input]
2901_asyncio._unregister_task
2902
2903 loop: object
2904 task: object
2905
2906Unregister a task.
2907
2908Returns None.
2909[clinic start generated code]*/
2910
2911static PyObject *
2912_asyncio__unregister_task_impl(PyObject *module, PyObject *loop,
2913 PyObject *task)
2914/*[clinic end generated code: output=f634743a76b84ebc input=51fa1820634ef331]*/
2915{
2916 if (unregister_task(loop, task) < 0) {
2917 return NULL;
2918 }
2919 Py_RETURN_NONE;
2920}
2921
2922
2923/*[clinic input]
2924_asyncio._enter_task
2925
2926 loop: object
2927 task: object
2928
2929Enter into task execution or resume suspended task.
2930
2931Task belongs to loop.
2932
2933Returns None.
2934[clinic start generated code]*/
2935
2936static PyObject *
2937_asyncio__enter_task_impl(PyObject *module, PyObject *loop, PyObject *task)
2938/*[clinic end generated code: output=a22611c858035b73 input=de1b06dca70d8737]*/
2939{
2940 if (enter_task(loop, task) < 0) {
2941 return NULL;
2942 }
2943 Py_RETURN_NONE;
2944}
2945
2946
2947/*[clinic input]
2948_asyncio._leave_task
2949
2950 loop: object
2951 task: object
2952
2953Leave task execution or suspend a task.
2954
2955Task belongs to loop.
2956
2957Returns None.
2958[clinic start generated code]*/
2959
2960static PyObject *
2961_asyncio__leave_task_impl(PyObject *module, PyObject *loop, PyObject *task)
2962/*[clinic end generated code: output=0ebf6db4b858fb41 input=51296a46313d1ad8]*/
2963{
2964 if (leave_task(loop, task) < 0) {
2965 return NULL;
2966 }
2967 Py_RETURN_NONE;
2968}
2969
Yury Selivanova70232f2017-12-13 14:49:42 -05002970
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002971/*********************** Module **************************/
2972
2973
2974static void
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05002975module_free_freelists()
2976{
2977 PyObject *next;
2978 PyObject *current;
2979
2980 next = (PyObject*) fi_freelist;
2981 while (next != NULL) {
2982 assert(fi_freelist_len > 0);
2983 fi_freelist_len--;
2984
2985 current = next;
2986 next = (PyObject*) ((futureiterobject*) current)->future;
2987 PyObject_GC_Del(current);
2988 }
2989 assert(fi_freelist_len == 0);
2990 fi_freelist = NULL;
2991}
2992
2993
2994static void
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002995module_free(void *m)
2996{
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002997 Py_CLEAR(asyncio_mod);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002998 Py_CLEAR(inspect_isgenerator);
Yury Selivanova70232f2017-12-13 14:49:42 -05002999 Py_CLEAR(os_getpid);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003000 Py_CLEAR(traceback_extract_stack);
3001 Py_CLEAR(asyncio_future_repr_info_func);
3002 Py_CLEAR(asyncio_get_event_loop_policy);
3003 Py_CLEAR(asyncio_iscoroutine_func);
3004 Py_CLEAR(asyncio_task_get_stack_func);
3005 Py_CLEAR(asyncio_task_print_stack_func);
3006 Py_CLEAR(asyncio_task_repr_info_func);
3007 Py_CLEAR(asyncio_InvalidStateError);
3008 Py_CLEAR(asyncio_CancelledError);
3009
3010 Py_CLEAR(current_tasks);
3011 Py_CLEAR(all_tasks);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05003012
3013 module_free_freelists();
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003014}
3015
3016static int
3017module_init(void)
3018{
3019 PyObject *module = NULL;
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003020
3021 asyncio_mod = PyImport_ImportModule("asyncio");
3022 if (asyncio_mod == NULL) {
3023 goto fail;
3024 }
3025
3026 current_tasks = PyDict_New();
3027 if (current_tasks == NULL) {
3028 goto fail;
3029 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003030
3031#define WITH_MOD(NAME) \
3032 Py_CLEAR(module); \
3033 module = PyImport_ImportModule(NAME); \
3034 if (module == NULL) { \
Serhiy Storchakabca49392017-09-03 08:10:14 +03003035 goto fail; \
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003036 }
3037
3038#define GET_MOD_ATTR(VAR, NAME) \
3039 VAR = PyObject_GetAttrString(module, NAME); \
3040 if (VAR == NULL) { \
3041 goto fail; \
3042 }
3043
3044 WITH_MOD("asyncio.events")
Yury Selivanova70232f2017-12-13 14:49:42 -05003045 GET_MOD_ATTR(asyncio_get_event_loop_policy, "get_event_loop_policy")
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003046
3047 WITH_MOD("asyncio.base_futures")
3048 GET_MOD_ATTR(asyncio_future_repr_info_func, "_future_repr_info")
3049 GET_MOD_ATTR(asyncio_InvalidStateError, "InvalidStateError")
3050 GET_MOD_ATTR(asyncio_CancelledError, "CancelledError")
3051
3052 WITH_MOD("asyncio.base_tasks")
3053 GET_MOD_ATTR(asyncio_task_repr_info_func, "_task_repr_info")
3054 GET_MOD_ATTR(asyncio_task_get_stack_func, "_task_get_stack")
3055 GET_MOD_ATTR(asyncio_task_print_stack_func, "_task_print_stack")
3056
Andrew Svetlovf74ef452017-12-15 07:04:38 +02003057 WITH_MOD("asyncio.coroutines")
3058 GET_MOD_ATTR(asyncio_iscoroutine_func, "iscoroutine")
3059
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003060 WITH_MOD("inspect")
3061 GET_MOD_ATTR(inspect_isgenerator, "isgenerator")
3062
Yury Selivanova70232f2017-12-13 14:49:42 -05003063 WITH_MOD("os")
3064 GET_MOD_ATTR(os_getpid, "getpid")
3065
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003066 WITH_MOD("traceback")
3067 GET_MOD_ATTR(traceback_extract_stack, "extract_stack")
3068
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003069 PyObject *weak_key_dict;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003070 WITH_MOD("weakref")
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003071 GET_MOD_ATTR(weak_key_dict, "WeakKeyDictionary");
3072 all_tasks = _PyObject_CallNoArg(weak_key_dict);
3073 Py_CLEAR(weak_key_dict);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003074 if (all_tasks == NULL) {
INADA Naokic411a7d2016-10-18 11:48:14 +09003075 goto fail;
3076 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003077
Serhiy Storchakabca49392017-09-03 08:10:14 +03003078 Py_DECREF(module);
INADA Naokic411a7d2016-10-18 11:48:14 +09003079 return 0;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003080
INADA Naokic411a7d2016-10-18 11:48:14 +09003081fail:
INADA Naokic411a7d2016-10-18 11:48:14 +09003082 Py_CLEAR(module);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003083 module_free(NULL);
INADA Naokic411a7d2016-10-18 11:48:14 +09003084 return -1;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003085
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003086#undef WITH_MOD
3087#undef GET_MOD_ATTR
3088}
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003089
INADA Naokic411a7d2016-10-18 11:48:14 +09003090PyDoc_STRVAR(module_doc, "Accelerator module for asyncio");
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003091
Yury Selivanova70232f2017-12-13 14:49:42 -05003092static PyMethodDef asyncio_methods[] = {
3093 _ASYNCIO_GET_EVENT_LOOP_METHODDEF
3094 _ASYNCIO_GET_RUNNING_LOOP_METHODDEF
3095 _ASYNCIO__GET_RUNNING_LOOP_METHODDEF
3096 _ASYNCIO__SET_RUNNING_LOOP_METHODDEF
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003097 _ASYNCIO__REGISTER_TASK_METHODDEF
3098 _ASYNCIO__UNREGISTER_TASK_METHODDEF
3099 _ASYNCIO__ENTER_TASK_METHODDEF
3100 _ASYNCIO__LEAVE_TASK_METHODDEF
Yury Selivanova70232f2017-12-13 14:49:42 -05003101 {NULL, NULL}
3102};
3103
INADA Naoki9f2ce252016-10-15 15:39:19 +09003104static struct PyModuleDef _asynciomodule = {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003105 PyModuleDef_HEAD_INIT, /* m_base */
INADA Naoki9f2ce252016-10-15 15:39:19 +09003106 "_asyncio", /* m_name */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003107 module_doc, /* m_doc */
3108 -1, /* m_size */
Yury Selivanova70232f2017-12-13 14:49:42 -05003109 asyncio_methods, /* m_methods */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003110 NULL, /* m_slots */
3111 NULL, /* m_traverse */
3112 NULL, /* m_clear */
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003113 (freefunc)module_free /* m_free */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003114};
3115
3116
3117PyMODINIT_FUNC
INADA Naoki9f2ce252016-10-15 15:39:19 +09003118PyInit__asyncio(void)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003119{
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003120 if (module_init() < 0) {
INADA Naokic411a7d2016-10-18 11:48:14 +09003121 return NULL;
3122 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003123 if (PyType_Ready(&FutureType) < 0) {
3124 return NULL;
3125 }
3126 if (PyType_Ready(&FutureIterType) < 0) {
3127 return NULL;
3128 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03003129 if (PyType_Ready(&TaskStepMethWrapper_Type) < 0) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003130 return NULL;
3131 }
3132 if(PyType_Ready(&TaskWakeupMethWrapper_Type) < 0) {
3133 return NULL;
3134 }
3135 if (PyType_Ready(&TaskType) < 0) {
3136 return NULL;
3137 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003138
INADA Naoki9f2ce252016-10-15 15:39:19 +09003139 PyObject *m = PyModule_Create(&_asynciomodule);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003140 if (m == NULL) {
3141 return NULL;
3142 }
3143
3144 Py_INCREF(&FutureType);
3145 if (PyModule_AddObject(m, "Future", (PyObject *)&FutureType) < 0) {
3146 Py_DECREF(&FutureType);
3147 return NULL;
3148 }
3149
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003150 Py_INCREF(&TaskType);
3151 if (PyModule_AddObject(m, "Task", (PyObject *)&TaskType) < 0) {
3152 Py_DECREF(&TaskType);
3153 return NULL;
3154 }
3155
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003156 Py_INCREF(all_tasks);
3157 if (PyModule_AddObject(m, "_all_tasks", all_tasks) < 0) {
3158 Py_DECREF(all_tasks);
3159 return NULL;
3160 }
3161
3162 Py_INCREF(current_tasks);
3163 if (PyModule_AddObject(m, "_current_tasks", current_tasks) < 0) {
3164 Py_DECREF(current_tasks);
3165 return NULL;
3166 }
3167
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003168 return m;
3169}