blob: 492b98359713df2ace13221e77a718b0eacfb995 [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{
Yury Selivanov176f2eb2017-06-11 14:00:14 +0000308 fut->fut_log_tb = 0;
309
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400310 if (fut->fut_state != STATE_PENDING) {
311 Py_RETURN_FALSE;
312 }
313 fut->fut_state = STATE_CANCELLED;
314
315 if (future_call_schedule_callbacks(fut) == -1) {
316 return NULL;
317 }
318
319 Py_RETURN_TRUE;
320}
321
322/*[clinic input]
323_asyncio.Future.__init__
324
325 *
326 loop: 'O' = NULL
327
328This class is *almost* compatible with concurrent.futures.Future.
329
330 Differences:
331
332 - result() and exception() do not take a timeout argument and
333 raise an exception when the future isn't done yet.
334
335 - Callbacks registered with add_done_callback() are always called
336 via the event loop's call_soon_threadsafe().
337
338 - This class is not compatible with the wait() and as_completed()
339 methods in the concurrent.futures package.
340[clinic start generated code]*/
341
342static int
343_asyncio_Future___init___impl(FutureObj *self, PyObject *loop)
344/*[clinic end generated code: output=9ed75799eaccb5d6 input=8e1681f23605be2d]*/
345
346{
347 return future_init(self, loop);
348}
349
350static int
351FutureObj_clear(FutureObj *fut)
352{
353 Py_CLEAR(fut->fut_loop);
354 Py_CLEAR(fut->fut_callbacks);
355 Py_CLEAR(fut->fut_result);
356 Py_CLEAR(fut->fut_exception);
357 Py_CLEAR(fut->fut_source_tb);
358 Py_CLEAR(fut->dict);
359 return 0;
360}
361
362static int
363FutureObj_traverse(FutureObj *fut, visitproc visit, void *arg)
364{
365 Py_VISIT(fut->fut_loop);
366 Py_VISIT(fut->fut_callbacks);
367 Py_VISIT(fut->fut_result);
368 Py_VISIT(fut->fut_exception);
369 Py_VISIT(fut->fut_source_tb);
370 Py_VISIT(fut->dict);
371 return 0;
372}
373
374/*[clinic input]
375_asyncio.Future.result
376
377Return the result this future represents.
378
379If the future has been cancelled, raises CancelledError. If the
380future's result isn't yet available, raises InvalidStateError. If
381the future is done and has an exception set, this exception is raised.
382[clinic start generated code]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900383
384static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400385_asyncio_Future_result_impl(FutureObj *self)
386/*[clinic end generated code: output=f35f940936a4b1e5 input=49ecf9cf5ec50dc5]*/
387{
388 PyObject *result;
389 int res = future_get_result(self, &result);
390
391 if (res == -1) {
392 return NULL;
393 }
394
395 if (res == 0) {
396 return result;
397 }
398
399 assert(res == 1);
400
401 PyErr_SetObject(PyExceptionInstance_Class(result), result);
402 Py_DECREF(result);
403 return NULL;
404}
405
406/*[clinic input]
407_asyncio.Future.exception
408
409Return the exception that was set on this future.
410
411The exception (or None if no exception was set) is returned only if
412the future is done. If the future has been cancelled, raises
413CancelledError. If the future isn't done yet, raises
414InvalidStateError.
415[clinic start generated code]*/
416
417static PyObject *
418_asyncio_Future_exception_impl(FutureObj *self)
419/*[clinic end generated code: output=88b20d4f855e0710 input=733547a70c841c68]*/
420{
421 if (self->fut_state == STATE_CANCELLED) {
422 PyErr_SetString(asyncio_CancelledError, "");
423 return NULL;
424 }
425
426 if (self->fut_state != STATE_FINISHED) {
427 PyErr_SetString(asyncio_InvalidStateError, "Result is not ready.");
428 return NULL;
429 }
430
431 if (self->fut_exception != NULL) {
432 self->fut_log_tb = 0;
433 Py_INCREF(self->fut_exception);
434 return self->fut_exception;
435 }
436
437 Py_RETURN_NONE;
438}
439
440/*[clinic input]
441_asyncio.Future.set_result
442
443 res: 'O'
444 /
445
446Mark the future done and set its result.
447
448If the future is already done when this method is called, raises
449InvalidStateError.
450[clinic start generated code]*/
451
452static PyObject *
453_asyncio_Future_set_result(FutureObj *self, PyObject *res)
454/*[clinic end generated code: output=a620abfc2796bfb6 input=8619565e0503357e]*/
455{
456 return future_set_result(self, res);
457}
458
459/*[clinic input]
460_asyncio.Future.set_exception
461
462 exception: 'O'
463 /
464
465Mark the future done and set an exception.
466
467If the future is already done when this method is called, raises
468InvalidStateError.
469[clinic start generated code]*/
470
471static PyObject *
472_asyncio_Future_set_exception(FutureObj *self, PyObject *exception)
473/*[clinic end generated code: output=f1c1b0cd321be360 input=1377dbe15e6ea186]*/
474{
475 return future_set_exception(self, exception);
476}
477
478/*[clinic input]
479_asyncio.Future.add_done_callback
480
481 fn: 'O'
482 /
483
484Add a callback to be run when the future becomes done.
485
486The callback is called with a single argument - the future object. If
487the future is already done when this is called, the callback is
488scheduled with call_soon.
489[clinic start generated code]*/
490
491static PyObject *
492_asyncio_Future_add_done_callback(FutureObj *self, PyObject *fn)
493/*[clinic end generated code: output=819e09629b2ec2b5 input=8cce187e32cec6a8]*/
494{
495 return future_add_done_callback(self, fn);
496}
497
498/*[clinic input]
499_asyncio.Future.remove_done_callback
500
501 fn: 'O'
502 /
503
504Remove all instances of a callback from the "call when done" list.
505
506Returns the number of callbacks removed.
507[clinic start generated code]*/
508
509static PyObject *
510_asyncio_Future_remove_done_callback(FutureObj *self, PyObject *fn)
511/*[clinic end generated code: output=5ab1fb52b24ef31f input=3fedb73e1409c31c]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900512{
513 PyObject *newlist;
514 Py_ssize_t len, i, j=0;
515
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400516 len = PyList_GET_SIZE(self->fut_callbacks);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900517 if (len == 0) {
518 return PyLong_FromSsize_t(0);
519 }
520
521 newlist = PyList_New(len);
522 if (newlist == NULL) {
523 return NULL;
524 }
525
Yury Selivanovd8b72e42017-03-02 23:46:56 -0500526 for (i = 0; i < PyList_GET_SIZE(self->fut_callbacks); i++) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900527 int ret;
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400528 PyObject *item = PyList_GET_ITEM(self->fut_callbacks, i);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900529
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400530 if ((ret = PyObject_RichCompareBool(fn, item, Py_EQ)) < 0) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900531 goto fail;
532 }
533 if (ret == 0) {
534 Py_INCREF(item);
535 PyList_SET_ITEM(newlist, j, item);
536 j++;
537 }
538 }
539
540 if (PyList_SetSlice(newlist, j, len, NULL) < 0) {
541 goto fail;
542 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400543 if (PyList_SetSlice(self->fut_callbacks, 0, len, newlist) < 0) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900544 goto fail;
545 }
546 Py_DECREF(newlist);
547 return PyLong_FromSsize_t(len - j);
548
549fail:
550 Py_DECREF(newlist);
551 return NULL;
552}
553
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400554/*[clinic input]
555_asyncio.Future.cancel
556
557Cancel the future and schedule callbacks.
558
559If the future is already done or cancelled, return False. Otherwise,
560change the future's state to cancelled, schedule the callbacks and
561return True.
562[clinic start generated code]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900563
564static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400565_asyncio_Future_cancel_impl(FutureObj *self)
566/*[clinic end generated code: output=e45b932ba8bd68a1 input=515709a127995109]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900567{
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400568 return future_cancel(self);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900569}
570
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400571/*[clinic input]
572_asyncio.Future.cancelled
573
574Return True if the future was cancelled.
575[clinic start generated code]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900576
577static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400578_asyncio_Future_cancelled_impl(FutureObj *self)
579/*[clinic end generated code: output=145197ced586357d input=943ab8b7b7b17e45]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900580{
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400581 if (self->fut_state == STATE_CANCELLED) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900582 Py_RETURN_TRUE;
583 }
584 else {
585 Py_RETURN_FALSE;
586 }
587}
588
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400589/*[clinic input]
590_asyncio.Future.done
591
592Return True if the future is done.
593
594Done means either that a result / exception are available, or that the
595future was cancelled.
596[clinic start generated code]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900597
598static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400599_asyncio_Future_done_impl(FutureObj *self)
600/*[clinic end generated code: output=244c5ac351145096 input=28d7b23fdb65d2ac]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900601{
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400602 if (self->fut_state == STATE_PENDING) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900603 Py_RETURN_FALSE;
604 }
605 else {
606 Py_RETURN_TRUE;
607 }
608}
609
610static PyObject *
611FutureObj_get_blocking(FutureObj *fut)
612{
613 if (fut->fut_blocking) {
614 Py_RETURN_TRUE;
615 }
616 else {
617 Py_RETURN_FALSE;
618 }
619}
620
621static int
622FutureObj_set_blocking(FutureObj *fut, PyObject *val)
623{
624 int is_true = PyObject_IsTrue(val);
625 if (is_true < 0) {
626 return -1;
627 }
628 fut->fut_blocking = is_true;
629 return 0;
630}
631
632static PyObject *
633FutureObj_get_log_traceback(FutureObj *fut)
634{
635 if (fut->fut_log_tb) {
636 Py_RETURN_TRUE;
637 }
638 else {
639 Py_RETURN_FALSE;
640 }
641}
642
Yury Selivanov176f2eb2017-06-11 14:00:14 +0000643static int
644FutureObj_set_log_traceback(FutureObj *fut, PyObject *val)
645{
646 int is_true = PyObject_IsTrue(val);
647 if (is_true < 0) {
648 return -1;
649 }
650 fut->fut_log_tb = is_true;
651 return 0;
652}
653
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900654static PyObject *
655FutureObj_get_loop(FutureObj *fut)
656{
657 if (fut->fut_loop == NULL) {
658 Py_RETURN_NONE;
659 }
660 Py_INCREF(fut->fut_loop);
661 return fut->fut_loop;
662}
663
664static PyObject *
665FutureObj_get_callbacks(FutureObj *fut)
666{
667 if (fut->fut_callbacks == NULL) {
668 Py_RETURN_NONE;
669 }
670 Py_INCREF(fut->fut_callbacks);
671 return fut->fut_callbacks;
672}
673
674static PyObject *
675FutureObj_get_result(FutureObj *fut)
676{
677 if (fut->fut_result == NULL) {
678 Py_RETURN_NONE;
679 }
680 Py_INCREF(fut->fut_result);
681 return fut->fut_result;
682}
683
684static PyObject *
685FutureObj_get_exception(FutureObj *fut)
686{
687 if (fut->fut_exception == NULL) {
688 Py_RETURN_NONE;
689 }
690 Py_INCREF(fut->fut_exception);
691 return fut->fut_exception;
692}
693
694static PyObject *
695FutureObj_get_source_traceback(FutureObj *fut)
696{
697 if (fut->fut_source_tb == NULL) {
698 Py_RETURN_NONE;
699 }
700 Py_INCREF(fut->fut_source_tb);
701 return fut->fut_source_tb;
702}
703
704static PyObject *
705FutureObj_get_state(FutureObj *fut)
706{
707 _Py_IDENTIFIER(PENDING);
708 _Py_IDENTIFIER(CANCELLED);
709 _Py_IDENTIFIER(FINISHED);
710 PyObject *ret = NULL;
711
712 switch (fut->fut_state) {
713 case STATE_PENDING:
714 ret = _PyUnicode_FromId(&PyId_PENDING);
715 break;
716 case STATE_CANCELLED:
717 ret = _PyUnicode_FromId(&PyId_CANCELLED);
718 break;
719 case STATE_FINISHED:
720 ret = _PyUnicode_FromId(&PyId_FINISHED);
721 break;
722 default:
723 assert (0);
724 }
725 Py_INCREF(ret);
726 return ret;
727}
728
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400729/*[clinic input]
730_asyncio.Future._repr_info
731[clinic start generated code]*/
732
733static PyObject *
734_asyncio_Future__repr_info_impl(FutureObj *self)
735/*[clinic end generated code: output=fa69e901bd176cfb input=f21504d8e2ae1ca2]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900736{
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400737 return PyObject_CallFunctionObjArgs(
738 asyncio_future_repr_info_func, self, NULL);
739}
740
741/*[clinic input]
742_asyncio.Future._schedule_callbacks
743[clinic start generated code]*/
744
745static PyObject *
746_asyncio_Future__schedule_callbacks_impl(FutureObj *self)
747/*[clinic end generated code: output=5e8958d89ea1c5dc input=4f5f295f263f4a88]*/
748{
749 int ret = future_schedule_callbacks(self);
750 if (ret == -1) {
751 return NULL;
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900752 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400753 Py_RETURN_NONE;
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900754}
755
756static PyObject *
757FutureObj_repr(FutureObj *fut)
758{
759 _Py_IDENTIFIER(_repr_info);
760
761 PyObject *_repr_info = _PyUnicode_FromId(&PyId__repr_info); // borrowed
762 if (_repr_info == NULL) {
763 return NULL;
764 }
765
766 PyObject *rinfo = PyObject_CallMethodObjArgs((PyObject*)fut, _repr_info,
767 NULL);
768 if (rinfo == NULL) {
769 return NULL;
770 }
771
772 PyObject *sp = PyUnicode_FromString(" ");
773 if (sp == NULL) {
774 Py_DECREF(rinfo);
775 return NULL;
776 }
777
778 PyObject *rinfo_s = PyUnicode_Join(sp, rinfo);
779 Py_DECREF(sp);
780 Py_DECREF(rinfo);
781 if (rinfo_s == NULL) {
782 return NULL;
783 }
784
785 PyObject *rstr = NULL;
786 PyObject *type_name = PyObject_GetAttrString((PyObject*)Py_TYPE(fut),
787 "__name__");
788 if (type_name != NULL) {
789 rstr = PyUnicode_FromFormat("<%S %S>", type_name, rinfo_s);
790 Py_DECREF(type_name);
791 }
792 Py_DECREF(rinfo_s);
793 return rstr;
794}
795
796static void
797FutureObj_finalize(FutureObj *fut)
798{
799 _Py_IDENTIFIER(call_exception_handler);
800 _Py_IDENTIFIER(message);
801 _Py_IDENTIFIER(exception);
802 _Py_IDENTIFIER(future);
803 _Py_IDENTIFIER(source_traceback);
804
805 if (!fut->fut_log_tb) {
806 return;
807 }
808 assert(fut->fut_exception != NULL);
809 fut->fut_log_tb = 0;;
810
811 PyObject *error_type, *error_value, *error_traceback;
812 /* Save the current exception, if any. */
813 PyErr_Fetch(&error_type, &error_value, &error_traceback);
814
815 PyObject *context = NULL;
816 PyObject *type_name = NULL;
817 PyObject *message = NULL;
818 PyObject *func = NULL;
819 PyObject *res = NULL;
820
821 context = PyDict_New();
822 if (context == NULL) {
823 goto finally;
824 }
825
826 type_name = PyObject_GetAttrString((PyObject*)Py_TYPE(fut), "__name__");
827 if (type_name == NULL) {
828 goto finally;
829 }
830
831 message = PyUnicode_FromFormat(
832 "%S exception was never retrieved", type_name);
833 if (message == NULL) {
834 goto finally;
835 }
836
837 if (_PyDict_SetItemId(context, &PyId_message, message) < 0 ||
838 _PyDict_SetItemId(context, &PyId_exception, fut->fut_exception) < 0 ||
839 _PyDict_SetItemId(context, &PyId_future, (PyObject*)fut) < 0) {
840 goto finally;
841 }
842 if (fut->fut_source_tb != NULL) {
843 if (_PyDict_SetItemId(context, &PyId_source_traceback,
844 fut->fut_source_tb) < 0) {
845 goto finally;
846 }
847 }
848
849 func = _PyObject_GetAttrId(fut->fut_loop, &PyId_call_exception_handler);
850 if (func != NULL) {
851 res = _PyObject_CallArg1(func, context);
852 if (res == NULL) {
853 PyErr_WriteUnraisable(func);
854 }
855 }
856
857finally:
858 Py_CLEAR(context);
859 Py_CLEAR(type_name);
860 Py_CLEAR(message);
861 Py_CLEAR(func);
862 Py_CLEAR(res);
863
864 /* Restore the saved exception. */
865 PyErr_Restore(error_type, error_value, error_traceback);
866}
867
868
869static PyAsyncMethods FutureType_as_async = {
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400870 (unaryfunc)future_new_iter, /* am_await */
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900871 0, /* am_aiter */
872 0 /* am_anext */
873};
874
875static PyMethodDef FutureType_methods[] = {
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400876 _ASYNCIO_FUTURE_RESULT_METHODDEF
877 _ASYNCIO_FUTURE_EXCEPTION_METHODDEF
878 _ASYNCIO_FUTURE_SET_RESULT_METHODDEF
879 _ASYNCIO_FUTURE_SET_EXCEPTION_METHODDEF
880 _ASYNCIO_FUTURE_ADD_DONE_CALLBACK_METHODDEF
881 _ASYNCIO_FUTURE_REMOVE_DONE_CALLBACK_METHODDEF
882 _ASYNCIO_FUTURE_CANCEL_METHODDEF
883 _ASYNCIO_FUTURE_CANCELLED_METHODDEF
884 _ASYNCIO_FUTURE_DONE_METHODDEF
885 _ASYNCIO_FUTURE__REPR_INFO_METHODDEF
886 _ASYNCIO_FUTURE__SCHEDULE_CALLBACKS_METHODDEF
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900887 {NULL, NULL} /* Sentinel */
888};
889
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400890#define FUTURE_COMMON_GETSETLIST \
891 {"_state", (getter)FutureObj_get_state, NULL, NULL}, \
892 {"_asyncio_future_blocking", (getter)FutureObj_get_blocking, \
893 (setter)FutureObj_set_blocking, NULL}, \
894 {"_loop", (getter)FutureObj_get_loop, NULL, NULL}, \
895 {"_callbacks", (getter)FutureObj_get_callbacks, NULL, NULL}, \
896 {"_result", (getter)FutureObj_get_result, NULL, NULL}, \
897 {"_exception", (getter)FutureObj_get_exception, NULL, NULL}, \
Yury Selivanov176f2eb2017-06-11 14:00:14 +0000898 {"_log_traceback", (getter)FutureObj_get_log_traceback, \
899 (setter)FutureObj_set_log_traceback, NULL}, \
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900900 {"_source_traceback", (getter)FutureObj_get_source_traceback, NULL, NULL},
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400901
902static PyGetSetDef FutureType_getsetlist[] = {
903 FUTURE_COMMON_GETSETLIST
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900904 {NULL} /* Sentinel */
905};
906
907static void FutureObj_dealloc(PyObject *self);
908
909static PyTypeObject FutureType = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +0200910 PyVarObject_HEAD_INIT(NULL, 0)
INADA Naoki9f2ce252016-10-15 15:39:19 +0900911 "_asyncio.Future",
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900912 sizeof(FutureObj), /* tp_basicsize */
913 .tp_dealloc = FutureObj_dealloc,
914 .tp_as_async = &FutureType_as_async,
915 .tp_repr = (reprfunc)FutureObj_repr,
916 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE
917 | Py_TPFLAGS_HAVE_FINALIZE,
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400918 .tp_doc = _asyncio_Future___init____doc__,
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900919 .tp_traverse = (traverseproc)FutureObj_traverse,
920 .tp_clear = (inquiry)FutureObj_clear,
921 .tp_weaklistoffset = offsetof(FutureObj, fut_weakreflist),
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400922 .tp_iter = (getiterfunc)future_new_iter,
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900923 .tp_methods = FutureType_methods,
924 .tp_getset = FutureType_getsetlist,
925 .tp_dictoffset = offsetof(FutureObj, dict),
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400926 .tp_init = (initproc)_asyncio_Future___init__,
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900927 .tp_new = PyType_GenericNew,
928 .tp_finalize = (destructor)FutureObj_finalize,
929};
930
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400931#define Future_CheckExact(obj) (Py_TYPE(obj) == &FutureType)
932
933static inline int
934future_call_schedule_callbacks(FutureObj *fut)
935{
936 if (Future_CheckExact(fut)) {
937 return future_schedule_callbacks(fut);
938 }
939 else {
940 /* `fut` is a subclass of Future */
941 PyObject *ret = _PyObject_CallMethodId(
942 (PyObject*)fut, &PyId__schedule_callbacks, NULL);
943 if (ret == NULL) {
944 return -1;
945 }
946
947 Py_DECREF(ret);
948 return 0;
949 }
950}
951
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900952static void
953FutureObj_dealloc(PyObject *self)
954{
955 FutureObj *fut = (FutureObj *)self;
956
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400957 if (Future_CheckExact(fut)) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900958 /* When fut is subclass of Future, finalizer is called from
959 * subtype_dealloc.
960 */
961 if (PyObject_CallFinalizerFromDealloc(self) < 0) {
962 // resurrected.
963 return;
964 }
965 }
966
967 if (fut->fut_weakreflist != NULL) {
968 PyObject_ClearWeakRefs(self);
969 }
970
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400971 (void)FutureObj_clear(fut);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900972 Py_TYPE(fut)->tp_free(fut);
973}
974
975
976/*********************** Future Iterator **************************/
977
978typedef struct {
979 PyObject_HEAD
980 FutureObj *future;
981} futureiterobject;
982
983static void
984FutureIter_dealloc(futureiterobject *it)
985{
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400986 PyObject_GC_UnTrack(it);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900987 Py_XDECREF(it->future);
988 PyObject_GC_Del(it);
989}
990
991static PyObject *
992FutureIter_iternext(futureiterobject *it)
993{
994 PyObject *res;
995 FutureObj *fut = it->future;
996
997 if (fut == NULL) {
998 return NULL;
999 }
1000
1001 if (fut->fut_state == STATE_PENDING) {
1002 if (!fut->fut_blocking) {
1003 fut->fut_blocking = 1;
1004 Py_INCREF(fut);
1005 return (PyObject *)fut;
1006 }
1007 PyErr_Format(PyExc_AssertionError,
1008 "yield from wasn't used with future");
1009 return NULL;
1010 }
1011
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001012 res = _asyncio_Future_result_impl(fut);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001013 if (res != NULL) {
Serhiy Storchaka60e49aa2016-11-06 18:47:03 +02001014 /* The result of the Future is not an exception. */
1015 if (_PyGen_SetStopIterationValue(res) < 0) {
1016 Py_DECREF(res);
Yury Selivanova4b884f2016-10-20 15:54:20 -04001017 return NULL;
1018 }
Serhiy Storchaka60e49aa2016-11-06 18:47:03 +02001019 Py_DECREF(res);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001020 }
1021
1022 it->future = NULL;
1023 Py_DECREF(fut);
1024 return NULL;
1025}
1026
1027static PyObject *
INADA Naoki74c17532016-10-25 19:00:45 +09001028FutureIter_send(futureiterobject *self, PyObject *unused)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001029{
INADA Naoki74c17532016-10-25 19:00:45 +09001030 /* Future.__iter__ doesn't care about values that are pushed to the
1031 * generator, it just returns "self.result().
1032 */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001033 return FutureIter_iternext(self);
1034}
1035
1036static PyObject *
1037FutureIter_throw(futureiterobject *self, PyObject *args)
1038{
1039 PyObject *type=NULL, *val=NULL, *tb=NULL;
1040 if (!PyArg_ParseTuple(args, "O|OO", &type, &val, &tb))
1041 return NULL;
1042
1043 if (val == Py_None) {
1044 val = NULL;
1045 }
1046 if (tb == Py_None) {
1047 tb = NULL;
Benjamin Peterson996fc1f2016-11-14 00:15:44 -08001048 } else if (tb != NULL && !PyTraceBack_Check(tb)) {
1049 PyErr_SetString(PyExc_TypeError, "throw() third argument must be a traceback");
1050 return NULL;
1051 }
1052
1053 Py_INCREF(type);
1054 Py_XINCREF(val);
1055 Py_XINCREF(tb);
1056
1057 if (PyExceptionClass_Check(type)) {
1058 PyErr_NormalizeException(&type, &val, &tb);
Yury Selivanovc2c8fe12016-12-01 11:36:22 -05001059 /* No need to call PyException_SetTraceback since we'll be calling
1060 PyErr_Restore for `type`, `val`, and `tb`. */
Benjamin Peterson996fc1f2016-11-14 00:15:44 -08001061 } else if (PyExceptionInstance_Check(type)) {
1062 if (val) {
1063 PyErr_SetString(PyExc_TypeError,
1064 "instance exception may not have a separate value");
1065 goto fail;
1066 }
1067 val = type;
1068 type = PyExceptionInstance_Class(type);
1069 Py_INCREF(type);
1070 if (tb == NULL)
1071 tb = PyException_GetTraceback(val);
1072 } else {
1073 PyErr_SetString(PyExc_TypeError,
1074 "exceptions must be classes deriving BaseException or "
1075 "instances of such a class");
1076 goto fail;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001077 }
1078
1079 Py_CLEAR(self->future);
1080
Benjamin Peterson996fc1f2016-11-14 00:15:44 -08001081 PyErr_Restore(type, val, tb);
1082
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001083 return FutureIter_iternext(self);
Benjamin Peterson996fc1f2016-11-14 00:15:44 -08001084
1085 fail:
1086 Py_DECREF(type);
1087 Py_XDECREF(val);
1088 Py_XDECREF(tb);
1089 return NULL;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001090}
1091
1092static PyObject *
1093FutureIter_close(futureiterobject *self, PyObject *arg)
1094{
1095 Py_CLEAR(self->future);
1096 Py_RETURN_NONE;
1097}
1098
1099static int
1100FutureIter_traverse(futureiterobject *it, visitproc visit, void *arg)
1101{
1102 Py_VISIT(it->future);
1103 return 0;
1104}
1105
1106static PyMethodDef FutureIter_methods[] = {
1107 {"send", (PyCFunction)FutureIter_send, METH_O, NULL},
1108 {"throw", (PyCFunction)FutureIter_throw, METH_VARARGS, NULL},
1109 {"close", (PyCFunction)FutureIter_close, METH_NOARGS, NULL},
1110 {NULL, NULL} /* Sentinel */
1111};
1112
1113static PyTypeObject FutureIterType = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02001114 PyVarObject_HEAD_INIT(NULL, 0)
INADA Naoki9f2ce252016-10-15 15:39:19 +09001115 "_asyncio.FutureIter",
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001116 .tp_basicsize = sizeof(futureiterobject),
1117 .tp_itemsize = 0,
1118 .tp_dealloc = (destructor)FutureIter_dealloc,
1119 .tp_getattro = PyObject_GenericGetAttr,
1120 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
1121 .tp_traverse = (traverseproc)FutureIter_traverse,
1122 .tp_iter = PyObject_SelfIter,
1123 .tp_iternext = (iternextfunc)FutureIter_iternext,
1124 .tp_methods = FutureIter_methods,
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001125};
1126
1127static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001128future_new_iter(PyObject *fut)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001129{
1130 futureiterobject *it;
1131
1132 if (!PyObject_TypeCheck(fut, &FutureType)) {
1133 PyErr_BadInternalCall();
1134 return NULL;
1135 }
1136 it = PyObject_GC_New(futureiterobject, &FutureIterType);
1137 if (it == NULL) {
1138 return NULL;
1139 }
1140 Py_INCREF(fut);
1141 it->future = (FutureObj*)fut;
INADA Naoki1be427b2016-10-11 02:12:34 +09001142 PyObject_GC_Track(it);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001143 return (PyObject*)it;
1144}
1145
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001146
1147/*********************** Task **************************/
1148
1149
1150/*[clinic input]
1151class _asyncio.Task "TaskObj *" "&Task_Type"
1152[clinic start generated code]*/
1153/*[clinic end generated code: output=da39a3ee5e6b4b0d input=719dcef0fcc03b37]*/
1154
1155static int task_call_step_soon(TaskObj *, PyObject *);
1156static inline PyObject * task_call_wakeup(TaskObj *, PyObject *);
1157static inline PyObject * task_call_step(TaskObj *, PyObject *);
1158static PyObject * task_wakeup(TaskObj *, PyObject *);
1159static PyObject * task_step(TaskObj *, PyObject *);
1160
1161/* ----- Task._step wrapper */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001162
INADA Naokic411a7d2016-10-18 11:48:14 +09001163static int
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001164TaskSendMethWrapper_clear(TaskSendMethWrapper *o)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001165{
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001166 Py_CLEAR(o->sw_task);
1167 Py_CLEAR(o->sw_arg);
1168 return 0;
1169}
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001170
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001171static void
1172TaskSendMethWrapper_dealloc(TaskSendMethWrapper *o)
1173{
1174 PyObject_GC_UnTrack(o);
1175 (void)TaskSendMethWrapper_clear(o);
1176 Py_TYPE(o)->tp_free(o);
1177}
1178
1179static PyObject *
1180TaskSendMethWrapper_call(TaskSendMethWrapper *o,
1181 PyObject *args, PyObject *kwds)
1182{
1183 return task_call_step(o->sw_task, o->sw_arg);
1184}
1185
1186static int
1187TaskSendMethWrapper_traverse(TaskSendMethWrapper *o,
1188 visitproc visit, void *arg)
1189{
1190 Py_VISIT(o->sw_task);
1191 Py_VISIT(o->sw_arg);
1192 return 0;
1193}
1194
1195static PyObject *
1196TaskSendMethWrapper_get___self__(TaskSendMethWrapper *o)
1197{
1198 if (o->sw_task) {
1199 Py_INCREF(o->sw_task);
1200 return (PyObject*)o->sw_task;
1201 }
1202 Py_RETURN_NONE;
1203}
1204
1205static PyGetSetDef TaskSendMethWrapper_getsetlist[] = {
1206 {"__self__", (getter)TaskSendMethWrapper_get___self__, NULL, NULL},
1207 {NULL} /* Sentinel */
1208};
1209
1210PyTypeObject TaskSendMethWrapper_Type = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02001211 PyVarObject_HEAD_INIT(NULL, 0)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001212 "TaskSendMethWrapper",
1213 .tp_basicsize = sizeof(TaskSendMethWrapper),
1214 .tp_itemsize = 0,
1215 .tp_getset = TaskSendMethWrapper_getsetlist,
1216 .tp_dealloc = (destructor)TaskSendMethWrapper_dealloc,
1217 .tp_call = (ternaryfunc)TaskSendMethWrapper_call,
1218 .tp_getattro = PyObject_GenericGetAttr,
1219 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
1220 .tp_traverse = (traverseproc)TaskSendMethWrapper_traverse,
1221 .tp_clear = (inquiry)TaskSendMethWrapper_clear,
1222};
1223
1224static PyObject *
1225TaskSendMethWrapper_new(TaskObj *task, PyObject *arg)
1226{
1227 TaskSendMethWrapper *o;
1228 o = PyObject_GC_New(TaskSendMethWrapper, &TaskSendMethWrapper_Type);
1229 if (o == NULL) {
1230 return NULL;
1231 }
1232
1233 Py_INCREF(task);
1234 o->sw_task = task;
1235
1236 Py_XINCREF(arg);
1237 o->sw_arg = arg;
1238
1239 PyObject_GC_Track(o);
1240 return (PyObject*) o;
1241}
1242
1243/* ----- Task._wakeup wrapper */
1244
1245static PyObject *
1246TaskWakeupMethWrapper_call(TaskWakeupMethWrapper *o,
1247 PyObject *args, PyObject *kwds)
1248{
1249 PyObject *fut;
1250
1251 if (!PyArg_ParseTuple(args, "O|", &fut)) {
1252 return NULL;
1253 }
1254
1255 return task_call_wakeup(o->ww_task, fut);
1256}
1257
1258static int
1259TaskWakeupMethWrapper_clear(TaskWakeupMethWrapper *o)
1260{
1261 Py_CLEAR(o->ww_task);
1262 return 0;
1263}
1264
1265static int
1266TaskWakeupMethWrapper_traverse(TaskWakeupMethWrapper *o,
1267 visitproc visit, void *arg)
1268{
1269 Py_VISIT(o->ww_task);
1270 return 0;
1271}
1272
1273static void
1274TaskWakeupMethWrapper_dealloc(TaskWakeupMethWrapper *o)
1275{
1276 PyObject_GC_UnTrack(o);
1277 (void)TaskWakeupMethWrapper_clear(o);
1278 Py_TYPE(o)->tp_free(o);
1279}
1280
1281PyTypeObject TaskWakeupMethWrapper_Type = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02001282 PyVarObject_HEAD_INIT(NULL, 0)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001283 "TaskWakeupMethWrapper",
1284 .tp_basicsize = sizeof(TaskWakeupMethWrapper),
1285 .tp_itemsize = 0,
1286 .tp_dealloc = (destructor)TaskWakeupMethWrapper_dealloc,
1287 .tp_call = (ternaryfunc)TaskWakeupMethWrapper_call,
1288 .tp_getattro = PyObject_GenericGetAttr,
1289 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
1290 .tp_traverse = (traverseproc)TaskWakeupMethWrapper_traverse,
1291 .tp_clear = (inquiry)TaskWakeupMethWrapper_clear,
1292};
1293
1294static PyObject *
1295TaskWakeupMethWrapper_new(TaskObj *task)
1296{
1297 TaskWakeupMethWrapper *o;
1298 o = PyObject_GC_New(TaskWakeupMethWrapper, &TaskWakeupMethWrapper_Type);
1299 if (o == NULL) {
1300 return NULL;
1301 }
1302
1303 Py_INCREF(task);
1304 o->ww_task = task;
1305
1306 PyObject_GC_Track(o);
1307 return (PyObject*) o;
1308}
1309
1310/* ----- Task */
1311
1312/*[clinic input]
1313_asyncio.Task.__init__
1314
1315 coro: 'O'
1316 *
1317 loop: 'O' = NULL
1318
1319A coroutine wrapped in a Future.
1320[clinic start generated code]*/
1321
1322static int
1323_asyncio_Task___init___impl(TaskObj *self, PyObject *coro, PyObject *loop)
1324/*[clinic end generated code: output=9f24774c2287fc2f input=71d8d28c201a18cd]*/
1325{
1326 PyObject *res;
1327 _Py_IDENTIFIER(add);
1328
1329 if (future_init((FutureObj*)self, loop)) {
INADA Naokic411a7d2016-10-18 11:48:14 +09001330 return -1;
1331 }
INADA Naokic411a7d2016-10-18 11:48:14 +09001332
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001333 self->task_fut_waiter = NULL;
1334 self->task_must_cancel = 0;
1335 self->task_log_destroy_pending = 1;
INADA Naokic411a7d2016-10-18 11:48:14 +09001336
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001337 Py_INCREF(coro);
1338 self->task_coro = coro;
1339
1340 if (task_call_step_soon(self, NULL)) {
1341 return -1;
INADA Naokic411a7d2016-10-18 11:48:14 +09001342 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001343
Victor Stinnercb2128c2016-12-15 09:05:11 +01001344 res = _PyObject_CallMethodIdObjArgs(all_tasks, &PyId_add, self, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001345 if (res == NULL) {
1346 return -1;
1347 }
1348 Py_DECREF(res);
1349
1350 return 0;
1351}
1352
1353static int
1354TaskObj_clear(TaskObj *task)
1355{
1356 (void)FutureObj_clear((FutureObj*) task);
1357 Py_CLEAR(task->task_coro);
1358 Py_CLEAR(task->task_fut_waiter);
1359 return 0;
1360}
1361
1362static int
1363TaskObj_traverse(TaskObj *task, visitproc visit, void *arg)
1364{
1365 Py_VISIT(task->task_coro);
1366 Py_VISIT(task->task_fut_waiter);
1367 (void)FutureObj_traverse((FutureObj*) task, visit, arg);
1368 return 0;
1369}
1370
1371static PyObject *
1372TaskObj_get_log_destroy_pending(TaskObj *task)
1373{
1374 if (task->task_log_destroy_pending) {
1375 Py_RETURN_TRUE;
1376 }
1377 else {
1378 Py_RETURN_FALSE;
1379 }
1380}
1381
1382static int
1383TaskObj_set_log_destroy_pending(TaskObj *task, PyObject *val)
1384{
1385 int is_true = PyObject_IsTrue(val);
1386 if (is_true < 0) {
1387 return -1;
1388 }
1389 task->task_log_destroy_pending = is_true;
1390 return 0;
1391}
1392
1393static PyObject *
1394TaskObj_get_must_cancel(TaskObj *task)
1395{
1396 if (task->task_must_cancel) {
1397 Py_RETURN_TRUE;
1398 }
1399 else {
1400 Py_RETURN_FALSE;
1401 }
1402}
1403
1404static PyObject *
1405TaskObj_get_coro(TaskObj *task)
1406{
1407 if (task->task_coro) {
1408 Py_INCREF(task->task_coro);
1409 return task->task_coro;
1410 }
1411
1412 Py_RETURN_NONE;
1413}
1414
1415static PyObject *
1416TaskObj_get_fut_waiter(TaskObj *task)
1417{
1418 if (task->task_fut_waiter) {
1419 Py_INCREF(task->task_fut_waiter);
1420 return task->task_fut_waiter;
1421 }
1422
1423 Py_RETURN_NONE;
1424}
1425
1426/*[clinic input]
1427@classmethod
1428_asyncio.Task.current_task
1429
Yury Selivanov13802a32017-03-02 22:16:33 -05001430 loop: 'O' = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001431
1432Return the currently running task in an event loop or None.
1433
1434By default the current task for the current event loop is returned.
1435
1436None is returned when called not in the context of a Task.
1437[clinic start generated code]*/
1438
1439static PyObject *
1440_asyncio_Task_current_task_impl(PyTypeObject *type, PyObject *loop)
Yury Selivanov13802a32017-03-02 22:16:33 -05001441/*[clinic end generated code: output=99fbe7332c516e03 input=a0d6cdf2e3b243e1]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001442{
1443 PyObject *res;
1444
Yury Selivanov13802a32017-03-02 22:16:33 -05001445 if (loop == Py_None) {
1446 loop = _PyObject_CallNoArg(asyncio_get_event_loop);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001447 if (loop == NULL) {
1448 return NULL;
1449 }
1450
Yury Selivanov684ef2c2016-10-28 19:01:21 -04001451 res = PyDict_GetItem(current_tasks, loop);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001452 Py_DECREF(loop);
1453 }
1454 else {
Yury Selivanov684ef2c2016-10-28 19:01:21 -04001455 res = PyDict_GetItem(current_tasks, loop);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001456 }
1457
1458 if (res == NULL) {
1459 Py_RETURN_NONE;
1460 }
1461 else {
1462 Py_INCREF(res);
1463 return res;
1464 }
1465}
1466
1467static PyObject *
1468task_all_tasks(PyObject *loop)
1469{
1470 PyObject *task;
1471 PyObject *task_loop;
1472 PyObject *set;
1473 PyObject *iter;
1474
1475 assert(loop != NULL);
1476
1477 set = PySet_New(NULL);
1478 if (set == NULL) {
1479 return NULL;
1480 }
1481
1482 iter = PyObject_GetIter(all_tasks);
1483 if (iter == NULL) {
INADA Naokic411a7d2016-10-18 11:48:14 +09001484 goto fail;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001485 }
1486
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001487 while ((task = PyIter_Next(iter))) {
1488 task_loop = PyObject_GetAttrString(task, "_loop");
1489 if (task_loop == NULL) {
1490 Py_DECREF(task);
1491 goto fail;
1492 }
1493 if (task_loop == loop) {
1494 if (PySet_Add(set, task) == -1) {
1495 Py_DECREF(task_loop);
1496 Py_DECREF(task);
1497 goto fail;
1498 }
1499 }
1500 Py_DECREF(task_loop);
1501 Py_DECREF(task);
1502 }
1503
1504 Py_DECREF(iter);
1505 return set;
1506
1507fail:
1508 Py_XDECREF(set);
1509 Py_XDECREF(iter);
1510 return NULL;
1511}
1512
1513/*[clinic input]
1514@classmethod
1515_asyncio.Task.all_tasks
1516
Yury Selivanov13802a32017-03-02 22:16:33 -05001517 loop: 'O' = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001518
1519Return a set of all tasks for an event loop.
1520
1521By default all tasks for the current event loop are returned.
1522[clinic start generated code]*/
1523
1524static PyObject *
1525_asyncio_Task_all_tasks_impl(PyTypeObject *type, PyObject *loop)
Yury Selivanov13802a32017-03-02 22:16:33 -05001526/*[clinic end generated code: output=11f9b20749ccca5d input=c6f5b53bd487488f]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001527{
1528 PyObject *res;
1529
Yury Selivanov13802a32017-03-02 22:16:33 -05001530 if (loop == Py_None) {
1531 loop = _PyObject_CallNoArg(asyncio_get_event_loop);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001532 if (loop == NULL) {
1533 return NULL;
1534 }
1535
1536 res = task_all_tasks(loop);
1537 Py_DECREF(loop);
1538 }
1539 else {
1540 res = task_all_tasks(loop);
1541 }
1542
1543 return res;
1544}
1545
1546/*[clinic input]
1547_asyncio.Task._repr_info
1548[clinic start generated code]*/
1549
1550static PyObject *
1551_asyncio_Task__repr_info_impl(TaskObj *self)
1552/*[clinic end generated code: output=6a490eb66d5ba34b input=3c6d051ed3ddec8b]*/
1553{
1554 return PyObject_CallFunctionObjArgs(
1555 asyncio_task_repr_info_func, self, NULL);
1556}
1557
1558/*[clinic input]
1559_asyncio.Task.cancel
1560
1561Request that this task cancel itself.
1562
1563This arranges for a CancelledError to be thrown into the
1564wrapped coroutine on the next cycle through the event loop.
1565The coroutine then has a chance to clean up or even deny
1566the request using try/except/finally.
1567
1568Unlike Future.cancel, this does not guarantee that the
1569task will be cancelled: the exception might be caught and
1570acted upon, delaying cancellation of the task or preventing
1571cancellation completely. The task may also return a value or
1572raise a different exception.
1573
1574Immediately after this method is called, Task.cancelled() will
1575not return True (unless the task was already cancelled). A
1576task will be marked as cancelled when the wrapped coroutine
1577terminates with a CancelledError exception (even if cancel()
1578was not called).
1579[clinic start generated code]*/
1580
1581static PyObject *
1582_asyncio_Task_cancel_impl(TaskObj *self)
1583/*[clinic end generated code: output=6bfc0479da9d5757 input=13f9bf496695cb52]*/
1584{
Yury Selivanov176f2eb2017-06-11 14:00:14 +00001585 self->task_log_tb = 0;
1586
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001587 if (self->task_state != STATE_PENDING) {
1588 Py_RETURN_FALSE;
1589 }
1590
1591 if (self->task_fut_waiter) {
1592 PyObject *res;
1593 int is_true;
1594
1595 res = _PyObject_CallMethodId(
1596 self->task_fut_waiter, &PyId_cancel, NULL);
1597 if (res == NULL) {
1598 return NULL;
1599 }
1600
1601 is_true = PyObject_IsTrue(res);
1602 Py_DECREF(res);
1603 if (is_true < 0) {
1604 return NULL;
1605 }
1606
1607 if (is_true) {
1608 Py_RETURN_TRUE;
1609 }
1610 }
1611
1612 self->task_must_cancel = 1;
1613 Py_RETURN_TRUE;
1614}
1615
1616/*[clinic input]
1617_asyncio.Task.get_stack
1618
1619 *
1620 limit: 'O' = None
1621
1622Return the list of stack frames for this task's coroutine.
1623
1624If the coroutine is not done, this returns the stack where it is
1625suspended. If the coroutine has completed successfully or was
1626cancelled, this returns an empty list. If the coroutine was
1627terminated by an exception, this returns the list of traceback
1628frames.
1629
1630The frames are always ordered from oldest to newest.
1631
1632The optional limit gives the maximum number of frames to
1633return; by default all available frames are returned. Its
1634meaning differs depending on whether a stack or a traceback is
1635returned: the newest frames of a stack are returned, but the
1636oldest frames of a traceback are returned. (This matches the
1637behavior of the traceback module.)
1638
1639For reasons beyond our control, only one stack frame is
1640returned for a suspended coroutine.
1641[clinic start generated code]*/
1642
1643static PyObject *
1644_asyncio_Task_get_stack_impl(TaskObj *self, PyObject *limit)
1645/*[clinic end generated code: output=c9aeeeebd1e18118 input=b1920230a766d17a]*/
1646{
1647 return PyObject_CallFunctionObjArgs(
1648 asyncio_task_get_stack_func, self, limit, NULL);
1649}
1650
1651/*[clinic input]
1652_asyncio.Task.print_stack
1653
1654 *
1655 limit: 'O' = None
1656 file: 'O' = None
1657
1658Print the stack or traceback for this task's coroutine.
1659
1660This produces output similar to that of the traceback module,
1661for the frames retrieved by get_stack(). The limit argument
1662is passed to get_stack(). The file argument is an I/O stream
1663to which the output is written; by default output is written
1664to sys.stderr.
1665[clinic start generated code]*/
1666
1667static PyObject *
1668_asyncio_Task_print_stack_impl(TaskObj *self, PyObject *limit,
1669 PyObject *file)
1670/*[clinic end generated code: output=7339e10314cd3f4d input=19f1e99ab5400bc3]*/
1671{
1672 return PyObject_CallFunctionObjArgs(
1673 asyncio_task_print_stack_func, self, limit, file, NULL);
1674}
1675
1676/*[clinic input]
1677_asyncio.Task._step
1678
1679 exc: 'O' = NULL
1680[clinic start generated code]*/
1681
1682static PyObject *
1683_asyncio_Task__step_impl(TaskObj *self, PyObject *exc)
1684/*[clinic end generated code: output=7ed23f0cefd5ae42 input=ada4b2324e5370af]*/
1685{
1686 return task_step(self, exc == Py_None ? NULL : exc);
1687}
1688
1689/*[clinic input]
1690_asyncio.Task._wakeup
1691
1692 fut: 'O'
1693[clinic start generated code]*/
1694
1695static PyObject *
1696_asyncio_Task__wakeup_impl(TaskObj *self, PyObject *fut)
1697/*[clinic end generated code: output=75cb341c760fd071 input=11ee4918a5bdbf21]*/
1698{
1699 return task_wakeup(self, fut);
1700}
1701
1702static void
1703TaskObj_finalize(TaskObj *task)
1704{
1705 _Py_IDENTIFIER(call_exception_handler);
1706 _Py_IDENTIFIER(task);
1707 _Py_IDENTIFIER(message);
1708 _Py_IDENTIFIER(source_traceback);
1709
1710 PyObject *message = NULL;
1711 PyObject *context = NULL;
1712 PyObject *func = NULL;
1713 PyObject *res = NULL;
1714
1715 PyObject *error_type, *error_value, *error_traceback;
1716
1717 if (task->task_state != STATE_PENDING || !task->task_log_destroy_pending) {
1718 goto done;
1719 }
1720
1721 /* Save the current exception, if any. */
1722 PyErr_Fetch(&error_type, &error_value, &error_traceback);
1723
1724 context = PyDict_New();
1725 if (context == NULL) {
1726 goto finally;
1727 }
1728
1729 message = PyUnicode_FromString("Task was destroyed but it is pending!");
1730 if (message == NULL) {
1731 goto finally;
1732 }
1733
1734 if (_PyDict_SetItemId(context, &PyId_message, message) < 0 ||
1735 _PyDict_SetItemId(context, &PyId_task, (PyObject*)task) < 0)
1736 {
1737 goto finally;
1738 }
1739
1740 if (task->task_source_tb != NULL) {
1741 if (_PyDict_SetItemId(context, &PyId_source_traceback,
1742 task->task_source_tb) < 0)
1743 {
1744 goto finally;
1745 }
1746 }
1747
1748 func = _PyObject_GetAttrId(task->task_loop, &PyId_call_exception_handler);
1749 if (func != NULL) {
1750 res = _PyObject_CallArg1(func, context);
1751 if (res == NULL) {
1752 PyErr_WriteUnraisable(func);
1753 }
1754 }
1755
1756finally:
1757 Py_CLEAR(context);
1758 Py_CLEAR(message);
1759 Py_CLEAR(func);
1760 Py_CLEAR(res);
1761
1762 /* Restore the saved exception. */
1763 PyErr_Restore(error_type, error_value, error_traceback);
1764
1765done:
1766 FutureObj_finalize((FutureObj*)task);
1767}
1768
1769static void TaskObj_dealloc(PyObject *); /* Needs Task_CheckExact */
1770
1771static PyMethodDef TaskType_methods[] = {
1772 _ASYNCIO_FUTURE_RESULT_METHODDEF
1773 _ASYNCIO_FUTURE_EXCEPTION_METHODDEF
1774 _ASYNCIO_FUTURE_SET_RESULT_METHODDEF
1775 _ASYNCIO_FUTURE_SET_EXCEPTION_METHODDEF
1776 _ASYNCIO_FUTURE_ADD_DONE_CALLBACK_METHODDEF
1777 _ASYNCIO_FUTURE_REMOVE_DONE_CALLBACK_METHODDEF
1778 _ASYNCIO_FUTURE_CANCELLED_METHODDEF
1779 _ASYNCIO_FUTURE_DONE_METHODDEF
1780 _ASYNCIO_TASK_CURRENT_TASK_METHODDEF
1781 _ASYNCIO_TASK_ALL_TASKS_METHODDEF
1782 _ASYNCIO_TASK_CANCEL_METHODDEF
1783 _ASYNCIO_TASK_GET_STACK_METHODDEF
1784 _ASYNCIO_TASK_PRINT_STACK_METHODDEF
1785 _ASYNCIO_TASK__WAKEUP_METHODDEF
1786 _ASYNCIO_TASK__STEP_METHODDEF
1787 _ASYNCIO_TASK__REPR_INFO_METHODDEF
1788 {NULL, NULL} /* Sentinel */
1789};
1790
1791static PyGetSetDef TaskType_getsetlist[] = {
1792 FUTURE_COMMON_GETSETLIST
1793 {"_log_destroy_pending", (getter)TaskObj_get_log_destroy_pending,
1794 (setter)TaskObj_set_log_destroy_pending, NULL},
1795 {"_must_cancel", (getter)TaskObj_get_must_cancel, NULL, NULL},
1796 {"_coro", (getter)TaskObj_get_coro, NULL, NULL},
1797 {"_fut_waiter", (getter)TaskObj_get_fut_waiter, NULL, NULL},
1798 {NULL} /* Sentinel */
1799};
1800
1801static PyTypeObject TaskType = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02001802 PyVarObject_HEAD_INIT(NULL, 0)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001803 "_asyncio.Task",
1804 sizeof(TaskObj), /* tp_basicsize */
1805 .tp_base = &FutureType,
1806 .tp_dealloc = TaskObj_dealloc,
1807 .tp_as_async = &FutureType_as_async,
1808 .tp_repr = (reprfunc)FutureObj_repr,
1809 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE
1810 | Py_TPFLAGS_HAVE_FINALIZE,
1811 .tp_doc = _asyncio_Task___init____doc__,
1812 .tp_traverse = (traverseproc)TaskObj_traverse,
1813 .tp_clear = (inquiry)TaskObj_clear,
1814 .tp_weaklistoffset = offsetof(TaskObj, task_weakreflist),
1815 .tp_iter = (getiterfunc)future_new_iter,
1816 .tp_methods = TaskType_methods,
1817 .tp_getset = TaskType_getsetlist,
1818 .tp_dictoffset = offsetof(TaskObj, dict),
1819 .tp_init = (initproc)_asyncio_Task___init__,
1820 .tp_new = PyType_GenericNew,
1821 .tp_finalize = (destructor)TaskObj_finalize,
1822};
1823
1824#define Task_CheckExact(obj) (Py_TYPE(obj) == &TaskType)
1825
1826static void
1827TaskObj_dealloc(PyObject *self)
1828{
1829 TaskObj *task = (TaskObj *)self;
1830
1831 if (Task_CheckExact(self)) {
1832 /* When fut is subclass of Task, finalizer is called from
1833 * subtype_dealloc.
1834 */
1835 if (PyObject_CallFinalizerFromDealloc(self) < 0) {
1836 // resurrected.
1837 return;
1838 }
1839 }
1840
1841 if (task->task_weakreflist != NULL) {
1842 PyObject_ClearWeakRefs(self);
1843 }
1844
1845 (void)TaskObj_clear(task);
1846 Py_TYPE(task)->tp_free(task);
1847}
1848
1849static inline PyObject *
1850task_call_wakeup(TaskObj *task, PyObject *fut)
1851{
1852 if (Task_CheckExact(task)) {
1853 return task_wakeup(task, fut);
1854 }
1855 else {
1856 /* `task` is a subclass of Task */
Victor Stinnercb2128c2016-12-15 09:05:11 +01001857 return _PyObject_CallMethodIdObjArgs((PyObject*)task, &PyId__wakeup,
1858 fut, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001859 }
1860}
1861
1862static inline PyObject *
1863task_call_step(TaskObj *task, PyObject *arg)
1864{
1865 if (Task_CheckExact(task)) {
1866 return task_step(task, arg);
1867 }
1868 else {
1869 /* `task` is a subclass of Task */
1870 if (arg == NULL) {
1871 arg = Py_None;
1872 }
Victor Stinnercb2128c2016-12-15 09:05:11 +01001873 return _PyObject_CallMethodIdObjArgs((PyObject*)task, &PyId__step,
1874 arg, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001875 }
1876}
1877
1878static int
1879task_call_step_soon(TaskObj *task, PyObject *arg)
1880{
1881 PyObject *handle;
1882
1883 PyObject *cb = TaskSendMethWrapper_new(task, arg);
1884 if (cb == NULL) {
1885 return -1;
1886 }
1887
Victor Stinnercb2128c2016-12-15 09:05:11 +01001888 handle = _PyObject_CallMethodIdObjArgs(task->task_loop, &PyId_call_soon,
1889 cb, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001890 Py_DECREF(cb);
1891 if (handle == NULL) {
1892 return -1;
1893 }
1894
1895 Py_DECREF(handle);
1896 return 0;
1897}
1898
1899static PyObject *
1900task_set_error_soon(TaskObj *task, PyObject *et, const char *format, ...)
1901{
1902 PyObject* msg;
1903
1904 va_list vargs;
1905#ifdef HAVE_STDARG_PROTOTYPES
1906 va_start(vargs, format);
1907#else
1908 va_start(vargs);
1909#endif
1910 msg = PyUnicode_FromFormatV(format, vargs);
1911 va_end(vargs);
1912
1913 if (msg == NULL) {
1914 return NULL;
1915 }
1916
1917 PyObject *e = PyObject_CallFunctionObjArgs(et, msg, NULL);
1918 Py_DECREF(msg);
1919 if (e == NULL) {
1920 return NULL;
1921 }
1922
1923 if (task_call_step_soon(task, e) == -1) {
1924 Py_DECREF(e);
1925 return NULL;
1926 }
1927
1928 Py_DECREF(e);
1929 Py_RETURN_NONE;
1930}
1931
1932static PyObject *
1933task_step_impl(TaskObj *task, PyObject *exc)
1934{
1935 int res;
1936 int clear_exc = 0;
1937 PyObject *result = NULL;
1938 PyObject *coro = task->task_coro;
1939 PyObject *o;
1940
1941 if (task->task_state != STATE_PENDING) {
1942 PyErr_Format(PyExc_AssertionError,
1943 "_step(): already done: %R %R",
1944 task,
1945 exc ? exc : Py_None);
INADA Naokic411a7d2016-10-18 11:48:14 +09001946 goto fail;
1947 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001948
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001949 if (task->task_must_cancel) {
1950 assert(exc != Py_None);
1951
1952 if (exc) {
1953 /* Check if exc is a CancelledError */
1954 res = PyObject_IsInstance(exc, asyncio_CancelledError);
1955 if (res == -1) {
1956 /* An error occurred, abort */
1957 goto fail;
1958 }
1959 if (res == 0) {
1960 /* exc is not CancelledError; reset it to NULL */
1961 exc = NULL;
1962 }
1963 }
1964
1965 if (!exc) {
1966 /* exc was not a CancelledError */
1967 exc = PyObject_CallFunctionObjArgs(asyncio_CancelledError, NULL);
1968 if (!exc) {
1969 goto fail;
1970 }
1971 clear_exc = 1;
1972 }
1973
1974 task->task_must_cancel = 0;
1975 }
1976
1977 Py_CLEAR(task->task_fut_waiter);
1978
1979 if (exc == NULL) {
1980 if (PyGen_CheckExact(coro) || PyCoro_CheckExact(coro)) {
1981 result = _PyGen_Send((PyGenObject*)coro, Py_None);
1982 }
1983 else {
1984 result = _PyObject_CallMethodIdObjArgs(
1985 coro, &PyId_send, Py_None, NULL);
1986 }
1987 }
1988 else {
1989 result = _PyObject_CallMethodIdObjArgs(
1990 coro, &PyId_throw, exc, NULL);
1991 if (clear_exc) {
1992 /* We created 'exc' during this call */
1993 Py_CLEAR(exc);
1994 }
1995 }
1996
1997 if (result == NULL) {
1998 PyObject *et, *ev, *tb;
1999
2000 if (_PyGen_FetchStopIterationValue(&o) == 0) {
2001 /* The error is StopIteration and that means that
2002 the underlying coroutine has resolved */
INADA Naoki3dc7c522017-05-11 21:56:42 +09002003 if (task->task_must_cancel) {
2004 // Task is cancelled right before coro stops.
2005 Py_DECREF(o);
2006 task->task_must_cancel = 0;
2007 et = asyncio_CancelledError;
2008 Py_INCREF(et);
2009 ev = NULL;
2010 tb = NULL;
2011 goto set_exception;
2012 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002013 PyObject *res = future_set_result((FutureObj*)task, o);
2014 Py_DECREF(o);
2015 if (res == NULL) {
2016 return NULL;
2017 }
2018 Py_DECREF(res);
2019 Py_RETURN_NONE;
2020 }
2021
2022 if (PyErr_ExceptionMatches(asyncio_CancelledError)) {
2023 /* CancelledError */
2024 PyErr_Clear();
2025 return future_cancel((FutureObj*)task);
2026 }
2027
2028 /* Some other exception; pop it and call Task.set_exception() */
2029 PyErr_Fetch(&et, &ev, &tb);
INADA Naoki3dc7c522017-05-11 21:56:42 +09002030
2031set_exception:
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002032 assert(et);
2033 if (!ev || !PyObject_TypeCheck(ev, (PyTypeObject *) et)) {
2034 PyErr_NormalizeException(&et, &ev, &tb);
2035 }
Yury Selivanovc2c8fe12016-12-01 11:36:22 -05002036 if (tb != NULL) {
2037 PyException_SetTraceback(ev, tb);
2038 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002039 o = future_set_exception((FutureObj*)task, ev);
2040 if (!o) {
2041 /* An exception in Task.set_exception() */
2042 Py_XDECREF(et);
2043 Py_XDECREF(tb);
2044 Py_XDECREF(ev);
2045 goto fail;
2046 }
2047 assert(o == Py_None);
2048 Py_CLEAR(o);
2049
2050 if (!PyErr_GivenExceptionMatches(et, PyExc_Exception)) {
2051 /* We've got a BaseException; re-raise it */
2052 PyErr_Restore(et, ev, tb);
2053 goto fail;
2054 }
2055
2056 Py_XDECREF(et);
2057 Py_XDECREF(tb);
2058 Py_XDECREF(ev);
2059
2060 Py_RETURN_NONE;
2061 }
2062
2063 if (result == (PyObject*)task) {
2064 /* We have a task that wants to await on itself */
2065 goto self_await;
2066 }
2067
2068 /* Check if `result` is FutureObj or TaskObj (and not a subclass) */
2069 if (Future_CheckExact(result) || Task_CheckExact(result)) {
2070 PyObject *wrapper;
2071 PyObject *res;
2072 FutureObj *fut = (FutureObj*)result;
2073
2074 /* Check if `result` future is attached to a different loop */
2075 if (fut->fut_loop != task->task_loop) {
2076 goto different_loop;
2077 }
2078
2079 if (fut->fut_blocking) {
2080 fut->fut_blocking = 0;
2081
2082 /* result.add_done_callback(task._wakeup) */
2083 wrapper = TaskWakeupMethWrapper_new(task);
2084 if (wrapper == NULL) {
2085 goto fail;
2086 }
2087 res = future_add_done_callback((FutureObj*)result, wrapper);
2088 Py_DECREF(wrapper);
2089 if (res == NULL) {
2090 goto fail;
2091 }
2092 Py_DECREF(res);
2093
2094 /* task._fut_waiter = result */
2095 task->task_fut_waiter = result; /* no incref is necessary */
2096
2097 if (task->task_must_cancel) {
2098 PyObject *r;
2099 r = future_cancel(fut);
2100 if (r == NULL) {
2101 return NULL;
2102 }
2103 if (r == Py_True) {
2104 task->task_must_cancel = 0;
2105 }
2106 Py_DECREF(r);
2107 }
2108
2109 Py_RETURN_NONE;
2110 }
2111 else {
2112 goto yield_insteadof_yf;
2113 }
2114 }
2115
2116 /* Check if `result` is a Future-compatible object */
2117 o = PyObject_GetAttrString(result, "_asyncio_future_blocking");
2118 if (o == NULL) {
2119 if (PyErr_ExceptionMatches(PyExc_AttributeError)) {
2120 PyErr_Clear();
2121 }
2122 else {
2123 goto fail;
2124 }
2125 }
2126 else {
2127 if (o == Py_None) {
2128 Py_CLEAR(o);
2129 }
2130 else {
2131 /* `result` is a Future-compatible object */
2132 PyObject *wrapper;
2133 PyObject *res;
2134
2135 int blocking = PyObject_IsTrue(o);
2136 Py_CLEAR(o);
2137 if (blocking < 0) {
2138 goto fail;
2139 }
2140
2141 /* Check if `result` future is attached to a different loop */
2142 PyObject *oloop = PyObject_GetAttrString(result, "_loop");
2143 if (oloop == NULL) {
2144 goto fail;
2145 }
2146 if (oloop != task->task_loop) {
2147 Py_DECREF(oloop);
2148 goto different_loop;
2149 }
2150 else {
2151 Py_DECREF(oloop);
2152 }
2153
2154 if (blocking) {
2155 /* result._asyncio_future_blocking = False */
2156 if (PyObject_SetAttrString(
2157 result, "_asyncio_future_blocking", Py_False) == -1) {
2158 goto fail;
2159 }
2160
2161 /* result.add_done_callback(task._wakeup) */
2162 wrapper = TaskWakeupMethWrapper_new(task);
2163 if (wrapper == NULL) {
2164 goto fail;
2165 }
Victor Stinnercb2128c2016-12-15 09:05:11 +01002166 res = _PyObject_CallMethodIdObjArgs(result,
2167 &PyId_add_done_callback,
2168 wrapper, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002169 Py_DECREF(wrapper);
2170 if (res == NULL) {
2171 goto fail;
2172 }
2173 Py_DECREF(res);
2174
2175 /* task._fut_waiter = result */
2176 task->task_fut_waiter = result; /* no incref is necessary */
2177
2178 if (task->task_must_cancel) {
2179 PyObject *r;
2180 int is_true;
2181 r = _PyObject_CallMethodId(result, &PyId_cancel, NULL);
2182 if (r == NULL) {
2183 return NULL;
2184 }
2185 is_true = PyObject_IsTrue(r);
2186 Py_DECREF(r);
2187 if (is_true < 0) {
2188 return NULL;
2189 }
2190 else if (is_true) {
2191 task->task_must_cancel = 0;
2192 }
2193 }
2194
2195 Py_RETURN_NONE;
2196 }
2197 else {
2198 goto yield_insteadof_yf;
2199 }
2200 }
2201 }
2202
2203 /* Check if `result` is None */
2204 if (result == Py_None) {
2205 /* Bare yield relinquishes control for one event loop iteration. */
2206 if (task_call_step_soon(task, NULL)) {
2207 goto fail;
2208 }
2209 return result;
2210 }
2211
2212 /* Check if `result` is a generator */
2213 o = PyObject_CallFunctionObjArgs(inspect_isgenerator, result, NULL);
2214 if (o == NULL) {
2215 /* An exception in inspect.isgenerator */
2216 goto fail;
2217 }
2218 res = PyObject_IsTrue(o);
2219 Py_CLEAR(o);
2220 if (res == -1) {
2221 /* An exception while checking if 'val' is True */
2222 goto fail;
2223 }
2224 if (res == 1) {
2225 /* `result` is a generator */
2226 PyObject *ret;
2227 ret = task_set_error_soon(
2228 task, PyExc_RuntimeError,
2229 "yield was used instead of yield from for "
2230 "generator in task %R with %S", task, result);
2231 Py_DECREF(result);
2232 return ret;
2233 }
2234
2235 /* The `result` is none of the above */
2236 Py_DECREF(result);
2237 return task_set_error_soon(
2238 task, PyExc_RuntimeError, "Task got bad yield: %R", result);
2239
2240self_await:
2241 o = task_set_error_soon(
2242 task, PyExc_RuntimeError,
2243 "Task cannot await on itself: %R", task);
2244 Py_DECREF(result);
2245 return o;
2246
2247yield_insteadof_yf:
2248 o = task_set_error_soon(
2249 task, PyExc_RuntimeError,
2250 "yield was used instead of yield from "
2251 "in task %R with %R",
2252 task, result);
2253 Py_DECREF(result);
2254 return o;
2255
2256different_loop:
2257 o = task_set_error_soon(
2258 task, PyExc_RuntimeError,
2259 "Task %R got Future %R attached to a different loop",
2260 task, result);
2261 Py_DECREF(result);
2262 return o;
2263
2264fail:
2265 Py_XDECREF(result);
2266 return NULL;
2267}
2268
2269static PyObject *
2270task_step(TaskObj *task, PyObject *exc)
2271{
2272 PyObject *res;
2273 PyObject *ot;
2274
Yury Selivanov684ef2c2016-10-28 19:01:21 -04002275 if (PyDict_SetItem(current_tasks,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002276 task->task_loop, (PyObject*)task) == -1)
2277 {
2278 return NULL;
2279 }
2280
2281 res = task_step_impl(task, exc);
2282
2283 if (res == NULL) {
2284 PyObject *et, *ev, *tb;
2285 PyErr_Fetch(&et, &ev, &tb);
2286 ot = _PyDict_Pop(current_tasks, task->task_loop, NULL);
2287 if (ot == NULL) {
2288 Py_XDECREF(et);
2289 Py_XDECREF(tb);
2290 Py_XDECREF(ev);
2291 return NULL;
2292 }
2293 Py_DECREF(ot);
2294 PyErr_Restore(et, ev, tb);
2295 return NULL;
2296 }
2297 else {
2298 ot = _PyDict_Pop(current_tasks, task->task_loop, NULL);
2299 if (ot == NULL) {
2300 Py_DECREF(res);
2301 return NULL;
2302 }
2303 else {
2304 Py_DECREF(ot);
2305 return res;
2306 }
2307 }
2308}
2309
2310static PyObject *
2311task_wakeup(TaskObj *task, PyObject *o)
2312{
2313 assert(o);
2314
2315 if (Future_CheckExact(o) || Task_CheckExact(o)) {
2316 PyObject *fut_result = NULL;
2317 int res = future_get_result((FutureObj*)o, &fut_result);
2318 PyObject *result;
2319
2320 switch(res) {
2321 case -1:
2322 assert(fut_result == NULL);
2323 return NULL;
2324 case 0:
2325 Py_DECREF(fut_result);
2326 return task_call_step(task, NULL);
2327 default:
2328 assert(res == 1);
2329 result = task_call_step(task, fut_result);
2330 Py_DECREF(fut_result);
2331 return result;
2332 }
2333 }
2334
2335 PyObject *fut_result = PyObject_CallMethod(o, "result", NULL);
2336 if (fut_result == NULL) {
2337 PyObject *et, *ev, *tb;
2338 PyObject *res;
2339
2340 PyErr_Fetch(&et, &ev, &tb);
2341 if (!ev || !PyObject_TypeCheck(ev, (PyTypeObject *) et)) {
2342 PyErr_NormalizeException(&et, &ev, &tb);
2343 }
2344
2345 res = task_call_step(task, ev);
2346
2347 Py_XDECREF(et);
2348 Py_XDECREF(tb);
2349 Py_XDECREF(ev);
2350
2351 return res;
2352 }
2353 else {
2354 Py_DECREF(fut_result);
2355 return task_call_step(task, NULL);
2356 }
2357}
2358
2359
2360/*********************** Module **************************/
2361
2362
2363static void
2364module_free(void *m)
2365{
2366 Py_CLEAR(current_tasks);
2367 Py_CLEAR(all_tasks);
2368 Py_CLEAR(traceback_extract_stack);
2369 Py_CLEAR(asyncio_get_event_loop);
2370 Py_CLEAR(asyncio_future_repr_info_func);
2371 Py_CLEAR(asyncio_task_repr_info_func);
2372 Py_CLEAR(asyncio_task_get_stack_func);
2373 Py_CLEAR(asyncio_task_print_stack_func);
2374 Py_CLEAR(asyncio_InvalidStateError);
2375 Py_CLEAR(asyncio_CancelledError);
2376 Py_CLEAR(inspect_isgenerator);
2377}
2378
2379static int
2380module_init(void)
2381{
2382 PyObject *module = NULL;
2383 PyObject *cls;
2384
2385#define WITH_MOD(NAME) \
2386 Py_CLEAR(module); \
2387 module = PyImport_ImportModule(NAME); \
2388 if (module == NULL) { \
2389 return -1; \
2390 }
2391
2392#define GET_MOD_ATTR(VAR, NAME) \
2393 VAR = PyObject_GetAttrString(module, NAME); \
2394 if (VAR == NULL) { \
2395 goto fail; \
2396 }
2397
2398 WITH_MOD("asyncio.events")
2399 GET_MOD_ATTR(asyncio_get_event_loop, "get_event_loop")
2400
2401 WITH_MOD("asyncio.base_futures")
2402 GET_MOD_ATTR(asyncio_future_repr_info_func, "_future_repr_info")
2403 GET_MOD_ATTR(asyncio_InvalidStateError, "InvalidStateError")
2404 GET_MOD_ATTR(asyncio_CancelledError, "CancelledError")
2405
2406 WITH_MOD("asyncio.base_tasks")
2407 GET_MOD_ATTR(asyncio_task_repr_info_func, "_task_repr_info")
2408 GET_MOD_ATTR(asyncio_task_get_stack_func, "_task_get_stack")
2409 GET_MOD_ATTR(asyncio_task_print_stack_func, "_task_print_stack")
2410
2411 WITH_MOD("inspect")
2412 GET_MOD_ATTR(inspect_isgenerator, "isgenerator")
2413
2414 WITH_MOD("traceback")
2415 GET_MOD_ATTR(traceback_extract_stack, "extract_stack")
2416
2417 WITH_MOD("weakref")
2418 GET_MOD_ATTR(cls, "WeakSet")
2419 all_tasks = PyObject_CallObject(cls, NULL);
2420 Py_CLEAR(cls);
2421 if (all_tasks == NULL) {
INADA Naokic411a7d2016-10-18 11:48:14 +09002422 goto fail;
2423 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09002424
Yury Selivanov684ef2c2016-10-28 19:01:21 -04002425 current_tasks = PyDict_New();
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002426 if (current_tasks == NULL) {
2427 goto fail;
2428 }
2429
2430 Py_CLEAR(module);
INADA Naokic411a7d2016-10-18 11:48:14 +09002431 return 0;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09002432
INADA Naokic411a7d2016-10-18 11:48:14 +09002433fail:
INADA Naokic411a7d2016-10-18 11:48:14 +09002434 Py_CLEAR(module);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002435 module_free(NULL);
INADA Naokic411a7d2016-10-18 11:48:14 +09002436 return -1;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09002437
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002438#undef WITH_MOD
2439#undef GET_MOD_ATTR
2440}
INADA Naoki9e4e38e2016-10-09 14:44:47 +09002441
INADA Naokic411a7d2016-10-18 11:48:14 +09002442PyDoc_STRVAR(module_doc, "Accelerator module for asyncio");
INADA Naoki9e4e38e2016-10-09 14:44:47 +09002443
INADA Naoki9f2ce252016-10-15 15:39:19 +09002444static struct PyModuleDef _asynciomodule = {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09002445 PyModuleDef_HEAD_INIT, /* m_base */
INADA Naoki9f2ce252016-10-15 15:39:19 +09002446 "_asyncio", /* m_name */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09002447 module_doc, /* m_doc */
2448 -1, /* m_size */
INADA Naokic411a7d2016-10-18 11:48:14 +09002449 NULL, /* m_methods */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09002450 NULL, /* m_slots */
2451 NULL, /* m_traverse */
2452 NULL, /* m_clear */
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002453 (freefunc)module_free /* m_free */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09002454};
2455
2456
2457PyMODINIT_FUNC
INADA Naoki9f2ce252016-10-15 15:39:19 +09002458PyInit__asyncio(void)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09002459{
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002460 if (module_init() < 0) {
INADA Naokic411a7d2016-10-18 11:48:14 +09002461 return NULL;
2462 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09002463 if (PyType_Ready(&FutureType) < 0) {
2464 return NULL;
2465 }
2466 if (PyType_Ready(&FutureIterType) < 0) {
2467 return NULL;
2468 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002469 if (PyType_Ready(&TaskSendMethWrapper_Type) < 0) {
2470 return NULL;
2471 }
2472 if(PyType_Ready(&TaskWakeupMethWrapper_Type) < 0) {
2473 return NULL;
2474 }
2475 if (PyType_Ready(&TaskType) < 0) {
2476 return NULL;
2477 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09002478
INADA Naoki9f2ce252016-10-15 15:39:19 +09002479 PyObject *m = PyModule_Create(&_asynciomodule);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09002480 if (m == NULL) {
2481 return NULL;
2482 }
2483
2484 Py_INCREF(&FutureType);
2485 if (PyModule_AddObject(m, "Future", (PyObject *)&FutureType) < 0) {
2486 Py_DECREF(&FutureType);
2487 return NULL;
2488 }
2489
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002490 Py_INCREF(&TaskType);
2491 if (PyModule_AddObject(m, "Task", (PyObject *)&TaskType) < 0) {
2492 Py_DECREF(&TaskType);
2493 return NULL;
2494 }
2495
INADA Naoki9e4e38e2016-10-09 14:44:47 +09002496 return m;
2497}