blob: df81b105ec505cdda9acc10c3bdcf25d00c57af7 [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;
71} TaskSendMethWrapper;
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;
95 PyObject* iters;
96 int i;
97
98 if (fut->fut_callbacks == NULL) {
99 PyErr_SetString(PyExc_RuntimeError, "NULL callbacks");
100 return -1;
101 }
102
103 len = PyList_GET_SIZE(fut->fut_callbacks);
104 if (len == 0) {
105 return 0;
106 }
107
108 iters = PyList_GetSlice(fut->fut_callbacks, 0, len);
109 if (iters == NULL) {
110 return -1;
111 }
112 if (PyList_SetSlice(fut->fut_callbacks, 0, len, NULL) < 0) {
113 Py_DECREF(iters);
114 return -1;
115 }
116
117 for (i = 0; i < len; i++) {
118 PyObject *handle = NULL;
119 PyObject *cb = PyList_GET_ITEM(iters, i);
120
121 handle = _PyObject_CallMethodId(
122 fut->fut_loop, &PyId_call_soon, "OO", cb, fut, NULL);
123
124 if (handle == NULL) {
125 Py_DECREF(iters);
126 return -1;
127 }
128 else {
129 Py_DECREF(handle);
130 }
131 }
132
133 Py_DECREF(iters);
134 return 0;
135}
136
137static int
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400138future_init(FutureObj *fut, PyObject *loop)
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900139{
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900140 PyObject *res = NULL;
141 _Py_IDENTIFIER(get_debug);
142
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900143 if (loop == NULL || loop == Py_None) {
144 loop = PyObject_CallObject(asyncio_get_event_loop, NULL);
145 if (loop == NULL) {
146 return -1;
147 }
148 }
149 else {
150 Py_INCREF(loop);
151 }
152 Py_CLEAR(fut->fut_loop);
153 fut->fut_loop = loop;
154
Victor Stinnerf94d1ee2016-10-29 09:05:39 +0200155 res = _PyObject_CallMethodId(fut->fut_loop, &PyId_get_debug, NULL);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900156 if (res == NULL) {
157 return -1;
158 }
159 if (PyObject_IsTrue(res)) {
160 Py_CLEAR(res);
161 fut->fut_source_tb = PyObject_CallObject(traceback_extract_stack, NULL);
162 if (fut->fut_source_tb == NULL) {
163 return -1;
164 }
165 }
166 else {
167 Py_CLEAR(res);
168 }
169
170 fut->fut_callbacks = PyList_New(0);
171 if (fut->fut_callbacks == NULL) {
172 return -1;
173 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400174
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900175 return 0;
176}
177
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900178static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400179future_set_result(FutureObj *fut, PyObject *res)
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900180{
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900181 if (fut->fut_state != STATE_PENDING) {
182 PyErr_SetString(asyncio_InvalidStateError, "invalid state");
183 return NULL;
184 }
185
186 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)) {
207 exc_val = PyObject_CallObject(exc, NULL);
208 if (exc_val == NULL) {
209 return NULL;
210 }
211 }
212 else {
213 exc_val = exc;
214 Py_INCREF(exc_val);
215 }
216 if (!PyExceptionInstance_Check(exc_val)) {
217 Py_DECREF(exc_val);
218 PyErr_SetString(PyExc_TypeError, "invalid exception object");
219 return NULL;
220 }
221 if ((PyObject*)Py_TYPE(exc_val) == PyExc_StopIteration) {
222 Py_DECREF(exc_val);
223 PyErr_SetString(PyExc_TypeError,
224 "StopIteration interacts badly with generators "
225 "and cannot be raised into a Future");
226 return NULL;
227 }
228
229 fut->fut_exception = exc_val;
230 fut->fut_state = STATE_FINISHED;
231
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400232 if (future_call_schedule_callbacks(fut) == -1) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900233 return NULL;
234 }
235
236 fut->fut_log_tb = 1;
237 Py_RETURN_NONE;
238}
239
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400240static int
241future_get_result(FutureObj *fut, PyObject **result)
242{
243 PyObject *exc;
244
245 if (fut->fut_state == STATE_CANCELLED) {
246 exc = _PyObject_CallNoArg(asyncio_CancelledError);
247 if (exc == NULL) {
248 return -1;
249 }
250 *result = exc;
251 return 1;
252 }
253
254 if (fut->fut_state != STATE_FINISHED) {
255 PyObject *msg = PyUnicode_FromString("Result is not ready.");
256 if (msg == NULL) {
257 return -1;
258 }
259
260 exc = _PyObject_CallArg1(asyncio_InvalidStateError, msg);
261 Py_DECREF(msg);
262 if (exc == NULL) {
263 return -1;
264 }
265
266 *result = exc;
267 return 1;
268 }
269
270 fut->fut_log_tb = 0;
271 if (fut->fut_exception != NULL) {
272 Py_INCREF(fut->fut_exception);
273 *result = fut->fut_exception;
274 return 1;
275 }
276
277 Py_INCREF(fut->fut_result);
278 *result = fut->fut_result;
279 return 0;
280}
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900281
282static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400283future_add_done_callback(FutureObj *fut, PyObject *arg)
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900284{
285 if (fut->fut_state != STATE_PENDING) {
286 PyObject *handle = _PyObject_CallMethodId(
287 fut->fut_loop, &PyId_call_soon, "OO", arg, fut, NULL);
288
289 if (handle == NULL) {
290 return NULL;
291 }
292 else {
293 Py_DECREF(handle);
294 }
295 }
296 else {
297 int err = PyList_Append(fut->fut_callbacks, arg);
298 if (err != 0) {
299 return NULL;
300 }
301 }
302 Py_RETURN_NONE;
303}
304
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400305static PyObject *
306future_cancel(FutureObj *fut)
307{
308 if (fut->fut_state != STATE_PENDING) {
309 Py_RETURN_FALSE;
310 }
311 fut->fut_state = STATE_CANCELLED;
312
313 if (future_call_schedule_callbacks(fut) == -1) {
314 return NULL;
315 }
316
317 Py_RETURN_TRUE;
318}
319
320/*[clinic input]
321_asyncio.Future.__init__
322
323 *
324 loop: 'O' = NULL
325
326This class is *almost* compatible with concurrent.futures.Future.
327
328 Differences:
329
330 - result() and exception() do not take a timeout argument and
331 raise an exception when the future isn't done yet.
332
333 - Callbacks registered with add_done_callback() are always called
334 via the event loop's call_soon_threadsafe().
335
336 - This class is not compatible with the wait() and as_completed()
337 methods in the concurrent.futures package.
338[clinic start generated code]*/
339
340static int
341_asyncio_Future___init___impl(FutureObj *self, PyObject *loop)
342/*[clinic end generated code: output=9ed75799eaccb5d6 input=8e1681f23605be2d]*/
343
344{
345 return future_init(self, loop);
346}
347
348static int
349FutureObj_clear(FutureObj *fut)
350{
351 Py_CLEAR(fut->fut_loop);
352 Py_CLEAR(fut->fut_callbacks);
353 Py_CLEAR(fut->fut_result);
354 Py_CLEAR(fut->fut_exception);
355 Py_CLEAR(fut->fut_source_tb);
356 Py_CLEAR(fut->dict);
357 return 0;
358}
359
360static int
361FutureObj_traverse(FutureObj *fut, visitproc visit, void *arg)
362{
363 Py_VISIT(fut->fut_loop);
364 Py_VISIT(fut->fut_callbacks);
365 Py_VISIT(fut->fut_result);
366 Py_VISIT(fut->fut_exception);
367 Py_VISIT(fut->fut_source_tb);
368 Py_VISIT(fut->dict);
369 return 0;
370}
371
372/*[clinic input]
373_asyncio.Future.result
374
375Return the result this future represents.
376
377If the future has been cancelled, raises CancelledError. If the
378future's result isn't yet available, raises InvalidStateError. If
379the future is done and has an exception set, this exception is raised.
380[clinic start generated code]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900381
382static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400383_asyncio_Future_result_impl(FutureObj *self)
384/*[clinic end generated code: output=f35f940936a4b1e5 input=49ecf9cf5ec50dc5]*/
385{
386 PyObject *result;
387 int res = future_get_result(self, &result);
388
389 if (res == -1) {
390 return NULL;
391 }
392
393 if (res == 0) {
394 return result;
395 }
396
397 assert(res == 1);
398
399 PyErr_SetObject(PyExceptionInstance_Class(result), result);
400 Py_DECREF(result);
401 return NULL;
402}
403
404/*[clinic input]
405_asyncio.Future.exception
406
407Return the exception that was set on this future.
408
409The exception (or None if no exception was set) is returned only if
410the future is done. If the future has been cancelled, raises
411CancelledError. If the future isn't done yet, raises
412InvalidStateError.
413[clinic start generated code]*/
414
415static PyObject *
416_asyncio_Future_exception_impl(FutureObj *self)
417/*[clinic end generated code: output=88b20d4f855e0710 input=733547a70c841c68]*/
418{
419 if (self->fut_state == STATE_CANCELLED) {
420 PyErr_SetString(asyncio_CancelledError, "");
421 return NULL;
422 }
423
424 if (self->fut_state != STATE_FINISHED) {
425 PyErr_SetString(asyncio_InvalidStateError, "Result is not ready.");
426 return NULL;
427 }
428
429 if (self->fut_exception != NULL) {
430 self->fut_log_tb = 0;
431 Py_INCREF(self->fut_exception);
432 return self->fut_exception;
433 }
434
435 Py_RETURN_NONE;
436}
437
438/*[clinic input]
439_asyncio.Future.set_result
440
441 res: 'O'
442 /
443
444Mark the future done and set its result.
445
446If the future is already done when this method is called, raises
447InvalidStateError.
448[clinic start generated code]*/
449
450static PyObject *
451_asyncio_Future_set_result(FutureObj *self, PyObject *res)
452/*[clinic end generated code: output=a620abfc2796bfb6 input=8619565e0503357e]*/
453{
454 return future_set_result(self, res);
455}
456
457/*[clinic input]
458_asyncio.Future.set_exception
459
460 exception: 'O'
461 /
462
463Mark the future done and set an exception.
464
465If the future is already done when this method is called, raises
466InvalidStateError.
467[clinic start generated code]*/
468
469static PyObject *
470_asyncio_Future_set_exception(FutureObj *self, PyObject *exception)
471/*[clinic end generated code: output=f1c1b0cd321be360 input=1377dbe15e6ea186]*/
472{
473 return future_set_exception(self, exception);
474}
475
476/*[clinic input]
477_asyncio.Future.add_done_callback
478
479 fn: 'O'
480 /
481
482Add a callback to be run when the future becomes done.
483
484The callback is called with a single argument - the future object. If
485the future is already done when this is called, the callback is
486scheduled with call_soon.
487[clinic start generated code]*/
488
489static PyObject *
490_asyncio_Future_add_done_callback(FutureObj *self, PyObject *fn)
491/*[clinic end generated code: output=819e09629b2ec2b5 input=8cce187e32cec6a8]*/
492{
493 return future_add_done_callback(self, fn);
494}
495
496/*[clinic input]
497_asyncio.Future.remove_done_callback
498
499 fn: 'O'
500 /
501
502Remove all instances of a callback from the "call when done" list.
503
504Returns the number of callbacks removed.
505[clinic start generated code]*/
506
507static PyObject *
508_asyncio_Future_remove_done_callback(FutureObj *self, PyObject *fn)
509/*[clinic end generated code: output=5ab1fb52b24ef31f input=3fedb73e1409c31c]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900510{
511 PyObject *newlist;
512 Py_ssize_t len, i, j=0;
513
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400514 len = PyList_GET_SIZE(self->fut_callbacks);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900515 if (len == 0) {
516 return PyLong_FromSsize_t(0);
517 }
518
519 newlist = PyList_New(len);
520 if (newlist == NULL) {
521 return NULL;
522 }
523
524 for (i = 0; i < len; i++) {
525 int ret;
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400526 PyObject *item = PyList_GET_ITEM(self->fut_callbacks, i);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900527
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400528 if ((ret = PyObject_RichCompareBool(fn, item, Py_EQ)) < 0) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900529 goto fail;
530 }
531 if (ret == 0) {
532 Py_INCREF(item);
533 PyList_SET_ITEM(newlist, j, item);
534 j++;
535 }
536 }
537
538 if (PyList_SetSlice(newlist, j, len, NULL) < 0) {
539 goto fail;
540 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400541 if (PyList_SetSlice(self->fut_callbacks, 0, len, newlist) < 0) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900542 goto fail;
543 }
544 Py_DECREF(newlist);
545 return PyLong_FromSsize_t(len - j);
546
547fail:
548 Py_DECREF(newlist);
549 return NULL;
550}
551
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400552/*[clinic input]
553_asyncio.Future.cancel
554
555Cancel the future and schedule callbacks.
556
557If the future is already done or cancelled, return False. Otherwise,
558change the future's state to cancelled, schedule the callbacks and
559return True.
560[clinic start generated code]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900561
562static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400563_asyncio_Future_cancel_impl(FutureObj *self)
564/*[clinic end generated code: output=e45b932ba8bd68a1 input=515709a127995109]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900565{
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400566 return future_cancel(self);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900567}
568
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400569/*[clinic input]
570_asyncio.Future.cancelled
571
572Return True if the future was cancelled.
573[clinic start generated code]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900574
575static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400576_asyncio_Future_cancelled_impl(FutureObj *self)
577/*[clinic end generated code: output=145197ced586357d input=943ab8b7b7b17e45]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900578{
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400579 if (self->fut_state == STATE_CANCELLED) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900580 Py_RETURN_TRUE;
581 }
582 else {
583 Py_RETURN_FALSE;
584 }
585}
586
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400587/*[clinic input]
588_asyncio.Future.done
589
590Return True if the future is done.
591
592Done means either that a result / exception are available, or that the
593future was cancelled.
594[clinic start generated code]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900595
596static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400597_asyncio_Future_done_impl(FutureObj *self)
598/*[clinic end generated code: output=244c5ac351145096 input=28d7b23fdb65d2ac]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900599{
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400600 if (self->fut_state == STATE_PENDING) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900601 Py_RETURN_FALSE;
602 }
603 else {
604 Py_RETURN_TRUE;
605 }
606}
607
608static PyObject *
609FutureObj_get_blocking(FutureObj *fut)
610{
611 if (fut->fut_blocking) {
612 Py_RETURN_TRUE;
613 }
614 else {
615 Py_RETURN_FALSE;
616 }
617}
618
619static int
620FutureObj_set_blocking(FutureObj *fut, PyObject *val)
621{
622 int is_true = PyObject_IsTrue(val);
623 if (is_true < 0) {
624 return -1;
625 }
626 fut->fut_blocking = is_true;
627 return 0;
628}
629
630static PyObject *
631FutureObj_get_log_traceback(FutureObj *fut)
632{
633 if (fut->fut_log_tb) {
634 Py_RETURN_TRUE;
635 }
636 else {
637 Py_RETURN_FALSE;
638 }
639}
640
641static PyObject *
642FutureObj_get_loop(FutureObj *fut)
643{
644 if (fut->fut_loop == NULL) {
645 Py_RETURN_NONE;
646 }
647 Py_INCREF(fut->fut_loop);
648 return fut->fut_loop;
649}
650
651static PyObject *
652FutureObj_get_callbacks(FutureObj *fut)
653{
654 if (fut->fut_callbacks == NULL) {
655 Py_RETURN_NONE;
656 }
657 Py_INCREF(fut->fut_callbacks);
658 return fut->fut_callbacks;
659}
660
661static PyObject *
662FutureObj_get_result(FutureObj *fut)
663{
664 if (fut->fut_result == NULL) {
665 Py_RETURN_NONE;
666 }
667 Py_INCREF(fut->fut_result);
668 return fut->fut_result;
669}
670
671static PyObject *
672FutureObj_get_exception(FutureObj *fut)
673{
674 if (fut->fut_exception == NULL) {
675 Py_RETURN_NONE;
676 }
677 Py_INCREF(fut->fut_exception);
678 return fut->fut_exception;
679}
680
681static PyObject *
682FutureObj_get_source_traceback(FutureObj *fut)
683{
684 if (fut->fut_source_tb == NULL) {
685 Py_RETURN_NONE;
686 }
687 Py_INCREF(fut->fut_source_tb);
688 return fut->fut_source_tb;
689}
690
691static PyObject *
692FutureObj_get_state(FutureObj *fut)
693{
694 _Py_IDENTIFIER(PENDING);
695 _Py_IDENTIFIER(CANCELLED);
696 _Py_IDENTIFIER(FINISHED);
697 PyObject *ret = NULL;
698
699 switch (fut->fut_state) {
700 case STATE_PENDING:
701 ret = _PyUnicode_FromId(&PyId_PENDING);
702 break;
703 case STATE_CANCELLED:
704 ret = _PyUnicode_FromId(&PyId_CANCELLED);
705 break;
706 case STATE_FINISHED:
707 ret = _PyUnicode_FromId(&PyId_FINISHED);
708 break;
709 default:
710 assert (0);
711 }
712 Py_INCREF(ret);
713 return ret;
714}
715
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400716/*[clinic input]
717_asyncio.Future._repr_info
718[clinic start generated code]*/
719
720static PyObject *
721_asyncio_Future__repr_info_impl(FutureObj *self)
722/*[clinic end generated code: output=fa69e901bd176cfb input=f21504d8e2ae1ca2]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900723{
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400724 return PyObject_CallFunctionObjArgs(
725 asyncio_future_repr_info_func, self, NULL);
726}
727
728/*[clinic input]
729_asyncio.Future._schedule_callbacks
730[clinic start generated code]*/
731
732static PyObject *
733_asyncio_Future__schedule_callbacks_impl(FutureObj *self)
734/*[clinic end generated code: output=5e8958d89ea1c5dc input=4f5f295f263f4a88]*/
735{
736 int ret = future_schedule_callbacks(self);
737 if (ret == -1) {
738 return NULL;
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900739 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400740 Py_RETURN_NONE;
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900741}
742
743static PyObject *
744FutureObj_repr(FutureObj *fut)
745{
746 _Py_IDENTIFIER(_repr_info);
747
748 PyObject *_repr_info = _PyUnicode_FromId(&PyId__repr_info); // borrowed
749 if (_repr_info == NULL) {
750 return NULL;
751 }
752
753 PyObject *rinfo = PyObject_CallMethodObjArgs((PyObject*)fut, _repr_info,
754 NULL);
755 if (rinfo == NULL) {
756 return NULL;
757 }
758
759 PyObject *sp = PyUnicode_FromString(" ");
760 if (sp == NULL) {
761 Py_DECREF(rinfo);
762 return NULL;
763 }
764
765 PyObject *rinfo_s = PyUnicode_Join(sp, rinfo);
766 Py_DECREF(sp);
767 Py_DECREF(rinfo);
768 if (rinfo_s == NULL) {
769 return NULL;
770 }
771
772 PyObject *rstr = NULL;
773 PyObject *type_name = PyObject_GetAttrString((PyObject*)Py_TYPE(fut),
774 "__name__");
775 if (type_name != NULL) {
776 rstr = PyUnicode_FromFormat("<%S %S>", type_name, rinfo_s);
777 Py_DECREF(type_name);
778 }
779 Py_DECREF(rinfo_s);
780 return rstr;
781}
782
783static void
784FutureObj_finalize(FutureObj *fut)
785{
786 _Py_IDENTIFIER(call_exception_handler);
787 _Py_IDENTIFIER(message);
788 _Py_IDENTIFIER(exception);
789 _Py_IDENTIFIER(future);
790 _Py_IDENTIFIER(source_traceback);
791
792 if (!fut->fut_log_tb) {
793 return;
794 }
795 assert(fut->fut_exception != NULL);
796 fut->fut_log_tb = 0;;
797
798 PyObject *error_type, *error_value, *error_traceback;
799 /* Save the current exception, if any. */
800 PyErr_Fetch(&error_type, &error_value, &error_traceback);
801
802 PyObject *context = NULL;
803 PyObject *type_name = NULL;
804 PyObject *message = NULL;
805 PyObject *func = NULL;
806 PyObject *res = NULL;
807
808 context = PyDict_New();
809 if (context == NULL) {
810 goto finally;
811 }
812
813 type_name = PyObject_GetAttrString((PyObject*)Py_TYPE(fut), "__name__");
814 if (type_name == NULL) {
815 goto finally;
816 }
817
818 message = PyUnicode_FromFormat(
819 "%S exception was never retrieved", type_name);
820 if (message == NULL) {
821 goto finally;
822 }
823
824 if (_PyDict_SetItemId(context, &PyId_message, message) < 0 ||
825 _PyDict_SetItemId(context, &PyId_exception, fut->fut_exception) < 0 ||
826 _PyDict_SetItemId(context, &PyId_future, (PyObject*)fut) < 0) {
827 goto finally;
828 }
829 if (fut->fut_source_tb != NULL) {
830 if (_PyDict_SetItemId(context, &PyId_source_traceback,
831 fut->fut_source_tb) < 0) {
832 goto finally;
833 }
834 }
835
836 func = _PyObject_GetAttrId(fut->fut_loop, &PyId_call_exception_handler);
837 if (func != NULL) {
838 res = _PyObject_CallArg1(func, context);
839 if (res == NULL) {
840 PyErr_WriteUnraisable(func);
841 }
842 }
843
844finally:
845 Py_CLEAR(context);
846 Py_CLEAR(type_name);
847 Py_CLEAR(message);
848 Py_CLEAR(func);
849 Py_CLEAR(res);
850
851 /* Restore the saved exception. */
852 PyErr_Restore(error_type, error_value, error_traceback);
853}
854
855
856static PyAsyncMethods FutureType_as_async = {
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400857 (unaryfunc)future_new_iter, /* am_await */
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900858 0, /* am_aiter */
859 0 /* am_anext */
860};
861
862static PyMethodDef FutureType_methods[] = {
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400863 _ASYNCIO_FUTURE_RESULT_METHODDEF
864 _ASYNCIO_FUTURE_EXCEPTION_METHODDEF
865 _ASYNCIO_FUTURE_SET_RESULT_METHODDEF
866 _ASYNCIO_FUTURE_SET_EXCEPTION_METHODDEF
867 _ASYNCIO_FUTURE_ADD_DONE_CALLBACK_METHODDEF
868 _ASYNCIO_FUTURE_REMOVE_DONE_CALLBACK_METHODDEF
869 _ASYNCIO_FUTURE_CANCEL_METHODDEF
870 _ASYNCIO_FUTURE_CANCELLED_METHODDEF
871 _ASYNCIO_FUTURE_DONE_METHODDEF
872 _ASYNCIO_FUTURE__REPR_INFO_METHODDEF
873 _ASYNCIO_FUTURE__SCHEDULE_CALLBACKS_METHODDEF
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900874 {NULL, NULL} /* Sentinel */
875};
876
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400877#define FUTURE_COMMON_GETSETLIST \
878 {"_state", (getter)FutureObj_get_state, NULL, NULL}, \
879 {"_asyncio_future_blocking", (getter)FutureObj_get_blocking, \
880 (setter)FutureObj_set_blocking, NULL}, \
881 {"_loop", (getter)FutureObj_get_loop, NULL, NULL}, \
882 {"_callbacks", (getter)FutureObj_get_callbacks, NULL, NULL}, \
883 {"_result", (getter)FutureObj_get_result, NULL, NULL}, \
884 {"_exception", (getter)FutureObj_get_exception, NULL, NULL}, \
885 {"_log_traceback", (getter)FutureObj_get_log_traceback, NULL, NULL}, \
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900886 {"_source_traceback", (getter)FutureObj_get_source_traceback, NULL, NULL},
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400887
888static PyGetSetDef FutureType_getsetlist[] = {
889 FUTURE_COMMON_GETSETLIST
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900890 {NULL} /* Sentinel */
891};
892
893static void FutureObj_dealloc(PyObject *self);
894
895static PyTypeObject FutureType = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +0200896 PyVarObject_HEAD_INIT(NULL, 0)
INADA Naoki9f2ce252016-10-15 15:39:19 +0900897 "_asyncio.Future",
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900898 sizeof(FutureObj), /* tp_basicsize */
899 .tp_dealloc = FutureObj_dealloc,
900 .tp_as_async = &FutureType_as_async,
901 .tp_repr = (reprfunc)FutureObj_repr,
902 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE
903 | Py_TPFLAGS_HAVE_FINALIZE,
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400904 .tp_doc = _asyncio_Future___init____doc__,
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900905 .tp_traverse = (traverseproc)FutureObj_traverse,
906 .tp_clear = (inquiry)FutureObj_clear,
907 .tp_weaklistoffset = offsetof(FutureObj, fut_weakreflist),
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400908 .tp_iter = (getiterfunc)future_new_iter,
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900909 .tp_methods = FutureType_methods,
910 .tp_getset = FutureType_getsetlist,
911 .tp_dictoffset = offsetof(FutureObj, dict),
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400912 .tp_init = (initproc)_asyncio_Future___init__,
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900913 .tp_new = PyType_GenericNew,
914 .tp_finalize = (destructor)FutureObj_finalize,
915};
916
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400917#define Future_CheckExact(obj) (Py_TYPE(obj) == &FutureType)
918
919static inline int
920future_call_schedule_callbacks(FutureObj *fut)
921{
922 if (Future_CheckExact(fut)) {
923 return future_schedule_callbacks(fut);
924 }
925 else {
926 /* `fut` is a subclass of Future */
927 PyObject *ret = _PyObject_CallMethodId(
928 (PyObject*)fut, &PyId__schedule_callbacks, NULL);
929 if (ret == NULL) {
930 return -1;
931 }
932
933 Py_DECREF(ret);
934 return 0;
935 }
936}
937
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900938static void
939FutureObj_dealloc(PyObject *self)
940{
941 FutureObj *fut = (FutureObj *)self;
942
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400943 if (Future_CheckExact(fut)) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900944 /* When fut is subclass of Future, finalizer is called from
945 * subtype_dealloc.
946 */
947 if (PyObject_CallFinalizerFromDealloc(self) < 0) {
948 // resurrected.
949 return;
950 }
951 }
952
953 if (fut->fut_weakreflist != NULL) {
954 PyObject_ClearWeakRefs(self);
955 }
956
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400957 (void)FutureObj_clear(fut);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900958 Py_TYPE(fut)->tp_free(fut);
959}
960
961
962/*********************** Future Iterator **************************/
963
964typedef struct {
965 PyObject_HEAD
966 FutureObj *future;
967} futureiterobject;
968
969static void
970FutureIter_dealloc(futureiterobject *it)
971{
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400972 PyObject_GC_UnTrack(it);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900973 Py_XDECREF(it->future);
974 PyObject_GC_Del(it);
975}
976
977static PyObject *
978FutureIter_iternext(futureiterobject *it)
979{
980 PyObject *res;
981 FutureObj *fut = it->future;
982
983 if (fut == NULL) {
984 return NULL;
985 }
986
987 if (fut->fut_state == STATE_PENDING) {
988 if (!fut->fut_blocking) {
989 fut->fut_blocking = 1;
990 Py_INCREF(fut);
991 return (PyObject *)fut;
992 }
993 PyErr_Format(PyExc_AssertionError,
994 "yield from wasn't used with future");
995 return NULL;
996 }
997
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400998 res = _asyncio_Future_result_impl(fut);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900999 if (res != NULL) {
Serhiy Storchaka60e49aa2016-11-06 18:47:03 +02001000 /* The result of the Future is not an exception. */
1001 if (_PyGen_SetStopIterationValue(res) < 0) {
1002 Py_DECREF(res);
Yury Selivanova4b884f2016-10-20 15:54:20 -04001003 return NULL;
1004 }
Serhiy Storchaka60e49aa2016-11-06 18:47:03 +02001005 Py_DECREF(res);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001006 }
1007
1008 it->future = NULL;
1009 Py_DECREF(fut);
1010 return NULL;
1011}
1012
1013static PyObject *
INADA Naoki74c17532016-10-25 19:00:45 +09001014FutureIter_send(futureiterobject *self, PyObject *unused)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001015{
INADA Naoki74c17532016-10-25 19:00:45 +09001016 /* Future.__iter__ doesn't care about values that are pushed to the
1017 * generator, it just returns "self.result().
1018 */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001019 return FutureIter_iternext(self);
1020}
1021
1022static PyObject *
1023FutureIter_throw(futureiterobject *self, PyObject *args)
1024{
1025 PyObject *type=NULL, *val=NULL, *tb=NULL;
1026 if (!PyArg_ParseTuple(args, "O|OO", &type, &val, &tb))
1027 return NULL;
1028
1029 if (val == Py_None) {
1030 val = NULL;
1031 }
1032 if (tb == Py_None) {
1033 tb = NULL;
1034 }
1035
1036 Py_CLEAR(self->future);
1037
1038 if (tb != NULL) {
1039 PyErr_Restore(type, val, tb);
1040 }
1041 else if (val != NULL) {
1042 PyErr_SetObject(type, val);
1043 }
1044 else {
1045 if (PyExceptionClass_Check(type)) {
1046 val = PyObject_CallObject(type, NULL);
Yury Selivanov692796a2016-11-08 19:04:57 -05001047 PyErr_SetObject(type, val);
1048 Py_DECREF(val);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001049 }
1050 else {
1051 val = type;
1052 assert (PyExceptionInstance_Check(val));
1053 type = (PyObject*)Py_TYPE(val);
1054 assert (PyExceptionClass_Check(type));
Yury Selivanov692796a2016-11-08 19:04:57 -05001055 PyErr_SetObject(type, val);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001056 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001057 }
1058 return FutureIter_iternext(self);
1059}
1060
1061static PyObject *
1062FutureIter_close(futureiterobject *self, PyObject *arg)
1063{
1064 Py_CLEAR(self->future);
1065 Py_RETURN_NONE;
1066}
1067
1068static int
1069FutureIter_traverse(futureiterobject *it, visitproc visit, void *arg)
1070{
1071 Py_VISIT(it->future);
1072 return 0;
1073}
1074
1075static PyMethodDef FutureIter_methods[] = {
1076 {"send", (PyCFunction)FutureIter_send, METH_O, NULL},
1077 {"throw", (PyCFunction)FutureIter_throw, METH_VARARGS, NULL},
1078 {"close", (PyCFunction)FutureIter_close, METH_NOARGS, NULL},
1079 {NULL, NULL} /* Sentinel */
1080};
1081
1082static PyTypeObject FutureIterType = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02001083 PyVarObject_HEAD_INIT(NULL, 0)
INADA Naoki9f2ce252016-10-15 15:39:19 +09001084 "_asyncio.FutureIter",
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001085 .tp_basicsize = sizeof(futureiterobject),
1086 .tp_itemsize = 0,
1087 .tp_dealloc = (destructor)FutureIter_dealloc,
1088 .tp_getattro = PyObject_GenericGetAttr,
1089 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
1090 .tp_traverse = (traverseproc)FutureIter_traverse,
1091 .tp_iter = PyObject_SelfIter,
1092 .tp_iternext = (iternextfunc)FutureIter_iternext,
1093 .tp_methods = FutureIter_methods,
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001094};
1095
1096static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001097future_new_iter(PyObject *fut)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001098{
1099 futureiterobject *it;
1100
1101 if (!PyObject_TypeCheck(fut, &FutureType)) {
1102 PyErr_BadInternalCall();
1103 return NULL;
1104 }
1105 it = PyObject_GC_New(futureiterobject, &FutureIterType);
1106 if (it == NULL) {
1107 return NULL;
1108 }
1109 Py_INCREF(fut);
1110 it->future = (FutureObj*)fut;
INADA Naoki1be427b2016-10-11 02:12:34 +09001111 PyObject_GC_Track(it);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001112 return (PyObject*)it;
1113}
1114
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001115
1116/*********************** Task **************************/
1117
1118
1119/*[clinic input]
1120class _asyncio.Task "TaskObj *" "&Task_Type"
1121[clinic start generated code]*/
1122/*[clinic end generated code: output=da39a3ee5e6b4b0d input=719dcef0fcc03b37]*/
1123
1124static int task_call_step_soon(TaskObj *, PyObject *);
1125static inline PyObject * task_call_wakeup(TaskObj *, PyObject *);
1126static inline PyObject * task_call_step(TaskObj *, PyObject *);
1127static PyObject * task_wakeup(TaskObj *, PyObject *);
1128static PyObject * task_step(TaskObj *, PyObject *);
1129
1130/* ----- Task._step wrapper */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001131
INADA Naokic411a7d2016-10-18 11:48:14 +09001132static int
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001133TaskSendMethWrapper_clear(TaskSendMethWrapper *o)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001134{
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001135 Py_CLEAR(o->sw_task);
1136 Py_CLEAR(o->sw_arg);
1137 return 0;
1138}
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001139
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001140static void
1141TaskSendMethWrapper_dealloc(TaskSendMethWrapper *o)
1142{
1143 PyObject_GC_UnTrack(o);
1144 (void)TaskSendMethWrapper_clear(o);
1145 Py_TYPE(o)->tp_free(o);
1146}
1147
1148static PyObject *
1149TaskSendMethWrapper_call(TaskSendMethWrapper *o,
1150 PyObject *args, PyObject *kwds)
1151{
1152 return task_call_step(o->sw_task, o->sw_arg);
1153}
1154
1155static int
1156TaskSendMethWrapper_traverse(TaskSendMethWrapper *o,
1157 visitproc visit, void *arg)
1158{
1159 Py_VISIT(o->sw_task);
1160 Py_VISIT(o->sw_arg);
1161 return 0;
1162}
1163
1164static PyObject *
1165TaskSendMethWrapper_get___self__(TaskSendMethWrapper *o)
1166{
1167 if (o->sw_task) {
1168 Py_INCREF(o->sw_task);
1169 return (PyObject*)o->sw_task;
1170 }
1171 Py_RETURN_NONE;
1172}
1173
1174static PyGetSetDef TaskSendMethWrapper_getsetlist[] = {
1175 {"__self__", (getter)TaskSendMethWrapper_get___self__, NULL, NULL},
1176 {NULL} /* Sentinel */
1177};
1178
1179PyTypeObject TaskSendMethWrapper_Type = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02001180 PyVarObject_HEAD_INIT(NULL, 0)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001181 "TaskSendMethWrapper",
1182 .tp_basicsize = sizeof(TaskSendMethWrapper),
1183 .tp_itemsize = 0,
1184 .tp_getset = TaskSendMethWrapper_getsetlist,
1185 .tp_dealloc = (destructor)TaskSendMethWrapper_dealloc,
1186 .tp_call = (ternaryfunc)TaskSendMethWrapper_call,
1187 .tp_getattro = PyObject_GenericGetAttr,
1188 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
1189 .tp_traverse = (traverseproc)TaskSendMethWrapper_traverse,
1190 .tp_clear = (inquiry)TaskSendMethWrapper_clear,
1191};
1192
1193static PyObject *
1194TaskSendMethWrapper_new(TaskObj *task, PyObject *arg)
1195{
1196 TaskSendMethWrapper *o;
1197 o = PyObject_GC_New(TaskSendMethWrapper, &TaskSendMethWrapper_Type);
1198 if (o == NULL) {
1199 return NULL;
1200 }
1201
1202 Py_INCREF(task);
1203 o->sw_task = task;
1204
1205 Py_XINCREF(arg);
1206 o->sw_arg = arg;
1207
1208 PyObject_GC_Track(o);
1209 return (PyObject*) o;
1210}
1211
1212/* ----- Task._wakeup wrapper */
1213
1214static PyObject *
1215TaskWakeupMethWrapper_call(TaskWakeupMethWrapper *o,
1216 PyObject *args, PyObject *kwds)
1217{
1218 PyObject *fut;
1219
1220 if (!PyArg_ParseTuple(args, "O|", &fut)) {
1221 return NULL;
1222 }
1223
1224 return task_call_wakeup(o->ww_task, fut);
1225}
1226
1227static int
1228TaskWakeupMethWrapper_clear(TaskWakeupMethWrapper *o)
1229{
1230 Py_CLEAR(o->ww_task);
1231 return 0;
1232}
1233
1234static int
1235TaskWakeupMethWrapper_traverse(TaskWakeupMethWrapper *o,
1236 visitproc visit, void *arg)
1237{
1238 Py_VISIT(o->ww_task);
1239 return 0;
1240}
1241
1242static void
1243TaskWakeupMethWrapper_dealloc(TaskWakeupMethWrapper *o)
1244{
1245 PyObject_GC_UnTrack(o);
1246 (void)TaskWakeupMethWrapper_clear(o);
1247 Py_TYPE(o)->tp_free(o);
1248}
1249
1250PyTypeObject TaskWakeupMethWrapper_Type = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02001251 PyVarObject_HEAD_INIT(NULL, 0)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001252 "TaskWakeupMethWrapper",
1253 .tp_basicsize = sizeof(TaskWakeupMethWrapper),
1254 .tp_itemsize = 0,
1255 .tp_dealloc = (destructor)TaskWakeupMethWrapper_dealloc,
1256 .tp_call = (ternaryfunc)TaskWakeupMethWrapper_call,
1257 .tp_getattro = PyObject_GenericGetAttr,
1258 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
1259 .tp_traverse = (traverseproc)TaskWakeupMethWrapper_traverse,
1260 .tp_clear = (inquiry)TaskWakeupMethWrapper_clear,
1261};
1262
1263static PyObject *
1264TaskWakeupMethWrapper_new(TaskObj *task)
1265{
1266 TaskWakeupMethWrapper *o;
1267 o = PyObject_GC_New(TaskWakeupMethWrapper, &TaskWakeupMethWrapper_Type);
1268 if (o == NULL) {
1269 return NULL;
1270 }
1271
1272 Py_INCREF(task);
1273 o->ww_task = task;
1274
1275 PyObject_GC_Track(o);
1276 return (PyObject*) o;
1277}
1278
1279/* ----- Task */
1280
1281/*[clinic input]
1282_asyncio.Task.__init__
1283
1284 coro: 'O'
1285 *
1286 loop: 'O' = NULL
1287
1288A coroutine wrapped in a Future.
1289[clinic start generated code]*/
1290
1291static int
1292_asyncio_Task___init___impl(TaskObj *self, PyObject *coro, PyObject *loop)
1293/*[clinic end generated code: output=9f24774c2287fc2f input=71d8d28c201a18cd]*/
1294{
1295 PyObject *res;
1296 _Py_IDENTIFIER(add);
1297
1298 if (future_init((FutureObj*)self, loop)) {
INADA Naokic411a7d2016-10-18 11:48:14 +09001299 return -1;
1300 }
INADA Naokic411a7d2016-10-18 11:48:14 +09001301
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001302 self->task_fut_waiter = NULL;
1303 self->task_must_cancel = 0;
1304 self->task_log_destroy_pending = 1;
INADA Naokic411a7d2016-10-18 11:48:14 +09001305
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001306 Py_INCREF(coro);
1307 self->task_coro = coro;
1308
1309 if (task_call_step_soon(self, NULL)) {
1310 return -1;
INADA Naokic411a7d2016-10-18 11:48:14 +09001311 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001312
1313 res = _PyObject_CallMethodId(all_tasks, &PyId_add, "O", self, NULL);
1314 if (res == NULL) {
1315 return -1;
1316 }
1317 Py_DECREF(res);
1318
1319 return 0;
1320}
1321
1322static int
1323TaskObj_clear(TaskObj *task)
1324{
1325 (void)FutureObj_clear((FutureObj*) task);
1326 Py_CLEAR(task->task_coro);
1327 Py_CLEAR(task->task_fut_waiter);
1328 return 0;
1329}
1330
1331static int
1332TaskObj_traverse(TaskObj *task, visitproc visit, void *arg)
1333{
1334 Py_VISIT(task->task_coro);
1335 Py_VISIT(task->task_fut_waiter);
1336 (void)FutureObj_traverse((FutureObj*) task, visit, arg);
1337 return 0;
1338}
1339
1340static PyObject *
1341TaskObj_get_log_destroy_pending(TaskObj *task)
1342{
1343 if (task->task_log_destroy_pending) {
1344 Py_RETURN_TRUE;
1345 }
1346 else {
1347 Py_RETURN_FALSE;
1348 }
1349}
1350
1351static int
1352TaskObj_set_log_destroy_pending(TaskObj *task, PyObject *val)
1353{
1354 int is_true = PyObject_IsTrue(val);
1355 if (is_true < 0) {
1356 return -1;
1357 }
1358 task->task_log_destroy_pending = is_true;
1359 return 0;
1360}
1361
1362static PyObject *
1363TaskObj_get_must_cancel(TaskObj *task)
1364{
1365 if (task->task_must_cancel) {
1366 Py_RETURN_TRUE;
1367 }
1368 else {
1369 Py_RETURN_FALSE;
1370 }
1371}
1372
1373static PyObject *
1374TaskObj_get_coro(TaskObj *task)
1375{
1376 if (task->task_coro) {
1377 Py_INCREF(task->task_coro);
1378 return task->task_coro;
1379 }
1380
1381 Py_RETURN_NONE;
1382}
1383
1384static PyObject *
1385TaskObj_get_fut_waiter(TaskObj *task)
1386{
1387 if (task->task_fut_waiter) {
1388 Py_INCREF(task->task_fut_waiter);
1389 return task->task_fut_waiter;
1390 }
1391
1392 Py_RETURN_NONE;
1393}
1394
1395/*[clinic input]
1396@classmethod
1397_asyncio.Task.current_task
1398
1399 loop: 'O' = NULL
1400
1401Return the currently running task in an event loop or None.
1402
1403By default the current task for the current event loop is returned.
1404
1405None is returned when called not in the context of a Task.
1406[clinic start generated code]*/
1407
1408static PyObject *
1409_asyncio_Task_current_task_impl(PyTypeObject *type, PyObject *loop)
1410/*[clinic end generated code: output=99fbe7332c516e03 input=cd784537f02cf833]*/
1411{
1412 PyObject *res;
1413
1414 if (loop == NULL) {
1415 loop = PyObject_CallObject(asyncio_get_event_loop, NULL);
1416 if (loop == NULL) {
1417 return NULL;
1418 }
1419
Yury Selivanov684ef2c2016-10-28 19:01:21 -04001420 res = PyDict_GetItem(current_tasks, loop);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001421 Py_DECREF(loop);
1422 }
1423 else {
Yury Selivanov684ef2c2016-10-28 19:01:21 -04001424 res = PyDict_GetItem(current_tasks, loop);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001425 }
1426
1427 if (res == NULL) {
1428 Py_RETURN_NONE;
1429 }
1430 else {
1431 Py_INCREF(res);
1432 return res;
1433 }
1434}
1435
1436static PyObject *
1437task_all_tasks(PyObject *loop)
1438{
1439 PyObject *task;
1440 PyObject *task_loop;
1441 PyObject *set;
1442 PyObject *iter;
1443
1444 assert(loop != NULL);
1445
1446 set = PySet_New(NULL);
1447 if (set == NULL) {
1448 return NULL;
1449 }
1450
1451 iter = PyObject_GetIter(all_tasks);
1452 if (iter == NULL) {
INADA Naokic411a7d2016-10-18 11:48:14 +09001453 goto fail;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001454 }
1455
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001456 while ((task = PyIter_Next(iter))) {
1457 task_loop = PyObject_GetAttrString(task, "_loop");
1458 if (task_loop == NULL) {
1459 Py_DECREF(task);
1460 goto fail;
1461 }
1462 if (task_loop == loop) {
1463 if (PySet_Add(set, task) == -1) {
1464 Py_DECREF(task_loop);
1465 Py_DECREF(task);
1466 goto fail;
1467 }
1468 }
1469 Py_DECREF(task_loop);
1470 Py_DECREF(task);
1471 }
1472
1473 Py_DECREF(iter);
1474 return set;
1475
1476fail:
1477 Py_XDECREF(set);
1478 Py_XDECREF(iter);
1479 return NULL;
1480}
1481
1482/*[clinic input]
1483@classmethod
1484_asyncio.Task.all_tasks
1485
1486 loop: 'O' = NULL
1487
1488Return a set of all tasks for an event loop.
1489
1490By default all tasks for the current event loop are returned.
1491[clinic start generated code]*/
1492
1493static PyObject *
1494_asyncio_Task_all_tasks_impl(PyTypeObject *type, PyObject *loop)
1495/*[clinic end generated code: output=11f9b20749ccca5d input=cd64aa5f88bd5c49]*/
1496{
1497 PyObject *res;
1498
1499 if (loop == NULL) {
1500 loop = PyObject_CallObject(asyncio_get_event_loop, NULL);
1501 if (loop == NULL) {
1502 return NULL;
1503 }
1504
1505 res = task_all_tasks(loop);
1506 Py_DECREF(loop);
1507 }
1508 else {
1509 res = task_all_tasks(loop);
1510 }
1511
1512 return res;
1513}
1514
1515/*[clinic input]
1516_asyncio.Task._repr_info
1517[clinic start generated code]*/
1518
1519static PyObject *
1520_asyncio_Task__repr_info_impl(TaskObj *self)
1521/*[clinic end generated code: output=6a490eb66d5ba34b input=3c6d051ed3ddec8b]*/
1522{
1523 return PyObject_CallFunctionObjArgs(
1524 asyncio_task_repr_info_func, self, NULL);
1525}
1526
1527/*[clinic input]
1528_asyncio.Task.cancel
1529
1530Request that this task cancel itself.
1531
1532This arranges for a CancelledError to be thrown into the
1533wrapped coroutine on the next cycle through the event loop.
1534The coroutine then has a chance to clean up or even deny
1535the request using try/except/finally.
1536
1537Unlike Future.cancel, this does not guarantee that the
1538task will be cancelled: the exception might be caught and
1539acted upon, delaying cancellation of the task or preventing
1540cancellation completely. The task may also return a value or
1541raise a different exception.
1542
1543Immediately after this method is called, Task.cancelled() will
1544not return True (unless the task was already cancelled). A
1545task will be marked as cancelled when the wrapped coroutine
1546terminates with a CancelledError exception (even if cancel()
1547was not called).
1548[clinic start generated code]*/
1549
1550static PyObject *
1551_asyncio_Task_cancel_impl(TaskObj *self)
1552/*[clinic end generated code: output=6bfc0479da9d5757 input=13f9bf496695cb52]*/
1553{
1554 if (self->task_state != STATE_PENDING) {
1555 Py_RETURN_FALSE;
1556 }
1557
1558 if (self->task_fut_waiter) {
1559 PyObject *res;
1560 int is_true;
1561
1562 res = _PyObject_CallMethodId(
1563 self->task_fut_waiter, &PyId_cancel, NULL);
1564 if (res == NULL) {
1565 return NULL;
1566 }
1567
1568 is_true = PyObject_IsTrue(res);
1569 Py_DECREF(res);
1570 if (is_true < 0) {
1571 return NULL;
1572 }
1573
1574 if (is_true) {
1575 Py_RETURN_TRUE;
1576 }
1577 }
1578
1579 self->task_must_cancel = 1;
1580 Py_RETURN_TRUE;
1581}
1582
1583/*[clinic input]
1584_asyncio.Task.get_stack
1585
1586 *
1587 limit: 'O' = None
1588
1589Return the list of stack frames for this task's coroutine.
1590
1591If the coroutine is not done, this returns the stack where it is
1592suspended. If the coroutine has completed successfully or was
1593cancelled, this returns an empty list. If the coroutine was
1594terminated by an exception, this returns the list of traceback
1595frames.
1596
1597The frames are always ordered from oldest to newest.
1598
1599The optional limit gives the maximum number of frames to
1600return; by default all available frames are returned. Its
1601meaning differs depending on whether a stack or a traceback is
1602returned: the newest frames of a stack are returned, but the
1603oldest frames of a traceback are returned. (This matches the
1604behavior of the traceback module.)
1605
1606For reasons beyond our control, only one stack frame is
1607returned for a suspended coroutine.
1608[clinic start generated code]*/
1609
1610static PyObject *
1611_asyncio_Task_get_stack_impl(TaskObj *self, PyObject *limit)
1612/*[clinic end generated code: output=c9aeeeebd1e18118 input=b1920230a766d17a]*/
1613{
1614 return PyObject_CallFunctionObjArgs(
1615 asyncio_task_get_stack_func, self, limit, NULL);
1616}
1617
1618/*[clinic input]
1619_asyncio.Task.print_stack
1620
1621 *
1622 limit: 'O' = None
1623 file: 'O' = None
1624
1625Print the stack or traceback for this task's coroutine.
1626
1627This produces output similar to that of the traceback module,
1628for the frames retrieved by get_stack(). The limit argument
1629is passed to get_stack(). The file argument is an I/O stream
1630to which the output is written; by default output is written
1631to sys.stderr.
1632[clinic start generated code]*/
1633
1634static PyObject *
1635_asyncio_Task_print_stack_impl(TaskObj *self, PyObject *limit,
1636 PyObject *file)
1637/*[clinic end generated code: output=7339e10314cd3f4d input=19f1e99ab5400bc3]*/
1638{
1639 return PyObject_CallFunctionObjArgs(
1640 asyncio_task_print_stack_func, self, limit, file, NULL);
1641}
1642
1643/*[clinic input]
1644_asyncio.Task._step
1645
1646 exc: 'O' = NULL
1647[clinic start generated code]*/
1648
1649static PyObject *
1650_asyncio_Task__step_impl(TaskObj *self, PyObject *exc)
1651/*[clinic end generated code: output=7ed23f0cefd5ae42 input=ada4b2324e5370af]*/
1652{
1653 return task_step(self, exc == Py_None ? NULL : exc);
1654}
1655
1656/*[clinic input]
1657_asyncio.Task._wakeup
1658
1659 fut: 'O'
1660[clinic start generated code]*/
1661
1662static PyObject *
1663_asyncio_Task__wakeup_impl(TaskObj *self, PyObject *fut)
1664/*[clinic end generated code: output=75cb341c760fd071 input=11ee4918a5bdbf21]*/
1665{
1666 return task_wakeup(self, fut);
1667}
1668
1669static void
1670TaskObj_finalize(TaskObj *task)
1671{
1672 _Py_IDENTIFIER(call_exception_handler);
1673 _Py_IDENTIFIER(task);
1674 _Py_IDENTIFIER(message);
1675 _Py_IDENTIFIER(source_traceback);
1676
1677 PyObject *message = NULL;
1678 PyObject *context = NULL;
1679 PyObject *func = NULL;
1680 PyObject *res = NULL;
1681
1682 PyObject *error_type, *error_value, *error_traceback;
1683
1684 if (task->task_state != STATE_PENDING || !task->task_log_destroy_pending) {
1685 goto done;
1686 }
1687
1688 /* Save the current exception, if any. */
1689 PyErr_Fetch(&error_type, &error_value, &error_traceback);
1690
1691 context = PyDict_New();
1692 if (context == NULL) {
1693 goto finally;
1694 }
1695
1696 message = PyUnicode_FromString("Task was destroyed but it is pending!");
1697 if (message == NULL) {
1698 goto finally;
1699 }
1700
1701 if (_PyDict_SetItemId(context, &PyId_message, message) < 0 ||
1702 _PyDict_SetItemId(context, &PyId_task, (PyObject*)task) < 0)
1703 {
1704 goto finally;
1705 }
1706
1707 if (task->task_source_tb != NULL) {
1708 if (_PyDict_SetItemId(context, &PyId_source_traceback,
1709 task->task_source_tb) < 0)
1710 {
1711 goto finally;
1712 }
1713 }
1714
1715 func = _PyObject_GetAttrId(task->task_loop, &PyId_call_exception_handler);
1716 if (func != NULL) {
1717 res = _PyObject_CallArg1(func, context);
1718 if (res == NULL) {
1719 PyErr_WriteUnraisable(func);
1720 }
1721 }
1722
1723finally:
1724 Py_CLEAR(context);
1725 Py_CLEAR(message);
1726 Py_CLEAR(func);
1727 Py_CLEAR(res);
1728
1729 /* Restore the saved exception. */
1730 PyErr_Restore(error_type, error_value, error_traceback);
1731
1732done:
1733 FutureObj_finalize((FutureObj*)task);
1734}
1735
1736static void TaskObj_dealloc(PyObject *); /* Needs Task_CheckExact */
1737
1738static PyMethodDef TaskType_methods[] = {
1739 _ASYNCIO_FUTURE_RESULT_METHODDEF
1740 _ASYNCIO_FUTURE_EXCEPTION_METHODDEF
1741 _ASYNCIO_FUTURE_SET_RESULT_METHODDEF
1742 _ASYNCIO_FUTURE_SET_EXCEPTION_METHODDEF
1743 _ASYNCIO_FUTURE_ADD_DONE_CALLBACK_METHODDEF
1744 _ASYNCIO_FUTURE_REMOVE_DONE_CALLBACK_METHODDEF
1745 _ASYNCIO_FUTURE_CANCELLED_METHODDEF
1746 _ASYNCIO_FUTURE_DONE_METHODDEF
1747 _ASYNCIO_TASK_CURRENT_TASK_METHODDEF
1748 _ASYNCIO_TASK_ALL_TASKS_METHODDEF
1749 _ASYNCIO_TASK_CANCEL_METHODDEF
1750 _ASYNCIO_TASK_GET_STACK_METHODDEF
1751 _ASYNCIO_TASK_PRINT_STACK_METHODDEF
1752 _ASYNCIO_TASK__WAKEUP_METHODDEF
1753 _ASYNCIO_TASK__STEP_METHODDEF
1754 _ASYNCIO_TASK__REPR_INFO_METHODDEF
1755 {NULL, NULL} /* Sentinel */
1756};
1757
1758static PyGetSetDef TaskType_getsetlist[] = {
1759 FUTURE_COMMON_GETSETLIST
1760 {"_log_destroy_pending", (getter)TaskObj_get_log_destroy_pending,
1761 (setter)TaskObj_set_log_destroy_pending, NULL},
1762 {"_must_cancel", (getter)TaskObj_get_must_cancel, NULL, NULL},
1763 {"_coro", (getter)TaskObj_get_coro, NULL, NULL},
1764 {"_fut_waiter", (getter)TaskObj_get_fut_waiter, NULL, NULL},
1765 {NULL} /* Sentinel */
1766};
1767
1768static PyTypeObject TaskType = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02001769 PyVarObject_HEAD_INIT(NULL, 0)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001770 "_asyncio.Task",
1771 sizeof(TaskObj), /* tp_basicsize */
1772 .tp_base = &FutureType,
1773 .tp_dealloc = TaskObj_dealloc,
1774 .tp_as_async = &FutureType_as_async,
1775 .tp_repr = (reprfunc)FutureObj_repr,
1776 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE
1777 | Py_TPFLAGS_HAVE_FINALIZE,
1778 .tp_doc = _asyncio_Task___init____doc__,
1779 .tp_traverse = (traverseproc)TaskObj_traverse,
1780 .tp_clear = (inquiry)TaskObj_clear,
1781 .tp_weaklistoffset = offsetof(TaskObj, task_weakreflist),
1782 .tp_iter = (getiterfunc)future_new_iter,
1783 .tp_methods = TaskType_methods,
1784 .tp_getset = TaskType_getsetlist,
1785 .tp_dictoffset = offsetof(TaskObj, dict),
1786 .tp_init = (initproc)_asyncio_Task___init__,
1787 .tp_new = PyType_GenericNew,
1788 .tp_finalize = (destructor)TaskObj_finalize,
1789};
1790
1791#define Task_CheckExact(obj) (Py_TYPE(obj) == &TaskType)
1792
1793static void
1794TaskObj_dealloc(PyObject *self)
1795{
1796 TaskObj *task = (TaskObj *)self;
1797
1798 if (Task_CheckExact(self)) {
1799 /* When fut is subclass of Task, finalizer is called from
1800 * subtype_dealloc.
1801 */
1802 if (PyObject_CallFinalizerFromDealloc(self) < 0) {
1803 // resurrected.
1804 return;
1805 }
1806 }
1807
1808 if (task->task_weakreflist != NULL) {
1809 PyObject_ClearWeakRefs(self);
1810 }
1811
1812 (void)TaskObj_clear(task);
1813 Py_TYPE(task)->tp_free(task);
1814}
1815
1816static inline PyObject *
1817task_call_wakeup(TaskObj *task, PyObject *fut)
1818{
1819 if (Task_CheckExact(task)) {
1820 return task_wakeup(task, fut);
1821 }
1822 else {
1823 /* `task` is a subclass of Task */
1824 return _PyObject_CallMethodId(
1825 (PyObject*)task, &PyId__wakeup, "O", fut, NULL);
1826 }
1827}
1828
1829static inline PyObject *
1830task_call_step(TaskObj *task, PyObject *arg)
1831{
1832 if (Task_CheckExact(task)) {
1833 return task_step(task, arg);
1834 }
1835 else {
1836 /* `task` is a subclass of Task */
1837 if (arg == NULL) {
1838 arg = Py_None;
1839 }
1840 return _PyObject_CallMethodId(
1841 (PyObject*)task, &PyId__step, "O", arg, NULL);
1842 }
1843}
1844
1845static int
1846task_call_step_soon(TaskObj *task, PyObject *arg)
1847{
1848 PyObject *handle;
1849
1850 PyObject *cb = TaskSendMethWrapper_new(task, arg);
1851 if (cb == NULL) {
1852 return -1;
1853 }
1854
1855 handle = _PyObject_CallMethodId(
1856 task->task_loop, &PyId_call_soon, "O", cb, NULL);
1857 Py_DECREF(cb);
1858 if (handle == NULL) {
1859 return -1;
1860 }
1861
1862 Py_DECREF(handle);
1863 return 0;
1864}
1865
1866static PyObject *
1867task_set_error_soon(TaskObj *task, PyObject *et, const char *format, ...)
1868{
1869 PyObject* msg;
1870
1871 va_list vargs;
1872#ifdef HAVE_STDARG_PROTOTYPES
1873 va_start(vargs, format);
1874#else
1875 va_start(vargs);
1876#endif
1877 msg = PyUnicode_FromFormatV(format, vargs);
1878 va_end(vargs);
1879
1880 if (msg == NULL) {
1881 return NULL;
1882 }
1883
1884 PyObject *e = PyObject_CallFunctionObjArgs(et, msg, NULL);
1885 Py_DECREF(msg);
1886 if (e == NULL) {
1887 return NULL;
1888 }
1889
1890 if (task_call_step_soon(task, e) == -1) {
1891 Py_DECREF(e);
1892 return NULL;
1893 }
1894
1895 Py_DECREF(e);
1896 Py_RETURN_NONE;
1897}
1898
1899static PyObject *
1900task_step_impl(TaskObj *task, PyObject *exc)
1901{
1902 int res;
1903 int clear_exc = 0;
1904 PyObject *result = NULL;
1905 PyObject *coro = task->task_coro;
1906 PyObject *o;
1907
1908 if (task->task_state != STATE_PENDING) {
1909 PyErr_Format(PyExc_AssertionError,
1910 "_step(): already done: %R %R",
1911 task,
1912 exc ? exc : Py_None);
INADA Naokic411a7d2016-10-18 11:48:14 +09001913 goto fail;
1914 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001915
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001916 if (task->task_must_cancel) {
1917 assert(exc != Py_None);
1918
1919 if (exc) {
1920 /* Check if exc is a CancelledError */
1921 res = PyObject_IsInstance(exc, asyncio_CancelledError);
1922 if (res == -1) {
1923 /* An error occurred, abort */
1924 goto fail;
1925 }
1926 if (res == 0) {
1927 /* exc is not CancelledError; reset it to NULL */
1928 exc = NULL;
1929 }
1930 }
1931
1932 if (!exc) {
1933 /* exc was not a CancelledError */
1934 exc = PyObject_CallFunctionObjArgs(asyncio_CancelledError, NULL);
1935 if (!exc) {
1936 goto fail;
1937 }
1938 clear_exc = 1;
1939 }
1940
1941 task->task_must_cancel = 0;
1942 }
1943
1944 Py_CLEAR(task->task_fut_waiter);
1945
1946 if (exc == NULL) {
1947 if (PyGen_CheckExact(coro) || PyCoro_CheckExact(coro)) {
1948 result = _PyGen_Send((PyGenObject*)coro, Py_None);
1949 }
1950 else {
1951 result = _PyObject_CallMethodIdObjArgs(
1952 coro, &PyId_send, Py_None, NULL);
1953 }
1954 }
1955 else {
1956 result = _PyObject_CallMethodIdObjArgs(
1957 coro, &PyId_throw, exc, NULL);
1958 if (clear_exc) {
1959 /* We created 'exc' during this call */
1960 Py_CLEAR(exc);
1961 }
1962 }
1963
1964 if (result == NULL) {
1965 PyObject *et, *ev, *tb;
1966
1967 if (_PyGen_FetchStopIterationValue(&o) == 0) {
1968 /* The error is StopIteration and that means that
1969 the underlying coroutine has resolved */
1970 PyObject *res = future_set_result((FutureObj*)task, o);
1971 Py_DECREF(o);
1972 if (res == NULL) {
1973 return NULL;
1974 }
1975 Py_DECREF(res);
1976 Py_RETURN_NONE;
1977 }
1978
1979 if (PyErr_ExceptionMatches(asyncio_CancelledError)) {
1980 /* CancelledError */
1981 PyErr_Clear();
1982 return future_cancel((FutureObj*)task);
1983 }
1984
1985 /* Some other exception; pop it and call Task.set_exception() */
1986 PyErr_Fetch(&et, &ev, &tb);
1987 assert(et);
1988 if (!ev || !PyObject_TypeCheck(ev, (PyTypeObject *) et)) {
1989 PyErr_NormalizeException(&et, &ev, &tb);
1990 }
1991 o = future_set_exception((FutureObj*)task, ev);
1992 if (!o) {
1993 /* An exception in Task.set_exception() */
1994 Py_XDECREF(et);
1995 Py_XDECREF(tb);
1996 Py_XDECREF(ev);
1997 goto fail;
1998 }
1999 assert(o == Py_None);
2000 Py_CLEAR(o);
2001
2002 if (!PyErr_GivenExceptionMatches(et, PyExc_Exception)) {
2003 /* We've got a BaseException; re-raise it */
2004 PyErr_Restore(et, ev, tb);
2005 goto fail;
2006 }
2007
2008 Py_XDECREF(et);
2009 Py_XDECREF(tb);
2010 Py_XDECREF(ev);
2011
2012 Py_RETURN_NONE;
2013 }
2014
2015 if (result == (PyObject*)task) {
2016 /* We have a task that wants to await on itself */
2017 goto self_await;
2018 }
2019
2020 /* Check if `result` is FutureObj or TaskObj (and not a subclass) */
2021 if (Future_CheckExact(result) || Task_CheckExact(result)) {
2022 PyObject *wrapper;
2023 PyObject *res;
2024 FutureObj *fut = (FutureObj*)result;
2025
2026 /* Check if `result` future is attached to a different loop */
2027 if (fut->fut_loop != task->task_loop) {
2028 goto different_loop;
2029 }
2030
2031 if (fut->fut_blocking) {
2032 fut->fut_blocking = 0;
2033
2034 /* result.add_done_callback(task._wakeup) */
2035 wrapper = TaskWakeupMethWrapper_new(task);
2036 if (wrapper == NULL) {
2037 goto fail;
2038 }
2039 res = future_add_done_callback((FutureObj*)result, wrapper);
2040 Py_DECREF(wrapper);
2041 if (res == NULL) {
2042 goto fail;
2043 }
2044 Py_DECREF(res);
2045
2046 /* task._fut_waiter = result */
2047 task->task_fut_waiter = result; /* no incref is necessary */
2048
2049 if (task->task_must_cancel) {
2050 PyObject *r;
2051 r = future_cancel(fut);
2052 if (r == NULL) {
2053 return NULL;
2054 }
2055 if (r == Py_True) {
2056 task->task_must_cancel = 0;
2057 }
2058 Py_DECREF(r);
2059 }
2060
2061 Py_RETURN_NONE;
2062 }
2063 else {
2064 goto yield_insteadof_yf;
2065 }
2066 }
2067
2068 /* Check if `result` is a Future-compatible object */
2069 o = PyObject_GetAttrString(result, "_asyncio_future_blocking");
2070 if (o == NULL) {
2071 if (PyErr_ExceptionMatches(PyExc_AttributeError)) {
2072 PyErr_Clear();
2073 }
2074 else {
2075 goto fail;
2076 }
2077 }
2078 else {
2079 if (o == Py_None) {
2080 Py_CLEAR(o);
2081 }
2082 else {
2083 /* `result` is a Future-compatible object */
2084 PyObject *wrapper;
2085 PyObject *res;
2086
2087 int blocking = PyObject_IsTrue(o);
2088 Py_CLEAR(o);
2089 if (blocking < 0) {
2090 goto fail;
2091 }
2092
2093 /* Check if `result` future is attached to a different loop */
2094 PyObject *oloop = PyObject_GetAttrString(result, "_loop");
2095 if (oloop == NULL) {
2096 goto fail;
2097 }
2098 if (oloop != task->task_loop) {
2099 Py_DECREF(oloop);
2100 goto different_loop;
2101 }
2102 else {
2103 Py_DECREF(oloop);
2104 }
2105
2106 if (blocking) {
2107 /* result._asyncio_future_blocking = False */
2108 if (PyObject_SetAttrString(
2109 result, "_asyncio_future_blocking", Py_False) == -1) {
2110 goto fail;
2111 }
2112
2113 /* result.add_done_callback(task._wakeup) */
2114 wrapper = TaskWakeupMethWrapper_new(task);
2115 if (wrapper == NULL) {
2116 goto fail;
2117 }
2118 res = _PyObject_CallMethodId(
2119 result, &PyId_add_done_callback, "O", wrapper, NULL);
2120 Py_DECREF(wrapper);
2121 if (res == NULL) {
2122 goto fail;
2123 }
2124 Py_DECREF(res);
2125
2126 /* task._fut_waiter = result */
2127 task->task_fut_waiter = result; /* no incref is necessary */
2128
2129 if (task->task_must_cancel) {
2130 PyObject *r;
2131 int is_true;
2132 r = _PyObject_CallMethodId(result, &PyId_cancel, NULL);
2133 if (r == NULL) {
2134 return NULL;
2135 }
2136 is_true = PyObject_IsTrue(r);
2137 Py_DECREF(r);
2138 if (is_true < 0) {
2139 return NULL;
2140 }
2141 else if (is_true) {
2142 task->task_must_cancel = 0;
2143 }
2144 }
2145
2146 Py_RETURN_NONE;
2147 }
2148 else {
2149 goto yield_insteadof_yf;
2150 }
2151 }
2152 }
2153
2154 /* Check if `result` is None */
2155 if (result == Py_None) {
2156 /* Bare yield relinquishes control for one event loop iteration. */
2157 if (task_call_step_soon(task, NULL)) {
2158 goto fail;
2159 }
2160 return result;
2161 }
2162
2163 /* Check if `result` is a generator */
2164 o = PyObject_CallFunctionObjArgs(inspect_isgenerator, result, NULL);
2165 if (o == NULL) {
2166 /* An exception in inspect.isgenerator */
2167 goto fail;
2168 }
2169 res = PyObject_IsTrue(o);
2170 Py_CLEAR(o);
2171 if (res == -1) {
2172 /* An exception while checking if 'val' is True */
2173 goto fail;
2174 }
2175 if (res == 1) {
2176 /* `result` is a generator */
2177 PyObject *ret;
2178 ret = task_set_error_soon(
2179 task, PyExc_RuntimeError,
2180 "yield was used instead of yield from for "
2181 "generator in task %R with %S", task, result);
2182 Py_DECREF(result);
2183 return ret;
2184 }
2185
2186 /* The `result` is none of the above */
2187 Py_DECREF(result);
2188 return task_set_error_soon(
2189 task, PyExc_RuntimeError, "Task got bad yield: %R", result);
2190
2191self_await:
2192 o = task_set_error_soon(
2193 task, PyExc_RuntimeError,
2194 "Task cannot await on itself: %R", task);
2195 Py_DECREF(result);
2196 return o;
2197
2198yield_insteadof_yf:
2199 o = task_set_error_soon(
2200 task, PyExc_RuntimeError,
2201 "yield was used instead of yield from "
2202 "in task %R with %R",
2203 task, result);
2204 Py_DECREF(result);
2205 return o;
2206
2207different_loop:
2208 o = task_set_error_soon(
2209 task, PyExc_RuntimeError,
2210 "Task %R got Future %R attached to a different loop",
2211 task, result);
2212 Py_DECREF(result);
2213 return o;
2214
2215fail:
2216 Py_XDECREF(result);
2217 return NULL;
2218}
2219
2220static PyObject *
2221task_step(TaskObj *task, PyObject *exc)
2222{
2223 PyObject *res;
2224 PyObject *ot;
2225
Yury Selivanov684ef2c2016-10-28 19:01:21 -04002226 if (PyDict_SetItem(current_tasks,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002227 task->task_loop, (PyObject*)task) == -1)
2228 {
2229 return NULL;
2230 }
2231
2232 res = task_step_impl(task, exc);
2233
2234 if (res == NULL) {
2235 PyObject *et, *ev, *tb;
2236 PyErr_Fetch(&et, &ev, &tb);
2237 ot = _PyDict_Pop(current_tasks, task->task_loop, NULL);
2238 if (ot == NULL) {
2239 Py_XDECREF(et);
2240 Py_XDECREF(tb);
2241 Py_XDECREF(ev);
2242 return NULL;
2243 }
2244 Py_DECREF(ot);
2245 PyErr_Restore(et, ev, tb);
2246 return NULL;
2247 }
2248 else {
2249 ot = _PyDict_Pop(current_tasks, task->task_loop, NULL);
2250 if (ot == NULL) {
2251 Py_DECREF(res);
2252 return NULL;
2253 }
2254 else {
2255 Py_DECREF(ot);
2256 return res;
2257 }
2258 }
2259}
2260
2261static PyObject *
2262task_wakeup(TaskObj *task, PyObject *o)
2263{
2264 assert(o);
2265
2266 if (Future_CheckExact(o) || Task_CheckExact(o)) {
2267 PyObject *fut_result = NULL;
2268 int res = future_get_result((FutureObj*)o, &fut_result);
2269 PyObject *result;
2270
2271 switch(res) {
2272 case -1:
2273 assert(fut_result == NULL);
2274 return NULL;
2275 case 0:
2276 Py_DECREF(fut_result);
2277 return task_call_step(task, NULL);
2278 default:
2279 assert(res == 1);
2280 result = task_call_step(task, fut_result);
2281 Py_DECREF(fut_result);
2282 return result;
2283 }
2284 }
2285
2286 PyObject *fut_result = PyObject_CallMethod(o, "result", NULL);
2287 if (fut_result == NULL) {
2288 PyObject *et, *ev, *tb;
2289 PyObject *res;
2290
2291 PyErr_Fetch(&et, &ev, &tb);
2292 if (!ev || !PyObject_TypeCheck(ev, (PyTypeObject *) et)) {
2293 PyErr_NormalizeException(&et, &ev, &tb);
2294 }
2295
2296 res = task_call_step(task, ev);
2297
2298 Py_XDECREF(et);
2299 Py_XDECREF(tb);
2300 Py_XDECREF(ev);
2301
2302 return res;
2303 }
2304 else {
2305 Py_DECREF(fut_result);
2306 return task_call_step(task, NULL);
2307 }
2308}
2309
2310
2311/*********************** Module **************************/
2312
2313
2314static void
2315module_free(void *m)
2316{
2317 Py_CLEAR(current_tasks);
2318 Py_CLEAR(all_tasks);
2319 Py_CLEAR(traceback_extract_stack);
2320 Py_CLEAR(asyncio_get_event_loop);
2321 Py_CLEAR(asyncio_future_repr_info_func);
2322 Py_CLEAR(asyncio_task_repr_info_func);
2323 Py_CLEAR(asyncio_task_get_stack_func);
2324 Py_CLEAR(asyncio_task_print_stack_func);
2325 Py_CLEAR(asyncio_InvalidStateError);
2326 Py_CLEAR(asyncio_CancelledError);
2327 Py_CLEAR(inspect_isgenerator);
2328}
2329
2330static int
2331module_init(void)
2332{
2333 PyObject *module = NULL;
2334 PyObject *cls;
2335
2336#define WITH_MOD(NAME) \
2337 Py_CLEAR(module); \
2338 module = PyImport_ImportModule(NAME); \
2339 if (module == NULL) { \
2340 return -1; \
2341 }
2342
2343#define GET_MOD_ATTR(VAR, NAME) \
2344 VAR = PyObject_GetAttrString(module, NAME); \
2345 if (VAR == NULL) { \
2346 goto fail; \
2347 }
2348
2349 WITH_MOD("asyncio.events")
2350 GET_MOD_ATTR(asyncio_get_event_loop, "get_event_loop")
2351
2352 WITH_MOD("asyncio.base_futures")
2353 GET_MOD_ATTR(asyncio_future_repr_info_func, "_future_repr_info")
2354 GET_MOD_ATTR(asyncio_InvalidStateError, "InvalidStateError")
2355 GET_MOD_ATTR(asyncio_CancelledError, "CancelledError")
2356
2357 WITH_MOD("asyncio.base_tasks")
2358 GET_MOD_ATTR(asyncio_task_repr_info_func, "_task_repr_info")
2359 GET_MOD_ATTR(asyncio_task_get_stack_func, "_task_get_stack")
2360 GET_MOD_ATTR(asyncio_task_print_stack_func, "_task_print_stack")
2361
2362 WITH_MOD("inspect")
2363 GET_MOD_ATTR(inspect_isgenerator, "isgenerator")
2364
2365 WITH_MOD("traceback")
2366 GET_MOD_ATTR(traceback_extract_stack, "extract_stack")
2367
2368 WITH_MOD("weakref")
2369 GET_MOD_ATTR(cls, "WeakSet")
2370 all_tasks = PyObject_CallObject(cls, NULL);
2371 Py_CLEAR(cls);
2372 if (all_tasks == NULL) {
INADA Naokic411a7d2016-10-18 11:48:14 +09002373 goto fail;
2374 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09002375
Yury Selivanov684ef2c2016-10-28 19:01:21 -04002376 current_tasks = PyDict_New();
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002377 if (current_tasks == NULL) {
2378 goto fail;
2379 }
2380
2381 Py_CLEAR(module);
INADA Naokic411a7d2016-10-18 11:48:14 +09002382 return 0;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09002383
INADA Naokic411a7d2016-10-18 11:48:14 +09002384fail:
INADA Naokic411a7d2016-10-18 11:48:14 +09002385 Py_CLEAR(module);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002386 module_free(NULL);
INADA Naokic411a7d2016-10-18 11:48:14 +09002387 return -1;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09002388
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002389#undef WITH_MOD
2390#undef GET_MOD_ATTR
2391}
INADA Naoki9e4e38e2016-10-09 14:44:47 +09002392
INADA Naokic411a7d2016-10-18 11:48:14 +09002393PyDoc_STRVAR(module_doc, "Accelerator module for asyncio");
INADA Naoki9e4e38e2016-10-09 14:44:47 +09002394
INADA Naoki9f2ce252016-10-15 15:39:19 +09002395static struct PyModuleDef _asynciomodule = {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09002396 PyModuleDef_HEAD_INIT, /* m_base */
INADA Naoki9f2ce252016-10-15 15:39:19 +09002397 "_asyncio", /* m_name */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09002398 module_doc, /* m_doc */
2399 -1, /* m_size */
INADA Naokic411a7d2016-10-18 11:48:14 +09002400 NULL, /* m_methods */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09002401 NULL, /* m_slots */
2402 NULL, /* m_traverse */
2403 NULL, /* m_clear */
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002404 (freefunc)module_free /* m_free */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09002405};
2406
2407
2408PyMODINIT_FUNC
INADA Naoki9f2ce252016-10-15 15:39:19 +09002409PyInit__asyncio(void)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09002410{
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002411 if (module_init() < 0) {
INADA Naokic411a7d2016-10-18 11:48:14 +09002412 return NULL;
2413 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09002414 if (PyType_Ready(&FutureType) < 0) {
2415 return NULL;
2416 }
2417 if (PyType_Ready(&FutureIterType) < 0) {
2418 return NULL;
2419 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002420 if (PyType_Ready(&TaskSendMethWrapper_Type) < 0) {
2421 return NULL;
2422 }
2423 if(PyType_Ready(&TaskWakeupMethWrapper_Type) < 0) {
2424 return NULL;
2425 }
2426 if (PyType_Ready(&TaskType) < 0) {
2427 return NULL;
2428 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09002429
INADA Naoki9f2ce252016-10-15 15:39:19 +09002430 PyObject *m = PyModule_Create(&_asynciomodule);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09002431 if (m == NULL) {
2432 return NULL;
2433 }
2434
2435 Py_INCREF(&FutureType);
2436 if (PyModule_AddObject(m, "Future", (PyObject *)&FutureType) < 0) {
2437 Py_DECREF(&FutureType);
2438 return NULL;
2439 }
2440
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002441 Py_INCREF(&TaskType);
2442 if (PyModule_AddObject(m, "Task", (PyObject *)&TaskType) < 0) {
2443 Py_DECREF(&TaskType);
2444 return NULL;
2445 }
2446
INADA Naoki9e4e38e2016-10-09 14:44:47 +09002447 return m;
2448}