blob: fff90468a5927c1d367a05124451df4d54ca934e [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;
Benjamin Peterson996fc1f2016-11-14 00:15:44 -08001034 } else if (tb != NULL && !PyTraceBack_Check(tb)) {
1035 PyErr_SetString(PyExc_TypeError, "throw() third argument must be a traceback");
1036 return NULL;
1037 }
1038
1039 Py_INCREF(type);
1040 Py_XINCREF(val);
1041 Py_XINCREF(tb);
1042
1043 if (PyExceptionClass_Check(type)) {
1044 PyErr_NormalizeException(&type, &val, &tb);
Yury Selivanovc2c8fe12016-12-01 11:36:22 -05001045 /* No need to call PyException_SetTraceback since we'll be calling
1046 PyErr_Restore for `type`, `val`, and `tb`. */
Benjamin Peterson996fc1f2016-11-14 00:15:44 -08001047 } else if (PyExceptionInstance_Check(type)) {
1048 if (val) {
1049 PyErr_SetString(PyExc_TypeError,
1050 "instance exception may not have a separate value");
1051 goto fail;
1052 }
1053 val = type;
1054 type = PyExceptionInstance_Class(type);
1055 Py_INCREF(type);
1056 if (tb == NULL)
1057 tb = PyException_GetTraceback(val);
1058 } else {
1059 PyErr_SetString(PyExc_TypeError,
1060 "exceptions must be classes deriving BaseException or "
1061 "instances of such a class");
1062 goto fail;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001063 }
1064
1065 Py_CLEAR(self->future);
1066
Benjamin Peterson996fc1f2016-11-14 00:15:44 -08001067 PyErr_Restore(type, val, tb);
1068
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001069 return FutureIter_iternext(self);
Benjamin Peterson996fc1f2016-11-14 00:15:44 -08001070
1071 fail:
1072 Py_DECREF(type);
1073 Py_XDECREF(val);
1074 Py_XDECREF(tb);
1075 return NULL;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001076}
1077
1078static PyObject *
1079FutureIter_close(futureiterobject *self, PyObject *arg)
1080{
1081 Py_CLEAR(self->future);
1082 Py_RETURN_NONE;
1083}
1084
1085static int
1086FutureIter_traverse(futureiterobject *it, visitproc visit, void *arg)
1087{
1088 Py_VISIT(it->future);
1089 return 0;
1090}
1091
1092static PyMethodDef FutureIter_methods[] = {
1093 {"send", (PyCFunction)FutureIter_send, METH_O, NULL},
1094 {"throw", (PyCFunction)FutureIter_throw, METH_VARARGS, NULL},
1095 {"close", (PyCFunction)FutureIter_close, METH_NOARGS, NULL},
1096 {NULL, NULL} /* Sentinel */
1097};
1098
1099static PyTypeObject FutureIterType = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02001100 PyVarObject_HEAD_INIT(NULL, 0)
INADA Naoki9f2ce252016-10-15 15:39:19 +09001101 "_asyncio.FutureIter",
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001102 .tp_basicsize = sizeof(futureiterobject),
1103 .tp_itemsize = 0,
1104 .tp_dealloc = (destructor)FutureIter_dealloc,
1105 .tp_getattro = PyObject_GenericGetAttr,
1106 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
1107 .tp_traverse = (traverseproc)FutureIter_traverse,
1108 .tp_iter = PyObject_SelfIter,
1109 .tp_iternext = (iternextfunc)FutureIter_iternext,
1110 .tp_methods = FutureIter_methods,
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001111};
1112
1113static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001114future_new_iter(PyObject *fut)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001115{
1116 futureiterobject *it;
1117
1118 if (!PyObject_TypeCheck(fut, &FutureType)) {
1119 PyErr_BadInternalCall();
1120 return NULL;
1121 }
1122 it = PyObject_GC_New(futureiterobject, &FutureIterType);
1123 if (it == NULL) {
1124 return NULL;
1125 }
1126 Py_INCREF(fut);
1127 it->future = (FutureObj*)fut;
INADA Naoki1be427b2016-10-11 02:12:34 +09001128 PyObject_GC_Track(it);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001129 return (PyObject*)it;
1130}
1131
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001132
1133/*********************** Task **************************/
1134
1135
1136/*[clinic input]
1137class _asyncio.Task "TaskObj *" "&Task_Type"
1138[clinic start generated code]*/
1139/*[clinic end generated code: output=da39a3ee5e6b4b0d input=719dcef0fcc03b37]*/
1140
1141static int task_call_step_soon(TaskObj *, PyObject *);
1142static inline PyObject * task_call_wakeup(TaskObj *, PyObject *);
1143static inline PyObject * task_call_step(TaskObj *, PyObject *);
1144static PyObject * task_wakeup(TaskObj *, PyObject *);
1145static PyObject * task_step(TaskObj *, PyObject *);
1146
1147/* ----- Task._step wrapper */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001148
INADA Naokic411a7d2016-10-18 11:48:14 +09001149static int
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001150TaskSendMethWrapper_clear(TaskSendMethWrapper *o)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001151{
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001152 Py_CLEAR(o->sw_task);
1153 Py_CLEAR(o->sw_arg);
1154 return 0;
1155}
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001156
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001157static void
1158TaskSendMethWrapper_dealloc(TaskSendMethWrapper *o)
1159{
1160 PyObject_GC_UnTrack(o);
1161 (void)TaskSendMethWrapper_clear(o);
1162 Py_TYPE(o)->tp_free(o);
1163}
1164
1165static PyObject *
1166TaskSendMethWrapper_call(TaskSendMethWrapper *o,
1167 PyObject *args, PyObject *kwds)
1168{
1169 return task_call_step(o->sw_task, o->sw_arg);
1170}
1171
1172static int
1173TaskSendMethWrapper_traverse(TaskSendMethWrapper *o,
1174 visitproc visit, void *arg)
1175{
1176 Py_VISIT(o->sw_task);
1177 Py_VISIT(o->sw_arg);
1178 return 0;
1179}
1180
1181static PyObject *
1182TaskSendMethWrapper_get___self__(TaskSendMethWrapper *o)
1183{
1184 if (o->sw_task) {
1185 Py_INCREF(o->sw_task);
1186 return (PyObject*)o->sw_task;
1187 }
1188 Py_RETURN_NONE;
1189}
1190
1191static PyGetSetDef TaskSendMethWrapper_getsetlist[] = {
1192 {"__self__", (getter)TaskSendMethWrapper_get___self__, NULL, NULL},
1193 {NULL} /* Sentinel */
1194};
1195
1196PyTypeObject TaskSendMethWrapper_Type = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02001197 PyVarObject_HEAD_INIT(NULL, 0)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001198 "TaskSendMethWrapper",
1199 .tp_basicsize = sizeof(TaskSendMethWrapper),
1200 .tp_itemsize = 0,
1201 .tp_getset = TaskSendMethWrapper_getsetlist,
1202 .tp_dealloc = (destructor)TaskSendMethWrapper_dealloc,
1203 .tp_call = (ternaryfunc)TaskSendMethWrapper_call,
1204 .tp_getattro = PyObject_GenericGetAttr,
1205 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
1206 .tp_traverse = (traverseproc)TaskSendMethWrapper_traverse,
1207 .tp_clear = (inquiry)TaskSendMethWrapper_clear,
1208};
1209
1210static PyObject *
1211TaskSendMethWrapper_new(TaskObj *task, PyObject *arg)
1212{
1213 TaskSendMethWrapper *o;
1214 o = PyObject_GC_New(TaskSendMethWrapper, &TaskSendMethWrapper_Type);
1215 if (o == NULL) {
1216 return NULL;
1217 }
1218
1219 Py_INCREF(task);
1220 o->sw_task = task;
1221
1222 Py_XINCREF(arg);
1223 o->sw_arg = arg;
1224
1225 PyObject_GC_Track(o);
1226 return (PyObject*) o;
1227}
1228
1229/* ----- Task._wakeup wrapper */
1230
1231static PyObject *
1232TaskWakeupMethWrapper_call(TaskWakeupMethWrapper *o,
1233 PyObject *args, PyObject *kwds)
1234{
1235 PyObject *fut;
1236
1237 if (!PyArg_ParseTuple(args, "O|", &fut)) {
1238 return NULL;
1239 }
1240
1241 return task_call_wakeup(o->ww_task, fut);
1242}
1243
1244static int
1245TaskWakeupMethWrapper_clear(TaskWakeupMethWrapper *o)
1246{
1247 Py_CLEAR(o->ww_task);
1248 return 0;
1249}
1250
1251static int
1252TaskWakeupMethWrapper_traverse(TaskWakeupMethWrapper *o,
1253 visitproc visit, void *arg)
1254{
1255 Py_VISIT(o->ww_task);
1256 return 0;
1257}
1258
1259static void
1260TaskWakeupMethWrapper_dealloc(TaskWakeupMethWrapper *o)
1261{
1262 PyObject_GC_UnTrack(o);
1263 (void)TaskWakeupMethWrapper_clear(o);
1264 Py_TYPE(o)->tp_free(o);
1265}
1266
1267PyTypeObject TaskWakeupMethWrapper_Type = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02001268 PyVarObject_HEAD_INIT(NULL, 0)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001269 "TaskWakeupMethWrapper",
1270 .tp_basicsize = sizeof(TaskWakeupMethWrapper),
1271 .tp_itemsize = 0,
1272 .tp_dealloc = (destructor)TaskWakeupMethWrapper_dealloc,
1273 .tp_call = (ternaryfunc)TaskWakeupMethWrapper_call,
1274 .tp_getattro = PyObject_GenericGetAttr,
1275 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
1276 .tp_traverse = (traverseproc)TaskWakeupMethWrapper_traverse,
1277 .tp_clear = (inquiry)TaskWakeupMethWrapper_clear,
1278};
1279
1280static PyObject *
1281TaskWakeupMethWrapper_new(TaskObj *task)
1282{
1283 TaskWakeupMethWrapper *o;
1284 o = PyObject_GC_New(TaskWakeupMethWrapper, &TaskWakeupMethWrapper_Type);
1285 if (o == NULL) {
1286 return NULL;
1287 }
1288
1289 Py_INCREF(task);
1290 o->ww_task = task;
1291
1292 PyObject_GC_Track(o);
1293 return (PyObject*) o;
1294}
1295
1296/* ----- Task */
1297
1298/*[clinic input]
1299_asyncio.Task.__init__
1300
1301 coro: 'O'
1302 *
1303 loop: 'O' = NULL
1304
1305A coroutine wrapped in a Future.
1306[clinic start generated code]*/
1307
1308static int
1309_asyncio_Task___init___impl(TaskObj *self, PyObject *coro, PyObject *loop)
1310/*[clinic end generated code: output=9f24774c2287fc2f input=71d8d28c201a18cd]*/
1311{
1312 PyObject *res;
1313 _Py_IDENTIFIER(add);
1314
1315 if (future_init((FutureObj*)self, loop)) {
INADA Naokic411a7d2016-10-18 11:48:14 +09001316 return -1;
1317 }
INADA Naokic411a7d2016-10-18 11:48:14 +09001318
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001319 self->task_fut_waiter = NULL;
1320 self->task_must_cancel = 0;
1321 self->task_log_destroy_pending = 1;
INADA Naokic411a7d2016-10-18 11:48:14 +09001322
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001323 Py_INCREF(coro);
1324 self->task_coro = coro;
1325
1326 if (task_call_step_soon(self, NULL)) {
1327 return -1;
INADA Naokic411a7d2016-10-18 11:48:14 +09001328 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001329
Victor Stinnercb2128c2016-12-15 09:05:11 +01001330 res = _PyObject_CallMethodIdObjArgs(all_tasks, &PyId_add, self, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001331 if (res == NULL) {
1332 return -1;
1333 }
1334 Py_DECREF(res);
1335
1336 return 0;
1337}
1338
1339static int
1340TaskObj_clear(TaskObj *task)
1341{
1342 (void)FutureObj_clear((FutureObj*) task);
1343 Py_CLEAR(task->task_coro);
1344 Py_CLEAR(task->task_fut_waiter);
1345 return 0;
1346}
1347
1348static int
1349TaskObj_traverse(TaskObj *task, visitproc visit, void *arg)
1350{
1351 Py_VISIT(task->task_coro);
1352 Py_VISIT(task->task_fut_waiter);
1353 (void)FutureObj_traverse((FutureObj*) task, visit, arg);
1354 return 0;
1355}
1356
1357static PyObject *
1358TaskObj_get_log_destroy_pending(TaskObj *task)
1359{
1360 if (task->task_log_destroy_pending) {
1361 Py_RETURN_TRUE;
1362 }
1363 else {
1364 Py_RETURN_FALSE;
1365 }
1366}
1367
1368static int
1369TaskObj_set_log_destroy_pending(TaskObj *task, PyObject *val)
1370{
1371 int is_true = PyObject_IsTrue(val);
1372 if (is_true < 0) {
1373 return -1;
1374 }
1375 task->task_log_destroy_pending = is_true;
1376 return 0;
1377}
1378
1379static PyObject *
1380TaskObj_get_must_cancel(TaskObj *task)
1381{
1382 if (task->task_must_cancel) {
1383 Py_RETURN_TRUE;
1384 }
1385 else {
1386 Py_RETURN_FALSE;
1387 }
1388}
1389
1390static PyObject *
1391TaskObj_get_coro(TaskObj *task)
1392{
1393 if (task->task_coro) {
1394 Py_INCREF(task->task_coro);
1395 return task->task_coro;
1396 }
1397
1398 Py_RETURN_NONE;
1399}
1400
1401static PyObject *
1402TaskObj_get_fut_waiter(TaskObj *task)
1403{
1404 if (task->task_fut_waiter) {
1405 Py_INCREF(task->task_fut_waiter);
1406 return task->task_fut_waiter;
1407 }
1408
1409 Py_RETURN_NONE;
1410}
1411
1412/*[clinic input]
1413@classmethod
1414_asyncio.Task.current_task
1415
1416 loop: 'O' = NULL
1417
1418Return the currently running task in an event loop or None.
1419
1420By default the current task for the current event loop is returned.
1421
1422None is returned when called not in the context of a Task.
1423[clinic start generated code]*/
1424
1425static PyObject *
1426_asyncio_Task_current_task_impl(PyTypeObject *type, PyObject *loop)
1427/*[clinic end generated code: output=99fbe7332c516e03 input=cd784537f02cf833]*/
1428{
1429 PyObject *res;
1430
1431 if (loop == NULL) {
1432 loop = PyObject_CallObject(asyncio_get_event_loop, NULL);
1433 if (loop == NULL) {
1434 return NULL;
1435 }
1436
Yury Selivanov684ef2c2016-10-28 19:01:21 -04001437 res = PyDict_GetItem(current_tasks, loop);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001438 Py_DECREF(loop);
1439 }
1440 else {
Yury Selivanov684ef2c2016-10-28 19:01:21 -04001441 res = PyDict_GetItem(current_tasks, loop);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001442 }
1443
1444 if (res == NULL) {
1445 Py_RETURN_NONE;
1446 }
1447 else {
1448 Py_INCREF(res);
1449 return res;
1450 }
1451}
1452
1453static PyObject *
1454task_all_tasks(PyObject *loop)
1455{
1456 PyObject *task;
1457 PyObject *task_loop;
1458 PyObject *set;
1459 PyObject *iter;
1460
1461 assert(loop != NULL);
1462
1463 set = PySet_New(NULL);
1464 if (set == NULL) {
1465 return NULL;
1466 }
1467
1468 iter = PyObject_GetIter(all_tasks);
1469 if (iter == NULL) {
INADA Naokic411a7d2016-10-18 11:48:14 +09001470 goto fail;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001471 }
1472
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001473 while ((task = PyIter_Next(iter))) {
1474 task_loop = PyObject_GetAttrString(task, "_loop");
1475 if (task_loop == NULL) {
1476 Py_DECREF(task);
1477 goto fail;
1478 }
1479 if (task_loop == loop) {
1480 if (PySet_Add(set, task) == -1) {
1481 Py_DECREF(task_loop);
1482 Py_DECREF(task);
1483 goto fail;
1484 }
1485 }
1486 Py_DECREF(task_loop);
1487 Py_DECREF(task);
1488 }
1489
1490 Py_DECREF(iter);
1491 return set;
1492
1493fail:
1494 Py_XDECREF(set);
1495 Py_XDECREF(iter);
1496 return NULL;
1497}
1498
1499/*[clinic input]
1500@classmethod
1501_asyncio.Task.all_tasks
1502
1503 loop: 'O' = NULL
1504
1505Return a set of all tasks for an event loop.
1506
1507By default all tasks for the current event loop are returned.
1508[clinic start generated code]*/
1509
1510static PyObject *
1511_asyncio_Task_all_tasks_impl(PyTypeObject *type, PyObject *loop)
1512/*[clinic end generated code: output=11f9b20749ccca5d input=cd64aa5f88bd5c49]*/
1513{
1514 PyObject *res;
1515
1516 if (loop == NULL) {
1517 loop = PyObject_CallObject(asyncio_get_event_loop, NULL);
1518 if (loop == NULL) {
1519 return NULL;
1520 }
1521
1522 res = task_all_tasks(loop);
1523 Py_DECREF(loop);
1524 }
1525 else {
1526 res = task_all_tasks(loop);
1527 }
1528
1529 return res;
1530}
1531
1532/*[clinic input]
1533_asyncio.Task._repr_info
1534[clinic start generated code]*/
1535
1536static PyObject *
1537_asyncio_Task__repr_info_impl(TaskObj *self)
1538/*[clinic end generated code: output=6a490eb66d5ba34b input=3c6d051ed3ddec8b]*/
1539{
1540 return PyObject_CallFunctionObjArgs(
1541 asyncio_task_repr_info_func, self, NULL);
1542}
1543
1544/*[clinic input]
1545_asyncio.Task.cancel
1546
1547Request that this task cancel itself.
1548
1549This arranges for a CancelledError to be thrown into the
1550wrapped coroutine on the next cycle through the event loop.
1551The coroutine then has a chance to clean up or even deny
1552the request using try/except/finally.
1553
1554Unlike Future.cancel, this does not guarantee that the
1555task will be cancelled: the exception might be caught and
1556acted upon, delaying cancellation of the task or preventing
1557cancellation completely. The task may also return a value or
1558raise a different exception.
1559
1560Immediately after this method is called, Task.cancelled() will
1561not return True (unless the task was already cancelled). A
1562task will be marked as cancelled when the wrapped coroutine
1563terminates with a CancelledError exception (even if cancel()
1564was not called).
1565[clinic start generated code]*/
1566
1567static PyObject *
1568_asyncio_Task_cancel_impl(TaskObj *self)
1569/*[clinic end generated code: output=6bfc0479da9d5757 input=13f9bf496695cb52]*/
1570{
1571 if (self->task_state != STATE_PENDING) {
1572 Py_RETURN_FALSE;
1573 }
1574
1575 if (self->task_fut_waiter) {
1576 PyObject *res;
1577 int is_true;
1578
1579 res = _PyObject_CallMethodId(
1580 self->task_fut_waiter, &PyId_cancel, NULL);
1581 if (res == NULL) {
1582 return NULL;
1583 }
1584
1585 is_true = PyObject_IsTrue(res);
1586 Py_DECREF(res);
1587 if (is_true < 0) {
1588 return NULL;
1589 }
1590
1591 if (is_true) {
1592 Py_RETURN_TRUE;
1593 }
1594 }
1595
1596 self->task_must_cancel = 1;
1597 Py_RETURN_TRUE;
1598}
1599
1600/*[clinic input]
1601_asyncio.Task.get_stack
1602
1603 *
1604 limit: 'O' = None
1605
1606Return the list of stack frames for this task's coroutine.
1607
1608If the coroutine is not done, this returns the stack where it is
1609suspended. If the coroutine has completed successfully or was
1610cancelled, this returns an empty list. If the coroutine was
1611terminated by an exception, this returns the list of traceback
1612frames.
1613
1614The frames are always ordered from oldest to newest.
1615
1616The optional limit gives the maximum number of frames to
1617return; by default all available frames are returned. Its
1618meaning differs depending on whether a stack or a traceback is
1619returned: the newest frames of a stack are returned, but the
1620oldest frames of a traceback are returned. (This matches the
1621behavior of the traceback module.)
1622
1623For reasons beyond our control, only one stack frame is
1624returned for a suspended coroutine.
1625[clinic start generated code]*/
1626
1627static PyObject *
1628_asyncio_Task_get_stack_impl(TaskObj *self, PyObject *limit)
1629/*[clinic end generated code: output=c9aeeeebd1e18118 input=b1920230a766d17a]*/
1630{
1631 return PyObject_CallFunctionObjArgs(
1632 asyncio_task_get_stack_func, self, limit, NULL);
1633}
1634
1635/*[clinic input]
1636_asyncio.Task.print_stack
1637
1638 *
1639 limit: 'O' = None
1640 file: 'O' = None
1641
1642Print the stack or traceback for this task's coroutine.
1643
1644This produces output similar to that of the traceback module,
1645for the frames retrieved by get_stack(). The limit argument
1646is passed to get_stack(). The file argument is an I/O stream
1647to which the output is written; by default output is written
1648to sys.stderr.
1649[clinic start generated code]*/
1650
1651static PyObject *
1652_asyncio_Task_print_stack_impl(TaskObj *self, PyObject *limit,
1653 PyObject *file)
1654/*[clinic end generated code: output=7339e10314cd3f4d input=19f1e99ab5400bc3]*/
1655{
1656 return PyObject_CallFunctionObjArgs(
1657 asyncio_task_print_stack_func, self, limit, file, NULL);
1658}
1659
1660/*[clinic input]
1661_asyncio.Task._step
1662
1663 exc: 'O' = NULL
1664[clinic start generated code]*/
1665
1666static PyObject *
1667_asyncio_Task__step_impl(TaskObj *self, PyObject *exc)
1668/*[clinic end generated code: output=7ed23f0cefd5ae42 input=ada4b2324e5370af]*/
1669{
1670 return task_step(self, exc == Py_None ? NULL : exc);
1671}
1672
1673/*[clinic input]
1674_asyncio.Task._wakeup
1675
1676 fut: 'O'
1677[clinic start generated code]*/
1678
1679static PyObject *
1680_asyncio_Task__wakeup_impl(TaskObj *self, PyObject *fut)
1681/*[clinic end generated code: output=75cb341c760fd071 input=11ee4918a5bdbf21]*/
1682{
1683 return task_wakeup(self, fut);
1684}
1685
1686static void
1687TaskObj_finalize(TaskObj *task)
1688{
1689 _Py_IDENTIFIER(call_exception_handler);
1690 _Py_IDENTIFIER(task);
1691 _Py_IDENTIFIER(message);
1692 _Py_IDENTIFIER(source_traceback);
1693
1694 PyObject *message = NULL;
1695 PyObject *context = NULL;
1696 PyObject *func = NULL;
1697 PyObject *res = NULL;
1698
1699 PyObject *error_type, *error_value, *error_traceback;
1700
1701 if (task->task_state != STATE_PENDING || !task->task_log_destroy_pending) {
1702 goto done;
1703 }
1704
1705 /* Save the current exception, if any. */
1706 PyErr_Fetch(&error_type, &error_value, &error_traceback);
1707
1708 context = PyDict_New();
1709 if (context == NULL) {
1710 goto finally;
1711 }
1712
1713 message = PyUnicode_FromString("Task was destroyed but it is pending!");
1714 if (message == NULL) {
1715 goto finally;
1716 }
1717
1718 if (_PyDict_SetItemId(context, &PyId_message, message) < 0 ||
1719 _PyDict_SetItemId(context, &PyId_task, (PyObject*)task) < 0)
1720 {
1721 goto finally;
1722 }
1723
1724 if (task->task_source_tb != NULL) {
1725 if (_PyDict_SetItemId(context, &PyId_source_traceback,
1726 task->task_source_tb) < 0)
1727 {
1728 goto finally;
1729 }
1730 }
1731
1732 func = _PyObject_GetAttrId(task->task_loop, &PyId_call_exception_handler);
1733 if (func != NULL) {
1734 res = _PyObject_CallArg1(func, context);
1735 if (res == NULL) {
1736 PyErr_WriteUnraisable(func);
1737 }
1738 }
1739
1740finally:
1741 Py_CLEAR(context);
1742 Py_CLEAR(message);
1743 Py_CLEAR(func);
1744 Py_CLEAR(res);
1745
1746 /* Restore the saved exception. */
1747 PyErr_Restore(error_type, error_value, error_traceback);
1748
1749done:
1750 FutureObj_finalize((FutureObj*)task);
1751}
1752
1753static void TaskObj_dealloc(PyObject *); /* Needs Task_CheckExact */
1754
1755static PyMethodDef TaskType_methods[] = {
1756 _ASYNCIO_FUTURE_RESULT_METHODDEF
1757 _ASYNCIO_FUTURE_EXCEPTION_METHODDEF
1758 _ASYNCIO_FUTURE_SET_RESULT_METHODDEF
1759 _ASYNCIO_FUTURE_SET_EXCEPTION_METHODDEF
1760 _ASYNCIO_FUTURE_ADD_DONE_CALLBACK_METHODDEF
1761 _ASYNCIO_FUTURE_REMOVE_DONE_CALLBACK_METHODDEF
1762 _ASYNCIO_FUTURE_CANCELLED_METHODDEF
1763 _ASYNCIO_FUTURE_DONE_METHODDEF
1764 _ASYNCIO_TASK_CURRENT_TASK_METHODDEF
1765 _ASYNCIO_TASK_ALL_TASKS_METHODDEF
1766 _ASYNCIO_TASK_CANCEL_METHODDEF
1767 _ASYNCIO_TASK_GET_STACK_METHODDEF
1768 _ASYNCIO_TASK_PRINT_STACK_METHODDEF
1769 _ASYNCIO_TASK__WAKEUP_METHODDEF
1770 _ASYNCIO_TASK__STEP_METHODDEF
1771 _ASYNCIO_TASK__REPR_INFO_METHODDEF
1772 {NULL, NULL} /* Sentinel */
1773};
1774
1775static PyGetSetDef TaskType_getsetlist[] = {
1776 FUTURE_COMMON_GETSETLIST
1777 {"_log_destroy_pending", (getter)TaskObj_get_log_destroy_pending,
1778 (setter)TaskObj_set_log_destroy_pending, NULL},
1779 {"_must_cancel", (getter)TaskObj_get_must_cancel, NULL, NULL},
1780 {"_coro", (getter)TaskObj_get_coro, NULL, NULL},
1781 {"_fut_waiter", (getter)TaskObj_get_fut_waiter, NULL, NULL},
1782 {NULL} /* Sentinel */
1783};
1784
1785static PyTypeObject TaskType = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02001786 PyVarObject_HEAD_INIT(NULL, 0)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001787 "_asyncio.Task",
1788 sizeof(TaskObj), /* tp_basicsize */
1789 .tp_base = &FutureType,
1790 .tp_dealloc = TaskObj_dealloc,
1791 .tp_as_async = &FutureType_as_async,
1792 .tp_repr = (reprfunc)FutureObj_repr,
1793 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE
1794 | Py_TPFLAGS_HAVE_FINALIZE,
1795 .tp_doc = _asyncio_Task___init____doc__,
1796 .tp_traverse = (traverseproc)TaskObj_traverse,
1797 .tp_clear = (inquiry)TaskObj_clear,
1798 .tp_weaklistoffset = offsetof(TaskObj, task_weakreflist),
1799 .tp_iter = (getiterfunc)future_new_iter,
1800 .tp_methods = TaskType_methods,
1801 .tp_getset = TaskType_getsetlist,
1802 .tp_dictoffset = offsetof(TaskObj, dict),
1803 .tp_init = (initproc)_asyncio_Task___init__,
1804 .tp_new = PyType_GenericNew,
1805 .tp_finalize = (destructor)TaskObj_finalize,
1806};
1807
1808#define Task_CheckExact(obj) (Py_TYPE(obj) == &TaskType)
1809
1810static void
1811TaskObj_dealloc(PyObject *self)
1812{
1813 TaskObj *task = (TaskObj *)self;
1814
1815 if (Task_CheckExact(self)) {
1816 /* When fut is subclass of Task, finalizer is called from
1817 * subtype_dealloc.
1818 */
1819 if (PyObject_CallFinalizerFromDealloc(self) < 0) {
1820 // resurrected.
1821 return;
1822 }
1823 }
1824
1825 if (task->task_weakreflist != NULL) {
1826 PyObject_ClearWeakRefs(self);
1827 }
1828
1829 (void)TaskObj_clear(task);
1830 Py_TYPE(task)->tp_free(task);
1831}
1832
1833static inline PyObject *
1834task_call_wakeup(TaskObj *task, PyObject *fut)
1835{
1836 if (Task_CheckExact(task)) {
1837 return task_wakeup(task, fut);
1838 }
1839 else {
1840 /* `task` is a subclass of Task */
Victor Stinnercb2128c2016-12-15 09:05:11 +01001841 return _PyObject_CallMethodIdObjArgs((PyObject*)task, &PyId__wakeup,
1842 fut, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001843 }
1844}
1845
1846static inline PyObject *
1847task_call_step(TaskObj *task, PyObject *arg)
1848{
1849 if (Task_CheckExact(task)) {
1850 return task_step(task, arg);
1851 }
1852 else {
1853 /* `task` is a subclass of Task */
1854 if (arg == NULL) {
1855 arg = Py_None;
1856 }
Victor Stinnercb2128c2016-12-15 09:05:11 +01001857 return _PyObject_CallMethodIdObjArgs((PyObject*)task, &PyId__step,
1858 arg, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001859 }
1860}
1861
1862static int
1863task_call_step_soon(TaskObj *task, PyObject *arg)
1864{
1865 PyObject *handle;
1866
1867 PyObject *cb = TaskSendMethWrapper_new(task, arg);
1868 if (cb == NULL) {
1869 return -1;
1870 }
1871
Victor Stinnercb2128c2016-12-15 09:05:11 +01001872 handle = _PyObject_CallMethodIdObjArgs(task->task_loop, &PyId_call_soon,
1873 cb, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001874 Py_DECREF(cb);
1875 if (handle == NULL) {
1876 return -1;
1877 }
1878
1879 Py_DECREF(handle);
1880 return 0;
1881}
1882
1883static PyObject *
1884task_set_error_soon(TaskObj *task, PyObject *et, const char *format, ...)
1885{
1886 PyObject* msg;
1887
1888 va_list vargs;
1889#ifdef HAVE_STDARG_PROTOTYPES
1890 va_start(vargs, format);
1891#else
1892 va_start(vargs);
1893#endif
1894 msg = PyUnicode_FromFormatV(format, vargs);
1895 va_end(vargs);
1896
1897 if (msg == NULL) {
1898 return NULL;
1899 }
1900
1901 PyObject *e = PyObject_CallFunctionObjArgs(et, msg, NULL);
1902 Py_DECREF(msg);
1903 if (e == NULL) {
1904 return NULL;
1905 }
1906
1907 if (task_call_step_soon(task, e) == -1) {
1908 Py_DECREF(e);
1909 return NULL;
1910 }
1911
1912 Py_DECREF(e);
1913 Py_RETURN_NONE;
1914}
1915
1916static PyObject *
1917task_step_impl(TaskObj *task, PyObject *exc)
1918{
1919 int res;
1920 int clear_exc = 0;
1921 PyObject *result = NULL;
1922 PyObject *coro = task->task_coro;
1923 PyObject *o;
1924
1925 if (task->task_state != STATE_PENDING) {
1926 PyErr_Format(PyExc_AssertionError,
1927 "_step(): already done: %R %R",
1928 task,
1929 exc ? exc : Py_None);
INADA Naokic411a7d2016-10-18 11:48:14 +09001930 goto fail;
1931 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001932
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001933 if (task->task_must_cancel) {
1934 assert(exc != Py_None);
1935
1936 if (exc) {
1937 /* Check if exc is a CancelledError */
1938 res = PyObject_IsInstance(exc, asyncio_CancelledError);
1939 if (res == -1) {
1940 /* An error occurred, abort */
1941 goto fail;
1942 }
1943 if (res == 0) {
1944 /* exc is not CancelledError; reset it to NULL */
1945 exc = NULL;
1946 }
1947 }
1948
1949 if (!exc) {
1950 /* exc was not a CancelledError */
1951 exc = PyObject_CallFunctionObjArgs(asyncio_CancelledError, NULL);
1952 if (!exc) {
1953 goto fail;
1954 }
1955 clear_exc = 1;
1956 }
1957
1958 task->task_must_cancel = 0;
1959 }
1960
1961 Py_CLEAR(task->task_fut_waiter);
1962
1963 if (exc == NULL) {
1964 if (PyGen_CheckExact(coro) || PyCoro_CheckExact(coro)) {
1965 result = _PyGen_Send((PyGenObject*)coro, Py_None);
1966 }
1967 else {
1968 result = _PyObject_CallMethodIdObjArgs(
1969 coro, &PyId_send, Py_None, NULL);
1970 }
1971 }
1972 else {
1973 result = _PyObject_CallMethodIdObjArgs(
1974 coro, &PyId_throw, exc, NULL);
1975 if (clear_exc) {
1976 /* We created 'exc' during this call */
1977 Py_CLEAR(exc);
1978 }
1979 }
1980
1981 if (result == NULL) {
1982 PyObject *et, *ev, *tb;
1983
1984 if (_PyGen_FetchStopIterationValue(&o) == 0) {
1985 /* The error is StopIteration and that means that
1986 the underlying coroutine has resolved */
1987 PyObject *res = future_set_result((FutureObj*)task, o);
1988 Py_DECREF(o);
1989 if (res == NULL) {
1990 return NULL;
1991 }
1992 Py_DECREF(res);
1993 Py_RETURN_NONE;
1994 }
1995
1996 if (PyErr_ExceptionMatches(asyncio_CancelledError)) {
1997 /* CancelledError */
1998 PyErr_Clear();
1999 return future_cancel((FutureObj*)task);
2000 }
2001
2002 /* Some other exception; pop it and call Task.set_exception() */
2003 PyErr_Fetch(&et, &ev, &tb);
2004 assert(et);
2005 if (!ev || !PyObject_TypeCheck(ev, (PyTypeObject *) et)) {
2006 PyErr_NormalizeException(&et, &ev, &tb);
2007 }
Yury Selivanovc2c8fe12016-12-01 11:36:22 -05002008 if (tb != NULL) {
2009 PyException_SetTraceback(ev, tb);
2010 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002011 o = future_set_exception((FutureObj*)task, ev);
2012 if (!o) {
2013 /* An exception in Task.set_exception() */
2014 Py_XDECREF(et);
2015 Py_XDECREF(tb);
2016 Py_XDECREF(ev);
2017 goto fail;
2018 }
2019 assert(o == Py_None);
2020 Py_CLEAR(o);
2021
2022 if (!PyErr_GivenExceptionMatches(et, PyExc_Exception)) {
2023 /* We've got a BaseException; re-raise it */
2024 PyErr_Restore(et, ev, tb);
2025 goto fail;
2026 }
2027
2028 Py_XDECREF(et);
2029 Py_XDECREF(tb);
2030 Py_XDECREF(ev);
2031
2032 Py_RETURN_NONE;
2033 }
2034
2035 if (result == (PyObject*)task) {
2036 /* We have a task that wants to await on itself */
2037 goto self_await;
2038 }
2039
2040 /* Check if `result` is FutureObj or TaskObj (and not a subclass) */
2041 if (Future_CheckExact(result) || Task_CheckExact(result)) {
2042 PyObject *wrapper;
2043 PyObject *res;
2044 FutureObj *fut = (FutureObj*)result;
2045
2046 /* Check if `result` future is attached to a different loop */
2047 if (fut->fut_loop != task->task_loop) {
2048 goto different_loop;
2049 }
2050
2051 if (fut->fut_blocking) {
2052 fut->fut_blocking = 0;
2053
2054 /* result.add_done_callback(task._wakeup) */
2055 wrapper = TaskWakeupMethWrapper_new(task);
2056 if (wrapper == NULL) {
2057 goto fail;
2058 }
2059 res = future_add_done_callback((FutureObj*)result, wrapper);
2060 Py_DECREF(wrapper);
2061 if (res == NULL) {
2062 goto fail;
2063 }
2064 Py_DECREF(res);
2065
2066 /* task._fut_waiter = result */
2067 task->task_fut_waiter = result; /* no incref is necessary */
2068
2069 if (task->task_must_cancel) {
2070 PyObject *r;
2071 r = future_cancel(fut);
2072 if (r == NULL) {
2073 return NULL;
2074 }
2075 if (r == Py_True) {
2076 task->task_must_cancel = 0;
2077 }
2078 Py_DECREF(r);
2079 }
2080
2081 Py_RETURN_NONE;
2082 }
2083 else {
2084 goto yield_insteadof_yf;
2085 }
2086 }
2087
2088 /* Check if `result` is a Future-compatible object */
2089 o = PyObject_GetAttrString(result, "_asyncio_future_blocking");
2090 if (o == NULL) {
2091 if (PyErr_ExceptionMatches(PyExc_AttributeError)) {
2092 PyErr_Clear();
2093 }
2094 else {
2095 goto fail;
2096 }
2097 }
2098 else {
2099 if (o == Py_None) {
2100 Py_CLEAR(o);
2101 }
2102 else {
2103 /* `result` is a Future-compatible object */
2104 PyObject *wrapper;
2105 PyObject *res;
2106
2107 int blocking = PyObject_IsTrue(o);
2108 Py_CLEAR(o);
2109 if (blocking < 0) {
2110 goto fail;
2111 }
2112
2113 /* Check if `result` future is attached to a different loop */
2114 PyObject *oloop = PyObject_GetAttrString(result, "_loop");
2115 if (oloop == NULL) {
2116 goto fail;
2117 }
2118 if (oloop != task->task_loop) {
2119 Py_DECREF(oloop);
2120 goto different_loop;
2121 }
2122 else {
2123 Py_DECREF(oloop);
2124 }
2125
2126 if (blocking) {
2127 /* result._asyncio_future_blocking = False */
2128 if (PyObject_SetAttrString(
2129 result, "_asyncio_future_blocking", Py_False) == -1) {
2130 goto fail;
2131 }
2132
2133 /* result.add_done_callback(task._wakeup) */
2134 wrapper = TaskWakeupMethWrapper_new(task);
2135 if (wrapper == NULL) {
2136 goto fail;
2137 }
Victor Stinnercb2128c2016-12-15 09:05:11 +01002138 res = _PyObject_CallMethodIdObjArgs(result,
2139 &PyId_add_done_callback,
2140 wrapper, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002141 Py_DECREF(wrapper);
2142 if (res == NULL) {
2143 goto fail;
2144 }
2145 Py_DECREF(res);
2146
2147 /* task._fut_waiter = result */
2148 task->task_fut_waiter = result; /* no incref is necessary */
2149
2150 if (task->task_must_cancel) {
2151 PyObject *r;
2152 int is_true;
2153 r = _PyObject_CallMethodId(result, &PyId_cancel, NULL);
2154 if (r == NULL) {
2155 return NULL;
2156 }
2157 is_true = PyObject_IsTrue(r);
2158 Py_DECREF(r);
2159 if (is_true < 0) {
2160 return NULL;
2161 }
2162 else if (is_true) {
2163 task->task_must_cancel = 0;
2164 }
2165 }
2166
2167 Py_RETURN_NONE;
2168 }
2169 else {
2170 goto yield_insteadof_yf;
2171 }
2172 }
2173 }
2174
2175 /* Check if `result` is None */
2176 if (result == Py_None) {
2177 /* Bare yield relinquishes control for one event loop iteration. */
2178 if (task_call_step_soon(task, NULL)) {
2179 goto fail;
2180 }
2181 return result;
2182 }
2183
2184 /* Check if `result` is a generator */
2185 o = PyObject_CallFunctionObjArgs(inspect_isgenerator, result, NULL);
2186 if (o == NULL) {
2187 /* An exception in inspect.isgenerator */
2188 goto fail;
2189 }
2190 res = PyObject_IsTrue(o);
2191 Py_CLEAR(o);
2192 if (res == -1) {
2193 /* An exception while checking if 'val' is True */
2194 goto fail;
2195 }
2196 if (res == 1) {
2197 /* `result` is a generator */
2198 PyObject *ret;
2199 ret = task_set_error_soon(
2200 task, PyExc_RuntimeError,
2201 "yield was used instead of yield from for "
2202 "generator in task %R with %S", task, result);
2203 Py_DECREF(result);
2204 return ret;
2205 }
2206
2207 /* The `result` is none of the above */
2208 Py_DECREF(result);
2209 return task_set_error_soon(
2210 task, PyExc_RuntimeError, "Task got bad yield: %R", result);
2211
2212self_await:
2213 o = task_set_error_soon(
2214 task, PyExc_RuntimeError,
2215 "Task cannot await on itself: %R", task);
2216 Py_DECREF(result);
2217 return o;
2218
2219yield_insteadof_yf:
2220 o = task_set_error_soon(
2221 task, PyExc_RuntimeError,
2222 "yield was used instead of yield from "
2223 "in task %R with %R",
2224 task, result);
2225 Py_DECREF(result);
2226 return o;
2227
2228different_loop:
2229 o = task_set_error_soon(
2230 task, PyExc_RuntimeError,
2231 "Task %R got Future %R attached to a different loop",
2232 task, result);
2233 Py_DECREF(result);
2234 return o;
2235
2236fail:
2237 Py_XDECREF(result);
2238 return NULL;
2239}
2240
2241static PyObject *
2242task_step(TaskObj *task, PyObject *exc)
2243{
2244 PyObject *res;
2245 PyObject *ot;
2246
Yury Selivanov684ef2c2016-10-28 19:01:21 -04002247 if (PyDict_SetItem(current_tasks,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002248 task->task_loop, (PyObject*)task) == -1)
2249 {
2250 return NULL;
2251 }
2252
2253 res = task_step_impl(task, exc);
2254
2255 if (res == NULL) {
2256 PyObject *et, *ev, *tb;
2257 PyErr_Fetch(&et, &ev, &tb);
2258 ot = _PyDict_Pop(current_tasks, task->task_loop, NULL);
2259 if (ot == NULL) {
2260 Py_XDECREF(et);
2261 Py_XDECREF(tb);
2262 Py_XDECREF(ev);
2263 return NULL;
2264 }
2265 Py_DECREF(ot);
2266 PyErr_Restore(et, ev, tb);
2267 return NULL;
2268 }
2269 else {
2270 ot = _PyDict_Pop(current_tasks, task->task_loop, NULL);
2271 if (ot == NULL) {
2272 Py_DECREF(res);
2273 return NULL;
2274 }
2275 else {
2276 Py_DECREF(ot);
2277 return res;
2278 }
2279 }
2280}
2281
2282static PyObject *
2283task_wakeup(TaskObj *task, PyObject *o)
2284{
2285 assert(o);
2286
2287 if (Future_CheckExact(o) || Task_CheckExact(o)) {
2288 PyObject *fut_result = NULL;
2289 int res = future_get_result((FutureObj*)o, &fut_result);
2290 PyObject *result;
2291
2292 switch(res) {
2293 case -1:
2294 assert(fut_result == NULL);
2295 return NULL;
2296 case 0:
2297 Py_DECREF(fut_result);
2298 return task_call_step(task, NULL);
2299 default:
2300 assert(res == 1);
2301 result = task_call_step(task, fut_result);
2302 Py_DECREF(fut_result);
2303 return result;
2304 }
2305 }
2306
2307 PyObject *fut_result = PyObject_CallMethod(o, "result", NULL);
2308 if (fut_result == NULL) {
2309 PyObject *et, *ev, *tb;
2310 PyObject *res;
2311
2312 PyErr_Fetch(&et, &ev, &tb);
2313 if (!ev || !PyObject_TypeCheck(ev, (PyTypeObject *) et)) {
2314 PyErr_NormalizeException(&et, &ev, &tb);
2315 }
2316
2317 res = task_call_step(task, ev);
2318
2319 Py_XDECREF(et);
2320 Py_XDECREF(tb);
2321 Py_XDECREF(ev);
2322
2323 return res;
2324 }
2325 else {
2326 Py_DECREF(fut_result);
2327 return task_call_step(task, NULL);
2328 }
2329}
2330
2331
2332/*********************** Module **************************/
2333
2334
2335static void
2336module_free(void *m)
2337{
2338 Py_CLEAR(current_tasks);
2339 Py_CLEAR(all_tasks);
2340 Py_CLEAR(traceback_extract_stack);
2341 Py_CLEAR(asyncio_get_event_loop);
2342 Py_CLEAR(asyncio_future_repr_info_func);
2343 Py_CLEAR(asyncio_task_repr_info_func);
2344 Py_CLEAR(asyncio_task_get_stack_func);
2345 Py_CLEAR(asyncio_task_print_stack_func);
2346 Py_CLEAR(asyncio_InvalidStateError);
2347 Py_CLEAR(asyncio_CancelledError);
2348 Py_CLEAR(inspect_isgenerator);
2349}
2350
2351static int
2352module_init(void)
2353{
2354 PyObject *module = NULL;
2355 PyObject *cls;
2356
2357#define WITH_MOD(NAME) \
2358 Py_CLEAR(module); \
2359 module = PyImport_ImportModule(NAME); \
2360 if (module == NULL) { \
2361 return -1; \
2362 }
2363
2364#define GET_MOD_ATTR(VAR, NAME) \
2365 VAR = PyObject_GetAttrString(module, NAME); \
2366 if (VAR == NULL) { \
2367 goto fail; \
2368 }
2369
2370 WITH_MOD("asyncio.events")
2371 GET_MOD_ATTR(asyncio_get_event_loop, "get_event_loop")
2372
2373 WITH_MOD("asyncio.base_futures")
2374 GET_MOD_ATTR(asyncio_future_repr_info_func, "_future_repr_info")
2375 GET_MOD_ATTR(asyncio_InvalidStateError, "InvalidStateError")
2376 GET_MOD_ATTR(asyncio_CancelledError, "CancelledError")
2377
2378 WITH_MOD("asyncio.base_tasks")
2379 GET_MOD_ATTR(asyncio_task_repr_info_func, "_task_repr_info")
2380 GET_MOD_ATTR(asyncio_task_get_stack_func, "_task_get_stack")
2381 GET_MOD_ATTR(asyncio_task_print_stack_func, "_task_print_stack")
2382
2383 WITH_MOD("inspect")
2384 GET_MOD_ATTR(inspect_isgenerator, "isgenerator")
2385
2386 WITH_MOD("traceback")
2387 GET_MOD_ATTR(traceback_extract_stack, "extract_stack")
2388
2389 WITH_MOD("weakref")
2390 GET_MOD_ATTR(cls, "WeakSet")
2391 all_tasks = PyObject_CallObject(cls, NULL);
2392 Py_CLEAR(cls);
2393 if (all_tasks == NULL) {
INADA Naokic411a7d2016-10-18 11:48:14 +09002394 goto fail;
2395 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09002396
Yury Selivanov684ef2c2016-10-28 19:01:21 -04002397 current_tasks = PyDict_New();
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002398 if (current_tasks == NULL) {
2399 goto fail;
2400 }
2401
2402 Py_CLEAR(module);
INADA Naokic411a7d2016-10-18 11:48:14 +09002403 return 0;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09002404
INADA Naokic411a7d2016-10-18 11:48:14 +09002405fail:
INADA Naokic411a7d2016-10-18 11:48:14 +09002406 Py_CLEAR(module);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002407 module_free(NULL);
INADA Naokic411a7d2016-10-18 11:48:14 +09002408 return -1;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09002409
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002410#undef WITH_MOD
2411#undef GET_MOD_ATTR
2412}
INADA Naoki9e4e38e2016-10-09 14:44:47 +09002413
INADA Naokic411a7d2016-10-18 11:48:14 +09002414PyDoc_STRVAR(module_doc, "Accelerator module for asyncio");
INADA Naoki9e4e38e2016-10-09 14:44:47 +09002415
INADA Naoki9f2ce252016-10-15 15:39:19 +09002416static struct PyModuleDef _asynciomodule = {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09002417 PyModuleDef_HEAD_INIT, /* m_base */
INADA Naoki9f2ce252016-10-15 15:39:19 +09002418 "_asyncio", /* m_name */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09002419 module_doc, /* m_doc */
2420 -1, /* m_size */
INADA Naokic411a7d2016-10-18 11:48:14 +09002421 NULL, /* m_methods */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09002422 NULL, /* m_slots */
2423 NULL, /* m_traverse */
2424 NULL, /* m_clear */
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002425 (freefunc)module_free /* m_free */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09002426};
2427
2428
2429PyMODINIT_FUNC
INADA Naoki9f2ce252016-10-15 15:39:19 +09002430PyInit__asyncio(void)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09002431{
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002432 if (module_init() < 0) {
INADA Naokic411a7d2016-10-18 11:48:14 +09002433 return NULL;
2434 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09002435 if (PyType_Ready(&FutureType) < 0) {
2436 return NULL;
2437 }
2438 if (PyType_Ready(&FutureIterType) < 0) {
2439 return NULL;
2440 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002441 if (PyType_Ready(&TaskSendMethWrapper_Type) < 0) {
2442 return NULL;
2443 }
2444 if(PyType_Ready(&TaskWakeupMethWrapper_Type) < 0) {
2445 return NULL;
2446 }
2447 if (PyType_Ready(&TaskType) < 0) {
2448 return NULL;
2449 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09002450
INADA Naoki9f2ce252016-10-15 15:39:19 +09002451 PyObject *m = PyModule_Create(&_asynciomodule);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09002452 if (m == NULL) {
2453 return NULL;
2454 }
2455
2456 Py_INCREF(&FutureType);
2457 if (PyModule_AddObject(m, "Future", (PyObject *)&FutureType) < 0) {
2458 Py_DECREF(&FutureType);
2459 return NULL;
2460 }
2461
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002462 Py_INCREF(&TaskType);
2463 if (PyModule_AddObject(m, "Task", (PyObject *)&TaskType) < 0) {
2464 Py_DECREF(&TaskType);
2465 return NULL;
2466 }
2467
INADA Naoki9e4e38e2016-10-09 14:44:47 +09002468 return m;
2469}