blob: 2c64c55e7e347673d833ef5225fee3caf6470ca9 [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 Selivanova0c1ba62016-10-28 12:52:37 -040012_Py_IDENTIFIER(add_done_callback);
INADA Naoki9e4e38e2016-10-09 14:44:47 +090013_Py_IDENTIFIER(call_soon);
Yury Selivanova0c1ba62016-10-28 12:52:37 -040014_Py_IDENTIFIER(cancel);
15_Py_IDENTIFIER(send);
16_Py_IDENTIFIER(throw);
17_Py_IDENTIFIER(_step);
18_Py_IDENTIFIER(_schedule_callbacks);
19_Py_IDENTIFIER(_wakeup);
INADA Naoki9e4e38e2016-10-09 14:44:47 +090020
21
INADA Naoki9f2ce252016-10-15 15:39:19 +090022/* State of the _asyncio module */
Yury Selivanova0c1ba62016-10-28 12:52:37 -040023static PyObject *all_tasks;
Yury Selivanov684ef2c2016-10-28 19:01:21 -040024static PyObject *current_tasks;
INADA Naoki9e4e38e2016-10-09 14:44:47 +090025static PyObject *traceback_extract_stack;
26static PyObject *asyncio_get_event_loop;
Yury Selivanova0c1ba62016-10-28 12:52:37 -040027static PyObject *asyncio_future_repr_info_func;
28static PyObject *asyncio_task_repr_info_func;
29static PyObject *asyncio_task_get_stack_func;
30static PyObject *asyncio_task_print_stack_func;
INADA Naoki9e4e38e2016-10-09 14:44:47 +090031static PyObject *asyncio_InvalidStateError;
32static PyObject *asyncio_CancelledError;
Yury Selivanova0c1ba62016-10-28 12:52:37 -040033static PyObject *inspect_isgenerator;
INADA Naoki9e4e38e2016-10-09 14:44:47 +090034
35
INADA Naoki9e4e38e2016-10-09 14:44:47 +090036typedef enum {
37 STATE_PENDING,
38 STATE_CANCELLED,
39 STATE_FINISHED
40} fut_state;
41
Yury Selivanova0c1ba62016-10-28 12:52:37 -040042#define FutureObj_HEAD(prefix) \
43 PyObject_HEAD \
44 PyObject *prefix##_loop; \
45 PyObject *prefix##_callbacks; \
46 PyObject *prefix##_exception; \
47 PyObject *prefix##_result; \
48 PyObject *prefix##_source_tb; \
49 fut_state prefix##_state; \
50 int prefix##_log_tb; \
51 int prefix##_blocking; \
52 PyObject *dict; \
53 PyObject *prefix##_weakreflist;
54
55typedef struct {
56 FutureObj_HEAD(fut)
57} FutureObj;
58
59typedef struct {
60 FutureObj_HEAD(task)
61 PyObject *task_fut_waiter;
62 PyObject *task_coro;
63 int task_must_cancel;
64 int task_log_destroy_pending;
65} TaskObj;
INADA Naoki9e4e38e2016-10-09 14:44:47 +090066
67typedef struct {
68 PyObject_HEAD
Yury Selivanova0c1ba62016-10-28 12:52:37 -040069 TaskObj *sw_task;
70 PyObject *sw_arg;
Serhiy Storchakabca49392017-09-03 08:10:14 +030071} TaskStepMethWrapper;
INADA Naoki9e4e38e2016-10-09 14:44:47 +090072
Yury Selivanova0c1ba62016-10-28 12:52:37 -040073typedef struct {
74 PyObject_HEAD
75 TaskObj *ww_task;
76} TaskWakeupMethWrapper;
77
78
79#include "clinic/_asynciomodule.c.h"
80
81
82/*[clinic input]
83class _asyncio.Future "FutureObj *" "&Future_Type"
84[clinic start generated code]*/
85/*[clinic end generated code: output=da39a3ee5e6b4b0d input=00d3e4abca711e0f]*/
86
87/* Get FutureIter from Future */
88static PyObject* future_new_iter(PyObject *);
89static inline int future_call_schedule_callbacks(FutureObj *);
INADA Naoki9e4e38e2016-10-09 14:44:47 +090090
91static int
Yury Selivanova0c1ba62016-10-28 12:52:37 -040092future_schedule_callbacks(FutureObj *fut)
INADA Naoki9e4e38e2016-10-09 14:44:47 +090093{
94 Py_ssize_t len;
Serhiy Storchakabca49392017-09-03 08:10:14 +030095 PyObject *callbacks;
INADA Naoki9e4e38e2016-10-09 14:44:47 +090096 int i;
97
98 if (fut->fut_callbacks == NULL) {
Serhiy Storchakabca49392017-09-03 08:10:14 +030099 PyErr_SetString(PyExc_RuntimeError, "uninitialized Future object");
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900100 return -1;
101 }
102
103 len = PyList_GET_SIZE(fut->fut_callbacks);
104 if (len == 0) {
105 return 0;
106 }
107
Serhiy Storchakabca49392017-09-03 08:10:14 +0300108 callbacks = PyList_GetSlice(fut->fut_callbacks, 0, len);
109 if (callbacks == NULL) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900110 return -1;
111 }
112 if (PyList_SetSlice(fut->fut_callbacks, 0, len, NULL) < 0) {
Serhiy Storchakabca49392017-09-03 08:10:14 +0300113 Py_DECREF(callbacks);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900114 return -1;
115 }
116
117 for (i = 0; i < len; i++) {
Serhiy Storchakabca49392017-09-03 08:10:14 +0300118 PyObject *handle;
119 PyObject *cb = PyList_GET_ITEM(callbacks, i);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900120
Victor Stinnerb6ed57d2016-12-09 14:24:02 +0100121 handle = _PyObject_CallMethodIdObjArgs(fut->fut_loop, &PyId_call_soon,
122 cb, fut, NULL);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900123
124 if (handle == NULL) {
Serhiy Storchakabca49392017-09-03 08:10:14 +0300125 Py_DECREF(callbacks);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900126 return -1;
127 }
Serhiy Storchakabca49392017-09-03 08:10:14 +0300128 Py_DECREF(handle);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900129 }
130
Serhiy Storchakabca49392017-09-03 08:10:14 +0300131 Py_DECREF(callbacks);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900132 return 0;
133}
134
135static int
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400136future_init(FutureObj *fut, PyObject *loop)
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900137{
Serhiy Storchakabca49392017-09-03 08:10:14 +0300138 PyObject *res;
139 int is_true;
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900140 _Py_IDENTIFIER(get_debug);
141
Serhiy Storchakabca49392017-09-03 08:10:14 +0300142 if (loop == Py_None) {
Victor Stinnera5ed5f02016-12-06 18:45:50 +0100143 loop = _PyObject_CallNoArg(asyncio_get_event_loop);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900144 if (loop == NULL) {
145 return -1;
146 }
147 }
148 else {
149 Py_INCREF(loop);
150 }
Serhiy Storchakabca49392017-09-03 08:10:14 +0300151 Py_XSETREF(fut->fut_loop, loop);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900152
Victor Stinnerf94d1ee2016-10-29 09:05:39 +0200153 res = _PyObject_CallMethodId(fut->fut_loop, &PyId_get_debug, NULL);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900154 if (res == NULL) {
155 return -1;
156 }
Serhiy Storchakabca49392017-09-03 08:10:14 +0300157 is_true = PyObject_IsTrue(res);
158 Py_DECREF(res);
159 if (is_true < 0) {
160 return -1;
161 }
162 if (is_true) {
163 Py_XSETREF(fut->fut_source_tb, _PyObject_CallNoArg(traceback_extract_stack));
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900164 if (fut->fut_source_tb == NULL) {
165 return -1;
166 }
167 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900168
Serhiy Storchakabca49392017-09-03 08:10:14 +0300169 Py_XSETREF(fut->fut_callbacks, PyList_New(0));
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900170 if (fut->fut_callbacks == NULL) {
171 return -1;
172 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400173
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900174 return 0;
175}
176
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900177static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400178future_set_result(FutureObj *fut, PyObject *res)
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900179{
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900180 if (fut->fut_state != STATE_PENDING) {
181 PyErr_SetString(asyncio_InvalidStateError, "invalid state");
182 return NULL;
183 }
184
Serhiy Storchakabca49392017-09-03 08:10:14 +0300185 assert(!fut->fut_result);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900186 Py_INCREF(res);
187 fut->fut_result = res;
188 fut->fut_state = STATE_FINISHED;
189
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400190 if (future_call_schedule_callbacks(fut) == -1) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900191 return NULL;
192 }
193 Py_RETURN_NONE;
194}
195
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900196static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400197future_set_exception(FutureObj *fut, PyObject *exc)
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900198{
199 PyObject *exc_val = NULL;
200
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900201 if (fut->fut_state != STATE_PENDING) {
202 PyErr_SetString(asyncio_InvalidStateError, "invalid state");
203 return NULL;
204 }
205
206 if (PyExceptionClass_Check(exc)) {
Victor Stinnera5ed5f02016-12-06 18:45:50 +0100207 exc_val = _PyObject_CallNoArg(exc);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900208 if (exc_val == NULL) {
209 return NULL;
210 }
Serhiy Storchakabca49392017-09-03 08:10:14 +0300211 if (fut->fut_state != STATE_PENDING) {
212 Py_DECREF(exc_val);
213 PyErr_SetString(asyncio_InvalidStateError, "invalid state");
214 return NULL;
215 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900216 }
217 else {
218 exc_val = exc;
219 Py_INCREF(exc_val);
220 }
221 if (!PyExceptionInstance_Check(exc_val)) {
222 Py_DECREF(exc_val);
223 PyErr_SetString(PyExc_TypeError, "invalid exception object");
224 return NULL;
225 }
226 if ((PyObject*)Py_TYPE(exc_val) == PyExc_StopIteration) {
227 Py_DECREF(exc_val);
228 PyErr_SetString(PyExc_TypeError,
229 "StopIteration interacts badly with generators "
230 "and cannot be raised into a Future");
231 return NULL;
232 }
233
Serhiy Storchakabca49392017-09-03 08:10:14 +0300234 assert(!fut->fut_exception);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900235 fut->fut_exception = exc_val;
236 fut->fut_state = STATE_FINISHED;
237
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400238 if (future_call_schedule_callbacks(fut) == -1) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900239 return NULL;
240 }
241
242 fut->fut_log_tb = 1;
243 Py_RETURN_NONE;
244}
245
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400246static int
247future_get_result(FutureObj *fut, PyObject **result)
248{
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400249 if (fut->fut_state == STATE_CANCELLED) {
Serhiy Storchakabca49392017-09-03 08:10:14 +0300250 PyErr_SetNone(asyncio_CancelledError);
251 return -1;
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400252 }
253
254 if (fut->fut_state != STATE_FINISHED) {
Serhiy Storchakabca49392017-09-03 08:10:14 +0300255 PyErr_SetString(asyncio_InvalidStateError, "Result is not set.");
256 return -1;
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400257 }
258
259 fut->fut_log_tb = 0;
260 if (fut->fut_exception != NULL) {
261 Py_INCREF(fut->fut_exception);
262 *result = fut->fut_exception;
263 return 1;
264 }
265
266 Py_INCREF(fut->fut_result);
267 *result = fut->fut_result;
268 return 0;
269}
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900270
271static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400272future_add_done_callback(FutureObj *fut, PyObject *arg)
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900273{
274 if (fut->fut_state != STATE_PENDING) {
Victor Stinnerb6ed57d2016-12-09 14:24:02 +0100275 PyObject *handle = _PyObject_CallMethodIdObjArgs(fut->fut_loop,
276 &PyId_call_soon,
277 arg, fut, NULL);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900278 if (handle == NULL) {
279 return NULL;
280 }
Serhiy Storchakabca49392017-09-03 08:10:14 +0300281 Py_DECREF(handle);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900282 }
283 else {
Serhiy Storchakabca49392017-09-03 08:10:14 +0300284 if (fut->fut_callbacks == NULL) {
285 PyErr_SetString(PyExc_RuntimeError, "uninitialized Future object");
286 return NULL;
287 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900288 int err = PyList_Append(fut->fut_callbacks, arg);
289 if (err != 0) {
290 return NULL;
291 }
292 }
293 Py_RETURN_NONE;
294}
295
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400296static PyObject *
297future_cancel(FutureObj *fut)
298{
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +0000299 fut->fut_log_tb = 0;
300
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400301 if (fut->fut_state != STATE_PENDING) {
302 Py_RETURN_FALSE;
303 }
304 fut->fut_state = STATE_CANCELLED;
305
306 if (future_call_schedule_callbacks(fut) == -1) {
307 return NULL;
308 }
309
310 Py_RETURN_TRUE;
311}
312
313/*[clinic input]
314_asyncio.Future.__init__
315
316 *
Serhiy Storchakabca49392017-09-03 08:10:14 +0300317 loop: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400318
319This class is *almost* compatible with concurrent.futures.Future.
320
321 Differences:
322
323 - result() and exception() do not take a timeout argument and
324 raise an exception when the future isn't done yet.
325
326 - Callbacks registered with add_done_callback() are always called
327 via the event loop's call_soon_threadsafe().
328
329 - This class is not compatible with the wait() and as_completed()
330 methods in the concurrent.futures package.
331[clinic start generated code]*/
332
333static int
334_asyncio_Future___init___impl(FutureObj *self, PyObject *loop)
Serhiy Storchakabca49392017-09-03 08:10:14 +0300335/*[clinic end generated code: output=9ed75799eaccb5d6 input=89af317082bc0bf8]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400336
337{
338 return future_init(self, loop);
339}
340
341static int
342FutureObj_clear(FutureObj *fut)
343{
344 Py_CLEAR(fut->fut_loop);
345 Py_CLEAR(fut->fut_callbacks);
346 Py_CLEAR(fut->fut_result);
347 Py_CLEAR(fut->fut_exception);
348 Py_CLEAR(fut->fut_source_tb);
349 Py_CLEAR(fut->dict);
350 return 0;
351}
352
353static int
354FutureObj_traverse(FutureObj *fut, visitproc visit, void *arg)
355{
356 Py_VISIT(fut->fut_loop);
357 Py_VISIT(fut->fut_callbacks);
358 Py_VISIT(fut->fut_result);
359 Py_VISIT(fut->fut_exception);
360 Py_VISIT(fut->fut_source_tb);
361 Py_VISIT(fut->dict);
362 return 0;
363}
364
365/*[clinic input]
366_asyncio.Future.result
367
368Return the result this future represents.
369
370If the future has been cancelled, raises CancelledError. If the
371future's result isn't yet available, raises InvalidStateError. If
372the future is done and has an exception set, this exception is raised.
373[clinic start generated code]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900374
375static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400376_asyncio_Future_result_impl(FutureObj *self)
377/*[clinic end generated code: output=f35f940936a4b1e5 input=49ecf9cf5ec50dc5]*/
378{
379 PyObject *result;
380 int res = future_get_result(self, &result);
381
382 if (res == -1) {
383 return NULL;
384 }
385
386 if (res == 0) {
387 return result;
388 }
389
390 assert(res == 1);
391
392 PyErr_SetObject(PyExceptionInstance_Class(result), result);
393 Py_DECREF(result);
394 return NULL;
395}
396
397/*[clinic input]
398_asyncio.Future.exception
399
400Return the exception that was set on this future.
401
402The exception (or None if no exception was set) is returned only if
403the future is done. If the future has been cancelled, raises
404CancelledError. If the future isn't done yet, raises
405InvalidStateError.
406[clinic start generated code]*/
407
408static PyObject *
409_asyncio_Future_exception_impl(FutureObj *self)
410/*[clinic end generated code: output=88b20d4f855e0710 input=733547a70c841c68]*/
411{
412 if (self->fut_state == STATE_CANCELLED) {
Serhiy Storchakabca49392017-09-03 08:10:14 +0300413 PyErr_SetNone(asyncio_CancelledError);
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400414 return NULL;
415 }
416
417 if (self->fut_state != STATE_FINISHED) {
Serhiy Storchakabca49392017-09-03 08:10:14 +0300418 PyErr_SetString(asyncio_InvalidStateError, "Exception is not set.");
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400419 return NULL;
420 }
421
422 if (self->fut_exception != NULL) {
423 self->fut_log_tb = 0;
424 Py_INCREF(self->fut_exception);
425 return self->fut_exception;
426 }
427
428 Py_RETURN_NONE;
429}
430
431/*[clinic input]
432_asyncio.Future.set_result
433
Serhiy Storchakabca49392017-09-03 08:10:14 +0300434 res: object
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400435 /
436
437Mark the future done and set its result.
438
439If the future is already done when this method is called, raises
440InvalidStateError.
441[clinic start generated code]*/
442
443static PyObject *
444_asyncio_Future_set_result(FutureObj *self, PyObject *res)
Serhiy Storchakabca49392017-09-03 08:10:14 +0300445/*[clinic end generated code: output=a620abfc2796bfb6 input=5b9dc180f1baa56d]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400446{
447 return future_set_result(self, res);
448}
449
450/*[clinic input]
451_asyncio.Future.set_exception
452
Serhiy Storchakabca49392017-09-03 08:10:14 +0300453 exception: object
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400454 /
455
456Mark the future done and set an exception.
457
458If the future is already done when this method is called, raises
459InvalidStateError.
460[clinic start generated code]*/
461
462static PyObject *
463_asyncio_Future_set_exception(FutureObj *self, PyObject *exception)
Serhiy Storchakabca49392017-09-03 08:10:14 +0300464/*[clinic end generated code: output=f1c1b0cd321be360 input=e45b7d7aa71cc66d]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400465{
466 return future_set_exception(self, exception);
467}
468
469/*[clinic input]
470_asyncio.Future.add_done_callback
471
Serhiy Storchakabca49392017-09-03 08:10:14 +0300472 fn: object
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400473 /
474
475Add a callback to be run when the future becomes done.
476
477The callback is called with a single argument - the future object. If
478the future is already done when this is called, the callback is
479scheduled with call_soon.
480[clinic start generated code]*/
481
482static PyObject *
483_asyncio_Future_add_done_callback(FutureObj *self, PyObject *fn)
Serhiy Storchakabca49392017-09-03 08:10:14 +0300484/*[clinic end generated code: output=819e09629b2ec2b5 input=8f818b39990b027d]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400485{
486 return future_add_done_callback(self, fn);
487}
488
489/*[clinic input]
490_asyncio.Future.remove_done_callback
491
Serhiy Storchakabca49392017-09-03 08:10:14 +0300492 fn: object
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400493 /
494
495Remove all instances of a callback from the "call when done" list.
496
497Returns the number of callbacks removed.
498[clinic start generated code]*/
499
500static PyObject *
501_asyncio_Future_remove_done_callback(FutureObj *self, PyObject *fn)
Serhiy Storchakabca49392017-09-03 08:10:14 +0300502/*[clinic end generated code: output=5ab1fb52b24ef31f input=0a43280a149d505b]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900503{
504 PyObject *newlist;
505 Py_ssize_t len, i, j=0;
506
Serhiy Storchakabca49392017-09-03 08:10:14 +0300507 if (self->fut_callbacks == NULL) {
508 PyErr_SetString(PyExc_RuntimeError, "uninitialized Future object");
509 return NULL;
510 }
511
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400512 len = PyList_GET_SIZE(self->fut_callbacks);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900513 if (len == 0) {
514 return PyLong_FromSsize_t(0);
515 }
516
517 newlist = PyList_New(len);
518 if (newlist == NULL) {
519 return NULL;
520 }
521
Yury Selivanov84af9032017-03-02 23:46:56 -0500522 for (i = 0; i < PyList_GET_SIZE(self->fut_callbacks); i++) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900523 int ret;
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400524 PyObject *item = PyList_GET_ITEM(self->fut_callbacks, i);
Serhiy Storchakabca49392017-09-03 08:10:14 +0300525 Py_INCREF(item);
526 ret = PyObject_RichCompareBool(fn, item, Py_EQ);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900527 if (ret == 0) {
Yury Selivanov833a3b02017-07-05 13:32:03 -0400528 if (j < len) {
Yury Selivanov833a3b02017-07-05 13:32:03 -0400529 PyList_SET_ITEM(newlist, j, item);
530 j++;
Serhiy Storchakabca49392017-09-03 08:10:14 +0300531 continue;
Yury Selivanov833a3b02017-07-05 13:32:03 -0400532 }
Serhiy Storchakabca49392017-09-03 08:10:14 +0300533 ret = PyList_Append(newlist, item);
534 }
535 Py_DECREF(item);
536 if (ret < 0) {
537 goto fail;
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900538 }
539 }
540
Serhiy Storchakabca49392017-09-03 08:10:14 +0300541 if (j < len) {
542 Py_SIZE(newlist) = j;
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900543 }
Serhiy Storchakabca49392017-09-03 08:10:14 +0300544 j = PyList_GET_SIZE(newlist);
545 len = PyList_GET_SIZE(self->fut_callbacks);
546 if (j != len) {
547 if (PyList_SetSlice(self->fut_callbacks, 0, len, newlist) < 0) {
548 goto fail;
549 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900550 }
551 Py_DECREF(newlist);
552 return PyLong_FromSsize_t(len - j);
553
554fail:
555 Py_DECREF(newlist);
556 return NULL;
557}
558
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400559/*[clinic input]
560_asyncio.Future.cancel
561
562Cancel the future and schedule callbacks.
563
564If the future is already done or cancelled, return False. Otherwise,
565change the future's state to cancelled, schedule the callbacks and
566return True.
567[clinic start generated code]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900568
569static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400570_asyncio_Future_cancel_impl(FutureObj *self)
571/*[clinic end generated code: output=e45b932ba8bd68a1 input=515709a127995109]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900572{
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400573 return future_cancel(self);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900574}
575
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400576/*[clinic input]
577_asyncio.Future.cancelled
578
579Return True if the future was cancelled.
580[clinic start generated code]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900581
582static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400583_asyncio_Future_cancelled_impl(FutureObj *self)
584/*[clinic end generated code: output=145197ced586357d input=943ab8b7b7b17e45]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900585{
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400586 if (self->fut_state == STATE_CANCELLED) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900587 Py_RETURN_TRUE;
588 }
589 else {
590 Py_RETURN_FALSE;
591 }
592}
593
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400594/*[clinic input]
595_asyncio.Future.done
596
597Return True if the future is done.
598
599Done means either that a result / exception are available, or that the
600future was cancelled.
601[clinic start generated code]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900602
603static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400604_asyncio_Future_done_impl(FutureObj *self)
605/*[clinic end generated code: output=244c5ac351145096 input=28d7b23fdb65d2ac]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900606{
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400607 if (self->fut_state == STATE_PENDING) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900608 Py_RETURN_FALSE;
609 }
610 else {
611 Py_RETURN_TRUE;
612 }
613}
614
615static PyObject *
616FutureObj_get_blocking(FutureObj *fut)
617{
618 if (fut->fut_blocking) {
619 Py_RETURN_TRUE;
620 }
621 else {
622 Py_RETURN_FALSE;
623 }
624}
625
626static int
627FutureObj_set_blocking(FutureObj *fut, PyObject *val)
628{
629 int is_true = PyObject_IsTrue(val);
630 if (is_true < 0) {
631 return -1;
632 }
633 fut->fut_blocking = is_true;
634 return 0;
635}
636
637static PyObject *
638FutureObj_get_log_traceback(FutureObj *fut)
639{
640 if (fut->fut_log_tb) {
641 Py_RETURN_TRUE;
642 }
643 else {
644 Py_RETURN_FALSE;
645 }
646}
647
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +0000648static int
649FutureObj_set_log_traceback(FutureObj *fut, PyObject *val)
650{
651 int is_true = PyObject_IsTrue(val);
652 if (is_true < 0) {
653 return -1;
654 }
655 fut->fut_log_tb = is_true;
656 return 0;
657}
658
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900659static PyObject *
660FutureObj_get_loop(FutureObj *fut)
661{
662 if (fut->fut_loop == NULL) {
663 Py_RETURN_NONE;
664 }
665 Py_INCREF(fut->fut_loop);
666 return fut->fut_loop;
667}
668
669static PyObject *
670FutureObj_get_callbacks(FutureObj *fut)
671{
672 if (fut->fut_callbacks == NULL) {
673 Py_RETURN_NONE;
674 }
675 Py_INCREF(fut->fut_callbacks);
676 return fut->fut_callbacks;
677}
678
679static PyObject *
680FutureObj_get_result(FutureObj *fut)
681{
682 if (fut->fut_result == NULL) {
683 Py_RETURN_NONE;
684 }
685 Py_INCREF(fut->fut_result);
686 return fut->fut_result;
687}
688
689static PyObject *
690FutureObj_get_exception(FutureObj *fut)
691{
692 if (fut->fut_exception == NULL) {
693 Py_RETURN_NONE;
694 }
695 Py_INCREF(fut->fut_exception);
696 return fut->fut_exception;
697}
698
699static PyObject *
700FutureObj_get_source_traceback(FutureObj *fut)
701{
702 if (fut->fut_source_tb == NULL) {
703 Py_RETURN_NONE;
704 }
705 Py_INCREF(fut->fut_source_tb);
706 return fut->fut_source_tb;
707}
708
709static PyObject *
710FutureObj_get_state(FutureObj *fut)
711{
712 _Py_IDENTIFIER(PENDING);
713 _Py_IDENTIFIER(CANCELLED);
714 _Py_IDENTIFIER(FINISHED);
715 PyObject *ret = NULL;
716
717 switch (fut->fut_state) {
718 case STATE_PENDING:
719 ret = _PyUnicode_FromId(&PyId_PENDING);
720 break;
721 case STATE_CANCELLED:
722 ret = _PyUnicode_FromId(&PyId_CANCELLED);
723 break;
724 case STATE_FINISHED:
725 ret = _PyUnicode_FromId(&PyId_FINISHED);
726 break;
727 default:
728 assert (0);
729 }
Serhiy Storchakabca49392017-09-03 08:10:14 +0300730 Py_XINCREF(ret);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900731 return ret;
732}
733
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400734/*[clinic input]
735_asyncio.Future._repr_info
736[clinic start generated code]*/
737
738static PyObject *
739_asyncio_Future__repr_info_impl(FutureObj *self)
740/*[clinic end generated code: output=fa69e901bd176cfb input=f21504d8e2ae1ca2]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900741{
Victor Stinnerde4ae3d2016-12-04 22:59:09 +0100742 return PyObject_CallFunctionObjArgs(
743 asyncio_future_repr_info_func, self, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400744}
745
746/*[clinic input]
747_asyncio.Future._schedule_callbacks
748[clinic start generated code]*/
749
750static PyObject *
751_asyncio_Future__schedule_callbacks_impl(FutureObj *self)
752/*[clinic end generated code: output=5e8958d89ea1c5dc input=4f5f295f263f4a88]*/
753{
754 int ret = future_schedule_callbacks(self);
755 if (ret == -1) {
756 return NULL;
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900757 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400758 Py_RETURN_NONE;
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900759}
760
761static PyObject *
762FutureObj_repr(FutureObj *fut)
763{
764 _Py_IDENTIFIER(_repr_info);
765
Serhiy Storchakabca49392017-09-03 08:10:14 +0300766 PyObject *rinfo = _PyObject_CallMethodIdObjArgs((PyObject*)fut,
767 &PyId__repr_info,
768 NULL);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900769 if (rinfo == NULL) {
770 return NULL;
771 }
772
Serhiy Storchakabca49392017-09-03 08:10:14 +0300773 PyObject *rinfo_s = PyUnicode_Join(NULL, rinfo);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900774 Py_DECREF(rinfo);
775 if (rinfo_s == NULL) {
776 return NULL;
777 }
778
779 PyObject *rstr = NULL;
780 PyObject *type_name = PyObject_GetAttrString((PyObject*)Py_TYPE(fut),
781 "__name__");
782 if (type_name != NULL) {
Serhiy Storchakabca49392017-09-03 08:10:14 +0300783 rstr = PyUnicode_FromFormat("<%S %U>", type_name, rinfo_s);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900784 Py_DECREF(type_name);
785 }
786 Py_DECREF(rinfo_s);
787 return rstr;
788}
789
790static void
791FutureObj_finalize(FutureObj *fut)
792{
793 _Py_IDENTIFIER(call_exception_handler);
794 _Py_IDENTIFIER(message);
795 _Py_IDENTIFIER(exception);
796 _Py_IDENTIFIER(future);
797 _Py_IDENTIFIER(source_traceback);
798
Serhiy Storchakabca49392017-09-03 08:10:14 +0300799 PyObject *error_type, *error_value, *error_traceback;
800 PyObject *context;
801 PyObject *type_name;
802 PyObject *message = NULL;
803 PyObject *func;
804
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900805 if (!fut->fut_log_tb) {
806 return;
807 }
808 assert(fut->fut_exception != NULL);
Serhiy Storchakabca49392017-09-03 08:10:14 +0300809 fut->fut_log_tb = 0;
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900810
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900811 /* Save the current exception, if any. */
812 PyErr_Fetch(&error_type, &error_value, &error_traceback);
813
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900814 context = PyDict_New();
815 if (context == NULL) {
816 goto finally;
817 }
818
819 type_name = PyObject_GetAttrString((PyObject*)Py_TYPE(fut), "__name__");
820 if (type_name == NULL) {
821 goto finally;
822 }
823
824 message = PyUnicode_FromFormat(
825 "%S exception was never retrieved", type_name);
Serhiy Storchakabca49392017-09-03 08:10:14 +0300826 Py_DECREF(type_name);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900827 if (message == NULL) {
828 goto finally;
829 }
830
831 if (_PyDict_SetItemId(context, &PyId_message, message) < 0 ||
832 _PyDict_SetItemId(context, &PyId_exception, fut->fut_exception) < 0 ||
833 _PyDict_SetItemId(context, &PyId_future, (PyObject*)fut) < 0) {
834 goto finally;
835 }
836 if (fut->fut_source_tb != NULL) {
837 if (_PyDict_SetItemId(context, &PyId_source_traceback,
838 fut->fut_source_tb) < 0) {
839 goto finally;
840 }
841 }
842
843 func = _PyObject_GetAttrId(fut->fut_loop, &PyId_call_exception_handler);
844 if (func != NULL) {
Serhiy Storchakabca49392017-09-03 08:10:14 +0300845 PyObject *res = PyObject_CallFunctionObjArgs(func, context, NULL);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900846 if (res == NULL) {
847 PyErr_WriteUnraisable(func);
848 }
Serhiy Storchakabca49392017-09-03 08:10:14 +0300849 else {
850 Py_DECREF(res);
851 }
852 Py_DECREF(func);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900853 }
854
855finally:
Serhiy Storchakabca49392017-09-03 08:10:14 +0300856 Py_XDECREF(context);
857 Py_XDECREF(message);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900858
859 /* Restore the saved exception. */
860 PyErr_Restore(error_type, error_value, error_traceback);
861}
862
863
864static PyAsyncMethods FutureType_as_async = {
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400865 (unaryfunc)future_new_iter, /* am_await */
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900866 0, /* am_aiter */
867 0 /* am_anext */
868};
869
870static PyMethodDef FutureType_methods[] = {
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400871 _ASYNCIO_FUTURE_RESULT_METHODDEF
872 _ASYNCIO_FUTURE_EXCEPTION_METHODDEF
873 _ASYNCIO_FUTURE_SET_RESULT_METHODDEF
874 _ASYNCIO_FUTURE_SET_EXCEPTION_METHODDEF
875 _ASYNCIO_FUTURE_ADD_DONE_CALLBACK_METHODDEF
876 _ASYNCIO_FUTURE_REMOVE_DONE_CALLBACK_METHODDEF
877 _ASYNCIO_FUTURE_CANCEL_METHODDEF
878 _ASYNCIO_FUTURE_CANCELLED_METHODDEF
879 _ASYNCIO_FUTURE_DONE_METHODDEF
880 _ASYNCIO_FUTURE__REPR_INFO_METHODDEF
881 _ASYNCIO_FUTURE__SCHEDULE_CALLBACKS_METHODDEF
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900882 {NULL, NULL} /* Sentinel */
883};
884
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400885#define FUTURE_COMMON_GETSETLIST \
886 {"_state", (getter)FutureObj_get_state, NULL, NULL}, \
887 {"_asyncio_future_blocking", (getter)FutureObj_get_blocking, \
888 (setter)FutureObj_set_blocking, NULL}, \
889 {"_loop", (getter)FutureObj_get_loop, NULL, NULL}, \
890 {"_callbacks", (getter)FutureObj_get_callbacks, NULL, NULL}, \
891 {"_result", (getter)FutureObj_get_result, NULL, NULL}, \
892 {"_exception", (getter)FutureObj_get_exception, NULL, NULL}, \
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +0000893 {"_log_traceback", (getter)FutureObj_get_log_traceback, \
894 (setter)FutureObj_set_log_traceback, NULL}, \
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900895 {"_source_traceback", (getter)FutureObj_get_source_traceback, NULL, NULL},
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400896
897static PyGetSetDef FutureType_getsetlist[] = {
898 FUTURE_COMMON_GETSETLIST
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900899 {NULL} /* Sentinel */
900};
901
902static void FutureObj_dealloc(PyObject *self);
903
904static PyTypeObject FutureType = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +0200905 PyVarObject_HEAD_INIT(NULL, 0)
INADA Naoki9f2ce252016-10-15 15:39:19 +0900906 "_asyncio.Future",
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900907 sizeof(FutureObj), /* tp_basicsize */
908 .tp_dealloc = FutureObj_dealloc,
909 .tp_as_async = &FutureType_as_async,
910 .tp_repr = (reprfunc)FutureObj_repr,
911 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE
912 | Py_TPFLAGS_HAVE_FINALIZE,
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400913 .tp_doc = _asyncio_Future___init____doc__,
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900914 .tp_traverse = (traverseproc)FutureObj_traverse,
915 .tp_clear = (inquiry)FutureObj_clear,
916 .tp_weaklistoffset = offsetof(FutureObj, fut_weakreflist),
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400917 .tp_iter = (getiterfunc)future_new_iter,
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900918 .tp_methods = FutureType_methods,
919 .tp_getset = FutureType_getsetlist,
920 .tp_dictoffset = offsetof(FutureObj, dict),
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400921 .tp_init = (initproc)_asyncio_Future___init__,
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900922 .tp_new = PyType_GenericNew,
923 .tp_finalize = (destructor)FutureObj_finalize,
924};
925
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400926#define Future_CheckExact(obj) (Py_TYPE(obj) == &FutureType)
927
928static inline int
929future_call_schedule_callbacks(FutureObj *fut)
930{
931 if (Future_CheckExact(fut)) {
932 return future_schedule_callbacks(fut);
933 }
934 else {
935 /* `fut` is a subclass of Future */
936 PyObject *ret = _PyObject_CallMethodId(
937 (PyObject*)fut, &PyId__schedule_callbacks, NULL);
938 if (ret == NULL) {
939 return -1;
940 }
941
942 Py_DECREF(ret);
943 return 0;
944 }
945}
946
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900947static void
948FutureObj_dealloc(PyObject *self)
949{
950 FutureObj *fut = (FutureObj *)self;
951
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400952 if (Future_CheckExact(fut)) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900953 /* When fut is subclass of Future, finalizer is called from
954 * subtype_dealloc.
955 */
956 if (PyObject_CallFinalizerFromDealloc(self) < 0) {
957 // resurrected.
958 return;
959 }
960 }
961
Alexander Mohrde34cbe2017-08-01 23:31:07 -0700962 PyObject_GC_UnTrack(self);
963
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900964 if (fut->fut_weakreflist != NULL) {
965 PyObject_ClearWeakRefs(self);
966 }
967
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400968 (void)FutureObj_clear(fut);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900969 Py_TYPE(fut)->tp_free(fut);
970}
971
972
973/*********************** Future Iterator **************************/
974
975typedef struct {
976 PyObject_HEAD
977 FutureObj *future;
978} futureiterobject;
979
980static void
981FutureIter_dealloc(futureiterobject *it)
982{
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400983 PyObject_GC_UnTrack(it);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900984 Py_XDECREF(it->future);
985 PyObject_GC_Del(it);
986}
987
988static PyObject *
989FutureIter_iternext(futureiterobject *it)
990{
991 PyObject *res;
992 FutureObj *fut = it->future;
993
994 if (fut == NULL) {
995 return NULL;
996 }
997
998 if (fut->fut_state == STATE_PENDING) {
999 if (!fut->fut_blocking) {
1000 fut->fut_blocking = 1;
1001 Py_INCREF(fut);
1002 return (PyObject *)fut;
1003 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03001004 PyErr_SetString(PyExc_AssertionError,
1005 "yield from wasn't used with future");
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001006 return NULL;
1007 }
1008
Serhiy Storchakabca49392017-09-03 08:10:14 +03001009 it->future = NULL;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001010 res = _asyncio_Future_result_impl(fut);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001011 if (res != NULL) {
Serhiy Storchaka60e49aa2016-11-06 18:47:03 +02001012 /* The result of the Future is not an exception. */
Serhiy Storchakabca49392017-09-03 08:10:14 +03001013 (void)_PyGen_SetStopIterationValue(res);
Serhiy Storchaka60e49aa2016-11-06 18:47:03 +02001014 Py_DECREF(res);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001015 }
1016
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001017 Py_DECREF(fut);
1018 return NULL;
1019}
1020
1021static PyObject *
INADA Naoki74c17532016-10-25 19:00:45 +09001022FutureIter_send(futureiterobject *self, PyObject *unused)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001023{
INADA Naoki74c17532016-10-25 19:00:45 +09001024 /* Future.__iter__ doesn't care about values that are pushed to the
1025 * generator, it just returns "self.result().
1026 */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001027 return FutureIter_iternext(self);
1028}
1029
1030static PyObject *
1031FutureIter_throw(futureiterobject *self, PyObject *args)
1032{
Serhiy Storchakabca49392017-09-03 08:10:14 +03001033 PyObject *type, *val = NULL, *tb = NULL;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001034 if (!PyArg_ParseTuple(args, "O|OO", &type, &val, &tb))
1035 return NULL;
1036
1037 if (val == Py_None) {
1038 val = NULL;
1039 }
1040 if (tb == Py_None) {
1041 tb = NULL;
Benjamin Peterson996fc1f2016-11-14 00:15:44 -08001042 } else if (tb != NULL && !PyTraceBack_Check(tb)) {
1043 PyErr_SetString(PyExc_TypeError, "throw() third argument must be a traceback");
1044 return NULL;
1045 }
1046
1047 Py_INCREF(type);
1048 Py_XINCREF(val);
1049 Py_XINCREF(tb);
1050
1051 if (PyExceptionClass_Check(type)) {
1052 PyErr_NormalizeException(&type, &val, &tb);
Yury Selivanovedfe8862016-12-01 11:37:47 -05001053 /* No need to call PyException_SetTraceback since we'll be calling
1054 PyErr_Restore for `type`, `val`, and `tb`. */
Benjamin Peterson996fc1f2016-11-14 00:15:44 -08001055 } else if (PyExceptionInstance_Check(type)) {
1056 if (val) {
1057 PyErr_SetString(PyExc_TypeError,
1058 "instance exception may not have a separate value");
1059 goto fail;
1060 }
1061 val = type;
1062 type = PyExceptionInstance_Class(type);
1063 Py_INCREF(type);
1064 if (tb == NULL)
1065 tb = PyException_GetTraceback(val);
1066 } else {
1067 PyErr_SetString(PyExc_TypeError,
1068 "exceptions must be classes deriving BaseException or "
1069 "instances of such a class");
1070 goto fail;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001071 }
1072
1073 Py_CLEAR(self->future);
1074
Benjamin Peterson996fc1f2016-11-14 00:15:44 -08001075 PyErr_Restore(type, val, tb);
1076
Serhiy Storchakabca49392017-09-03 08:10:14 +03001077 return NULL;
Benjamin Peterson996fc1f2016-11-14 00:15:44 -08001078
1079 fail:
1080 Py_DECREF(type);
1081 Py_XDECREF(val);
1082 Py_XDECREF(tb);
1083 return NULL;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001084}
1085
1086static PyObject *
1087FutureIter_close(futureiterobject *self, PyObject *arg)
1088{
1089 Py_CLEAR(self->future);
1090 Py_RETURN_NONE;
1091}
1092
1093static int
1094FutureIter_traverse(futureiterobject *it, visitproc visit, void *arg)
1095{
1096 Py_VISIT(it->future);
1097 return 0;
1098}
1099
1100static PyMethodDef FutureIter_methods[] = {
1101 {"send", (PyCFunction)FutureIter_send, METH_O, NULL},
1102 {"throw", (PyCFunction)FutureIter_throw, METH_VARARGS, NULL},
1103 {"close", (PyCFunction)FutureIter_close, METH_NOARGS, NULL},
1104 {NULL, NULL} /* Sentinel */
1105};
1106
1107static PyTypeObject FutureIterType = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02001108 PyVarObject_HEAD_INIT(NULL, 0)
INADA Naoki9f2ce252016-10-15 15:39:19 +09001109 "_asyncio.FutureIter",
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001110 .tp_basicsize = sizeof(futureiterobject),
1111 .tp_itemsize = 0,
1112 .tp_dealloc = (destructor)FutureIter_dealloc,
1113 .tp_getattro = PyObject_GenericGetAttr,
1114 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
1115 .tp_traverse = (traverseproc)FutureIter_traverse,
1116 .tp_iter = PyObject_SelfIter,
1117 .tp_iternext = (iternextfunc)FutureIter_iternext,
1118 .tp_methods = FutureIter_methods,
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001119};
1120
1121static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001122future_new_iter(PyObject *fut)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001123{
1124 futureiterobject *it;
1125
1126 if (!PyObject_TypeCheck(fut, &FutureType)) {
1127 PyErr_BadInternalCall();
1128 return NULL;
1129 }
1130 it = PyObject_GC_New(futureiterobject, &FutureIterType);
1131 if (it == NULL) {
1132 return NULL;
1133 }
1134 Py_INCREF(fut);
1135 it->future = (FutureObj*)fut;
INADA Naoki1be427b2016-10-11 02:12:34 +09001136 PyObject_GC_Track(it);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001137 return (PyObject*)it;
1138}
1139
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001140
1141/*********************** Task **************************/
1142
1143
1144/*[clinic input]
1145class _asyncio.Task "TaskObj *" "&Task_Type"
1146[clinic start generated code]*/
1147/*[clinic end generated code: output=da39a3ee5e6b4b0d input=719dcef0fcc03b37]*/
1148
1149static int task_call_step_soon(TaskObj *, PyObject *);
1150static inline PyObject * task_call_wakeup(TaskObj *, PyObject *);
1151static inline PyObject * task_call_step(TaskObj *, PyObject *);
1152static PyObject * task_wakeup(TaskObj *, PyObject *);
1153static PyObject * task_step(TaskObj *, PyObject *);
1154
1155/* ----- Task._step wrapper */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001156
INADA Naokic411a7d2016-10-18 11:48:14 +09001157static int
Serhiy Storchakabca49392017-09-03 08:10:14 +03001158TaskStepMethWrapper_clear(TaskStepMethWrapper *o)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001159{
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001160 Py_CLEAR(o->sw_task);
1161 Py_CLEAR(o->sw_arg);
1162 return 0;
1163}
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001164
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001165static void
Serhiy Storchakabca49392017-09-03 08:10:14 +03001166TaskStepMethWrapper_dealloc(TaskStepMethWrapper *o)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001167{
1168 PyObject_GC_UnTrack(o);
Serhiy Storchakabca49392017-09-03 08:10:14 +03001169 (void)TaskStepMethWrapper_clear(o);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001170 Py_TYPE(o)->tp_free(o);
1171}
1172
1173static PyObject *
Serhiy Storchakabca49392017-09-03 08:10:14 +03001174TaskStepMethWrapper_call(TaskStepMethWrapper *o,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001175 PyObject *args, PyObject *kwds)
1176{
Serhiy Storchakabca49392017-09-03 08:10:14 +03001177 if (kwds != NULL && PyDict_GET_SIZE(kwds) != 0) {
1178 PyErr_SetString(PyExc_TypeError, "function takes no keyword arguments");
1179 return NULL;
1180 }
1181 if (args != NULL && PyTuple_GET_SIZE(args) != 0) {
1182 PyErr_SetString(PyExc_TypeError, "function takes no positional arguments");
1183 return NULL;
1184 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001185 return task_call_step(o->sw_task, o->sw_arg);
1186}
1187
1188static int
Serhiy Storchakabca49392017-09-03 08:10:14 +03001189TaskStepMethWrapper_traverse(TaskStepMethWrapper *o,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001190 visitproc visit, void *arg)
1191{
1192 Py_VISIT(o->sw_task);
1193 Py_VISIT(o->sw_arg);
1194 return 0;
1195}
1196
1197static PyObject *
Serhiy Storchakabca49392017-09-03 08:10:14 +03001198TaskStepMethWrapper_get___self__(TaskStepMethWrapper *o)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001199{
1200 if (o->sw_task) {
1201 Py_INCREF(o->sw_task);
1202 return (PyObject*)o->sw_task;
1203 }
1204 Py_RETURN_NONE;
1205}
1206
Serhiy Storchakabca49392017-09-03 08:10:14 +03001207static PyGetSetDef TaskStepMethWrapper_getsetlist[] = {
1208 {"__self__", (getter)TaskStepMethWrapper_get___self__, NULL, NULL},
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001209 {NULL} /* Sentinel */
1210};
1211
Serhiy Storchakabca49392017-09-03 08:10:14 +03001212PyTypeObject TaskStepMethWrapper_Type = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02001213 PyVarObject_HEAD_INIT(NULL, 0)
Serhiy Storchakabca49392017-09-03 08:10:14 +03001214 "TaskStepMethWrapper",
1215 .tp_basicsize = sizeof(TaskStepMethWrapper),
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001216 .tp_itemsize = 0,
Serhiy Storchakabca49392017-09-03 08:10:14 +03001217 .tp_getset = TaskStepMethWrapper_getsetlist,
1218 .tp_dealloc = (destructor)TaskStepMethWrapper_dealloc,
1219 .tp_call = (ternaryfunc)TaskStepMethWrapper_call,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001220 .tp_getattro = PyObject_GenericGetAttr,
1221 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
Serhiy Storchakabca49392017-09-03 08:10:14 +03001222 .tp_traverse = (traverseproc)TaskStepMethWrapper_traverse,
1223 .tp_clear = (inquiry)TaskStepMethWrapper_clear,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001224};
1225
1226static PyObject *
Serhiy Storchakabca49392017-09-03 08:10:14 +03001227TaskStepMethWrapper_new(TaskObj *task, PyObject *arg)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001228{
Serhiy Storchakabca49392017-09-03 08:10:14 +03001229 TaskStepMethWrapper *o;
1230 o = PyObject_GC_New(TaskStepMethWrapper, &TaskStepMethWrapper_Type);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001231 if (o == NULL) {
1232 return NULL;
1233 }
1234
1235 Py_INCREF(task);
1236 o->sw_task = task;
1237
1238 Py_XINCREF(arg);
1239 o->sw_arg = arg;
1240
1241 PyObject_GC_Track(o);
1242 return (PyObject*) o;
1243}
1244
1245/* ----- Task._wakeup wrapper */
1246
1247static PyObject *
1248TaskWakeupMethWrapper_call(TaskWakeupMethWrapper *o,
1249 PyObject *args, PyObject *kwds)
1250{
1251 PyObject *fut;
1252
Serhiy Storchakabca49392017-09-03 08:10:14 +03001253 if (kwds != NULL && PyDict_GET_SIZE(kwds) != 0) {
1254 PyErr_SetString(PyExc_TypeError, "function takes no keyword arguments");
1255 return NULL;
1256 }
1257 if (!PyArg_ParseTuple(args, "O", &fut)) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001258 return NULL;
1259 }
1260
1261 return task_call_wakeup(o->ww_task, fut);
1262}
1263
1264static int
1265TaskWakeupMethWrapper_clear(TaskWakeupMethWrapper *o)
1266{
1267 Py_CLEAR(o->ww_task);
1268 return 0;
1269}
1270
1271static int
1272TaskWakeupMethWrapper_traverse(TaskWakeupMethWrapper *o,
1273 visitproc visit, void *arg)
1274{
1275 Py_VISIT(o->ww_task);
1276 return 0;
1277}
1278
1279static void
1280TaskWakeupMethWrapper_dealloc(TaskWakeupMethWrapper *o)
1281{
1282 PyObject_GC_UnTrack(o);
1283 (void)TaskWakeupMethWrapper_clear(o);
1284 Py_TYPE(o)->tp_free(o);
1285}
1286
1287PyTypeObject TaskWakeupMethWrapper_Type = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02001288 PyVarObject_HEAD_INIT(NULL, 0)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001289 "TaskWakeupMethWrapper",
1290 .tp_basicsize = sizeof(TaskWakeupMethWrapper),
1291 .tp_itemsize = 0,
1292 .tp_dealloc = (destructor)TaskWakeupMethWrapper_dealloc,
1293 .tp_call = (ternaryfunc)TaskWakeupMethWrapper_call,
1294 .tp_getattro = PyObject_GenericGetAttr,
1295 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
1296 .tp_traverse = (traverseproc)TaskWakeupMethWrapper_traverse,
1297 .tp_clear = (inquiry)TaskWakeupMethWrapper_clear,
1298};
1299
1300static PyObject *
1301TaskWakeupMethWrapper_new(TaskObj *task)
1302{
1303 TaskWakeupMethWrapper *o;
1304 o = PyObject_GC_New(TaskWakeupMethWrapper, &TaskWakeupMethWrapper_Type);
1305 if (o == NULL) {
1306 return NULL;
1307 }
1308
1309 Py_INCREF(task);
1310 o->ww_task = task;
1311
1312 PyObject_GC_Track(o);
1313 return (PyObject*) o;
1314}
1315
1316/* ----- Task */
1317
1318/*[clinic input]
1319_asyncio.Task.__init__
1320
Serhiy Storchakabca49392017-09-03 08:10:14 +03001321 coro: object
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001322 *
Serhiy Storchakabca49392017-09-03 08:10:14 +03001323 loop: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001324
1325A coroutine wrapped in a Future.
1326[clinic start generated code]*/
1327
1328static int
1329_asyncio_Task___init___impl(TaskObj *self, PyObject *coro, PyObject *loop)
Serhiy Storchakabca49392017-09-03 08:10:14 +03001330/*[clinic end generated code: output=9f24774c2287fc2f input=8d132974b049593e]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001331{
1332 PyObject *res;
1333 _Py_IDENTIFIER(add);
1334
1335 if (future_init((FutureObj*)self, loop)) {
INADA Naokic411a7d2016-10-18 11:48:14 +09001336 return -1;
1337 }
INADA Naokic411a7d2016-10-18 11:48:14 +09001338
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001339 self->task_fut_waiter = NULL;
1340 self->task_must_cancel = 0;
1341 self->task_log_destroy_pending = 1;
INADA Naokic411a7d2016-10-18 11:48:14 +09001342
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001343 Py_INCREF(coro);
1344 self->task_coro = coro;
1345
1346 if (task_call_step_soon(self, NULL)) {
1347 return -1;
INADA Naokic411a7d2016-10-18 11:48:14 +09001348 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001349
Victor Stinnerb6ed57d2016-12-09 14:24:02 +01001350 res = _PyObject_CallMethodIdObjArgs(all_tasks, &PyId_add, self, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001351 if (res == NULL) {
1352 return -1;
1353 }
1354 Py_DECREF(res);
1355
1356 return 0;
1357}
1358
1359static int
1360TaskObj_clear(TaskObj *task)
1361{
1362 (void)FutureObj_clear((FutureObj*) task);
1363 Py_CLEAR(task->task_coro);
1364 Py_CLEAR(task->task_fut_waiter);
1365 return 0;
1366}
1367
1368static int
1369TaskObj_traverse(TaskObj *task, visitproc visit, void *arg)
1370{
1371 Py_VISIT(task->task_coro);
1372 Py_VISIT(task->task_fut_waiter);
1373 (void)FutureObj_traverse((FutureObj*) task, visit, arg);
1374 return 0;
1375}
1376
1377static PyObject *
1378TaskObj_get_log_destroy_pending(TaskObj *task)
1379{
1380 if (task->task_log_destroy_pending) {
1381 Py_RETURN_TRUE;
1382 }
1383 else {
1384 Py_RETURN_FALSE;
1385 }
1386}
1387
1388static int
1389TaskObj_set_log_destroy_pending(TaskObj *task, PyObject *val)
1390{
1391 int is_true = PyObject_IsTrue(val);
1392 if (is_true < 0) {
1393 return -1;
1394 }
1395 task->task_log_destroy_pending = is_true;
1396 return 0;
1397}
1398
1399static PyObject *
1400TaskObj_get_must_cancel(TaskObj *task)
1401{
1402 if (task->task_must_cancel) {
1403 Py_RETURN_TRUE;
1404 }
1405 else {
1406 Py_RETURN_FALSE;
1407 }
1408}
1409
1410static PyObject *
1411TaskObj_get_coro(TaskObj *task)
1412{
1413 if (task->task_coro) {
1414 Py_INCREF(task->task_coro);
1415 return task->task_coro;
1416 }
1417
1418 Py_RETURN_NONE;
1419}
1420
1421static PyObject *
1422TaskObj_get_fut_waiter(TaskObj *task)
1423{
1424 if (task->task_fut_waiter) {
1425 Py_INCREF(task->task_fut_waiter);
1426 return task->task_fut_waiter;
1427 }
1428
1429 Py_RETURN_NONE;
1430}
1431
1432/*[clinic input]
1433@classmethod
1434_asyncio.Task.current_task
1435
Serhiy Storchakabca49392017-09-03 08:10:14 +03001436 loop: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001437
1438Return the currently running task in an event loop or None.
1439
1440By default the current task for the current event loop is returned.
1441
1442None is returned when called not in the context of a Task.
1443[clinic start generated code]*/
1444
1445static PyObject *
1446_asyncio_Task_current_task_impl(PyTypeObject *type, PyObject *loop)
Serhiy Storchakabca49392017-09-03 08:10:14 +03001447/*[clinic end generated code: output=99fbe7332c516e03 input=cd14770c5b79c7eb]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001448{
1449 PyObject *res;
1450
Yury Selivanov8d26aa92017-03-02 22:16:33 -05001451 if (loop == Py_None) {
Victor Stinnera5ed5f02016-12-06 18:45:50 +01001452 loop = _PyObject_CallNoArg(asyncio_get_event_loop);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001453 if (loop == NULL) {
1454 return NULL;
1455 }
1456
Yury Selivanov684ef2c2016-10-28 19:01:21 -04001457 res = PyDict_GetItem(current_tasks, loop);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001458 Py_DECREF(loop);
1459 }
1460 else {
Yury Selivanov684ef2c2016-10-28 19:01:21 -04001461 res = PyDict_GetItem(current_tasks, loop);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001462 }
1463
1464 if (res == NULL) {
1465 Py_RETURN_NONE;
1466 }
1467 else {
1468 Py_INCREF(res);
1469 return res;
1470 }
1471}
1472
1473static PyObject *
1474task_all_tasks(PyObject *loop)
1475{
1476 PyObject *task;
1477 PyObject *task_loop;
1478 PyObject *set;
1479 PyObject *iter;
1480
1481 assert(loop != NULL);
1482
1483 set = PySet_New(NULL);
1484 if (set == NULL) {
1485 return NULL;
1486 }
1487
1488 iter = PyObject_GetIter(all_tasks);
1489 if (iter == NULL) {
INADA Naokic411a7d2016-10-18 11:48:14 +09001490 goto fail;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001491 }
1492
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001493 while ((task = PyIter_Next(iter))) {
1494 task_loop = PyObject_GetAttrString(task, "_loop");
1495 if (task_loop == NULL) {
1496 Py_DECREF(task);
1497 goto fail;
1498 }
1499 if (task_loop == loop) {
1500 if (PySet_Add(set, task) == -1) {
1501 Py_DECREF(task_loop);
1502 Py_DECREF(task);
1503 goto fail;
1504 }
1505 }
1506 Py_DECREF(task_loop);
1507 Py_DECREF(task);
1508 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03001509 if (PyErr_Occurred()) {
1510 goto fail;
1511 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001512 Py_DECREF(iter);
1513 return set;
1514
1515fail:
Serhiy Storchakabca49392017-09-03 08:10:14 +03001516 Py_DECREF(set);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001517 Py_XDECREF(iter);
1518 return NULL;
1519}
1520
1521/*[clinic input]
1522@classmethod
1523_asyncio.Task.all_tasks
1524
Serhiy Storchakabca49392017-09-03 08:10:14 +03001525 loop: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001526
1527Return a set of all tasks for an event loop.
1528
1529By default all tasks for the current event loop are returned.
1530[clinic start generated code]*/
1531
1532static PyObject *
1533_asyncio_Task_all_tasks_impl(PyTypeObject *type, PyObject *loop)
Serhiy Storchakabca49392017-09-03 08:10:14 +03001534/*[clinic end generated code: output=11f9b20749ccca5d input=497f80bc9ce726b5]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001535{
1536 PyObject *res;
1537
Yury Selivanov8d26aa92017-03-02 22:16:33 -05001538 if (loop == Py_None) {
Victor Stinnera5ed5f02016-12-06 18:45:50 +01001539 loop = _PyObject_CallNoArg(asyncio_get_event_loop);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001540 if (loop == NULL) {
1541 return NULL;
1542 }
1543
1544 res = task_all_tasks(loop);
1545 Py_DECREF(loop);
1546 }
1547 else {
1548 res = task_all_tasks(loop);
1549 }
1550
1551 return res;
1552}
1553
1554/*[clinic input]
1555_asyncio.Task._repr_info
1556[clinic start generated code]*/
1557
1558static PyObject *
1559_asyncio_Task__repr_info_impl(TaskObj *self)
1560/*[clinic end generated code: output=6a490eb66d5ba34b input=3c6d051ed3ddec8b]*/
1561{
Victor Stinnerde4ae3d2016-12-04 22:59:09 +01001562 return PyObject_CallFunctionObjArgs(
1563 asyncio_task_repr_info_func, self, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001564}
1565
1566/*[clinic input]
1567_asyncio.Task.cancel
1568
1569Request that this task cancel itself.
1570
1571This arranges for a CancelledError to be thrown into the
1572wrapped coroutine on the next cycle through the event loop.
1573The coroutine then has a chance to clean up or even deny
1574the request using try/except/finally.
1575
1576Unlike Future.cancel, this does not guarantee that the
1577task will be cancelled: the exception might be caught and
1578acted upon, delaying cancellation of the task or preventing
1579cancellation completely. The task may also return a value or
1580raise a different exception.
1581
1582Immediately after this method is called, Task.cancelled() will
1583not return True (unless the task was already cancelled). A
1584task will be marked as cancelled when the wrapped coroutine
1585terminates with a CancelledError exception (even if cancel()
1586was not called).
1587[clinic start generated code]*/
1588
1589static PyObject *
1590_asyncio_Task_cancel_impl(TaskObj *self)
1591/*[clinic end generated code: output=6bfc0479da9d5757 input=13f9bf496695cb52]*/
1592{
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +00001593 self->task_log_tb = 0;
1594
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001595 if (self->task_state != STATE_PENDING) {
1596 Py_RETURN_FALSE;
1597 }
1598
1599 if (self->task_fut_waiter) {
1600 PyObject *res;
1601 int is_true;
1602
1603 res = _PyObject_CallMethodId(
1604 self->task_fut_waiter, &PyId_cancel, NULL);
1605 if (res == NULL) {
1606 return NULL;
1607 }
1608
1609 is_true = PyObject_IsTrue(res);
1610 Py_DECREF(res);
1611 if (is_true < 0) {
1612 return NULL;
1613 }
1614
1615 if (is_true) {
1616 Py_RETURN_TRUE;
1617 }
1618 }
1619
1620 self->task_must_cancel = 1;
1621 Py_RETURN_TRUE;
1622}
1623
1624/*[clinic input]
1625_asyncio.Task.get_stack
1626
1627 *
Serhiy Storchakabca49392017-09-03 08:10:14 +03001628 limit: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001629
1630Return the list of stack frames for this task's coroutine.
1631
1632If the coroutine is not done, this returns the stack where it is
1633suspended. If the coroutine has completed successfully or was
1634cancelled, this returns an empty list. If the coroutine was
1635terminated by an exception, this returns the list of traceback
1636frames.
1637
1638The frames are always ordered from oldest to newest.
1639
1640The optional limit gives the maximum number of frames to
1641return; by default all available frames are returned. Its
1642meaning differs depending on whether a stack or a traceback is
1643returned: the newest frames of a stack are returned, but the
1644oldest frames of a traceback are returned. (This matches the
1645behavior of the traceback module.)
1646
1647For reasons beyond our control, only one stack frame is
1648returned for a suspended coroutine.
1649[clinic start generated code]*/
1650
1651static PyObject *
1652_asyncio_Task_get_stack_impl(TaskObj *self, PyObject *limit)
Serhiy Storchakabca49392017-09-03 08:10:14 +03001653/*[clinic end generated code: output=c9aeeeebd1e18118 input=05b323d42b809b90]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001654{
1655 return PyObject_CallFunctionObjArgs(
1656 asyncio_task_get_stack_func, self, limit, NULL);
1657}
1658
1659/*[clinic input]
1660_asyncio.Task.print_stack
1661
1662 *
Serhiy Storchakabca49392017-09-03 08:10:14 +03001663 limit: object = None
1664 file: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001665
1666Print the stack or traceback for this task's coroutine.
1667
1668This produces output similar to that of the traceback module,
1669for the frames retrieved by get_stack(). The limit argument
1670is passed to get_stack(). The file argument is an I/O stream
1671to which the output is written; by default output is written
1672to sys.stderr.
1673[clinic start generated code]*/
1674
1675static PyObject *
1676_asyncio_Task_print_stack_impl(TaskObj *self, PyObject *limit,
1677 PyObject *file)
Serhiy Storchakabca49392017-09-03 08:10:14 +03001678/*[clinic end generated code: output=7339e10314cd3f4d input=1a0352913b7fcd92]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001679{
1680 return PyObject_CallFunctionObjArgs(
1681 asyncio_task_print_stack_func, self, limit, file, NULL);
1682}
1683
1684/*[clinic input]
1685_asyncio.Task._step
1686
Serhiy Storchakabca49392017-09-03 08:10:14 +03001687 exc: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001688[clinic start generated code]*/
1689
1690static PyObject *
1691_asyncio_Task__step_impl(TaskObj *self, PyObject *exc)
Serhiy Storchakabca49392017-09-03 08:10:14 +03001692/*[clinic end generated code: output=7ed23f0cefd5ae42 input=1e19a985ace87ca4]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001693{
1694 return task_step(self, exc == Py_None ? NULL : exc);
1695}
1696
1697/*[clinic input]
1698_asyncio.Task._wakeup
1699
Serhiy Storchakabca49392017-09-03 08:10:14 +03001700 fut: object
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001701[clinic start generated code]*/
1702
1703static PyObject *
1704_asyncio_Task__wakeup_impl(TaskObj *self, PyObject *fut)
Serhiy Storchakabca49392017-09-03 08:10:14 +03001705/*[clinic end generated code: output=75cb341c760fd071 input=6a0616406f829a7b]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001706{
1707 return task_wakeup(self, fut);
1708}
1709
1710static void
1711TaskObj_finalize(TaskObj *task)
1712{
1713 _Py_IDENTIFIER(call_exception_handler);
1714 _Py_IDENTIFIER(task);
1715 _Py_IDENTIFIER(message);
1716 _Py_IDENTIFIER(source_traceback);
1717
Serhiy Storchakabca49392017-09-03 08:10:14 +03001718 PyObject *context;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001719 PyObject *message = NULL;
Serhiy Storchakabca49392017-09-03 08:10:14 +03001720 PyObject *func;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001721 PyObject *error_type, *error_value, *error_traceback;
1722
1723 if (task->task_state != STATE_PENDING || !task->task_log_destroy_pending) {
1724 goto done;
1725 }
1726
1727 /* Save the current exception, if any. */
1728 PyErr_Fetch(&error_type, &error_value, &error_traceback);
1729
1730 context = PyDict_New();
1731 if (context == NULL) {
1732 goto finally;
1733 }
1734
1735 message = PyUnicode_FromString("Task was destroyed but it is pending!");
1736 if (message == NULL) {
1737 goto finally;
1738 }
1739
1740 if (_PyDict_SetItemId(context, &PyId_message, message) < 0 ||
1741 _PyDict_SetItemId(context, &PyId_task, (PyObject*)task) < 0)
1742 {
1743 goto finally;
1744 }
1745
1746 if (task->task_source_tb != NULL) {
1747 if (_PyDict_SetItemId(context, &PyId_source_traceback,
1748 task->task_source_tb) < 0)
1749 {
1750 goto finally;
1751 }
1752 }
1753
1754 func = _PyObject_GetAttrId(task->task_loop, &PyId_call_exception_handler);
1755 if (func != NULL) {
Serhiy Storchakabca49392017-09-03 08:10:14 +03001756 PyObject *res = PyObject_CallFunctionObjArgs(func, context, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001757 if (res == NULL) {
1758 PyErr_WriteUnraisable(func);
1759 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03001760 else {
1761 Py_DECREF(res);
1762 }
1763 Py_DECREF(func);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001764 }
1765
1766finally:
Serhiy Storchakabca49392017-09-03 08:10:14 +03001767 Py_XDECREF(context);
1768 Py_XDECREF(message);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001769
1770 /* Restore the saved exception. */
1771 PyErr_Restore(error_type, error_value, error_traceback);
1772
1773done:
1774 FutureObj_finalize((FutureObj*)task);
1775}
1776
1777static void TaskObj_dealloc(PyObject *); /* Needs Task_CheckExact */
1778
1779static PyMethodDef TaskType_methods[] = {
1780 _ASYNCIO_FUTURE_RESULT_METHODDEF
1781 _ASYNCIO_FUTURE_EXCEPTION_METHODDEF
1782 _ASYNCIO_FUTURE_SET_RESULT_METHODDEF
1783 _ASYNCIO_FUTURE_SET_EXCEPTION_METHODDEF
1784 _ASYNCIO_FUTURE_ADD_DONE_CALLBACK_METHODDEF
1785 _ASYNCIO_FUTURE_REMOVE_DONE_CALLBACK_METHODDEF
1786 _ASYNCIO_FUTURE_CANCELLED_METHODDEF
1787 _ASYNCIO_FUTURE_DONE_METHODDEF
1788 _ASYNCIO_TASK_CURRENT_TASK_METHODDEF
1789 _ASYNCIO_TASK_ALL_TASKS_METHODDEF
1790 _ASYNCIO_TASK_CANCEL_METHODDEF
1791 _ASYNCIO_TASK_GET_STACK_METHODDEF
1792 _ASYNCIO_TASK_PRINT_STACK_METHODDEF
1793 _ASYNCIO_TASK__WAKEUP_METHODDEF
1794 _ASYNCIO_TASK__STEP_METHODDEF
1795 _ASYNCIO_TASK__REPR_INFO_METHODDEF
1796 {NULL, NULL} /* Sentinel */
1797};
1798
1799static PyGetSetDef TaskType_getsetlist[] = {
1800 FUTURE_COMMON_GETSETLIST
1801 {"_log_destroy_pending", (getter)TaskObj_get_log_destroy_pending,
1802 (setter)TaskObj_set_log_destroy_pending, NULL},
1803 {"_must_cancel", (getter)TaskObj_get_must_cancel, NULL, NULL},
1804 {"_coro", (getter)TaskObj_get_coro, NULL, NULL},
1805 {"_fut_waiter", (getter)TaskObj_get_fut_waiter, NULL, NULL},
1806 {NULL} /* Sentinel */
1807};
1808
1809static PyTypeObject TaskType = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02001810 PyVarObject_HEAD_INIT(NULL, 0)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001811 "_asyncio.Task",
1812 sizeof(TaskObj), /* tp_basicsize */
1813 .tp_base = &FutureType,
1814 .tp_dealloc = TaskObj_dealloc,
1815 .tp_as_async = &FutureType_as_async,
1816 .tp_repr = (reprfunc)FutureObj_repr,
1817 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE
1818 | Py_TPFLAGS_HAVE_FINALIZE,
1819 .tp_doc = _asyncio_Task___init____doc__,
1820 .tp_traverse = (traverseproc)TaskObj_traverse,
1821 .tp_clear = (inquiry)TaskObj_clear,
1822 .tp_weaklistoffset = offsetof(TaskObj, task_weakreflist),
1823 .tp_iter = (getiterfunc)future_new_iter,
1824 .tp_methods = TaskType_methods,
1825 .tp_getset = TaskType_getsetlist,
1826 .tp_dictoffset = offsetof(TaskObj, dict),
1827 .tp_init = (initproc)_asyncio_Task___init__,
1828 .tp_new = PyType_GenericNew,
1829 .tp_finalize = (destructor)TaskObj_finalize,
1830};
1831
1832#define Task_CheckExact(obj) (Py_TYPE(obj) == &TaskType)
1833
1834static void
1835TaskObj_dealloc(PyObject *self)
1836{
1837 TaskObj *task = (TaskObj *)self;
1838
1839 if (Task_CheckExact(self)) {
1840 /* When fut is subclass of Task, finalizer is called from
1841 * subtype_dealloc.
1842 */
1843 if (PyObject_CallFinalizerFromDealloc(self) < 0) {
1844 // resurrected.
1845 return;
1846 }
1847 }
1848
Alexander Mohrde34cbe2017-08-01 23:31:07 -07001849 PyObject_GC_UnTrack(self);
1850
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001851 if (task->task_weakreflist != NULL) {
1852 PyObject_ClearWeakRefs(self);
1853 }
1854
1855 (void)TaskObj_clear(task);
1856 Py_TYPE(task)->tp_free(task);
1857}
1858
1859static inline PyObject *
1860task_call_wakeup(TaskObj *task, PyObject *fut)
1861{
1862 if (Task_CheckExact(task)) {
1863 return task_wakeup(task, fut);
1864 }
1865 else {
1866 /* `task` is a subclass of Task */
Victor Stinnerb6ed57d2016-12-09 14:24:02 +01001867 return _PyObject_CallMethodIdObjArgs((PyObject*)task, &PyId__wakeup,
1868 fut, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001869 }
1870}
1871
1872static inline PyObject *
1873task_call_step(TaskObj *task, PyObject *arg)
1874{
1875 if (Task_CheckExact(task)) {
1876 return task_step(task, arg);
1877 }
1878 else {
1879 /* `task` is a subclass of Task */
Victor Stinnerb6ed57d2016-12-09 14:24:02 +01001880 return _PyObject_CallMethodIdObjArgs((PyObject*)task, &PyId__step,
1881 arg, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001882 }
1883}
1884
1885static int
1886task_call_step_soon(TaskObj *task, PyObject *arg)
1887{
1888 PyObject *handle;
1889
Serhiy Storchakabca49392017-09-03 08:10:14 +03001890 PyObject *cb = TaskStepMethWrapper_new(task, arg);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001891 if (cb == NULL) {
1892 return -1;
1893 }
1894
Victor Stinnerb6ed57d2016-12-09 14:24:02 +01001895 handle = _PyObject_CallMethodIdObjArgs(task->task_loop, &PyId_call_soon,
1896 cb, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001897 Py_DECREF(cb);
1898 if (handle == NULL) {
1899 return -1;
1900 }
1901
1902 Py_DECREF(handle);
1903 return 0;
1904}
1905
1906static PyObject *
1907task_set_error_soon(TaskObj *task, PyObject *et, const char *format, ...)
1908{
1909 PyObject* msg;
1910
1911 va_list vargs;
1912#ifdef HAVE_STDARG_PROTOTYPES
1913 va_start(vargs, format);
1914#else
1915 va_start(vargs);
1916#endif
1917 msg = PyUnicode_FromFormatV(format, vargs);
1918 va_end(vargs);
1919
1920 if (msg == NULL) {
1921 return NULL;
1922 }
1923
Victor Stinnerde4ae3d2016-12-04 22:59:09 +01001924 PyObject *e = PyObject_CallFunctionObjArgs(et, msg, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001925 Py_DECREF(msg);
1926 if (e == NULL) {
1927 return NULL;
1928 }
1929
1930 if (task_call_step_soon(task, e) == -1) {
1931 Py_DECREF(e);
1932 return NULL;
1933 }
1934
1935 Py_DECREF(e);
1936 Py_RETURN_NONE;
1937}
1938
1939static PyObject *
1940task_step_impl(TaskObj *task, PyObject *exc)
1941{
1942 int res;
1943 int clear_exc = 0;
1944 PyObject *result = NULL;
Serhiy Storchakabca49392017-09-03 08:10:14 +03001945 PyObject *coro;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001946 PyObject *o;
1947
1948 if (task->task_state != STATE_PENDING) {
1949 PyErr_Format(PyExc_AssertionError,
1950 "_step(): already done: %R %R",
1951 task,
1952 exc ? exc : Py_None);
INADA Naokic411a7d2016-10-18 11:48:14 +09001953 goto fail;
1954 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001955
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001956 if (task->task_must_cancel) {
1957 assert(exc != Py_None);
1958
1959 if (exc) {
1960 /* Check if exc is a CancelledError */
1961 res = PyObject_IsInstance(exc, asyncio_CancelledError);
1962 if (res == -1) {
1963 /* An error occurred, abort */
1964 goto fail;
1965 }
1966 if (res == 0) {
1967 /* exc is not CancelledError; reset it to NULL */
1968 exc = NULL;
1969 }
1970 }
1971
1972 if (!exc) {
1973 /* exc was not a CancelledError */
Victor Stinnerf17c3de2016-12-06 18:46:19 +01001974 exc = _PyObject_CallNoArg(asyncio_CancelledError);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001975 if (!exc) {
1976 goto fail;
1977 }
1978 clear_exc = 1;
1979 }
1980
1981 task->task_must_cancel = 0;
1982 }
1983
1984 Py_CLEAR(task->task_fut_waiter);
1985
Serhiy Storchakabca49392017-09-03 08:10:14 +03001986 coro = task->task_coro;
1987 if (coro == NULL) {
1988 PyErr_SetString(PyExc_RuntimeError, "uninitialized Task object");
1989 return NULL;
1990 }
1991
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001992 if (exc == NULL) {
1993 if (PyGen_CheckExact(coro) || PyCoro_CheckExact(coro)) {
1994 result = _PyGen_Send((PyGenObject*)coro, Py_None);
1995 }
1996 else {
Victor Stinnerb6ed57d2016-12-09 14:24:02 +01001997 result = _PyObject_CallMethodIdObjArgs(coro, &PyId_send,
1998 Py_None, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001999 }
2000 }
2001 else {
Victor Stinnerb6ed57d2016-12-09 14:24:02 +01002002 result = _PyObject_CallMethodIdObjArgs(coro, &PyId_throw,
2003 exc, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002004 if (clear_exc) {
2005 /* We created 'exc' during this call */
Serhiy Storchakabca49392017-09-03 08:10:14 +03002006 Py_DECREF(exc);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002007 }
2008 }
2009
2010 if (result == NULL) {
2011 PyObject *et, *ev, *tb;
2012
2013 if (_PyGen_FetchStopIterationValue(&o) == 0) {
2014 /* The error is StopIteration and that means that
2015 the underlying coroutine has resolved */
INADA Naoki991adca2017-05-11 21:18:38 +09002016 if (task->task_must_cancel) {
2017 // Task is cancelled right before coro stops.
2018 Py_DECREF(o);
2019 task->task_must_cancel = 0;
2020 et = asyncio_CancelledError;
2021 Py_INCREF(et);
2022 ev = NULL;
2023 tb = NULL;
2024 goto set_exception;
2025 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002026 PyObject *res = future_set_result((FutureObj*)task, o);
2027 Py_DECREF(o);
2028 if (res == NULL) {
2029 return NULL;
2030 }
2031 Py_DECREF(res);
2032 Py_RETURN_NONE;
2033 }
2034
2035 if (PyErr_ExceptionMatches(asyncio_CancelledError)) {
2036 /* CancelledError */
2037 PyErr_Clear();
2038 return future_cancel((FutureObj*)task);
2039 }
2040
2041 /* Some other exception; pop it and call Task.set_exception() */
2042 PyErr_Fetch(&et, &ev, &tb);
INADA Naoki991adca2017-05-11 21:18:38 +09002043
2044set_exception:
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002045 assert(et);
2046 if (!ev || !PyObject_TypeCheck(ev, (PyTypeObject *) et)) {
2047 PyErr_NormalizeException(&et, &ev, &tb);
2048 }
Yury Selivanovedfe8862016-12-01 11:37:47 -05002049 if (tb != NULL) {
2050 PyException_SetTraceback(ev, tb);
2051 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002052 o = future_set_exception((FutureObj*)task, ev);
2053 if (!o) {
2054 /* An exception in Task.set_exception() */
Serhiy Storchakabca49392017-09-03 08:10:14 +03002055 Py_DECREF(et);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002056 Py_XDECREF(tb);
2057 Py_XDECREF(ev);
2058 goto fail;
2059 }
2060 assert(o == Py_None);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002061 Py_DECREF(o);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002062
2063 if (!PyErr_GivenExceptionMatches(et, PyExc_Exception)) {
2064 /* We've got a BaseException; re-raise it */
2065 PyErr_Restore(et, ev, tb);
2066 goto fail;
2067 }
2068
Serhiy Storchakabca49392017-09-03 08:10:14 +03002069 Py_DECREF(et);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002070 Py_XDECREF(tb);
2071 Py_XDECREF(ev);
2072
2073 Py_RETURN_NONE;
2074 }
2075
2076 if (result == (PyObject*)task) {
2077 /* We have a task that wants to await on itself */
2078 goto self_await;
2079 }
2080
2081 /* Check if `result` is FutureObj or TaskObj (and not a subclass) */
2082 if (Future_CheckExact(result) || Task_CheckExact(result)) {
2083 PyObject *wrapper;
2084 PyObject *res;
2085 FutureObj *fut = (FutureObj*)result;
2086
2087 /* Check if `result` future is attached to a different loop */
2088 if (fut->fut_loop != task->task_loop) {
2089 goto different_loop;
2090 }
2091
2092 if (fut->fut_blocking) {
2093 fut->fut_blocking = 0;
2094
2095 /* result.add_done_callback(task._wakeup) */
2096 wrapper = TaskWakeupMethWrapper_new(task);
2097 if (wrapper == NULL) {
2098 goto fail;
2099 }
2100 res = future_add_done_callback((FutureObj*)result, wrapper);
2101 Py_DECREF(wrapper);
2102 if (res == NULL) {
2103 goto fail;
2104 }
2105 Py_DECREF(res);
2106
2107 /* task._fut_waiter = result */
2108 task->task_fut_waiter = result; /* no incref is necessary */
2109
2110 if (task->task_must_cancel) {
2111 PyObject *r;
2112 r = future_cancel(fut);
2113 if (r == NULL) {
2114 return NULL;
2115 }
2116 if (r == Py_True) {
2117 task->task_must_cancel = 0;
2118 }
2119 Py_DECREF(r);
2120 }
2121
2122 Py_RETURN_NONE;
2123 }
2124 else {
2125 goto yield_insteadof_yf;
2126 }
2127 }
2128
2129 /* Check if `result` is a Future-compatible object */
2130 o = PyObject_GetAttrString(result, "_asyncio_future_blocking");
2131 if (o == NULL) {
2132 if (PyErr_ExceptionMatches(PyExc_AttributeError)) {
2133 PyErr_Clear();
2134 }
2135 else {
2136 goto fail;
2137 }
2138 }
2139 else {
2140 if (o == Py_None) {
Serhiy Storchakabca49392017-09-03 08:10:14 +03002141 Py_DECREF(o);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002142 }
2143 else {
2144 /* `result` is a Future-compatible object */
2145 PyObject *wrapper;
2146 PyObject *res;
2147
2148 int blocking = PyObject_IsTrue(o);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002149 Py_DECREF(o);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002150 if (blocking < 0) {
2151 goto fail;
2152 }
2153
2154 /* Check if `result` future is attached to a different loop */
2155 PyObject *oloop = PyObject_GetAttrString(result, "_loop");
2156 if (oloop == NULL) {
2157 goto fail;
2158 }
2159 if (oloop != task->task_loop) {
2160 Py_DECREF(oloop);
2161 goto different_loop;
2162 }
2163 else {
2164 Py_DECREF(oloop);
2165 }
2166
2167 if (blocking) {
2168 /* result._asyncio_future_blocking = False */
2169 if (PyObject_SetAttrString(
2170 result, "_asyncio_future_blocking", Py_False) == -1) {
2171 goto fail;
2172 }
2173
2174 /* result.add_done_callback(task._wakeup) */
2175 wrapper = TaskWakeupMethWrapper_new(task);
2176 if (wrapper == NULL) {
2177 goto fail;
2178 }
Victor Stinnerb6ed57d2016-12-09 14:24:02 +01002179 res = _PyObject_CallMethodIdObjArgs(result,
2180 &PyId_add_done_callback,
2181 wrapper, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002182 Py_DECREF(wrapper);
2183 if (res == NULL) {
2184 goto fail;
2185 }
2186 Py_DECREF(res);
2187
2188 /* task._fut_waiter = result */
2189 task->task_fut_waiter = result; /* no incref is necessary */
2190
2191 if (task->task_must_cancel) {
2192 PyObject *r;
2193 int is_true;
2194 r = _PyObject_CallMethodId(result, &PyId_cancel, NULL);
2195 if (r == NULL) {
2196 return NULL;
2197 }
2198 is_true = PyObject_IsTrue(r);
2199 Py_DECREF(r);
2200 if (is_true < 0) {
2201 return NULL;
2202 }
2203 else if (is_true) {
2204 task->task_must_cancel = 0;
2205 }
2206 }
2207
2208 Py_RETURN_NONE;
2209 }
2210 else {
2211 goto yield_insteadof_yf;
2212 }
2213 }
2214 }
2215
2216 /* Check if `result` is None */
2217 if (result == Py_None) {
2218 /* Bare yield relinquishes control for one event loop iteration. */
2219 if (task_call_step_soon(task, NULL)) {
2220 goto fail;
2221 }
2222 return result;
2223 }
2224
2225 /* Check if `result` is a generator */
Victor Stinnerde4ae3d2016-12-04 22:59:09 +01002226 o = PyObject_CallFunctionObjArgs(inspect_isgenerator, result, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002227 if (o == NULL) {
2228 /* An exception in inspect.isgenerator */
2229 goto fail;
2230 }
2231 res = PyObject_IsTrue(o);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002232 Py_DECREF(o);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002233 if (res == -1) {
2234 /* An exception while checking if 'val' is True */
2235 goto fail;
2236 }
2237 if (res == 1) {
2238 /* `result` is a generator */
2239 PyObject *ret;
2240 ret = task_set_error_soon(
2241 task, PyExc_RuntimeError,
2242 "yield was used instead of yield from for "
2243 "generator in task %R with %S", task, result);
2244 Py_DECREF(result);
2245 return ret;
2246 }
2247
2248 /* The `result` is none of the above */
2249 Py_DECREF(result);
2250 return task_set_error_soon(
2251 task, PyExc_RuntimeError, "Task got bad yield: %R", result);
2252
2253self_await:
2254 o = task_set_error_soon(
2255 task, PyExc_RuntimeError,
2256 "Task cannot await on itself: %R", task);
2257 Py_DECREF(result);
2258 return o;
2259
2260yield_insteadof_yf:
2261 o = task_set_error_soon(
2262 task, PyExc_RuntimeError,
2263 "yield was used instead of yield from "
2264 "in task %R with %R",
2265 task, result);
2266 Py_DECREF(result);
2267 return o;
2268
2269different_loop:
2270 o = task_set_error_soon(
2271 task, PyExc_RuntimeError,
2272 "Task %R got Future %R attached to a different loop",
2273 task, result);
2274 Py_DECREF(result);
2275 return o;
2276
2277fail:
2278 Py_XDECREF(result);
2279 return NULL;
2280}
2281
2282static PyObject *
2283task_step(TaskObj *task, PyObject *exc)
2284{
2285 PyObject *res;
2286 PyObject *ot;
2287
Yury Selivanov684ef2c2016-10-28 19:01:21 -04002288 if (PyDict_SetItem(current_tasks,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002289 task->task_loop, (PyObject*)task) == -1)
2290 {
2291 return NULL;
2292 }
2293
2294 res = task_step_impl(task, exc);
2295
2296 if (res == NULL) {
2297 PyObject *et, *ev, *tb;
2298 PyErr_Fetch(&et, &ev, &tb);
2299 ot = _PyDict_Pop(current_tasks, task->task_loop, NULL);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002300 Py_XDECREF(ot);
2301 _PyErr_ChainExceptions(et, ev, tb);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002302 return NULL;
2303 }
2304 else {
2305 ot = _PyDict_Pop(current_tasks, task->task_loop, NULL);
2306 if (ot == NULL) {
2307 Py_DECREF(res);
2308 return NULL;
2309 }
2310 else {
2311 Py_DECREF(ot);
2312 return res;
2313 }
2314 }
2315}
2316
2317static PyObject *
2318task_wakeup(TaskObj *task, PyObject *o)
2319{
Serhiy Storchakabca49392017-09-03 08:10:14 +03002320 PyObject *et, *ev, *tb;
2321 PyObject *result;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002322 assert(o);
2323
2324 if (Future_CheckExact(o) || Task_CheckExact(o)) {
2325 PyObject *fut_result = NULL;
2326 int res = future_get_result((FutureObj*)o, &fut_result);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002327
2328 switch(res) {
2329 case -1:
2330 assert(fut_result == NULL);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002331 break; /* exception raised */
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002332 case 0:
2333 Py_DECREF(fut_result);
2334 return task_call_step(task, NULL);
2335 default:
2336 assert(res == 1);
2337 result = task_call_step(task, fut_result);
2338 Py_DECREF(fut_result);
2339 return result;
2340 }
2341 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002342 else {
Serhiy Storchakabca49392017-09-03 08:10:14 +03002343 PyObject *fut_result = PyObject_CallMethod(o, "result", NULL);
2344 if (fut_result != NULL) {
2345 Py_DECREF(fut_result);
2346 return task_call_step(task, NULL);
2347 }
2348 /* exception raised */
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002349 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03002350
2351 PyErr_Fetch(&et, &ev, &tb);
2352 if (!PyErr_GivenExceptionMatches(et, PyExc_Exception)) {
2353 /* We've got a BaseException; re-raise it */
2354 PyErr_Restore(et, ev, tb);
2355 return NULL;
2356 }
2357 if (!ev || !PyObject_TypeCheck(ev, (PyTypeObject *) et)) {
2358 PyErr_NormalizeException(&et, &ev, &tb);
2359 }
2360
2361 result = task_call_step(task, ev);
2362
2363 Py_DECREF(et);
2364 Py_XDECREF(tb);
2365 Py_XDECREF(ev);
2366
2367 return result;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002368}
2369
2370
2371/*********************** Module **************************/
2372
2373
2374static void
2375module_free(void *m)
2376{
2377 Py_CLEAR(current_tasks);
2378 Py_CLEAR(all_tasks);
2379 Py_CLEAR(traceback_extract_stack);
2380 Py_CLEAR(asyncio_get_event_loop);
2381 Py_CLEAR(asyncio_future_repr_info_func);
2382 Py_CLEAR(asyncio_task_repr_info_func);
2383 Py_CLEAR(asyncio_task_get_stack_func);
2384 Py_CLEAR(asyncio_task_print_stack_func);
2385 Py_CLEAR(asyncio_InvalidStateError);
2386 Py_CLEAR(asyncio_CancelledError);
2387 Py_CLEAR(inspect_isgenerator);
2388}
2389
2390static int
2391module_init(void)
2392{
2393 PyObject *module = NULL;
2394 PyObject *cls;
2395
2396#define WITH_MOD(NAME) \
2397 Py_CLEAR(module); \
2398 module = PyImport_ImportModule(NAME); \
2399 if (module == NULL) { \
Serhiy Storchakabca49392017-09-03 08:10:14 +03002400 goto fail; \
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002401 }
2402
2403#define GET_MOD_ATTR(VAR, NAME) \
2404 VAR = PyObject_GetAttrString(module, NAME); \
2405 if (VAR == NULL) { \
2406 goto fail; \
2407 }
2408
2409 WITH_MOD("asyncio.events")
2410 GET_MOD_ATTR(asyncio_get_event_loop, "get_event_loop")
2411
2412 WITH_MOD("asyncio.base_futures")
2413 GET_MOD_ATTR(asyncio_future_repr_info_func, "_future_repr_info")
2414 GET_MOD_ATTR(asyncio_InvalidStateError, "InvalidStateError")
2415 GET_MOD_ATTR(asyncio_CancelledError, "CancelledError")
2416
2417 WITH_MOD("asyncio.base_tasks")
2418 GET_MOD_ATTR(asyncio_task_repr_info_func, "_task_repr_info")
2419 GET_MOD_ATTR(asyncio_task_get_stack_func, "_task_get_stack")
2420 GET_MOD_ATTR(asyncio_task_print_stack_func, "_task_print_stack")
2421
2422 WITH_MOD("inspect")
2423 GET_MOD_ATTR(inspect_isgenerator, "isgenerator")
2424
2425 WITH_MOD("traceback")
2426 GET_MOD_ATTR(traceback_extract_stack, "extract_stack")
2427
2428 WITH_MOD("weakref")
2429 GET_MOD_ATTR(cls, "WeakSet")
Victor Stinnera5ed5f02016-12-06 18:45:50 +01002430 all_tasks = _PyObject_CallNoArg(cls);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002431 Py_DECREF(cls);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002432 if (all_tasks == NULL) {
INADA Naokic411a7d2016-10-18 11:48:14 +09002433 goto fail;
2434 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09002435
Yury Selivanov684ef2c2016-10-28 19:01:21 -04002436 current_tasks = PyDict_New();
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002437 if (current_tasks == NULL) {
2438 goto fail;
2439 }
2440
Serhiy Storchakabca49392017-09-03 08:10:14 +03002441 Py_DECREF(module);
INADA Naokic411a7d2016-10-18 11:48:14 +09002442 return 0;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09002443
INADA Naokic411a7d2016-10-18 11:48:14 +09002444fail:
INADA Naokic411a7d2016-10-18 11:48:14 +09002445 Py_CLEAR(module);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002446 module_free(NULL);
INADA Naokic411a7d2016-10-18 11:48:14 +09002447 return -1;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09002448
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002449#undef WITH_MOD
2450#undef GET_MOD_ATTR
2451}
INADA Naoki9e4e38e2016-10-09 14:44:47 +09002452
INADA Naokic411a7d2016-10-18 11:48:14 +09002453PyDoc_STRVAR(module_doc, "Accelerator module for asyncio");
INADA Naoki9e4e38e2016-10-09 14:44:47 +09002454
INADA Naoki9f2ce252016-10-15 15:39:19 +09002455static struct PyModuleDef _asynciomodule = {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09002456 PyModuleDef_HEAD_INIT, /* m_base */
INADA Naoki9f2ce252016-10-15 15:39:19 +09002457 "_asyncio", /* m_name */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09002458 module_doc, /* m_doc */
2459 -1, /* m_size */
INADA Naokic411a7d2016-10-18 11:48:14 +09002460 NULL, /* m_methods */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09002461 NULL, /* m_slots */
2462 NULL, /* m_traverse */
2463 NULL, /* m_clear */
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002464 (freefunc)module_free /* m_free */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09002465};
2466
2467
2468PyMODINIT_FUNC
INADA Naoki9f2ce252016-10-15 15:39:19 +09002469PyInit__asyncio(void)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09002470{
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002471 if (module_init() < 0) {
INADA Naokic411a7d2016-10-18 11:48:14 +09002472 return NULL;
2473 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09002474 if (PyType_Ready(&FutureType) < 0) {
2475 return NULL;
2476 }
2477 if (PyType_Ready(&FutureIterType) < 0) {
2478 return NULL;
2479 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03002480 if (PyType_Ready(&TaskStepMethWrapper_Type) < 0) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002481 return NULL;
2482 }
2483 if(PyType_Ready(&TaskWakeupMethWrapper_Type) < 0) {
2484 return NULL;
2485 }
2486 if (PyType_Ready(&TaskType) < 0) {
2487 return NULL;
2488 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09002489
INADA Naoki9f2ce252016-10-15 15:39:19 +09002490 PyObject *m = PyModule_Create(&_asynciomodule);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09002491 if (m == NULL) {
2492 return NULL;
2493 }
2494
2495 Py_INCREF(&FutureType);
2496 if (PyModule_AddObject(m, "Future", (PyObject *)&FutureType) < 0) {
2497 Py_DECREF(&FutureType);
2498 return NULL;
2499 }
2500
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002501 Py_INCREF(&TaskType);
2502 if (PyModule_AddObject(m, "Task", (PyObject *)&TaskType) < 0) {
2503 Py_DECREF(&TaskType);
2504 return NULL;
2505 }
2506
INADA Naoki9e4e38e2016-10-09 14:44:47 +09002507 return m;
2508}