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