blob: 01c38b80b95f8f25b09b4ea82c8a236adc12941c [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);
INADA Naoki9e4e38e2016-10-09 14:44:47 +090014_Py_IDENTIFIER(call_soon);
Yury Selivanova0c1ba62016-10-28 12:52:37 -040015_Py_IDENTIFIER(cancel);
Yury Selivanova70232f2017-12-13 14:49:42 -050016_Py_IDENTIFIER(get_event_loop);
Yury Selivanova0c1ba62016-10-28 12:52:37 -040017_Py_IDENTIFIER(send);
18_Py_IDENTIFIER(throw);
19_Py_IDENTIFIER(_step);
20_Py_IDENTIFIER(_schedule_callbacks);
21_Py_IDENTIFIER(_wakeup);
INADA Naoki9e4e38e2016-10-09 14:44:47 +090022
23
INADA Naoki9f2ce252016-10-15 15:39:19 +090024/* State of the _asyncio module */
Yury Selivanova0c1ba62016-10-28 12:52:37 -040025static PyObject *all_tasks;
Yury Selivanov684ef2c2016-10-28 19:01:21 -040026static PyObject *current_tasks;
INADA Naoki9e4e38e2016-10-09 14:44:47 +090027static PyObject *traceback_extract_stack;
Yury Selivanova70232f2017-12-13 14:49:42 -050028static PyObject *asyncio_get_event_loop_policy;
Yury Selivanova0c1ba62016-10-28 12:52:37 -040029static PyObject *asyncio_future_repr_info_func;
30static PyObject *asyncio_task_repr_info_func;
31static PyObject *asyncio_task_get_stack_func;
32static PyObject *asyncio_task_print_stack_func;
INADA Naoki9e4e38e2016-10-09 14:44:47 +090033static PyObject *asyncio_InvalidStateError;
34static PyObject *asyncio_CancelledError;
Yury Selivanova0c1ba62016-10-28 12:52:37 -040035static PyObject *inspect_isgenerator;
Yury Selivanova70232f2017-12-13 14:49:42 -050036static PyObject *os_getpid;
INADA Naoki9e4e38e2016-10-09 14:44:47 +090037
38
INADA Naoki9e4e38e2016-10-09 14:44:47 +090039typedef enum {
40 STATE_PENDING,
41 STATE_CANCELLED,
42 STATE_FINISHED
43} fut_state;
44
Yury Selivanova0c1ba62016-10-28 12:52:37 -040045#define FutureObj_HEAD(prefix) \
46 PyObject_HEAD \
47 PyObject *prefix##_loop; \
48 PyObject *prefix##_callbacks; \
49 PyObject *prefix##_exception; \
50 PyObject *prefix##_result; \
51 PyObject *prefix##_source_tb; \
52 fut_state prefix##_state; \
53 int prefix##_log_tb; \
54 int prefix##_blocking; \
55 PyObject *dict; \
56 PyObject *prefix##_weakreflist;
57
58typedef struct {
59 FutureObj_HEAD(fut)
60} FutureObj;
61
62typedef struct {
63 FutureObj_HEAD(task)
64 PyObject *task_fut_waiter;
65 PyObject *task_coro;
66 int task_must_cancel;
67 int task_log_destroy_pending;
68} TaskObj;
INADA Naoki9e4e38e2016-10-09 14:44:47 +090069
70typedef struct {
71 PyObject_HEAD
Yury Selivanova0c1ba62016-10-28 12:52:37 -040072 TaskObj *sw_task;
73 PyObject *sw_arg;
Serhiy Storchakabca49392017-09-03 08:10:14 +030074} TaskStepMethWrapper;
INADA Naoki9e4e38e2016-10-09 14:44:47 +090075
Yury Selivanova0c1ba62016-10-28 12:52:37 -040076typedef struct {
77 PyObject_HEAD
78 TaskObj *ww_task;
79} TaskWakeupMethWrapper;
80
81
82#include "clinic/_asynciomodule.c.h"
83
84
85/*[clinic input]
86class _asyncio.Future "FutureObj *" "&Future_Type"
87[clinic start generated code]*/
88/*[clinic end generated code: output=da39a3ee5e6b4b0d input=00d3e4abca711e0f]*/
89
90/* Get FutureIter from Future */
91static PyObject* future_new_iter(PyObject *);
92static inline int future_call_schedule_callbacks(FutureObj *);
INADA Naoki9e4e38e2016-10-09 14:44:47 +090093
Yury Selivanova70232f2017-12-13 14:49:42 -050094
95static int
96get_running_loop(PyObject **loop)
97{
98 PyObject *ts_dict;
99 PyObject *running_tuple;
100 PyObject *running_loop;
101 PyObject *running_loop_pid;
102 PyObject *current_pid;
103 int same_pid;
104
105 ts_dict = PyThreadState_GetDict(); // borrowed
106 if (ts_dict == NULL) {
107 PyErr_SetString(
108 PyExc_RuntimeError, "thread-local storage is not available");
109 goto error;
110 }
111
112 running_tuple = _PyDict_GetItemId(
113 ts_dict, &PyId___asyncio_running_event_loop__); // borrowed
114 if (running_tuple == NULL) {
115 /* _PyDict_GetItemId doesn't set an error if key is not found */
116 goto not_found;
117 }
118
119 assert(PyTuple_CheckExact(running_tuple));
120 assert(PyTuple_Size(running_tuple) == 2);
121 running_loop = PyTuple_GET_ITEM(running_tuple, 0); // borrowed
122 running_loop_pid = PyTuple_GET_ITEM(running_tuple, 1); // borrowed
123
124 if (running_loop == Py_None) {
125 goto not_found;
126 }
127
128 current_pid = _PyObject_CallNoArg(os_getpid);
129 if (current_pid == NULL) {
130 goto error;
131 }
132 same_pid = PyObject_RichCompareBool(current_pid, running_loop_pid, Py_EQ);
133 Py_DECREF(current_pid);
134 if (same_pid == -1) {
135 goto error;
136 }
137
138 if (same_pid) {
139 // current_pid == running_loop_pid
140 goto found;
141 }
142
143not_found:
144 *loop = NULL;
145 return 0;
146
147found:
148 Py_INCREF(running_loop);
149 *loop = running_loop;
150 return 0;
151
152error:
153 *loop = NULL;
154 return -1;
155}
156
157
158static int
159set_running_loop(PyObject *loop)
160{
161 PyObject *ts_dict;
162 PyObject *running_tuple;
163 PyObject *current_pid;
164
165 ts_dict = PyThreadState_GetDict(); // borrowed
166 if (ts_dict == NULL) {
167 PyErr_SetString(
168 PyExc_RuntimeError, "thread-local storage is not available");
169 return -1;
170 }
171
172 current_pid = _PyObject_CallNoArg(os_getpid);
173 if (current_pid == NULL) {
174 return -1;
175 }
176
177 running_tuple = PyTuple_New(2);
178 if (running_tuple == NULL) {
179 Py_DECREF(current_pid);
180 return -1;
181 }
182
183 Py_INCREF(loop);
184 PyTuple_SET_ITEM(running_tuple, 0, loop);
185 PyTuple_SET_ITEM(running_tuple, 1, current_pid); // borrowed
186
187 if (_PyDict_SetItemId(
188 ts_dict, &PyId___asyncio_running_event_loop__, running_tuple)) {
189 Py_DECREF(running_tuple); // will cleanup loop & current_pid
190 return -1;
191 }
192 Py_DECREF(running_tuple);
193
194 return 0;
195}
196
197
198static PyObject *
199get_event_loop(void)
200{
201 PyObject *loop;
202 PyObject *policy;
203
204 if (get_running_loop(&loop)) {
205 return NULL;
206 }
207 if (loop != NULL) {
208 return loop;
209 }
210
211 policy = _PyObject_CallNoArg(asyncio_get_event_loop_policy);
212 if (policy == NULL) {
213 return NULL;
214 }
215
216 loop = _PyObject_CallMethodId(policy, &PyId_get_event_loop, NULL);
217 Py_DECREF(policy);
218 return loop;
219}
220
221
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900222static int
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400223future_schedule_callbacks(FutureObj *fut)
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900224{
225 Py_ssize_t len;
Serhiy Storchakabca49392017-09-03 08:10:14 +0300226 PyObject *callbacks;
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900227 int i;
228
229 if (fut->fut_callbacks == NULL) {
Serhiy Storchakabca49392017-09-03 08:10:14 +0300230 PyErr_SetString(PyExc_RuntimeError, "uninitialized Future object");
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900231 return -1;
232 }
233
234 len = PyList_GET_SIZE(fut->fut_callbacks);
235 if (len == 0) {
236 return 0;
237 }
238
Serhiy Storchakabca49392017-09-03 08:10:14 +0300239 callbacks = PyList_GetSlice(fut->fut_callbacks, 0, len);
240 if (callbacks == NULL) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900241 return -1;
242 }
243 if (PyList_SetSlice(fut->fut_callbacks, 0, len, NULL) < 0) {
Serhiy Storchakabca49392017-09-03 08:10:14 +0300244 Py_DECREF(callbacks);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900245 return -1;
246 }
247
248 for (i = 0; i < len; i++) {
Serhiy Storchakabca49392017-09-03 08:10:14 +0300249 PyObject *handle;
250 PyObject *cb = PyList_GET_ITEM(callbacks, i);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900251
Victor Stinnerb6ed57d2016-12-09 14:24:02 +0100252 handle = _PyObject_CallMethodIdObjArgs(fut->fut_loop, &PyId_call_soon,
253 cb, fut, NULL);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900254
255 if (handle == NULL) {
Serhiy Storchakabca49392017-09-03 08:10:14 +0300256 Py_DECREF(callbacks);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900257 return -1;
258 }
Serhiy Storchakabca49392017-09-03 08:10:14 +0300259 Py_DECREF(handle);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900260 }
261
Serhiy Storchakabca49392017-09-03 08:10:14 +0300262 Py_DECREF(callbacks);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900263 return 0;
264}
265
266static int
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400267future_init(FutureObj *fut, PyObject *loop)
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900268{
Serhiy Storchakabca49392017-09-03 08:10:14 +0300269 PyObject *res;
270 int is_true;
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900271 _Py_IDENTIFIER(get_debug);
272
Serhiy Storchakabca49392017-09-03 08:10:14 +0300273 if (loop == Py_None) {
Yury Selivanova70232f2017-12-13 14:49:42 -0500274 loop = get_event_loop();
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900275 if (loop == NULL) {
276 return -1;
277 }
278 }
279 else {
280 Py_INCREF(loop);
281 }
Serhiy Storchakabca49392017-09-03 08:10:14 +0300282 Py_XSETREF(fut->fut_loop, loop);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900283
Victor Stinnerf94d1ee2016-10-29 09:05:39 +0200284 res = _PyObject_CallMethodId(fut->fut_loop, &PyId_get_debug, NULL);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900285 if (res == NULL) {
286 return -1;
287 }
Serhiy Storchakabca49392017-09-03 08:10:14 +0300288 is_true = PyObject_IsTrue(res);
289 Py_DECREF(res);
290 if (is_true < 0) {
291 return -1;
292 }
293 if (is_true) {
294 Py_XSETREF(fut->fut_source_tb, _PyObject_CallNoArg(traceback_extract_stack));
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900295 if (fut->fut_source_tb == NULL) {
296 return -1;
297 }
298 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900299
Serhiy Storchakabca49392017-09-03 08:10:14 +0300300 Py_XSETREF(fut->fut_callbacks, PyList_New(0));
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900301 if (fut->fut_callbacks == NULL) {
302 return -1;
303 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400304
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900305 return 0;
306}
307
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900308static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400309future_set_result(FutureObj *fut, PyObject *res)
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900310{
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900311 if (fut->fut_state != STATE_PENDING) {
312 PyErr_SetString(asyncio_InvalidStateError, "invalid state");
313 return NULL;
314 }
315
Serhiy Storchakabca49392017-09-03 08:10:14 +0300316 assert(!fut->fut_result);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900317 Py_INCREF(res);
318 fut->fut_result = res;
319 fut->fut_state = STATE_FINISHED;
320
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400321 if (future_call_schedule_callbacks(fut) == -1) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900322 return NULL;
323 }
324 Py_RETURN_NONE;
325}
326
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900327static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400328future_set_exception(FutureObj *fut, PyObject *exc)
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900329{
330 PyObject *exc_val = NULL;
331
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900332 if (fut->fut_state != STATE_PENDING) {
333 PyErr_SetString(asyncio_InvalidStateError, "invalid state");
334 return NULL;
335 }
336
337 if (PyExceptionClass_Check(exc)) {
Victor Stinnera5ed5f02016-12-06 18:45:50 +0100338 exc_val = _PyObject_CallNoArg(exc);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900339 if (exc_val == NULL) {
340 return NULL;
341 }
Serhiy Storchakabca49392017-09-03 08:10:14 +0300342 if (fut->fut_state != STATE_PENDING) {
343 Py_DECREF(exc_val);
344 PyErr_SetString(asyncio_InvalidStateError, "invalid state");
345 return NULL;
346 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900347 }
348 else {
349 exc_val = exc;
350 Py_INCREF(exc_val);
351 }
352 if (!PyExceptionInstance_Check(exc_val)) {
353 Py_DECREF(exc_val);
354 PyErr_SetString(PyExc_TypeError, "invalid exception object");
355 return NULL;
356 }
357 if ((PyObject*)Py_TYPE(exc_val) == PyExc_StopIteration) {
358 Py_DECREF(exc_val);
359 PyErr_SetString(PyExc_TypeError,
360 "StopIteration interacts badly with generators "
361 "and cannot be raised into a Future");
362 return NULL;
363 }
364
Serhiy Storchakabca49392017-09-03 08:10:14 +0300365 assert(!fut->fut_exception);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900366 fut->fut_exception = exc_val;
367 fut->fut_state = STATE_FINISHED;
368
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400369 if (future_call_schedule_callbacks(fut) == -1) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900370 return NULL;
371 }
372
373 fut->fut_log_tb = 1;
374 Py_RETURN_NONE;
375}
376
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400377static int
378future_get_result(FutureObj *fut, PyObject **result)
379{
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400380 if (fut->fut_state == STATE_CANCELLED) {
Serhiy Storchakabca49392017-09-03 08:10:14 +0300381 PyErr_SetNone(asyncio_CancelledError);
382 return -1;
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400383 }
384
385 if (fut->fut_state != STATE_FINISHED) {
Serhiy Storchakabca49392017-09-03 08:10:14 +0300386 PyErr_SetString(asyncio_InvalidStateError, "Result is not set.");
387 return -1;
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400388 }
389
390 fut->fut_log_tb = 0;
391 if (fut->fut_exception != NULL) {
392 Py_INCREF(fut->fut_exception);
393 *result = fut->fut_exception;
394 return 1;
395 }
396
397 Py_INCREF(fut->fut_result);
398 *result = fut->fut_result;
399 return 0;
400}
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900401
402static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400403future_add_done_callback(FutureObj *fut, PyObject *arg)
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900404{
405 if (fut->fut_state != STATE_PENDING) {
Victor Stinnerb6ed57d2016-12-09 14:24:02 +0100406 PyObject *handle = _PyObject_CallMethodIdObjArgs(fut->fut_loop,
407 &PyId_call_soon,
408 arg, fut, NULL);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900409 if (handle == NULL) {
410 return NULL;
411 }
Serhiy Storchakabca49392017-09-03 08:10:14 +0300412 Py_DECREF(handle);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900413 }
414 else {
Serhiy Storchakabca49392017-09-03 08:10:14 +0300415 if (fut->fut_callbacks == NULL) {
416 PyErr_SetString(PyExc_RuntimeError, "uninitialized Future object");
417 return NULL;
418 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900419 int err = PyList_Append(fut->fut_callbacks, arg);
420 if (err != 0) {
421 return NULL;
422 }
423 }
424 Py_RETURN_NONE;
425}
426
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400427static PyObject *
428future_cancel(FutureObj *fut)
429{
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +0000430 fut->fut_log_tb = 0;
431
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400432 if (fut->fut_state != STATE_PENDING) {
433 Py_RETURN_FALSE;
434 }
435 fut->fut_state = STATE_CANCELLED;
436
437 if (future_call_schedule_callbacks(fut) == -1) {
438 return NULL;
439 }
440
441 Py_RETURN_TRUE;
442}
443
444/*[clinic input]
445_asyncio.Future.__init__
446
447 *
Serhiy Storchakabca49392017-09-03 08:10:14 +0300448 loop: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400449
450This class is *almost* compatible with concurrent.futures.Future.
451
452 Differences:
453
454 - result() and exception() do not take a timeout argument and
455 raise an exception when the future isn't done yet.
456
457 - Callbacks registered with add_done_callback() are always called
458 via the event loop's call_soon_threadsafe().
459
460 - This class is not compatible with the wait() and as_completed()
461 methods in the concurrent.futures package.
462[clinic start generated code]*/
463
464static int
465_asyncio_Future___init___impl(FutureObj *self, PyObject *loop)
Serhiy Storchakabca49392017-09-03 08:10:14 +0300466/*[clinic end generated code: output=9ed75799eaccb5d6 input=89af317082bc0bf8]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400467
468{
469 return future_init(self, loop);
470}
471
472static int
473FutureObj_clear(FutureObj *fut)
474{
475 Py_CLEAR(fut->fut_loop);
476 Py_CLEAR(fut->fut_callbacks);
477 Py_CLEAR(fut->fut_result);
478 Py_CLEAR(fut->fut_exception);
479 Py_CLEAR(fut->fut_source_tb);
480 Py_CLEAR(fut->dict);
481 return 0;
482}
483
484static int
485FutureObj_traverse(FutureObj *fut, visitproc visit, void *arg)
486{
487 Py_VISIT(fut->fut_loop);
488 Py_VISIT(fut->fut_callbacks);
489 Py_VISIT(fut->fut_result);
490 Py_VISIT(fut->fut_exception);
491 Py_VISIT(fut->fut_source_tb);
492 Py_VISIT(fut->dict);
493 return 0;
494}
495
496/*[clinic input]
497_asyncio.Future.result
498
499Return the result this future represents.
500
501If the future has been cancelled, raises CancelledError. If the
502future's result isn't yet available, raises InvalidStateError. If
503the future is done and has an exception set, this exception is raised.
504[clinic start generated code]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900505
506static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400507_asyncio_Future_result_impl(FutureObj *self)
508/*[clinic end generated code: output=f35f940936a4b1e5 input=49ecf9cf5ec50dc5]*/
509{
510 PyObject *result;
511 int res = future_get_result(self, &result);
512
513 if (res == -1) {
514 return NULL;
515 }
516
517 if (res == 0) {
518 return result;
519 }
520
521 assert(res == 1);
522
523 PyErr_SetObject(PyExceptionInstance_Class(result), result);
524 Py_DECREF(result);
525 return NULL;
526}
527
528/*[clinic input]
529_asyncio.Future.exception
530
531Return the exception that was set on this future.
532
533The exception (or None if no exception was set) is returned only if
534the future is done. If the future has been cancelled, raises
535CancelledError. If the future isn't done yet, raises
536InvalidStateError.
537[clinic start generated code]*/
538
539static PyObject *
540_asyncio_Future_exception_impl(FutureObj *self)
541/*[clinic end generated code: output=88b20d4f855e0710 input=733547a70c841c68]*/
542{
543 if (self->fut_state == STATE_CANCELLED) {
Serhiy Storchakabca49392017-09-03 08:10:14 +0300544 PyErr_SetNone(asyncio_CancelledError);
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400545 return NULL;
546 }
547
548 if (self->fut_state != STATE_FINISHED) {
Serhiy Storchakabca49392017-09-03 08:10:14 +0300549 PyErr_SetString(asyncio_InvalidStateError, "Exception is not set.");
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400550 return NULL;
551 }
552
553 if (self->fut_exception != NULL) {
554 self->fut_log_tb = 0;
555 Py_INCREF(self->fut_exception);
556 return self->fut_exception;
557 }
558
559 Py_RETURN_NONE;
560}
561
562/*[clinic input]
563_asyncio.Future.set_result
564
Serhiy Storchakabca49392017-09-03 08:10:14 +0300565 res: object
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400566 /
567
568Mark the future done and set its result.
569
570If the future is already done when this method is called, raises
571InvalidStateError.
572[clinic start generated code]*/
573
574static PyObject *
575_asyncio_Future_set_result(FutureObj *self, PyObject *res)
Serhiy Storchakabca49392017-09-03 08:10:14 +0300576/*[clinic end generated code: output=a620abfc2796bfb6 input=5b9dc180f1baa56d]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400577{
578 return future_set_result(self, res);
579}
580
581/*[clinic input]
582_asyncio.Future.set_exception
583
Serhiy Storchakabca49392017-09-03 08:10:14 +0300584 exception: object
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400585 /
586
587Mark the future done and set an exception.
588
589If the future is already done when this method is called, raises
590InvalidStateError.
591[clinic start generated code]*/
592
593static PyObject *
594_asyncio_Future_set_exception(FutureObj *self, PyObject *exception)
Serhiy Storchakabca49392017-09-03 08:10:14 +0300595/*[clinic end generated code: output=f1c1b0cd321be360 input=e45b7d7aa71cc66d]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400596{
597 return future_set_exception(self, exception);
598}
599
600/*[clinic input]
601_asyncio.Future.add_done_callback
602
Serhiy Storchakabca49392017-09-03 08:10:14 +0300603 fn: object
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400604 /
605
606Add a callback to be run when the future becomes done.
607
608The callback is called with a single argument - the future object. If
609the future is already done when this is called, the callback is
610scheduled with call_soon.
611[clinic start generated code]*/
612
613static PyObject *
614_asyncio_Future_add_done_callback(FutureObj *self, PyObject *fn)
Serhiy Storchakabca49392017-09-03 08:10:14 +0300615/*[clinic end generated code: output=819e09629b2ec2b5 input=8f818b39990b027d]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400616{
617 return future_add_done_callback(self, fn);
618}
619
620/*[clinic input]
621_asyncio.Future.remove_done_callback
622
Serhiy Storchakabca49392017-09-03 08:10:14 +0300623 fn: object
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400624 /
625
626Remove all instances of a callback from the "call when done" list.
627
628Returns the number of callbacks removed.
629[clinic start generated code]*/
630
631static PyObject *
632_asyncio_Future_remove_done_callback(FutureObj *self, PyObject *fn)
Serhiy Storchakabca49392017-09-03 08:10:14 +0300633/*[clinic end generated code: output=5ab1fb52b24ef31f input=0a43280a149d505b]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900634{
635 PyObject *newlist;
636 Py_ssize_t len, i, j=0;
637
Serhiy Storchakabca49392017-09-03 08:10:14 +0300638 if (self->fut_callbacks == NULL) {
639 PyErr_SetString(PyExc_RuntimeError, "uninitialized Future object");
640 return NULL;
641 }
642
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400643 len = PyList_GET_SIZE(self->fut_callbacks);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900644 if (len == 0) {
645 return PyLong_FromSsize_t(0);
646 }
647
648 newlist = PyList_New(len);
649 if (newlist == NULL) {
650 return NULL;
651 }
652
Yury Selivanov84af9032017-03-02 23:46:56 -0500653 for (i = 0; i < PyList_GET_SIZE(self->fut_callbacks); i++) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900654 int ret;
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400655 PyObject *item = PyList_GET_ITEM(self->fut_callbacks, i);
Serhiy Storchakabca49392017-09-03 08:10:14 +0300656 Py_INCREF(item);
657 ret = PyObject_RichCompareBool(fn, item, Py_EQ);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900658 if (ret == 0) {
Yury Selivanov833a3b02017-07-05 13:32:03 -0400659 if (j < len) {
Yury Selivanov833a3b02017-07-05 13:32:03 -0400660 PyList_SET_ITEM(newlist, j, item);
661 j++;
Serhiy Storchakabca49392017-09-03 08:10:14 +0300662 continue;
Yury Selivanov833a3b02017-07-05 13:32:03 -0400663 }
Serhiy Storchakabca49392017-09-03 08:10:14 +0300664 ret = PyList_Append(newlist, item);
665 }
666 Py_DECREF(item);
667 if (ret < 0) {
668 goto fail;
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900669 }
670 }
671
Serhiy Storchakabca49392017-09-03 08:10:14 +0300672 if (j < len) {
673 Py_SIZE(newlist) = j;
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900674 }
Serhiy Storchakabca49392017-09-03 08:10:14 +0300675 j = PyList_GET_SIZE(newlist);
676 len = PyList_GET_SIZE(self->fut_callbacks);
677 if (j != len) {
678 if (PyList_SetSlice(self->fut_callbacks, 0, len, newlist) < 0) {
679 goto fail;
680 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900681 }
682 Py_DECREF(newlist);
683 return PyLong_FromSsize_t(len - j);
684
685fail:
686 Py_DECREF(newlist);
687 return NULL;
688}
689
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400690/*[clinic input]
691_asyncio.Future.cancel
692
693Cancel the future and schedule callbacks.
694
695If the future is already done or cancelled, return False. Otherwise,
696change the future's state to cancelled, schedule the callbacks and
697return True.
698[clinic start generated code]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900699
700static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400701_asyncio_Future_cancel_impl(FutureObj *self)
702/*[clinic end generated code: output=e45b932ba8bd68a1 input=515709a127995109]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900703{
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400704 return future_cancel(self);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900705}
706
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400707/*[clinic input]
708_asyncio.Future.cancelled
709
710Return True if the future was cancelled.
711[clinic start generated code]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900712
713static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400714_asyncio_Future_cancelled_impl(FutureObj *self)
715/*[clinic end generated code: output=145197ced586357d input=943ab8b7b7b17e45]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900716{
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400717 if (self->fut_state == STATE_CANCELLED) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900718 Py_RETURN_TRUE;
719 }
720 else {
721 Py_RETURN_FALSE;
722 }
723}
724
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400725/*[clinic input]
726_asyncio.Future.done
727
728Return True if the future is done.
729
730Done means either that a result / exception are available, or that the
731future was cancelled.
732[clinic start generated code]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900733
734static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400735_asyncio_Future_done_impl(FutureObj *self)
736/*[clinic end generated code: output=244c5ac351145096 input=28d7b23fdb65d2ac]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900737{
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400738 if (self->fut_state == STATE_PENDING) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900739 Py_RETURN_FALSE;
740 }
741 else {
742 Py_RETURN_TRUE;
743 }
744}
745
746static PyObject *
747FutureObj_get_blocking(FutureObj *fut)
748{
749 if (fut->fut_blocking) {
750 Py_RETURN_TRUE;
751 }
752 else {
753 Py_RETURN_FALSE;
754 }
755}
756
757static int
758FutureObj_set_blocking(FutureObj *fut, PyObject *val)
759{
760 int is_true = PyObject_IsTrue(val);
761 if (is_true < 0) {
762 return -1;
763 }
764 fut->fut_blocking = is_true;
765 return 0;
766}
767
768static PyObject *
769FutureObj_get_log_traceback(FutureObj *fut)
770{
771 if (fut->fut_log_tb) {
772 Py_RETURN_TRUE;
773 }
774 else {
775 Py_RETURN_FALSE;
776 }
777}
778
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +0000779static int
780FutureObj_set_log_traceback(FutureObj *fut, PyObject *val)
781{
782 int is_true = PyObject_IsTrue(val);
783 if (is_true < 0) {
784 return -1;
785 }
786 fut->fut_log_tb = is_true;
787 return 0;
788}
789
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900790static PyObject *
791FutureObj_get_loop(FutureObj *fut)
792{
793 if (fut->fut_loop == NULL) {
794 Py_RETURN_NONE;
795 }
796 Py_INCREF(fut->fut_loop);
797 return fut->fut_loop;
798}
799
800static PyObject *
801FutureObj_get_callbacks(FutureObj *fut)
802{
803 if (fut->fut_callbacks == NULL) {
804 Py_RETURN_NONE;
805 }
806 Py_INCREF(fut->fut_callbacks);
807 return fut->fut_callbacks;
808}
809
810static PyObject *
811FutureObj_get_result(FutureObj *fut)
812{
813 if (fut->fut_result == NULL) {
814 Py_RETURN_NONE;
815 }
816 Py_INCREF(fut->fut_result);
817 return fut->fut_result;
818}
819
820static PyObject *
821FutureObj_get_exception(FutureObj *fut)
822{
823 if (fut->fut_exception == NULL) {
824 Py_RETURN_NONE;
825 }
826 Py_INCREF(fut->fut_exception);
827 return fut->fut_exception;
828}
829
830static PyObject *
831FutureObj_get_source_traceback(FutureObj *fut)
832{
833 if (fut->fut_source_tb == NULL) {
834 Py_RETURN_NONE;
835 }
836 Py_INCREF(fut->fut_source_tb);
837 return fut->fut_source_tb;
838}
839
840static PyObject *
841FutureObj_get_state(FutureObj *fut)
842{
843 _Py_IDENTIFIER(PENDING);
844 _Py_IDENTIFIER(CANCELLED);
845 _Py_IDENTIFIER(FINISHED);
846 PyObject *ret = NULL;
847
848 switch (fut->fut_state) {
849 case STATE_PENDING:
850 ret = _PyUnicode_FromId(&PyId_PENDING);
851 break;
852 case STATE_CANCELLED:
853 ret = _PyUnicode_FromId(&PyId_CANCELLED);
854 break;
855 case STATE_FINISHED:
856 ret = _PyUnicode_FromId(&PyId_FINISHED);
857 break;
858 default:
859 assert (0);
860 }
Serhiy Storchakabca49392017-09-03 08:10:14 +0300861 Py_XINCREF(ret);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900862 return ret;
863}
864
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400865/*[clinic input]
866_asyncio.Future._repr_info
867[clinic start generated code]*/
868
869static PyObject *
870_asyncio_Future__repr_info_impl(FutureObj *self)
871/*[clinic end generated code: output=fa69e901bd176cfb input=f21504d8e2ae1ca2]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900872{
Victor Stinnerde4ae3d2016-12-04 22:59:09 +0100873 return PyObject_CallFunctionObjArgs(
874 asyncio_future_repr_info_func, self, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400875}
876
877/*[clinic input]
878_asyncio.Future._schedule_callbacks
879[clinic start generated code]*/
880
881static PyObject *
882_asyncio_Future__schedule_callbacks_impl(FutureObj *self)
883/*[clinic end generated code: output=5e8958d89ea1c5dc input=4f5f295f263f4a88]*/
884{
885 int ret = future_schedule_callbacks(self);
886 if (ret == -1) {
887 return NULL;
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900888 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400889 Py_RETURN_NONE;
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900890}
891
892static PyObject *
893FutureObj_repr(FutureObj *fut)
894{
895 _Py_IDENTIFIER(_repr_info);
896
Serhiy Storchakabca49392017-09-03 08:10:14 +0300897 PyObject *rinfo = _PyObject_CallMethodIdObjArgs((PyObject*)fut,
898 &PyId__repr_info,
899 NULL);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900900 if (rinfo == NULL) {
901 return NULL;
902 }
903
Serhiy Storchakabca49392017-09-03 08:10:14 +0300904 PyObject *rinfo_s = PyUnicode_Join(NULL, rinfo);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900905 Py_DECREF(rinfo);
906 if (rinfo_s == NULL) {
907 return NULL;
908 }
909
910 PyObject *rstr = NULL;
911 PyObject *type_name = PyObject_GetAttrString((PyObject*)Py_TYPE(fut),
912 "__name__");
913 if (type_name != NULL) {
Serhiy Storchakabca49392017-09-03 08:10:14 +0300914 rstr = PyUnicode_FromFormat("<%S %U>", type_name, rinfo_s);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900915 Py_DECREF(type_name);
916 }
917 Py_DECREF(rinfo_s);
918 return rstr;
919}
920
921static void
922FutureObj_finalize(FutureObj *fut)
923{
924 _Py_IDENTIFIER(call_exception_handler);
925 _Py_IDENTIFIER(message);
926 _Py_IDENTIFIER(exception);
927 _Py_IDENTIFIER(future);
928 _Py_IDENTIFIER(source_traceback);
929
Serhiy Storchakabca49392017-09-03 08:10:14 +0300930 PyObject *error_type, *error_value, *error_traceback;
931 PyObject *context;
932 PyObject *type_name;
933 PyObject *message = NULL;
934 PyObject *func;
935
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900936 if (!fut->fut_log_tb) {
937 return;
938 }
939 assert(fut->fut_exception != NULL);
Serhiy Storchakabca49392017-09-03 08:10:14 +0300940 fut->fut_log_tb = 0;
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900941
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900942 /* Save the current exception, if any. */
943 PyErr_Fetch(&error_type, &error_value, &error_traceback);
944
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900945 context = PyDict_New();
946 if (context == NULL) {
947 goto finally;
948 }
949
950 type_name = PyObject_GetAttrString((PyObject*)Py_TYPE(fut), "__name__");
951 if (type_name == NULL) {
952 goto finally;
953 }
954
955 message = PyUnicode_FromFormat(
956 "%S exception was never retrieved", type_name);
Serhiy Storchakabca49392017-09-03 08:10:14 +0300957 Py_DECREF(type_name);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900958 if (message == NULL) {
959 goto finally;
960 }
961
962 if (_PyDict_SetItemId(context, &PyId_message, message) < 0 ||
963 _PyDict_SetItemId(context, &PyId_exception, fut->fut_exception) < 0 ||
964 _PyDict_SetItemId(context, &PyId_future, (PyObject*)fut) < 0) {
965 goto finally;
966 }
967 if (fut->fut_source_tb != NULL) {
968 if (_PyDict_SetItemId(context, &PyId_source_traceback,
969 fut->fut_source_tb) < 0) {
970 goto finally;
971 }
972 }
973
974 func = _PyObject_GetAttrId(fut->fut_loop, &PyId_call_exception_handler);
975 if (func != NULL) {
Serhiy Storchakabca49392017-09-03 08:10:14 +0300976 PyObject *res = PyObject_CallFunctionObjArgs(func, context, NULL);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900977 if (res == NULL) {
978 PyErr_WriteUnraisable(func);
979 }
Serhiy Storchakabca49392017-09-03 08:10:14 +0300980 else {
981 Py_DECREF(res);
982 }
983 Py_DECREF(func);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900984 }
985
986finally:
Serhiy Storchakabca49392017-09-03 08:10:14 +0300987 Py_XDECREF(context);
988 Py_XDECREF(message);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900989
990 /* Restore the saved exception. */
991 PyErr_Restore(error_type, error_value, error_traceback);
992}
993
994
995static PyAsyncMethods FutureType_as_async = {
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400996 (unaryfunc)future_new_iter, /* am_await */
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900997 0, /* am_aiter */
998 0 /* am_anext */
999};
1000
1001static PyMethodDef FutureType_methods[] = {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001002 _ASYNCIO_FUTURE_RESULT_METHODDEF
1003 _ASYNCIO_FUTURE_EXCEPTION_METHODDEF
1004 _ASYNCIO_FUTURE_SET_RESULT_METHODDEF
1005 _ASYNCIO_FUTURE_SET_EXCEPTION_METHODDEF
1006 _ASYNCIO_FUTURE_ADD_DONE_CALLBACK_METHODDEF
1007 _ASYNCIO_FUTURE_REMOVE_DONE_CALLBACK_METHODDEF
1008 _ASYNCIO_FUTURE_CANCEL_METHODDEF
1009 _ASYNCIO_FUTURE_CANCELLED_METHODDEF
1010 _ASYNCIO_FUTURE_DONE_METHODDEF
1011 _ASYNCIO_FUTURE__REPR_INFO_METHODDEF
1012 _ASYNCIO_FUTURE__SCHEDULE_CALLBACKS_METHODDEF
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001013 {NULL, NULL} /* Sentinel */
1014};
1015
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001016#define FUTURE_COMMON_GETSETLIST \
1017 {"_state", (getter)FutureObj_get_state, NULL, NULL}, \
1018 {"_asyncio_future_blocking", (getter)FutureObj_get_blocking, \
1019 (setter)FutureObj_set_blocking, NULL}, \
1020 {"_loop", (getter)FutureObj_get_loop, NULL, NULL}, \
1021 {"_callbacks", (getter)FutureObj_get_callbacks, NULL, NULL}, \
1022 {"_result", (getter)FutureObj_get_result, NULL, NULL}, \
1023 {"_exception", (getter)FutureObj_get_exception, NULL, NULL}, \
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +00001024 {"_log_traceback", (getter)FutureObj_get_log_traceback, \
1025 (setter)FutureObj_set_log_traceback, NULL}, \
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001026 {"_source_traceback", (getter)FutureObj_get_source_traceback, NULL, NULL},
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001027
1028static PyGetSetDef FutureType_getsetlist[] = {
1029 FUTURE_COMMON_GETSETLIST
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001030 {NULL} /* Sentinel */
1031};
1032
1033static void FutureObj_dealloc(PyObject *self);
1034
1035static PyTypeObject FutureType = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02001036 PyVarObject_HEAD_INIT(NULL, 0)
INADA Naoki9f2ce252016-10-15 15:39:19 +09001037 "_asyncio.Future",
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001038 sizeof(FutureObj), /* tp_basicsize */
1039 .tp_dealloc = FutureObj_dealloc,
1040 .tp_as_async = &FutureType_as_async,
1041 .tp_repr = (reprfunc)FutureObj_repr,
1042 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE
1043 | Py_TPFLAGS_HAVE_FINALIZE,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001044 .tp_doc = _asyncio_Future___init____doc__,
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001045 .tp_traverse = (traverseproc)FutureObj_traverse,
1046 .tp_clear = (inquiry)FutureObj_clear,
1047 .tp_weaklistoffset = offsetof(FutureObj, fut_weakreflist),
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001048 .tp_iter = (getiterfunc)future_new_iter,
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001049 .tp_methods = FutureType_methods,
1050 .tp_getset = FutureType_getsetlist,
1051 .tp_dictoffset = offsetof(FutureObj, dict),
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001052 .tp_init = (initproc)_asyncio_Future___init__,
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001053 .tp_new = PyType_GenericNew,
1054 .tp_finalize = (destructor)FutureObj_finalize,
1055};
1056
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001057#define Future_CheckExact(obj) (Py_TYPE(obj) == &FutureType)
1058
1059static inline int
1060future_call_schedule_callbacks(FutureObj *fut)
1061{
1062 if (Future_CheckExact(fut)) {
1063 return future_schedule_callbacks(fut);
1064 }
1065 else {
1066 /* `fut` is a subclass of Future */
1067 PyObject *ret = _PyObject_CallMethodId(
1068 (PyObject*)fut, &PyId__schedule_callbacks, NULL);
1069 if (ret == NULL) {
1070 return -1;
1071 }
1072
1073 Py_DECREF(ret);
1074 return 0;
1075 }
1076}
1077
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001078static void
1079FutureObj_dealloc(PyObject *self)
1080{
1081 FutureObj *fut = (FutureObj *)self;
1082
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001083 if (Future_CheckExact(fut)) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001084 /* When fut is subclass of Future, finalizer is called from
1085 * subtype_dealloc.
1086 */
1087 if (PyObject_CallFinalizerFromDealloc(self) < 0) {
1088 // resurrected.
1089 return;
1090 }
1091 }
1092
Alexander Mohrde34cbe2017-08-01 23:31:07 -07001093 PyObject_GC_UnTrack(self);
1094
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001095 if (fut->fut_weakreflist != NULL) {
1096 PyObject_ClearWeakRefs(self);
1097 }
1098
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001099 (void)FutureObj_clear(fut);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001100 Py_TYPE(fut)->tp_free(fut);
1101}
1102
1103
1104/*********************** Future Iterator **************************/
1105
1106typedef struct {
1107 PyObject_HEAD
1108 FutureObj *future;
1109} futureiterobject;
1110
1111static void
1112FutureIter_dealloc(futureiterobject *it)
1113{
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001114 PyObject_GC_UnTrack(it);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001115 Py_XDECREF(it->future);
1116 PyObject_GC_Del(it);
1117}
1118
1119static PyObject *
1120FutureIter_iternext(futureiterobject *it)
1121{
1122 PyObject *res;
1123 FutureObj *fut = it->future;
1124
1125 if (fut == NULL) {
1126 return NULL;
1127 }
1128
1129 if (fut->fut_state == STATE_PENDING) {
1130 if (!fut->fut_blocking) {
1131 fut->fut_blocking = 1;
1132 Py_INCREF(fut);
1133 return (PyObject *)fut;
1134 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03001135 PyErr_SetString(PyExc_AssertionError,
1136 "yield from wasn't used with future");
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001137 return NULL;
1138 }
1139
Serhiy Storchakabca49392017-09-03 08:10:14 +03001140 it->future = NULL;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001141 res = _asyncio_Future_result_impl(fut);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001142 if (res != NULL) {
Serhiy Storchaka60e49aa2016-11-06 18:47:03 +02001143 /* The result of the Future is not an exception. */
Serhiy Storchakabca49392017-09-03 08:10:14 +03001144 (void)_PyGen_SetStopIterationValue(res);
Serhiy Storchaka60e49aa2016-11-06 18:47:03 +02001145 Py_DECREF(res);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001146 }
1147
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001148 Py_DECREF(fut);
1149 return NULL;
1150}
1151
1152static PyObject *
INADA Naoki74c17532016-10-25 19:00:45 +09001153FutureIter_send(futureiterobject *self, PyObject *unused)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001154{
INADA Naoki74c17532016-10-25 19:00:45 +09001155 /* Future.__iter__ doesn't care about values that are pushed to the
1156 * generator, it just returns "self.result().
1157 */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001158 return FutureIter_iternext(self);
1159}
1160
1161static PyObject *
1162FutureIter_throw(futureiterobject *self, PyObject *args)
1163{
Serhiy Storchakabca49392017-09-03 08:10:14 +03001164 PyObject *type, *val = NULL, *tb = NULL;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001165 if (!PyArg_ParseTuple(args, "O|OO", &type, &val, &tb))
1166 return NULL;
1167
1168 if (val == Py_None) {
1169 val = NULL;
1170 }
1171 if (tb == Py_None) {
1172 tb = NULL;
Benjamin Peterson996fc1f2016-11-14 00:15:44 -08001173 } else if (tb != NULL && !PyTraceBack_Check(tb)) {
1174 PyErr_SetString(PyExc_TypeError, "throw() third argument must be a traceback");
1175 return NULL;
1176 }
1177
1178 Py_INCREF(type);
1179 Py_XINCREF(val);
1180 Py_XINCREF(tb);
1181
1182 if (PyExceptionClass_Check(type)) {
1183 PyErr_NormalizeException(&type, &val, &tb);
Yury Selivanovedfe8862016-12-01 11:37:47 -05001184 /* No need to call PyException_SetTraceback since we'll be calling
1185 PyErr_Restore for `type`, `val`, and `tb`. */
Benjamin Peterson996fc1f2016-11-14 00:15:44 -08001186 } else if (PyExceptionInstance_Check(type)) {
1187 if (val) {
1188 PyErr_SetString(PyExc_TypeError,
1189 "instance exception may not have a separate value");
1190 goto fail;
1191 }
1192 val = type;
1193 type = PyExceptionInstance_Class(type);
1194 Py_INCREF(type);
1195 if (tb == NULL)
1196 tb = PyException_GetTraceback(val);
1197 } else {
1198 PyErr_SetString(PyExc_TypeError,
1199 "exceptions must be classes deriving BaseException or "
1200 "instances of such a class");
1201 goto fail;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001202 }
1203
1204 Py_CLEAR(self->future);
1205
Benjamin Peterson996fc1f2016-11-14 00:15:44 -08001206 PyErr_Restore(type, val, tb);
1207
Serhiy Storchakabca49392017-09-03 08:10:14 +03001208 return NULL;
Benjamin Peterson996fc1f2016-11-14 00:15:44 -08001209
1210 fail:
1211 Py_DECREF(type);
1212 Py_XDECREF(val);
1213 Py_XDECREF(tb);
1214 return NULL;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001215}
1216
1217static PyObject *
1218FutureIter_close(futureiterobject *self, PyObject *arg)
1219{
1220 Py_CLEAR(self->future);
1221 Py_RETURN_NONE;
1222}
1223
1224static int
1225FutureIter_traverse(futureiterobject *it, visitproc visit, void *arg)
1226{
1227 Py_VISIT(it->future);
1228 return 0;
1229}
1230
1231static PyMethodDef FutureIter_methods[] = {
1232 {"send", (PyCFunction)FutureIter_send, METH_O, NULL},
1233 {"throw", (PyCFunction)FutureIter_throw, METH_VARARGS, NULL},
1234 {"close", (PyCFunction)FutureIter_close, METH_NOARGS, NULL},
1235 {NULL, NULL} /* Sentinel */
1236};
1237
1238static PyTypeObject FutureIterType = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02001239 PyVarObject_HEAD_INIT(NULL, 0)
INADA Naoki9f2ce252016-10-15 15:39:19 +09001240 "_asyncio.FutureIter",
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001241 .tp_basicsize = sizeof(futureiterobject),
1242 .tp_itemsize = 0,
1243 .tp_dealloc = (destructor)FutureIter_dealloc,
1244 .tp_getattro = PyObject_GenericGetAttr,
1245 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
1246 .tp_traverse = (traverseproc)FutureIter_traverse,
1247 .tp_iter = PyObject_SelfIter,
1248 .tp_iternext = (iternextfunc)FutureIter_iternext,
1249 .tp_methods = FutureIter_methods,
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001250};
1251
1252static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001253future_new_iter(PyObject *fut)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001254{
1255 futureiterobject *it;
1256
1257 if (!PyObject_TypeCheck(fut, &FutureType)) {
1258 PyErr_BadInternalCall();
1259 return NULL;
1260 }
1261 it = PyObject_GC_New(futureiterobject, &FutureIterType);
1262 if (it == NULL) {
1263 return NULL;
1264 }
1265 Py_INCREF(fut);
1266 it->future = (FutureObj*)fut;
INADA Naoki1be427b2016-10-11 02:12:34 +09001267 PyObject_GC_Track(it);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001268 return (PyObject*)it;
1269}
1270
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001271
1272/*********************** Task **************************/
1273
1274
1275/*[clinic input]
1276class _asyncio.Task "TaskObj *" "&Task_Type"
1277[clinic start generated code]*/
1278/*[clinic end generated code: output=da39a3ee5e6b4b0d input=719dcef0fcc03b37]*/
1279
1280static int task_call_step_soon(TaskObj *, PyObject *);
1281static inline PyObject * task_call_wakeup(TaskObj *, PyObject *);
1282static inline PyObject * task_call_step(TaskObj *, PyObject *);
1283static PyObject * task_wakeup(TaskObj *, PyObject *);
1284static PyObject * task_step(TaskObj *, PyObject *);
1285
1286/* ----- Task._step wrapper */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001287
INADA Naokic411a7d2016-10-18 11:48:14 +09001288static int
Serhiy Storchakabca49392017-09-03 08:10:14 +03001289TaskStepMethWrapper_clear(TaskStepMethWrapper *o)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001290{
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001291 Py_CLEAR(o->sw_task);
1292 Py_CLEAR(o->sw_arg);
1293 return 0;
1294}
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001295
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001296static void
Serhiy Storchakabca49392017-09-03 08:10:14 +03001297TaskStepMethWrapper_dealloc(TaskStepMethWrapper *o)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001298{
1299 PyObject_GC_UnTrack(o);
Serhiy Storchakabca49392017-09-03 08:10:14 +03001300 (void)TaskStepMethWrapper_clear(o);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001301 Py_TYPE(o)->tp_free(o);
1302}
1303
1304static PyObject *
Serhiy Storchakabca49392017-09-03 08:10:14 +03001305TaskStepMethWrapper_call(TaskStepMethWrapper *o,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001306 PyObject *args, PyObject *kwds)
1307{
Serhiy Storchakabca49392017-09-03 08:10:14 +03001308 if (kwds != NULL && PyDict_GET_SIZE(kwds) != 0) {
1309 PyErr_SetString(PyExc_TypeError, "function takes no keyword arguments");
1310 return NULL;
1311 }
1312 if (args != NULL && PyTuple_GET_SIZE(args) != 0) {
1313 PyErr_SetString(PyExc_TypeError, "function takes no positional arguments");
1314 return NULL;
1315 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001316 return task_call_step(o->sw_task, o->sw_arg);
1317}
1318
1319static int
Serhiy Storchakabca49392017-09-03 08:10:14 +03001320TaskStepMethWrapper_traverse(TaskStepMethWrapper *o,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001321 visitproc visit, void *arg)
1322{
1323 Py_VISIT(o->sw_task);
1324 Py_VISIT(o->sw_arg);
1325 return 0;
1326}
1327
1328static PyObject *
Serhiy Storchakabca49392017-09-03 08:10:14 +03001329TaskStepMethWrapper_get___self__(TaskStepMethWrapper *o)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001330{
1331 if (o->sw_task) {
1332 Py_INCREF(o->sw_task);
1333 return (PyObject*)o->sw_task;
1334 }
1335 Py_RETURN_NONE;
1336}
1337
Serhiy Storchakabca49392017-09-03 08:10:14 +03001338static PyGetSetDef TaskStepMethWrapper_getsetlist[] = {
1339 {"__self__", (getter)TaskStepMethWrapper_get___self__, NULL, NULL},
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001340 {NULL} /* Sentinel */
1341};
1342
Serhiy Storchakabca49392017-09-03 08:10:14 +03001343PyTypeObject TaskStepMethWrapper_Type = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02001344 PyVarObject_HEAD_INIT(NULL, 0)
Serhiy Storchakabca49392017-09-03 08:10:14 +03001345 "TaskStepMethWrapper",
1346 .tp_basicsize = sizeof(TaskStepMethWrapper),
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001347 .tp_itemsize = 0,
Serhiy Storchakabca49392017-09-03 08:10:14 +03001348 .tp_getset = TaskStepMethWrapper_getsetlist,
1349 .tp_dealloc = (destructor)TaskStepMethWrapper_dealloc,
1350 .tp_call = (ternaryfunc)TaskStepMethWrapper_call,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001351 .tp_getattro = PyObject_GenericGetAttr,
1352 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
Serhiy Storchakabca49392017-09-03 08:10:14 +03001353 .tp_traverse = (traverseproc)TaskStepMethWrapper_traverse,
1354 .tp_clear = (inquiry)TaskStepMethWrapper_clear,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001355};
1356
1357static PyObject *
Serhiy Storchakabca49392017-09-03 08:10:14 +03001358TaskStepMethWrapper_new(TaskObj *task, PyObject *arg)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001359{
Serhiy Storchakabca49392017-09-03 08:10:14 +03001360 TaskStepMethWrapper *o;
1361 o = PyObject_GC_New(TaskStepMethWrapper, &TaskStepMethWrapper_Type);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001362 if (o == NULL) {
1363 return NULL;
1364 }
1365
1366 Py_INCREF(task);
1367 o->sw_task = task;
1368
1369 Py_XINCREF(arg);
1370 o->sw_arg = arg;
1371
1372 PyObject_GC_Track(o);
1373 return (PyObject*) o;
1374}
1375
1376/* ----- Task._wakeup wrapper */
1377
1378static PyObject *
1379TaskWakeupMethWrapper_call(TaskWakeupMethWrapper *o,
1380 PyObject *args, PyObject *kwds)
1381{
1382 PyObject *fut;
1383
Serhiy Storchakabca49392017-09-03 08:10:14 +03001384 if (kwds != NULL && PyDict_GET_SIZE(kwds) != 0) {
1385 PyErr_SetString(PyExc_TypeError, "function takes no keyword arguments");
1386 return NULL;
1387 }
1388 if (!PyArg_ParseTuple(args, "O", &fut)) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001389 return NULL;
1390 }
1391
1392 return task_call_wakeup(o->ww_task, fut);
1393}
1394
1395static int
1396TaskWakeupMethWrapper_clear(TaskWakeupMethWrapper *o)
1397{
1398 Py_CLEAR(o->ww_task);
1399 return 0;
1400}
1401
1402static int
1403TaskWakeupMethWrapper_traverse(TaskWakeupMethWrapper *o,
1404 visitproc visit, void *arg)
1405{
1406 Py_VISIT(o->ww_task);
1407 return 0;
1408}
1409
1410static void
1411TaskWakeupMethWrapper_dealloc(TaskWakeupMethWrapper *o)
1412{
1413 PyObject_GC_UnTrack(o);
1414 (void)TaskWakeupMethWrapper_clear(o);
1415 Py_TYPE(o)->tp_free(o);
1416}
1417
1418PyTypeObject TaskWakeupMethWrapper_Type = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02001419 PyVarObject_HEAD_INIT(NULL, 0)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001420 "TaskWakeupMethWrapper",
1421 .tp_basicsize = sizeof(TaskWakeupMethWrapper),
1422 .tp_itemsize = 0,
1423 .tp_dealloc = (destructor)TaskWakeupMethWrapper_dealloc,
1424 .tp_call = (ternaryfunc)TaskWakeupMethWrapper_call,
1425 .tp_getattro = PyObject_GenericGetAttr,
1426 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
1427 .tp_traverse = (traverseproc)TaskWakeupMethWrapper_traverse,
1428 .tp_clear = (inquiry)TaskWakeupMethWrapper_clear,
1429};
1430
1431static PyObject *
1432TaskWakeupMethWrapper_new(TaskObj *task)
1433{
1434 TaskWakeupMethWrapper *o;
1435 o = PyObject_GC_New(TaskWakeupMethWrapper, &TaskWakeupMethWrapper_Type);
1436 if (o == NULL) {
1437 return NULL;
1438 }
1439
1440 Py_INCREF(task);
1441 o->ww_task = task;
1442
1443 PyObject_GC_Track(o);
1444 return (PyObject*) o;
1445}
1446
1447/* ----- Task */
1448
1449/*[clinic input]
1450_asyncio.Task.__init__
1451
Serhiy Storchakabca49392017-09-03 08:10:14 +03001452 coro: object
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001453 *
Serhiy Storchakabca49392017-09-03 08:10:14 +03001454 loop: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001455
1456A coroutine wrapped in a Future.
1457[clinic start generated code]*/
1458
1459static int
1460_asyncio_Task___init___impl(TaskObj *self, PyObject *coro, PyObject *loop)
Serhiy Storchakabca49392017-09-03 08:10:14 +03001461/*[clinic end generated code: output=9f24774c2287fc2f input=8d132974b049593e]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001462{
1463 PyObject *res;
1464 _Py_IDENTIFIER(add);
1465
1466 if (future_init((FutureObj*)self, loop)) {
INADA Naokic411a7d2016-10-18 11:48:14 +09001467 return -1;
1468 }
INADA Naokic411a7d2016-10-18 11:48:14 +09001469
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001470 self->task_fut_waiter = NULL;
1471 self->task_must_cancel = 0;
1472 self->task_log_destroy_pending = 1;
INADA Naokic411a7d2016-10-18 11:48:14 +09001473
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001474 Py_INCREF(coro);
1475 self->task_coro = coro;
1476
1477 if (task_call_step_soon(self, NULL)) {
1478 return -1;
INADA Naokic411a7d2016-10-18 11:48:14 +09001479 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001480
Victor Stinnerb6ed57d2016-12-09 14:24:02 +01001481 res = _PyObject_CallMethodIdObjArgs(all_tasks, &PyId_add, self, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001482 if (res == NULL) {
1483 return -1;
1484 }
1485 Py_DECREF(res);
1486
1487 return 0;
1488}
1489
1490static int
1491TaskObj_clear(TaskObj *task)
1492{
1493 (void)FutureObj_clear((FutureObj*) task);
1494 Py_CLEAR(task->task_coro);
1495 Py_CLEAR(task->task_fut_waiter);
1496 return 0;
1497}
1498
1499static int
1500TaskObj_traverse(TaskObj *task, visitproc visit, void *arg)
1501{
1502 Py_VISIT(task->task_coro);
1503 Py_VISIT(task->task_fut_waiter);
1504 (void)FutureObj_traverse((FutureObj*) task, visit, arg);
1505 return 0;
1506}
1507
1508static PyObject *
1509TaskObj_get_log_destroy_pending(TaskObj *task)
1510{
1511 if (task->task_log_destroy_pending) {
1512 Py_RETURN_TRUE;
1513 }
1514 else {
1515 Py_RETURN_FALSE;
1516 }
1517}
1518
1519static int
1520TaskObj_set_log_destroy_pending(TaskObj *task, PyObject *val)
1521{
1522 int is_true = PyObject_IsTrue(val);
1523 if (is_true < 0) {
1524 return -1;
1525 }
1526 task->task_log_destroy_pending = is_true;
1527 return 0;
1528}
1529
1530static PyObject *
1531TaskObj_get_must_cancel(TaskObj *task)
1532{
1533 if (task->task_must_cancel) {
1534 Py_RETURN_TRUE;
1535 }
1536 else {
1537 Py_RETURN_FALSE;
1538 }
1539}
1540
1541static PyObject *
1542TaskObj_get_coro(TaskObj *task)
1543{
1544 if (task->task_coro) {
1545 Py_INCREF(task->task_coro);
1546 return task->task_coro;
1547 }
1548
1549 Py_RETURN_NONE;
1550}
1551
1552static PyObject *
1553TaskObj_get_fut_waiter(TaskObj *task)
1554{
1555 if (task->task_fut_waiter) {
1556 Py_INCREF(task->task_fut_waiter);
1557 return task->task_fut_waiter;
1558 }
1559
1560 Py_RETURN_NONE;
1561}
1562
1563/*[clinic input]
1564@classmethod
1565_asyncio.Task.current_task
1566
Serhiy Storchakabca49392017-09-03 08:10:14 +03001567 loop: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001568
1569Return the currently running task in an event loop or None.
1570
1571By default the current task for the current event loop is returned.
1572
1573None is returned when called not in the context of a Task.
1574[clinic start generated code]*/
1575
1576static PyObject *
1577_asyncio_Task_current_task_impl(PyTypeObject *type, PyObject *loop)
Serhiy Storchakabca49392017-09-03 08:10:14 +03001578/*[clinic end generated code: output=99fbe7332c516e03 input=cd14770c5b79c7eb]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001579{
1580 PyObject *res;
1581
Yury Selivanov8d26aa92017-03-02 22:16:33 -05001582 if (loop == Py_None) {
Yury Selivanova70232f2017-12-13 14:49:42 -05001583 loop = get_event_loop();
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001584 if (loop == NULL) {
1585 return NULL;
1586 }
1587
Yury Selivanov684ef2c2016-10-28 19:01:21 -04001588 res = PyDict_GetItem(current_tasks, loop);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001589 Py_DECREF(loop);
1590 }
1591 else {
Yury Selivanov684ef2c2016-10-28 19:01:21 -04001592 res = PyDict_GetItem(current_tasks, loop);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001593 }
1594
1595 if (res == NULL) {
1596 Py_RETURN_NONE;
1597 }
1598 else {
1599 Py_INCREF(res);
1600 return res;
1601 }
1602}
1603
1604static PyObject *
1605task_all_tasks(PyObject *loop)
1606{
1607 PyObject *task;
1608 PyObject *task_loop;
1609 PyObject *set;
1610 PyObject *iter;
1611
1612 assert(loop != NULL);
1613
1614 set = PySet_New(NULL);
1615 if (set == NULL) {
1616 return NULL;
1617 }
1618
1619 iter = PyObject_GetIter(all_tasks);
1620 if (iter == NULL) {
INADA Naokic411a7d2016-10-18 11:48:14 +09001621 goto fail;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001622 }
1623
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001624 while ((task = PyIter_Next(iter))) {
1625 task_loop = PyObject_GetAttrString(task, "_loop");
1626 if (task_loop == NULL) {
1627 Py_DECREF(task);
1628 goto fail;
1629 }
1630 if (task_loop == loop) {
1631 if (PySet_Add(set, task) == -1) {
1632 Py_DECREF(task_loop);
1633 Py_DECREF(task);
1634 goto fail;
1635 }
1636 }
1637 Py_DECREF(task_loop);
1638 Py_DECREF(task);
1639 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03001640 if (PyErr_Occurred()) {
1641 goto fail;
1642 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001643 Py_DECREF(iter);
1644 return set;
1645
1646fail:
Serhiy Storchakabca49392017-09-03 08:10:14 +03001647 Py_DECREF(set);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001648 Py_XDECREF(iter);
1649 return NULL;
1650}
1651
1652/*[clinic input]
1653@classmethod
1654_asyncio.Task.all_tasks
1655
Serhiy Storchakabca49392017-09-03 08:10:14 +03001656 loop: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001657
1658Return a set of all tasks for an event loop.
1659
1660By default all tasks for the current event loop are returned.
1661[clinic start generated code]*/
1662
1663static PyObject *
1664_asyncio_Task_all_tasks_impl(PyTypeObject *type, PyObject *loop)
Serhiy Storchakabca49392017-09-03 08:10:14 +03001665/*[clinic end generated code: output=11f9b20749ccca5d input=497f80bc9ce726b5]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001666{
1667 PyObject *res;
1668
Yury Selivanov8d26aa92017-03-02 22:16:33 -05001669 if (loop == Py_None) {
Yury Selivanova70232f2017-12-13 14:49:42 -05001670 loop = get_event_loop();
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001671 if (loop == NULL) {
1672 return NULL;
1673 }
1674
1675 res = task_all_tasks(loop);
1676 Py_DECREF(loop);
1677 }
1678 else {
1679 res = task_all_tasks(loop);
1680 }
1681
1682 return res;
1683}
1684
1685/*[clinic input]
1686_asyncio.Task._repr_info
1687[clinic start generated code]*/
1688
1689static PyObject *
1690_asyncio_Task__repr_info_impl(TaskObj *self)
1691/*[clinic end generated code: output=6a490eb66d5ba34b input=3c6d051ed3ddec8b]*/
1692{
Victor Stinnerde4ae3d2016-12-04 22:59:09 +01001693 return PyObject_CallFunctionObjArgs(
1694 asyncio_task_repr_info_func, self, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001695}
1696
1697/*[clinic input]
1698_asyncio.Task.cancel
1699
1700Request that this task cancel itself.
1701
1702This arranges for a CancelledError to be thrown into the
1703wrapped coroutine on the next cycle through the event loop.
1704The coroutine then has a chance to clean up or even deny
1705the request using try/except/finally.
1706
1707Unlike Future.cancel, this does not guarantee that the
1708task will be cancelled: the exception might be caught and
1709acted upon, delaying cancellation of the task or preventing
1710cancellation completely. The task may also return a value or
1711raise a different exception.
1712
1713Immediately after this method is called, Task.cancelled() will
1714not return True (unless the task was already cancelled). A
1715task will be marked as cancelled when the wrapped coroutine
1716terminates with a CancelledError exception (even if cancel()
1717was not called).
1718[clinic start generated code]*/
1719
1720static PyObject *
1721_asyncio_Task_cancel_impl(TaskObj *self)
1722/*[clinic end generated code: output=6bfc0479da9d5757 input=13f9bf496695cb52]*/
1723{
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +00001724 self->task_log_tb = 0;
1725
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001726 if (self->task_state != STATE_PENDING) {
1727 Py_RETURN_FALSE;
1728 }
1729
1730 if (self->task_fut_waiter) {
1731 PyObject *res;
1732 int is_true;
1733
1734 res = _PyObject_CallMethodId(
1735 self->task_fut_waiter, &PyId_cancel, NULL);
1736 if (res == NULL) {
1737 return NULL;
1738 }
1739
1740 is_true = PyObject_IsTrue(res);
1741 Py_DECREF(res);
1742 if (is_true < 0) {
1743 return NULL;
1744 }
1745
1746 if (is_true) {
1747 Py_RETURN_TRUE;
1748 }
1749 }
1750
1751 self->task_must_cancel = 1;
1752 Py_RETURN_TRUE;
1753}
1754
1755/*[clinic input]
1756_asyncio.Task.get_stack
1757
1758 *
Serhiy Storchakabca49392017-09-03 08:10:14 +03001759 limit: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001760
1761Return the list of stack frames for this task's coroutine.
1762
1763If the coroutine is not done, this returns the stack where it is
1764suspended. If the coroutine has completed successfully or was
1765cancelled, this returns an empty list. If the coroutine was
1766terminated by an exception, this returns the list of traceback
1767frames.
1768
1769The frames are always ordered from oldest to newest.
1770
1771The optional limit gives the maximum number of frames to
1772return; by default all available frames are returned. Its
1773meaning differs depending on whether a stack or a traceback is
1774returned: the newest frames of a stack are returned, but the
1775oldest frames of a traceback are returned. (This matches the
1776behavior of the traceback module.)
1777
1778For reasons beyond our control, only one stack frame is
1779returned for a suspended coroutine.
1780[clinic start generated code]*/
1781
1782static PyObject *
1783_asyncio_Task_get_stack_impl(TaskObj *self, PyObject *limit)
Serhiy Storchakabca49392017-09-03 08:10:14 +03001784/*[clinic end generated code: output=c9aeeeebd1e18118 input=05b323d42b809b90]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001785{
1786 return PyObject_CallFunctionObjArgs(
1787 asyncio_task_get_stack_func, self, limit, NULL);
1788}
1789
1790/*[clinic input]
1791_asyncio.Task.print_stack
1792
1793 *
Serhiy Storchakabca49392017-09-03 08:10:14 +03001794 limit: object = None
1795 file: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001796
1797Print the stack or traceback for this task's coroutine.
1798
1799This produces output similar to that of the traceback module,
1800for the frames retrieved by get_stack(). The limit argument
1801is passed to get_stack(). The file argument is an I/O stream
1802to which the output is written; by default output is written
1803to sys.stderr.
1804[clinic start generated code]*/
1805
1806static PyObject *
1807_asyncio_Task_print_stack_impl(TaskObj *self, PyObject *limit,
1808 PyObject *file)
Serhiy Storchakabca49392017-09-03 08:10:14 +03001809/*[clinic end generated code: output=7339e10314cd3f4d input=1a0352913b7fcd92]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001810{
1811 return PyObject_CallFunctionObjArgs(
1812 asyncio_task_print_stack_func, self, limit, file, NULL);
1813}
1814
1815/*[clinic input]
1816_asyncio.Task._step
1817
Serhiy Storchakabca49392017-09-03 08:10:14 +03001818 exc: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001819[clinic start generated code]*/
1820
1821static PyObject *
1822_asyncio_Task__step_impl(TaskObj *self, PyObject *exc)
Serhiy Storchakabca49392017-09-03 08:10:14 +03001823/*[clinic end generated code: output=7ed23f0cefd5ae42 input=1e19a985ace87ca4]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001824{
1825 return task_step(self, exc == Py_None ? NULL : exc);
1826}
1827
1828/*[clinic input]
1829_asyncio.Task._wakeup
1830
Serhiy Storchakabca49392017-09-03 08:10:14 +03001831 fut: object
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001832[clinic start generated code]*/
1833
1834static PyObject *
1835_asyncio_Task__wakeup_impl(TaskObj *self, PyObject *fut)
Serhiy Storchakabca49392017-09-03 08:10:14 +03001836/*[clinic end generated code: output=75cb341c760fd071 input=6a0616406f829a7b]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001837{
1838 return task_wakeup(self, fut);
1839}
1840
1841static void
1842TaskObj_finalize(TaskObj *task)
1843{
1844 _Py_IDENTIFIER(call_exception_handler);
1845 _Py_IDENTIFIER(task);
1846 _Py_IDENTIFIER(message);
1847 _Py_IDENTIFIER(source_traceback);
1848
Serhiy Storchakabca49392017-09-03 08:10:14 +03001849 PyObject *context;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001850 PyObject *message = NULL;
Serhiy Storchakabca49392017-09-03 08:10:14 +03001851 PyObject *func;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001852 PyObject *error_type, *error_value, *error_traceback;
1853
1854 if (task->task_state != STATE_PENDING || !task->task_log_destroy_pending) {
1855 goto done;
1856 }
1857
1858 /* Save the current exception, if any. */
1859 PyErr_Fetch(&error_type, &error_value, &error_traceback);
1860
1861 context = PyDict_New();
1862 if (context == NULL) {
1863 goto finally;
1864 }
1865
1866 message = PyUnicode_FromString("Task was destroyed but it is pending!");
1867 if (message == NULL) {
1868 goto finally;
1869 }
1870
1871 if (_PyDict_SetItemId(context, &PyId_message, message) < 0 ||
1872 _PyDict_SetItemId(context, &PyId_task, (PyObject*)task) < 0)
1873 {
1874 goto finally;
1875 }
1876
1877 if (task->task_source_tb != NULL) {
1878 if (_PyDict_SetItemId(context, &PyId_source_traceback,
1879 task->task_source_tb) < 0)
1880 {
1881 goto finally;
1882 }
1883 }
1884
1885 func = _PyObject_GetAttrId(task->task_loop, &PyId_call_exception_handler);
1886 if (func != NULL) {
Serhiy Storchakabca49392017-09-03 08:10:14 +03001887 PyObject *res = PyObject_CallFunctionObjArgs(func, context, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001888 if (res == NULL) {
1889 PyErr_WriteUnraisable(func);
1890 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03001891 else {
1892 Py_DECREF(res);
1893 }
1894 Py_DECREF(func);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001895 }
1896
1897finally:
Serhiy Storchakabca49392017-09-03 08:10:14 +03001898 Py_XDECREF(context);
1899 Py_XDECREF(message);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001900
1901 /* Restore the saved exception. */
1902 PyErr_Restore(error_type, error_value, error_traceback);
1903
1904done:
1905 FutureObj_finalize((FutureObj*)task);
1906}
1907
1908static void TaskObj_dealloc(PyObject *); /* Needs Task_CheckExact */
1909
1910static PyMethodDef TaskType_methods[] = {
1911 _ASYNCIO_FUTURE_RESULT_METHODDEF
1912 _ASYNCIO_FUTURE_EXCEPTION_METHODDEF
1913 _ASYNCIO_FUTURE_SET_RESULT_METHODDEF
1914 _ASYNCIO_FUTURE_SET_EXCEPTION_METHODDEF
1915 _ASYNCIO_FUTURE_ADD_DONE_CALLBACK_METHODDEF
1916 _ASYNCIO_FUTURE_REMOVE_DONE_CALLBACK_METHODDEF
1917 _ASYNCIO_FUTURE_CANCELLED_METHODDEF
1918 _ASYNCIO_FUTURE_DONE_METHODDEF
1919 _ASYNCIO_TASK_CURRENT_TASK_METHODDEF
1920 _ASYNCIO_TASK_ALL_TASKS_METHODDEF
1921 _ASYNCIO_TASK_CANCEL_METHODDEF
1922 _ASYNCIO_TASK_GET_STACK_METHODDEF
1923 _ASYNCIO_TASK_PRINT_STACK_METHODDEF
1924 _ASYNCIO_TASK__WAKEUP_METHODDEF
1925 _ASYNCIO_TASK__STEP_METHODDEF
1926 _ASYNCIO_TASK__REPR_INFO_METHODDEF
1927 {NULL, NULL} /* Sentinel */
1928};
1929
1930static PyGetSetDef TaskType_getsetlist[] = {
1931 FUTURE_COMMON_GETSETLIST
1932 {"_log_destroy_pending", (getter)TaskObj_get_log_destroy_pending,
1933 (setter)TaskObj_set_log_destroy_pending, NULL},
1934 {"_must_cancel", (getter)TaskObj_get_must_cancel, NULL, NULL},
1935 {"_coro", (getter)TaskObj_get_coro, NULL, NULL},
1936 {"_fut_waiter", (getter)TaskObj_get_fut_waiter, NULL, NULL},
1937 {NULL} /* Sentinel */
1938};
1939
1940static PyTypeObject TaskType = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02001941 PyVarObject_HEAD_INIT(NULL, 0)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001942 "_asyncio.Task",
1943 sizeof(TaskObj), /* tp_basicsize */
1944 .tp_base = &FutureType,
1945 .tp_dealloc = TaskObj_dealloc,
1946 .tp_as_async = &FutureType_as_async,
1947 .tp_repr = (reprfunc)FutureObj_repr,
1948 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE
1949 | Py_TPFLAGS_HAVE_FINALIZE,
1950 .tp_doc = _asyncio_Task___init____doc__,
1951 .tp_traverse = (traverseproc)TaskObj_traverse,
1952 .tp_clear = (inquiry)TaskObj_clear,
1953 .tp_weaklistoffset = offsetof(TaskObj, task_weakreflist),
1954 .tp_iter = (getiterfunc)future_new_iter,
1955 .tp_methods = TaskType_methods,
1956 .tp_getset = TaskType_getsetlist,
1957 .tp_dictoffset = offsetof(TaskObj, dict),
1958 .tp_init = (initproc)_asyncio_Task___init__,
1959 .tp_new = PyType_GenericNew,
1960 .tp_finalize = (destructor)TaskObj_finalize,
1961};
1962
1963#define Task_CheckExact(obj) (Py_TYPE(obj) == &TaskType)
1964
1965static void
1966TaskObj_dealloc(PyObject *self)
1967{
1968 TaskObj *task = (TaskObj *)self;
1969
1970 if (Task_CheckExact(self)) {
1971 /* When fut is subclass of Task, finalizer is called from
1972 * subtype_dealloc.
1973 */
1974 if (PyObject_CallFinalizerFromDealloc(self) < 0) {
1975 // resurrected.
1976 return;
1977 }
1978 }
1979
Alexander Mohrde34cbe2017-08-01 23:31:07 -07001980 PyObject_GC_UnTrack(self);
1981
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001982 if (task->task_weakreflist != NULL) {
1983 PyObject_ClearWeakRefs(self);
1984 }
1985
1986 (void)TaskObj_clear(task);
1987 Py_TYPE(task)->tp_free(task);
1988}
1989
1990static inline PyObject *
1991task_call_wakeup(TaskObj *task, PyObject *fut)
1992{
1993 if (Task_CheckExact(task)) {
1994 return task_wakeup(task, fut);
1995 }
1996 else {
1997 /* `task` is a subclass of Task */
Victor Stinnerb6ed57d2016-12-09 14:24:02 +01001998 return _PyObject_CallMethodIdObjArgs((PyObject*)task, &PyId__wakeup,
1999 fut, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002000 }
2001}
2002
2003static inline PyObject *
2004task_call_step(TaskObj *task, PyObject *arg)
2005{
2006 if (Task_CheckExact(task)) {
2007 return task_step(task, arg);
2008 }
2009 else {
2010 /* `task` is a subclass of Task */
Victor Stinnerb6ed57d2016-12-09 14:24:02 +01002011 return _PyObject_CallMethodIdObjArgs((PyObject*)task, &PyId__step,
2012 arg, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002013 }
2014}
2015
2016static int
2017task_call_step_soon(TaskObj *task, PyObject *arg)
2018{
2019 PyObject *handle;
2020
Serhiy Storchakabca49392017-09-03 08:10:14 +03002021 PyObject *cb = TaskStepMethWrapper_new(task, arg);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002022 if (cb == NULL) {
2023 return -1;
2024 }
2025
Victor Stinnerb6ed57d2016-12-09 14:24:02 +01002026 handle = _PyObject_CallMethodIdObjArgs(task->task_loop, &PyId_call_soon,
2027 cb, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002028 Py_DECREF(cb);
2029 if (handle == NULL) {
2030 return -1;
2031 }
2032
2033 Py_DECREF(handle);
2034 return 0;
2035}
2036
2037static PyObject *
2038task_set_error_soon(TaskObj *task, PyObject *et, const char *format, ...)
2039{
2040 PyObject* msg;
2041
2042 va_list vargs;
2043#ifdef HAVE_STDARG_PROTOTYPES
2044 va_start(vargs, format);
2045#else
2046 va_start(vargs);
2047#endif
2048 msg = PyUnicode_FromFormatV(format, vargs);
2049 va_end(vargs);
2050
2051 if (msg == NULL) {
2052 return NULL;
2053 }
2054
Victor Stinnerde4ae3d2016-12-04 22:59:09 +01002055 PyObject *e = PyObject_CallFunctionObjArgs(et, msg, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002056 Py_DECREF(msg);
2057 if (e == NULL) {
2058 return NULL;
2059 }
2060
2061 if (task_call_step_soon(task, e) == -1) {
2062 Py_DECREF(e);
2063 return NULL;
2064 }
2065
2066 Py_DECREF(e);
2067 Py_RETURN_NONE;
2068}
2069
2070static PyObject *
2071task_step_impl(TaskObj *task, PyObject *exc)
2072{
2073 int res;
2074 int clear_exc = 0;
2075 PyObject *result = NULL;
Serhiy Storchakabca49392017-09-03 08:10:14 +03002076 PyObject *coro;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002077 PyObject *o;
2078
2079 if (task->task_state != STATE_PENDING) {
2080 PyErr_Format(PyExc_AssertionError,
2081 "_step(): already done: %R %R",
2082 task,
2083 exc ? exc : Py_None);
INADA Naokic411a7d2016-10-18 11:48:14 +09002084 goto fail;
2085 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09002086
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002087 if (task->task_must_cancel) {
2088 assert(exc != Py_None);
2089
2090 if (exc) {
2091 /* Check if exc is a CancelledError */
2092 res = PyObject_IsInstance(exc, asyncio_CancelledError);
2093 if (res == -1) {
2094 /* An error occurred, abort */
2095 goto fail;
2096 }
2097 if (res == 0) {
2098 /* exc is not CancelledError; reset it to NULL */
2099 exc = NULL;
2100 }
2101 }
2102
2103 if (!exc) {
2104 /* exc was not a CancelledError */
Victor Stinnerf17c3de2016-12-06 18:46:19 +01002105 exc = _PyObject_CallNoArg(asyncio_CancelledError);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002106 if (!exc) {
2107 goto fail;
2108 }
2109 clear_exc = 1;
2110 }
2111
2112 task->task_must_cancel = 0;
2113 }
2114
2115 Py_CLEAR(task->task_fut_waiter);
2116
Serhiy Storchakabca49392017-09-03 08:10:14 +03002117 coro = task->task_coro;
2118 if (coro == NULL) {
2119 PyErr_SetString(PyExc_RuntimeError, "uninitialized Task object");
2120 return NULL;
2121 }
2122
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002123 if (exc == NULL) {
2124 if (PyGen_CheckExact(coro) || PyCoro_CheckExact(coro)) {
2125 result = _PyGen_Send((PyGenObject*)coro, Py_None);
2126 }
2127 else {
Victor Stinnerb6ed57d2016-12-09 14:24:02 +01002128 result = _PyObject_CallMethodIdObjArgs(coro, &PyId_send,
2129 Py_None, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002130 }
2131 }
2132 else {
Victor Stinnerb6ed57d2016-12-09 14:24:02 +01002133 result = _PyObject_CallMethodIdObjArgs(coro, &PyId_throw,
2134 exc, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002135 if (clear_exc) {
2136 /* We created 'exc' during this call */
Serhiy Storchakabca49392017-09-03 08:10:14 +03002137 Py_DECREF(exc);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002138 }
2139 }
2140
2141 if (result == NULL) {
2142 PyObject *et, *ev, *tb;
2143
2144 if (_PyGen_FetchStopIterationValue(&o) == 0) {
2145 /* The error is StopIteration and that means that
2146 the underlying coroutine has resolved */
INADA Naoki991adca2017-05-11 21:18:38 +09002147 if (task->task_must_cancel) {
2148 // Task is cancelled right before coro stops.
2149 Py_DECREF(o);
2150 task->task_must_cancel = 0;
2151 et = asyncio_CancelledError;
2152 Py_INCREF(et);
2153 ev = NULL;
2154 tb = NULL;
2155 goto set_exception;
2156 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002157 PyObject *res = future_set_result((FutureObj*)task, o);
2158 Py_DECREF(o);
2159 if (res == NULL) {
2160 return NULL;
2161 }
2162 Py_DECREF(res);
2163 Py_RETURN_NONE;
2164 }
2165
2166 if (PyErr_ExceptionMatches(asyncio_CancelledError)) {
2167 /* CancelledError */
2168 PyErr_Clear();
2169 return future_cancel((FutureObj*)task);
2170 }
2171
2172 /* Some other exception; pop it and call Task.set_exception() */
2173 PyErr_Fetch(&et, &ev, &tb);
INADA Naoki991adca2017-05-11 21:18:38 +09002174
2175set_exception:
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002176 assert(et);
2177 if (!ev || !PyObject_TypeCheck(ev, (PyTypeObject *) et)) {
2178 PyErr_NormalizeException(&et, &ev, &tb);
2179 }
Yury Selivanovedfe8862016-12-01 11:37:47 -05002180 if (tb != NULL) {
2181 PyException_SetTraceback(ev, tb);
2182 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002183 o = future_set_exception((FutureObj*)task, ev);
2184 if (!o) {
2185 /* An exception in Task.set_exception() */
Serhiy Storchakabca49392017-09-03 08:10:14 +03002186 Py_DECREF(et);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002187 Py_XDECREF(tb);
2188 Py_XDECREF(ev);
2189 goto fail;
2190 }
2191 assert(o == Py_None);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002192 Py_DECREF(o);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002193
2194 if (!PyErr_GivenExceptionMatches(et, PyExc_Exception)) {
2195 /* We've got a BaseException; re-raise it */
2196 PyErr_Restore(et, ev, tb);
2197 goto fail;
2198 }
2199
Serhiy Storchakabca49392017-09-03 08:10:14 +03002200 Py_DECREF(et);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002201 Py_XDECREF(tb);
2202 Py_XDECREF(ev);
2203
2204 Py_RETURN_NONE;
2205 }
2206
2207 if (result == (PyObject*)task) {
2208 /* We have a task that wants to await on itself */
2209 goto self_await;
2210 }
2211
2212 /* Check if `result` is FutureObj or TaskObj (and not a subclass) */
2213 if (Future_CheckExact(result) || Task_CheckExact(result)) {
2214 PyObject *wrapper;
2215 PyObject *res;
2216 FutureObj *fut = (FutureObj*)result;
2217
2218 /* Check if `result` future is attached to a different loop */
2219 if (fut->fut_loop != task->task_loop) {
2220 goto different_loop;
2221 }
2222
2223 if (fut->fut_blocking) {
2224 fut->fut_blocking = 0;
2225
2226 /* result.add_done_callback(task._wakeup) */
2227 wrapper = TaskWakeupMethWrapper_new(task);
2228 if (wrapper == NULL) {
2229 goto fail;
2230 }
2231 res = future_add_done_callback((FutureObj*)result, wrapper);
2232 Py_DECREF(wrapper);
2233 if (res == NULL) {
2234 goto fail;
2235 }
2236 Py_DECREF(res);
2237
2238 /* task._fut_waiter = result */
2239 task->task_fut_waiter = result; /* no incref is necessary */
2240
2241 if (task->task_must_cancel) {
2242 PyObject *r;
2243 r = future_cancel(fut);
2244 if (r == NULL) {
2245 return NULL;
2246 }
2247 if (r == Py_True) {
2248 task->task_must_cancel = 0;
2249 }
2250 Py_DECREF(r);
2251 }
2252
2253 Py_RETURN_NONE;
2254 }
2255 else {
2256 goto yield_insteadof_yf;
2257 }
2258 }
2259
2260 /* Check if `result` is a Future-compatible object */
2261 o = PyObject_GetAttrString(result, "_asyncio_future_blocking");
2262 if (o == NULL) {
2263 if (PyErr_ExceptionMatches(PyExc_AttributeError)) {
2264 PyErr_Clear();
2265 }
2266 else {
2267 goto fail;
2268 }
2269 }
2270 else {
2271 if (o == Py_None) {
Serhiy Storchakabca49392017-09-03 08:10:14 +03002272 Py_DECREF(o);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002273 }
2274 else {
2275 /* `result` is a Future-compatible object */
2276 PyObject *wrapper;
2277 PyObject *res;
2278
2279 int blocking = PyObject_IsTrue(o);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002280 Py_DECREF(o);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002281 if (blocking < 0) {
2282 goto fail;
2283 }
2284
2285 /* Check if `result` future is attached to a different loop */
2286 PyObject *oloop = PyObject_GetAttrString(result, "_loop");
2287 if (oloop == NULL) {
2288 goto fail;
2289 }
2290 if (oloop != task->task_loop) {
2291 Py_DECREF(oloop);
2292 goto different_loop;
2293 }
2294 else {
2295 Py_DECREF(oloop);
2296 }
2297
2298 if (blocking) {
2299 /* result._asyncio_future_blocking = False */
2300 if (PyObject_SetAttrString(
2301 result, "_asyncio_future_blocking", Py_False) == -1) {
2302 goto fail;
2303 }
2304
2305 /* result.add_done_callback(task._wakeup) */
2306 wrapper = TaskWakeupMethWrapper_new(task);
2307 if (wrapper == NULL) {
2308 goto fail;
2309 }
Victor Stinnerb6ed57d2016-12-09 14:24:02 +01002310 res = _PyObject_CallMethodIdObjArgs(result,
2311 &PyId_add_done_callback,
2312 wrapper, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002313 Py_DECREF(wrapper);
2314 if (res == NULL) {
2315 goto fail;
2316 }
2317 Py_DECREF(res);
2318
2319 /* task._fut_waiter = result */
2320 task->task_fut_waiter = result; /* no incref is necessary */
2321
2322 if (task->task_must_cancel) {
2323 PyObject *r;
2324 int is_true;
2325 r = _PyObject_CallMethodId(result, &PyId_cancel, NULL);
2326 if (r == NULL) {
2327 return NULL;
2328 }
2329 is_true = PyObject_IsTrue(r);
2330 Py_DECREF(r);
2331 if (is_true < 0) {
2332 return NULL;
2333 }
2334 else if (is_true) {
2335 task->task_must_cancel = 0;
2336 }
2337 }
2338
2339 Py_RETURN_NONE;
2340 }
2341 else {
2342 goto yield_insteadof_yf;
2343 }
2344 }
2345 }
2346
2347 /* Check if `result` is None */
2348 if (result == Py_None) {
2349 /* Bare yield relinquishes control for one event loop iteration. */
2350 if (task_call_step_soon(task, NULL)) {
2351 goto fail;
2352 }
2353 return result;
2354 }
2355
2356 /* Check if `result` is a generator */
Victor Stinnerde4ae3d2016-12-04 22:59:09 +01002357 o = PyObject_CallFunctionObjArgs(inspect_isgenerator, result, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002358 if (o == NULL) {
2359 /* An exception in inspect.isgenerator */
2360 goto fail;
2361 }
2362 res = PyObject_IsTrue(o);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002363 Py_DECREF(o);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002364 if (res == -1) {
2365 /* An exception while checking if 'val' is True */
2366 goto fail;
2367 }
2368 if (res == 1) {
2369 /* `result` is a generator */
2370 PyObject *ret;
2371 ret = task_set_error_soon(
2372 task, PyExc_RuntimeError,
2373 "yield was used instead of yield from for "
2374 "generator in task %R with %S", task, result);
2375 Py_DECREF(result);
2376 return ret;
2377 }
2378
2379 /* The `result` is none of the above */
2380 Py_DECREF(result);
2381 return task_set_error_soon(
2382 task, PyExc_RuntimeError, "Task got bad yield: %R", result);
2383
2384self_await:
2385 o = task_set_error_soon(
2386 task, PyExc_RuntimeError,
2387 "Task cannot await on itself: %R", task);
2388 Py_DECREF(result);
2389 return o;
2390
2391yield_insteadof_yf:
2392 o = task_set_error_soon(
2393 task, PyExc_RuntimeError,
2394 "yield was used instead of yield from "
2395 "in task %R with %R",
2396 task, result);
2397 Py_DECREF(result);
2398 return o;
2399
2400different_loop:
2401 o = task_set_error_soon(
2402 task, PyExc_RuntimeError,
2403 "Task %R got Future %R attached to a different loop",
2404 task, result);
2405 Py_DECREF(result);
2406 return o;
2407
2408fail:
2409 Py_XDECREF(result);
2410 return NULL;
2411}
2412
2413static PyObject *
2414task_step(TaskObj *task, PyObject *exc)
2415{
2416 PyObject *res;
2417 PyObject *ot;
2418
Yury Selivanov684ef2c2016-10-28 19:01:21 -04002419 if (PyDict_SetItem(current_tasks,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002420 task->task_loop, (PyObject*)task) == -1)
2421 {
2422 return NULL;
2423 }
2424
2425 res = task_step_impl(task, exc);
2426
2427 if (res == NULL) {
2428 PyObject *et, *ev, *tb;
2429 PyErr_Fetch(&et, &ev, &tb);
2430 ot = _PyDict_Pop(current_tasks, task->task_loop, NULL);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002431 Py_XDECREF(ot);
2432 _PyErr_ChainExceptions(et, ev, tb);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002433 return NULL;
2434 }
2435 else {
2436 ot = _PyDict_Pop(current_tasks, task->task_loop, NULL);
2437 if (ot == NULL) {
2438 Py_DECREF(res);
2439 return NULL;
2440 }
2441 else {
2442 Py_DECREF(ot);
2443 return res;
2444 }
2445 }
2446}
2447
2448static PyObject *
2449task_wakeup(TaskObj *task, PyObject *o)
2450{
Serhiy Storchakabca49392017-09-03 08:10:14 +03002451 PyObject *et, *ev, *tb;
2452 PyObject *result;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002453 assert(o);
2454
2455 if (Future_CheckExact(o) || Task_CheckExact(o)) {
2456 PyObject *fut_result = NULL;
2457 int res = future_get_result((FutureObj*)o, &fut_result);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002458
2459 switch(res) {
2460 case -1:
2461 assert(fut_result == NULL);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002462 break; /* exception raised */
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002463 case 0:
2464 Py_DECREF(fut_result);
2465 return task_call_step(task, NULL);
2466 default:
2467 assert(res == 1);
2468 result = task_call_step(task, fut_result);
2469 Py_DECREF(fut_result);
2470 return result;
2471 }
2472 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002473 else {
Serhiy Storchakabca49392017-09-03 08:10:14 +03002474 PyObject *fut_result = PyObject_CallMethod(o, "result", NULL);
2475 if (fut_result != NULL) {
2476 Py_DECREF(fut_result);
2477 return task_call_step(task, NULL);
2478 }
2479 /* exception raised */
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002480 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03002481
2482 PyErr_Fetch(&et, &ev, &tb);
2483 if (!PyErr_GivenExceptionMatches(et, PyExc_Exception)) {
2484 /* We've got a BaseException; re-raise it */
2485 PyErr_Restore(et, ev, tb);
2486 return NULL;
2487 }
2488 if (!ev || !PyObject_TypeCheck(ev, (PyTypeObject *) et)) {
2489 PyErr_NormalizeException(&et, &ev, &tb);
2490 }
2491
2492 result = task_call_step(task, ev);
2493
2494 Py_DECREF(et);
2495 Py_XDECREF(tb);
2496 Py_XDECREF(ev);
2497
2498 return result;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002499}
2500
2501
Yury Selivanova70232f2017-12-13 14:49:42 -05002502/*********************** Functions **************************/
2503
2504
2505/*[clinic input]
2506_asyncio._get_running_loop
2507
2508Return the running event loop or None.
2509
2510This is a low-level function intended to be used by event loops.
2511This function is thread-specific.
2512
2513[clinic start generated code]*/
2514
2515static PyObject *
2516_asyncio__get_running_loop_impl(PyObject *module)
2517/*[clinic end generated code: output=b4390af721411a0a input=0a21627e25a4bd43]*/
2518{
2519 PyObject *loop;
2520 if (get_running_loop(&loop)) {
2521 return NULL;
2522 }
2523 if (loop == NULL) {
2524 /* There's no currently running event loop */
2525 Py_RETURN_NONE;
2526 }
2527 return loop;
2528}
2529
2530/*[clinic input]
2531_asyncio._set_running_loop
2532 loop: 'O'
2533 /
2534
2535Set the running event loop.
2536
2537This is a low-level function intended to be used by event loops.
2538This function is thread-specific.
2539[clinic start generated code]*/
2540
2541static PyObject *
2542_asyncio__set_running_loop(PyObject *module, PyObject *loop)
2543/*[clinic end generated code: output=ae56bf7a28ca189a input=4c9720233d606604]*/
2544{
2545 if (set_running_loop(loop)) {
2546 return NULL;
2547 }
2548 Py_RETURN_NONE;
2549}
2550
2551/*[clinic input]
2552_asyncio.get_event_loop
2553
2554Return an asyncio event loop.
2555
2556When called from a coroutine or a callback (e.g. scheduled with
2557call_soon or similar API), this function will always return the
2558running event loop.
2559
2560If there is no running event loop set, the function will return
2561the result of `get_event_loop_policy().get_event_loop()` call.
2562[clinic start generated code]*/
2563
2564static PyObject *
2565_asyncio_get_event_loop_impl(PyObject *module)
2566/*[clinic end generated code: output=2a2d8b2f824c648b input=9364bf2916c8655d]*/
2567{
2568 return get_event_loop();
2569}
2570
2571/*[clinic input]
2572_asyncio.get_running_loop
2573
2574Return the running event loop. Raise a RuntimeError if there is none.
2575
2576This function is thread-specific.
2577[clinic start generated code]*/
2578
2579static PyObject *
2580_asyncio_get_running_loop_impl(PyObject *module)
2581/*[clinic end generated code: output=c247b5f9e529530e input=2a3bf02ba39f173d]*/
2582{
2583 PyObject *loop;
2584 if (get_running_loop(&loop)) {
2585 return NULL;
2586 }
2587 if (loop == NULL) {
2588 /* There's no currently running event loop */
2589 PyErr_SetString(
2590 PyExc_RuntimeError, "no running event loop");
2591 }
2592 return loop;
2593}
2594
2595
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002596/*********************** Module **************************/
2597
2598
2599static void
2600module_free(void *m)
2601{
2602 Py_CLEAR(current_tasks);
2603 Py_CLEAR(all_tasks);
2604 Py_CLEAR(traceback_extract_stack);
Yury Selivanova70232f2017-12-13 14:49:42 -05002605 Py_CLEAR(asyncio_get_event_loop_policy);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002606 Py_CLEAR(asyncio_future_repr_info_func);
2607 Py_CLEAR(asyncio_task_repr_info_func);
2608 Py_CLEAR(asyncio_task_get_stack_func);
2609 Py_CLEAR(asyncio_task_print_stack_func);
2610 Py_CLEAR(asyncio_InvalidStateError);
2611 Py_CLEAR(asyncio_CancelledError);
2612 Py_CLEAR(inspect_isgenerator);
Yury Selivanova70232f2017-12-13 14:49:42 -05002613 Py_CLEAR(os_getpid);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002614}
2615
2616static int
2617module_init(void)
2618{
2619 PyObject *module = NULL;
2620 PyObject *cls;
2621
2622#define WITH_MOD(NAME) \
2623 Py_CLEAR(module); \
2624 module = PyImport_ImportModule(NAME); \
2625 if (module == NULL) { \
Serhiy Storchakabca49392017-09-03 08:10:14 +03002626 goto fail; \
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002627 }
2628
2629#define GET_MOD_ATTR(VAR, NAME) \
2630 VAR = PyObject_GetAttrString(module, NAME); \
2631 if (VAR == NULL) { \
2632 goto fail; \
2633 }
2634
2635 WITH_MOD("asyncio.events")
Yury Selivanova70232f2017-12-13 14:49:42 -05002636 GET_MOD_ATTR(asyncio_get_event_loop_policy, "get_event_loop_policy")
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002637
2638 WITH_MOD("asyncio.base_futures")
2639 GET_MOD_ATTR(asyncio_future_repr_info_func, "_future_repr_info")
2640 GET_MOD_ATTR(asyncio_InvalidStateError, "InvalidStateError")
2641 GET_MOD_ATTR(asyncio_CancelledError, "CancelledError")
2642
2643 WITH_MOD("asyncio.base_tasks")
2644 GET_MOD_ATTR(asyncio_task_repr_info_func, "_task_repr_info")
2645 GET_MOD_ATTR(asyncio_task_get_stack_func, "_task_get_stack")
2646 GET_MOD_ATTR(asyncio_task_print_stack_func, "_task_print_stack")
2647
2648 WITH_MOD("inspect")
2649 GET_MOD_ATTR(inspect_isgenerator, "isgenerator")
2650
Yury Selivanova70232f2017-12-13 14:49:42 -05002651 WITH_MOD("os")
2652 GET_MOD_ATTR(os_getpid, "getpid")
2653
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002654 WITH_MOD("traceback")
2655 GET_MOD_ATTR(traceback_extract_stack, "extract_stack")
2656
2657 WITH_MOD("weakref")
2658 GET_MOD_ATTR(cls, "WeakSet")
Victor Stinnera5ed5f02016-12-06 18:45:50 +01002659 all_tasks = _PyObject_CallNoArg(cls);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002660 Py_DECREF(cls);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002661 if (all_tasks == NULL) {
INADA Naokic411a7d2016-10-18 11:48:14 +09002662 goto fail;
2663 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09002664
Yury Selivanov684ef2c2016-10-28 19:01:21 -04002665 current_tasks = PyDict_New();
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002666 if (current_tasks == NULL) {
2667 goto fail;
2668 }
2669
Serhiy Storchakabca49392017-09-03 08:10:14 +03002670 Py_DECREF(module);
INADA Naokic411a7d2016-10-18 11:48:14 +09002671 return 0;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09002672
INADA Naokic411a7d2016-10-18 11:48:14 +09002673fail:
INADA Naokic411a7d2016-10-18 11:48:14 +09002674 Py_CLEAR(module);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002675 module_free(NULL);
INADA Naokic411a7d2016-10-18 11:48:14 +09002676 return -1;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09002677
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002678#undef WITH_MOD
2679#undef GET_MOD_ATTR
2680}
INADA Naoki9e4e38e2016-10-09 14:44:47 +09002681
INADA Naokic411a7d2016-10-18 11:48:14 +09002682PyDoc_STRVAR(module_doc, "Accelerator module for asyncio");
INADA Naoki9e4e38e2016-10-09 14:44:47 +09002683
Yury Selivanova70232f2017-12-13 14:49:42 -05002684static PyMethodDef asyncio_methods[] = {
2685 _ASYNCIO_GET_EVENT_LOOP_METHODDEF
2686 _ASYNCIO_GET_RUNNING_LOOP_METHODDEF
2687 _ASYNCIO__GET_RUNNING_LOOP_METHODDEF
2688 _ASYNCIO__SET_RUNNING_LOOP_METHODDEF
2689 {NULL, NULL}
2690};
2691
INADA Naoki9f2ce252016-10-15 15:39:19 +09002692static struct PyModuleDef _asynciomodule = {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09002693 PyModuleDef_HEAD_INIT, /* m_base */
INADA Naoki9f2ce252016-10-15 15:39:19 +09002694 "_asyncio", /* m_name */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09002695 module_doc, /* m_doc */
2696 -1, /* m_size */
Yury Selivanova70232f2017-12-13 14:49:42 -05002697 asyncio_methods, /* m_methods */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09002698 NULL, /* m_slots */
2699 NULL, /* m_traverse */
2700 NULL, /* m_clear */
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002701 (freefunc)module_free /* m_free */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09002702};
2703
2704
2705PyMODINIT_FUNC
INADA Naoki9f2ce252016-10-15 15:39:19 +09002706PyInit__asyncio(void)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09002707{
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002708 if (module_init() < 0) {
INADA Naokic411a7d2016-10-18 11:48:14 +09002709 return NULL;
2710 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09002711 if (PyType_Ready(&FutureType) < 0) {
2712 return NULL;
2713 }
2714 if (PyType_Ready(&FutureIterType) < 0) {
2715 return NULL;
2716 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03002717 if (PyType_Ready(&TaskStepMethWrapper_Type) < 0) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002718 return NULL;
2719 }
2720 if(PyType_Ready(&TaskWakeupMethWrapper_Type) < 0) {
2721 return NULL;
2722 }
2723 if (PyType_Ready(&TaskType) < 0) {
2724 return NULL;
2725 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09002726
INADA Naoki9f2ce252016-10-15 15:39:19 +09002727 PyObject *m = PyModule_Create(&_asynciomodule);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09002728 if (m == NULL) {
2729 return NULL;
2730 }
2731
2732 Py_INCREF(&FutureType);
2733 if (PyModule_AddObject(m, "Future", (PyObject *)&FutureType) < 0) {
2734 Py_DECREF(&FutureType);
2735 return NULL;
2736 }
2737
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002738 Py_INCREF(&TaskType);
2739 if (PyModule_AddObject(m, "Task", (PyObject *)&TaskType) < 0) {
2740 Py_DECREF(&TaskType);
2741 return NULL;
2742 }
2743
INADA Naoki9e4e38e2016-10-09 14:44:47 +09002744 return m;
2745}