blob: ceac7f0039e949094659a33da1c5451296d2a8c6 [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
Victor Stinnerb6ed57d2016-12-09 14:24:02 +0100121 handle = _PyObject_CallMethodIdObjArgs(fut->fut_loop, &PyId_call_soon,
122 cb, fut, NULL);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900123
124 if (handle == NULL) {
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) {
Victor Stinnera5ed5f02016-12-06 18:45:50 +0100144 loop = _PyObject_CallNoArg(asyncio_get_event_loop);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900145 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);
Victor Stinnera5ed5f02016-12-06 18:45:50 +0100161 fut->fut_source_tb = _PyObject_CallNoArg(traceback_extract_stack);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900162 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)) {
Victor Stinnera5ed5f02016-12-06 18:45:50 +0100207 exc_val = _PyObject_CallNoArg(exc);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900208 if (exc_val == NULL) {
209 return NULL;
210 }
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
Victor Stinner7bfb42d2016-12-05 17:04:32 +0100260 exc = PyObject_CallFunctionObjArgs(asyncio_InvalidStateError, msg, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400261 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) {
Victor Stinnerb6ed57d2016-12-09 14:24:02 +0100286 PyObject *handle = _PyObject_CallMethodIdObjArgs(fut->fut_loop,
287 &PyId_call_soon,
288 arg, fut, NULL);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900289
290 if (handle == NULL) {
291 return NULL;
292 }
293 else {
294 Py_DECREF(handle);
295 }
296 }
297 else {
298 int err = PyList_Append(fut->fut_callbacks, arg);
299 if (err != 0) {
300 return NULL;
301 }
302 }
303 Py_RETURN_NONE;
304}
305
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400306static PyObject *
307future_cancel(FutureObj *fut)
308{
309 if (fut->fut_state != STATE_PENDING) {
310 Py_RETURN_FALSE;
311 }
312 fut->fut_state = STATE_CANCELLED;
313
314 if (future_call_schedule_callbacks(fut) == -1) {
315 return NULL;
316 }
317
318 Py_RETURN_TRUE;
319}
320
321/*[clinic input]
322_asyncio.Future.__init__
323
324 *
325 loop: 'O' = NULL
326
327This class is *almost* compatible with concurrent.futures.Future.
328
329 Differences:
330
331 - result() and exception() do not take a timeout argument and
332 raise an exception when the future isn't done yet.
333
334 - Callbacks registered with add_done_callback() are always called
335 via the event loop's call_soon_threadsafe().
336
337 - This class is not compatible with the wait() and as_completed()
338 methods in the concurrent.futures package.
339[clinic start generated code]*/
340
341static int
342_asyncio_Future___init___impl(FutureObj *self, PyObject *loop)
343/*[clinic end generated code: output=9ed75799eaccb5d6 input=8e1681f23605be2d]*/
344
345{
346 return future_init(self, loop);
347}
348
349static int
350FutureObj_clear(FutureObj *fut)
351{
352 Py_CLEAR(fut->fut_loop);
353 Py_CLEAR(fut->fut_callbacks);
354 Py_CLEAR(fut->fut_result);
355 Py_CLEAR(fut->fut_exception);
356 Py_CLEAR(fut->fut_source_tb);
357 Py_CLEAR(fut->dict);
358 return 0;
359}
360
361static int
362FutureObj_traverse(FutureObj *fut, visitproc visit, void *arg)
363{
364 Py_VISIT(fut->fut_loop);
365 Py_VISIT(fut->fut_callbacks);
366 Py_VISIT(fut->fut_result);
367 Py_VISIT(fut->fut_exception);
368 Py_VISIT(fut->fut_source_tb);
369 Py_VISIT(fut->dict);
370 return 0;
371}
372
373/*[clinic input]
374_asyncio.Future.result
375
376Return the result this future represents.
377
378If the future has been cancelled, raises CancelledError. If the
379future's result isn't yet available, raises InvalidStateError. If
380the future is done and has an exception set, this exception is raised.
381[clinic start generated code]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900382
383static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400384_asyncio_Future_result_impl(FutureObj *self)
385/*[clinic end generated code: output=f35f940936a4b1e5 input=49ecf9cf5ec50dc5]*/
386{
387 PyObject *result;
388 int res = future_get_result(self, &result);
389
390 if (res == -1) {
391 return NULL;
392 }
393
394 if (res == 0) {
395 return result;
396 }
397
398 assert(res == 1);
399
400 PyErr_SetObject(PyExceptionInstance_Class(result), result);
401 Py_DECREF(result);
402 return NULL;
403}
404
405/*[clinic input]
406_asyncio.Future.exception
407
408Return the exception that was set on this future.
409
410The exception (or None if no exception was set) is returned only if
411the future is done. If the future has been cancelled, raises
412CancelledError. If the future isn't done yet, raises
413InvalidStateError.
414[clinic start generated code]*/
415
416static PyObject *
417_asyncio_Future_exception_impl(FutureObj *self)
418/*[clinic end generated code: output=88b20d4f855e0710 input=733547a70c841c68]*/
419{
420 if (self->fut_state == STATE_CANCELLED) {
421 PyErr_SetString(asyncio_CancelledError, "");
422 return NULL;
423 }
424
425 if (self->fut_state != STATE_FINISHED) {
426 PyErr_SetString(asyncio_InvalidStateError, "Result is not ready.");
427 return NULL;
428 }
429
430 if (self->fut_exception != NULL) {
431 self->fut_log_tb = 0;
432 Py_INCREF(self->fut_exception);
433 return self->fut_exception;
434 }
435
436 Py_RETURN_NONE;
437}
438
439/*[clinic input]
440_asyncio.Future.set_result
441
442 res: 'O'
443 /
444
445Mark the future done and set its result.
446
447If the future is already done when this method is called, raises
448InvalidStateError.
449[clinic start generated code]*/
450
451static PyObject *
452_asyncio_Future_set_result(FutureObj *self, PyObject *res)
453/*[clinic end generated code: output=a620abfc2796bfb6 input=8619565e0503357e]*/
454{
455 return future_set_result(self, res);
456}
457
458/*[clinic input]
459_asyncio.Future.set_exception
460
461 exception: 'O'
462 /
463
464Mark the future done and set an exception.
465
466If the future is already done when this method is called, raises
467InvalidStateError.
468[clinic start generated code]*/
469
470static PyObject *
471_asyncio_Future_set_exception(FutureObj *self, PyObject *exception)
472/*[clinic end generated code: output=f1c1b0cd321be360 input=1377dbe15e6ea186]*/
473{
474 return future_set_exception(self, exception);
475}
476
477/*[clinic input]
478_asyncio.Future.add_done_callback
479
480 fn: 'O'
481 /
482
483Add a callback to be run when the future becomes done.
484
485The callback is called with a single argument - the future object. If
486the future is already done when this is called, the callback is
487scheduled with call_soon.
488[clinic start generated code]*/
489
490static PyObject *
491_asyncio_Future_add_done_callback(FutureObj *self, PyObject *fn)
492/*[clinic end generated code: output=819e09629b2ec2b5 input=8cce187e32cec6a8]*/
493{
494 return future_add_done_callback(self, fn);
495}
496
497/*[clinic input]
498_asyncio.Future.remove_done_callback
499
500 fn: 'O'
501 /
502
503Remove all instances of a callback from the "call when done" list.
504
505Returns the number of callbacks removed.
506[clinic start generated code]*/
507
508static PyObject *
509_asyncio_Future_remove_done_callback(FutureObj *self, PyObject *fn)
510/*[clinic end generated code: output=5ab1fb52b24ef31f input=3fedb73e1409c31c]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900511{
512 PyObject *newlist;
513 Py_ssize_t len, i, j=0;
514
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400515 len = PyList_GET_SIZE(self->fut_callbacks);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900516 if (len == 0) {
517 return PyLong_FromSsize_t(0);
518 }
519
520 newlist = PyList_New(len);
521 if (newlist == NULL) {
522 return NULL;
523 }
524
525 for (i = 0; i < len; i++) {
526 int ret;
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400527 PyObject *item = PyList_GET_ITEM(self->fut_callbacks, i);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900528
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400529 if ((ret = PyObject_RichCompareBool(fn, item, Py_EQ)) < 0) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900530 goto fail;
531 }
532 if (ret == 0) {
533 Py_INCREF(item);
534 PyList_SET_ITEM(newlist, j, item);
535 j++;
536 }
537 }
538
539 if (PyList_SetSlice(newlist, j, len, NULL) < 0) {
540 goto fail;
541 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400542 if (PyList_SetSlice(self->fut_callbacks, 0, len, newlist) < 0) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900543 goto fail;
544 }
545 Py_DECREF(newlist);
546 return PyLong_FromSsize_t(len - j);
547
548fail:
549 Py_DECREF(newlist);
550 return NULL;
551}
552
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400553/*[clinic input]
554_asyncio.Future.cancel
555
556Cancel the future and schedule callbacks.
557
558If the future is already done or cancelled, return False. Otherwise,
559change the future's state to cancelled, schedule the callbacks and
560return True.
561[clinic start generated code]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900562
563static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400564_asyncio_Future_cancel_impl(FutureObj *self)
565/*[clinic end generated code: output=e45b932ba8bd68a1 input=515709a127995109]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900566{
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400567 return future_cancel(self);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900568}
569
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400570/*[clinic input]
571_asyncio.Future.cancelled
572
573Return True if the future was cancelled.
574[clinic start generated code]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900575
576static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400577_asyncio_Future_cancelled_impl(FutureObj *self)
578/*[clinic end generated code: output=145197ced586357d input=943ab8b7b7b17e45]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900579{
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400580 if (self->fut_state == STATE_CANCELLED) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900581 Py_RETURN_TRUE;
582 }
583 else {
584 Py_RETURN_FALSE;
585 }
586}
587
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400588/*[clinic input]
589_asyncio.Future.done
590
591Return True if the future is done.
592
593Done means either that a result / exception are available, or that the
594future was cancelled.
595[clinic start generated code]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900596
597static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400598_asyncio_Future_done_impl(FutureObj *self)
599/*[clinic end generated code: output=244c5ac351145096 input=28d7b23fdb65d2ac]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900600{
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400601 if (self->fut_state == STATE_PENDING) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900602 Py_RETURN_FALSE;
603 }
604 else {
605 Py_RETURN_TRUE;
606 }
607}
608
609static PyObject *
610FutureObj_get_blocking(FutureObj *fut)
611{
612 if (fut->fut_blocking) {
613 Py_RETURN_TRUE;
614 }
615 else {
616 Py_RETURN_FALSE;
617 }
618}
619
620static int
621FutureObj_set_blocking(FutureObj *fut, PyObject *val)
622{
623 int is_true = PyObject_IsTrue(val);
624 if (is_true < 0) {
625 return -1;
626 }
627 fut->fut_blocking = is_true;
628 return 0;
629}
630
631static PyObject *
632FutureObj_get_log_traceback(FutureObj *fut)
633{
634 if (fut->fut_log_tb) {
635 Py_RETURN_TRUE;
636 }
637 else {
638 Py_RETURN_FALSE;
639 }
640}
641
642static PyObject *
643FutureObj_get_loop(FutureObj *fut)
644{
645 if (fut->fut_loop == NULL) {
646 Py_RETURN_NONE;
647 }
648 Py_INCREF(fut->fut_loop);
649 return fut->fut_loop;
650}
651
652static PyObject *
653FutureObj_get_callbacks(FutureObj *fut)
654{
655 if (fut->fut_callbacks == NULL) {
656 Py_RETURN_NONE;
657 }
658 Py_INCREF(fut->fut_callbacks);
659 return fut->fut_callbacks;
660}
661
662static PyObject *
663FutureObj_get_result(FutureObj *fut)
664{
665 if (fut->fut_result == NULL) {
666 Py_RETURN_NONE;
667 }
668 Py_INCREF(fut->fut_result);
669 return fut->fut_result;
670}
671
672static PyObject *
673FutureObj_get_exception(FutureObj *fut)
674{
675 if (fut->fut_exception == NULL) {
676 Py_RETURN_NONE;
677 }
678 Py_INCREF(fut->fut_exception);
679 return fut->fut_exception;
680}
681
682static PyObject *
683FutureObj_get_source_traceback(FutureObj *fut)
684{
685 if (fut->fut_source_tb == NULL) {
686 Py_RETURN_NONE;
687 }
688 Py_INCREF(fut->fut_source_tb);
689 return fut->fut_source_tb;
690}
691
692static PyObject *
693FutureObj_get_state(FutureObj *fut)
694{
695 _Py_IDENTIFIER(PENDING);
696 _Py_IDENTIFIER(CANCELLED);
697 _Py_IDENTIFIER(FINISHED);
698 PyObject *ret = NULL;
699
700 switch (fut->fut_state) {
701 case STATE_PENDING:
702 ret = _PyUnicode_FromId(&PyId_PENDING);
703 break;
704 case STATE_CANCELLED:
705 ret = _PyUnicode_FromId(&PyId_CANCELLED);
706 break;
707 case STATE_FINISHED:
708 ret = _PyUnicode_FromId(&PyId_FINISHED);
709 break;
710 default:
711 assert (0);
712 }
713 Py_INCREF(ret);
714 return ret;
715}
716
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400717/*[clinic input]
718_asyncio.Future._repr_info
719[clinic start generated code]*/
720
721static PyObject *
722_asyncio_Future__repr_info_impl(FutureObj *self)
723/*[clinic end generated code: output=fa69e901bd176cfb input=f21504d8e2ae1ca2]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900724{
Victor Stinnerde4ae3d2016-12-04 22:59:09 +0100725 return PyObject_CallFunctionObjArgs(
726 asyncio_future_repr_info_func, self, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400727}
728
729/*[clinic input]
730_asyncio.Future._schedule_callbacks
731[clinic start generated code]*/
732
733static PyObject *
734_asyncio_Future__schedule_callbacks_impl(FutureObj *self)
735/*[clinic end generated code: output=5e8958d89ea1c5dc input=4f5f295f263f4a88]*/
736{
737 int ret = future_schedule_callbacks(self);
738 if (ret == -1) {
739 return NULL;
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900740 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400741 Py_RETURN_NONE;
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900742}
743
744static PyObject *
745FutureObj_repr(FutureObj *fut)
746{
747 _Py_IDENTIFIER(_repr_info);
748
749 PyObject *_repr_info = _PyUnicode_FromId(&PyId__repr_info); // borrowed
750 if (_repr_info == NULL) {
751 return NULL;
752 }
753
754 PyObject *rinfo = PyObject_CallMethodObjArgs((PyObject*)fut, _repr_info,
755 NULL);
756 if (rinfo == NULL) {
757 return NULL;
758 }
759
760 PyObject *sp = PyUnicode_FromString(" ");
761 if (sp == NULL) {
762 Py_DECREF(rinfo);
763 return NULL;
764 }
765
766 PyObject *rinfo_s = PyUnicode_Join(sp, rinfo);
767 Py_DECREF(sp);
768 Py_DECREF(rinfo);
769 if (rinfo_s == NULL) {
770 return NULL;
771 }
772
773 PyObject *rstr = NULL;
774 PyObject *type_name = PyObject_GetAttrString((PyObject*)Py_TYPE(fut),
775 "__name__");
776 if (type_name != NULL) {
777 rstr = PyUnicode_FromFormat("<%S %S>", type_name, rinfo_s);
778 Py_DECREF(type_name);
779 }
780 Py_DECREF(rinfo_s);
781 return rstr;
782}
783
784static void
785FutureObj_finalize(FutureObj *fut)
786{
787 _Py_IDENTIFIER(call_exception_handler);
788 _Py_IDENTIFIER(message);
789 _Py_IDENTIFIER(exception);
790 _Py_IDENTIFIER(future);
791 _Py_IDENTIFIER(source_traceback);
792
793 if (!fut->fut_log_tb) {
794 return;
795 }
796 assert(fut->fut_exception != NULL);
797 fut->fut_log_tb = 0;;
798
799 PyObject *error_type, *error_value, *error_traceback;
800 /* Save the current exception, if any. */
801 PyErr_Fetch(&error_type, &error_value, &error_traceback);
802
803 PyObject *context = NULL;
804 PyObject *type_name = NULL;
805 PyObject *message = NULL;
806 PyObject *func = NULL;
807 PyObject *res = NULL;
808
809 context = PyDict_New();
810 if (context == NULL) {
811 goto finally;
812 }
813
814 type_name = PyObject_GetAttrString((PyObject*)Py_TYPE(fut), "__name__");
815 if (type_name == NULL) {
816 goto finally;
817 }
818
819 message = PyUnicode_FromFormat(
820 "%S exception was never retrieved", type_name);
821 if (message == NULL) {
822 goto finally;
823 }
824
825 if (_PyDict_SetItemId(context, &PyId_message, message) < 0 ||
826 _PyDict_SetItemId(context, &PyId_exception, fut->fut_exception) < 0 ||
827 _PyDict_SetItemId(context, &PyId_future, (PyObject*)fut) < 0) {
828 goto finally;
829 }
830 if (fut->fut_source_tb != NULL) {
831 if (_PyDict_SetItemId(context, &PyId_source_traceback,
832 fut->fut_source_tb) < 0) {
833 goto finally;
834 }
835 }
836
837 func = _PyObject_GetAttrId(fut->fut_loop, &PyId_call_exception_handler);
838 if (func != NULL) {
Victor Stinner7bfb42d2016-12-05 17:04:32 +0100839 res = PyObject_CallFunctionObjArgs(func, context, NULL);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900840 if (res == NULL) {
841 PyErr_WriteUnraisable(func);
842 }
843 }
844
845finally:
846 Py_CLEAR(context);
847 Py_CLEAR(type_name);
848 Py_CLEAR(message);
849 Py_CLEAR(func);
850 Py_CLEAR(res);
851
852 /* Restore the saved exception. */
853 PyErr_Restore(error_type, error_value, error_traceback);
854}
855
856
857static PyAsyncMethods FutureType_as_async = {
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400858 (unaryfunc)future_new_iter, /* am_await */
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900859 0, /* am_aiter */
860 0 /* am_anext */
861};
862
863static PyMethodDef FutureType_methods[] = {
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400864 _ASYNCIO_FUTURE_RESULT_METHODDEF
865 _ASYNCIO_FUTURE_EXCEPTION_METHODDEF
866 _ASYNCIO_FUTURE_SET_RESULT_METHODDEF
867 _ASYNCIO_FUTURE_SET_EXCEPTION_METHODDEF
868 _ASYNCIO_FUTURE_ADD_DONE_CALLBACK_METHODDEF
869 _ASYNCIO_FUTURE_REMOVE_DONE_CALLBACK_METHODDEF
870 _ASYNCIO_FUTURE_CANCEL_METHODDEF
871 _ASYNCIO_FUTURE_CANCELLED_METHODDEF
872 _ASYNCIO_FUTURE_DONE_METHODDEF
873 _ASYNCIO_FUTURE__REPR_INFO_METHODDEF
874 _ASYNCIO_FUTURE__SCHEDULE_CALLBACKS_METHODDEF
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900875 {NULL, NULL} /* Sentinel */
876};
877
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400878#define FUTURE_COMMON_GETSETLIST \
879 {"_state", (getter)FutureObj_get_state, NULL, NULL}, \
880 {"_asyncio_future_blocking", (getter)FutureObj_get_blocking, \
881 (setter)FutureObj_set_blocking, NULL}, \
882 {"_loop", (getter)FutureObj_get_loop, NULL, NULL}, \
883 {"_callbacks", (getter)FutureObj_get_callbacks, NULL, NULL}, \
884 {"_result", (getter)FutureObj_get_result, NULL, NULL}, \
885 {"_exception", (getter)FutureObj_get_exception, NULL, NULL}, \
886 {"_log_traceback", (getter)FutureObj_get_log_traceback, NULL, NULL}, \
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900887 {"_source_traceback", (getter)FutureObj_get_source_traceback, NULL, NULL},
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400888
889static PyGetSetDef FutureType_getsetlist[] = {
890 FUTURE_COMMON_GETSETLIST
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900891 {NULL} /* Sentinel */
892};
893
894static void FutureObj_dealloc(PyObject *self);
895
896static PyTypeObject FutureType = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +0200897 PyVarObject_HEAD_INIT(NULL, 0)
INADA Naoki9f2ce252016-10-15 15:39:19 +0900898 "_asyncio.Future",
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900899 sizeof(FutureObj), /* tp_basicsize */
900 .tp_dealloc = FutureObj_dealloc,
901 .tp_as_async = &FutureType_as_async,
902 .tp_repr = (reprfunc)FutureObj_repr,
903 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE
904 | Py_TPFLAGS_HAVE_FINALIZE,
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400905 .tp_doc = _asyncio_Future___init____doc__,
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900906 .tp_traverse = (traverseproc)FutureObj_traverse,
907 .tp_clear = (inquiry)FutureObj_clear,
908 .tp_weaklistoffset = offsetof(FutureObj, fut_weakreflist),
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400909 .tp_iter = (getiterfunc)future_new_iter,
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900910 .tp_methods = FutureType_methods,
911 .tp_getset = FutureType_getsetlist,
912 .tp_dictoffset = offsetof(FutureObj, dict),
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400913 .tp_init = (initproc)_asyncio_Future___init__,
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900914 .tp_new = PyType_GenericNew,
915 .tp_finalize = (destructor)FutureObj_finalize,
916};
917
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400918#define Future_CheckExact(obj) (Py_TYPE(obj) == &FutureType)
919
920static inline int
921future_call_schedule_callbacks(FutureObj *fut)
922{
923 if (Future_CheckExact(fut)) {
924 return future_schedule_callbacks(fut);
925 }
926 else {
927 /* `fut` is a subclass of Future */
928 PyObject *ret = _PyObject_CallMethodId(
929 (PyObject*)fut, &PyId__schedule_callbacks, NULL);
930 if (ret == NULL) {
931 return -1;
932 }
933
934 Py_DECREF(ret);
935 return 0;
936 }
937}
938
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900939static void
940FutureObj_dealloc(PyObject *self)
941{
942 FutureObj *fut = (FutureObj *)self;
943
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400944 if (Future_CheckExact(fut)) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900945 /* When fut is subclass of Future, finalizer is called from
946 * subtype_dealloc.
947 */
948 if (PyObject_CallFinalizerFromDealloc(self) < 0) {
949 // resurrected.
950 return;
951 }
952 }
953
954 if (fut->fut_weakreflist != NULL) {
955 PyObject_ClearWeakRefs(self);
956 }
957
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400958 (void)FutureObj_clear(fut);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900959 Py_TYPE(fut)->tp_free(fut);
960}
961
962
963/*********************** Future Iterator **************************/
964
965typedef struct {
966 PyObject_HEAD
967 FutureObj *future;
968} futureiterobject;
969
970static void
971FutureIter_dealloc(futureiterobject *it)
972{
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400973 PyObject_GC_UnTrack(it);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900974 Py_XDECREF(it->future);
975 PyObject_GC_Del(it);
976}
977
978static PyObject *
979FutureIter_iternext(futureiterobject *it)
980{
981 PyObject *res;
982 FutureObj *fut = it->future;
983
984 if (fut == NULL) {
985 return NULL;
986 }
987
988 if (fut->fut_state == STATE_PENDING) {
989 if (!fut->fut_blocking) {
990 fut->fut_blocking = 1;
991 Py_INCREF(fut);
992 return (PyObject *)fut;
993 }
994 PyErr_Format(PyExc_AssertionError,
995 "yield from wasn't used with future");
996 return NULL;
997 }
998
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400999 res = _asyncio_Future_result_impl(fut);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001000 if (res != NULL) {
Serhiy Storchaka60e49aa2016-11-06 18:47:03 +02001001 /* The result of the Future is not an exception. */
1002 if (_PyGen_SetStopIterationValue(res) < 0) {
1003 Py_DECREF(res);
Yury Selivanova4b884f2016-10-20 15:54:20 -04001004 return NULL;
1005 }
Serhiy Storchaka60e49aa2016-11-06 18:47:03 +02001006 Py_DECREF(res);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001007 }
1008
1009 it->future = NULL;
1010 Py_DECREF(fut);
1011 return NULL;
1012}
1013
1014static PyObject *
INADA Naoki74c17532016-10-25 19:00:45 +09001015FutureIter_send(futureiterobject *self, PyObject *unused)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001016{
INADA Naoki74c17532016-10-25 19:00:45 +09001017 /* Future.__iter__ doesn't care about values that are pushed to the
1018 * generator, it just returns "self.result().
1019 */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001020 return FutureIter_iternext(self);
1021}
1022
1023static PyObject *
1024FutureIter_throw(futureiterobject *self, PyObject *args)
1025{
1026 PyObject *type=NULL, *val=NULL, *tb=NULL;
1027 if (!PyArg_ParseTuple(args, "O|OO", &type, &val, &tb))
1028 return NULL;
1029
1030 if (val == Py_None) {
1031 val = NULL;
1032 }
1033 if (tb == Py_None) {
1034 tb = NULL;
Benjamin Peterson996fc1f2016-11-14 00:15:44 -08001035 } else if (tb != NULL && !PyTraceBack_Check(tb)) {
1036 PyErr_SetString(PyExc_TypeError, "throw() third argument must be a traceback");
1037 return NULL;
1038 }
1039
1040 Py_INCREF(type);
1041 Py_XINCREF(val);
1042 Py_XINCREF(tb);
1043
1044 if (PyExceptionClass_Check(type)) {
1045 PyErr_NormalizeException(&type, &val, &tb);
Yury Selivanovedfe8862016-12-01 11:37:47 -05001046 /* No need to call PyException_SetTraceback since we'll be calling
1047 PyErr_Restore for `type`, `val`, and `tb`. */
Benjamin Peterson996fc1f2016-11-14 00:15:44 -08001048 } else if (PyExceptionInstance_Check(type)) {
1049 if (val) {
1050 PyErr_SetString(PyExc_TypeError,
1051 "instance exception may not have a separate value");
1052 goto fail;
1053 }
1054 val = type;
1055 type = PyExceptionInstance_Class(type);
1056 Py_INCREF(type);
1057 if (tb == NULL)
1058 tb = PyException_GetTraceback(val);
1059 } else {
1060 PyErr_SetString(PyExc_TypeError,
1061 "exceptions must be classes deriving BaseException or "
1062 "instances of such a class");
1063 goto fail;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001064 }
1065
1066 Py_CLEAR(self->future);
1067
Benjamin Peterson996fc1f2016-11-14 00:15:44 -08001068 PyErr_Restore(type, val, tb);
1069
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001070 return FutureIter_iternext(self);
Benjamin Peterson996fc1f2016-11-14 00:15:44 -08001071
1072 fail:
1073 Py_DECREF(type);
1074 Py_XDECREF(val);
1075 Py_XDECREF(tb);
1076 return NULL;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001077}
1078
1079static PyObject *
1080FutureIter_close(futureiterobject *self, PyObject *arg)
1081{
1082 Py_CLEAR(self->future);
1083 Py_RETURN_NONE;
1084}
1085
1086static int
1087FutureIter_traverse(futureiterobject *it, visitproc visit, void *arg)
1088{
1089 Py_VISIT(it->future);
1090 return 0;
1091}
1092
1093static PyMethodDef FutureIter_methods[] = {
1094 {"send", (PyCFunction)FutureIter_send, METH_O, NULL},
1095 {"throw", (PyCFunction)FutureIter_throw, METH_VARARGS, NULL},
1096 {"close", (PyCFunction)FutureIter_close, METH_NOARGS, NULL},
1097 {NULL, NULL} /* Sentinel */
1098};
1099
1100static PyTypeObject FutureIterType = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02001101 PyVarObject_HEAD_INIT(NULL, 0)
INADA Naoki9f2ce252016-10-15 15:39:19 +09001102 "_asyncio.FutureIter",
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001103 .tp_basicsize = sizeof(futureiterobject),
1104 .tp_itemsize = 0,
1105 .tp_dealloc = (destructor)FutureIter_dealloc,
1106 .tp_getattro = PyObject_GenericGetAttr,
1107 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
1108 .tp_traverse = (traverseproc)FutureIter_traverse,
1109 .tp_iter = PyObject_SelfIter,
1110 .tp_iternext = (iternextfunc)FutureIter_iternext,
1111 .tp_methods = FutureIter_methods,
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001112};
1113
1114static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001115future_new_iter(PyObject *fut)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001116{
1117 futureiterobject *it;
1118
1119 if (!PyObject_TypeCheck(fut, &FutureType)) {
1120 PyErr_BadInternalCall();
1121 return NULL;
1122 }
1123 it = PyObject_GC_New(futureiterobject, &FutureIterType);
1124 if (it == NULL) {
1125 return NULL;
1126 }
1127 Py_INCREF(fut);
1128 it->future = (FutureObj*)fut;
INADA Naoki1be427b2016-10-11 02:12:34 +09001129 PyObject_GC_Track(it);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001130 return (PyObject*)it;
1131}
1132
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001133
1134/*********************** Task **************************/
1135
1136
1137/*[clinic input]
1138class _asyncio.Task "TaskObj *" "&Task_Type"
1139[clinic start generated code]*/
1140/*[clinic end generated code: output=da39a3ee5e6b4b0d input=719dcef0fcc03b37]*/
1141
1142static int task_call_step_soon(TaskObj *, PyObject *);
1143static inline PyObject * task_call_wakeup(TaskObj *, PyObject *);
1144static inline PyObject * task_call_step(TaskObj *, PyObject *);
1145static PyObject * task_wakeup(TaskObj *, PyObject *);
1146static PyObject * task_step(TaskObj *, PyObject *);
1147
1148/* ----- Task._step wrapper */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001149
INADA Naokic411a7d2016-10-18 11:48:14 +09001150static int
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001151TaskSendMethWrapper_clear(TaskSendMethWrapper *o)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001152{
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001153 Py_CLEAR(o->sw_task);
1154 Py_CLEAR(o->sw_arg);
1155 return 0;
1156}
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001157
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001158static void
1159TaskSendMethWrapper_dealloc(TaskSendMethWrapper *o)
1160{
1161 PyObject_GC_UnTrack(o);
1162 (void)TaskSendMethWrapper_clear(o);
1163 Py_TYPE(o)->tp_free(o);
1164}
1165
1166static PyObject *
1167TaskSendMethWrapper_call(TaskSendMethWrapper *o,
1168 PyObject *args, PyObject *kwds)
1169{
1170 return task_call_step(o->sw_task, o->sw_arg);
1171}
1172
1173static int
1174TaskSendMethWrapper_traverse(TaskSendMethWrapper *o,
1175 visitproc visit, void *arg)
1176{
1177 Py_VISIT(o->sw_task);
1178 Py_VISIT(o->sw_arg);
1179 return 0;
1180}
1181
1182static PyObject *
1183TaskSendMethWrapper_get___self__(TaskSendMethWrapper *o)
1184{
1185 if (o->sw_task) {
1186 Py_INCREF(o->sw_task);
1187 return (PyObject*)o->sw_task;
1188 }
1189 Py_RETURN_NONE;
1190}
1191
1192static PyGetSetDef TaskSendMethWrapper_getsetlist[] = {
1193 {"__self__", (getter)TaskSendMethWrapper_get___self__, NULL, NULL},
1194 {NULL} /* Sentinel */
1195};
1196
1197PyTypeObject TaskSendMethWrapper_Type = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02001198 PyVarObject_HEAD_INIT(NULL, 0)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001199 "TaskSendMethWrapper",
1200 .tp_basicsize = sizeof(TaskSendMethWrapper),
1201 .tp_itemsize = 0,
1202 .tp_getset = TaskSendMethWrapper_getsetlist,
1203 .tp_dealloc = (destructor)TaskSendMethWrapper_dealloc,
1204 .tp_call = (ternaryfunc)TaskSendMethWrapper_call,
1205 .tp_getattro = PyObject_GenericGetAttr,
1206 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
1207 .tp_traverse = (traverseproc)TaskSendMethWrapper_traverse,
1208 .tp_clear = (inquiry)TaskSendMethWrapper_clear,
1209};
1210
1211static PyObject *
1212TaskSendMethWrapper_new(TaskObj *task, PyObject *arg)
1213{
1214 TaskSendMethWrapper *o;
1215 o = PyObject_GC_New(TaskSendMethWrapper, &TaskSendMethWrapper_Type);
1216 if (o == NULL) {
1217 return NULL;
1218 }
1219
1220 Py_INCREF(task);
1221 o->sw_task = task;
1222
1223 Py_XINCREF(arg);
1224 o->sw_arg = arg;
1225
1226 PyObject_GC_Track(o);
1227 return (PyObject*) o;
1228}
1229
1230/* ----- Task._wakeup wrapper */
1231
1232static PyObject *
1233TaskWakeupMethWrapper_call(TaskWakeupMethWrapper *o,
1234 PyObject *args, PyObject *kwds)
1235{
1236 PyObject *fut;
1237
1238 if (!PyArg_ParseTuple(args, "O|", &fut)) {
1239 return NULL;
1240 }
1241
1242 return task_call_wakeup(o->ww_task, fut);
1243}
1244
1245static int
1246TaskWakeupMethWrapper_clear(TaskWakeupMethWrapper *o)
1247{
1248 Py_CLEAR(o->ww_task);
1249 return 0;
1250}
1251
1252static int
1253TaskWakeupMethWrapper_traverse(TaskWakeupMethWrapper *o,
1254 visitproc visit, void *arg)
1255{
1256 Py_VISIT(o->ww_task);
1257 return 0;
1258}
1259
1260static void
1261TaskWakeupMethWrapper_dealloc(TaskWakeupMethWrapper *o)
1262{
1263 PyObject_GC_UnTrack(o);
1264 (void)TaskWakeupMethWrapper_clear(o);
1265 Py_TYPE(o)->tp_free(o);
1266}
1267
1268PyTypeObject TaskWakeupMethWrapper_Type = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02001269 PyVarObject_HEAD_INIT(NULL, 0)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001270 "TaskWakeupMethWrapper",
1271 .tp_basicsize = sizeof(TaskWakeupMethWrapper),
1272 .tp_itemsize = 0,
1273 .tp_dealloc = (destructor)TaskWakeupMethWrapper_dealloc,
1274 .tp_call = (ternaryfunc)TaskWakeupMethWrapper_call,
1275 .tp_getattro = PyObject_GenericGetAttr,
1276 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
1277 .tp_traverse = (traverseproc)TaskWakeupMethWrapper_traverse,
1278 .tp_clear = (inquiry)TaskWakeupMethWrapper_clear,
1279};
1280
1281static PyObject *
1282TaskWakeupMethWrapper_new(TaskObj *task)
1283{
1284 TaskWakeupMethWrapper *o;
1285 o = PyObject_GC_New(TaskWakeupMethWrapper, &TaskWakeupMethWrapper_Type);
1286 if (o == NULL) {
1287 return NULL;
1288 }
1289
1290 Py_INCREF(task);
1291 o->ww_task = task;
1292
1293 PyObject_GC_Track(o);
1294 return (PyObject*) o;
1295}
1296
1297/* ----- Task */
1298
1299/*[clinic input]
1300_asyncio.Task.__init__
1301
1302 coro: 'O'
1303 *
1304 loop: 'O' = NULL
1305
1306A coroutine wrapped in a Future.
1307[clinic start generated code]*/
1308
1309static int
1310_asyncio_Task___init___impl(TaskObj *self, PyObject *coro, PyObject *loop)
1311/*[clinic end generated code: output=9f24774c2287fc2f input=71d8d28c201a18cd]*/
1312{
1313 PyObject *res;
1314 _Py_IDENTIFIER(add);
1315
1316 if (future_init((FutureObj*)self, loop)) {
INADA Naokic411a7d2016-10-18 11:48:14 +09001317 return -1;
1318 }
INADA Naokic411a7d2016-10-18 11:48:14 +09001319
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001320 self->task_fut_waiter = NULL;
1321 self->task_must_cancel = 0;
1322 self->task_log_destroy_pending = 1;
INADA Naokic411a7d2016-10-18 11:48:14 +09001323
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001324 Py_INCREF(coro);
1325 self->task_coro = coro;
1326
1327 if (task_call_step_soon(self, NULL)) {
1328 return -1;
INADA Naokic411a7d2016-10-18 11:48:14 +09001329 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001330
Victor Stinnerb6ed57d2016-12-09 14:24:02 +01001331 res = _PyObject_CallMethodIdObjArgs(all_tasks, &PyId_add, self, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001332 if (res == NULL) {
1333 return -1;
1334 }
1335 Py_DECREF(res);
1336
1337 return 0;
1338}
1339
1340static int
1341TaskObj_clear(TaskObj *task)
1342{
1343 (void)FutureObj_clear((FutureObj*) task);
1344 Py_CLEAR(task->task_coro);
1345 Py_CLEAR(task->task_fut_waiter);
1346 return 0;
1347}
1348
1349static int
1350TaskObj_traverse(TaskObj *task, visitproc visit, void *arg)
1351{
1352 Py_VISIT(task->task_coro);
1353 Py_VISIT(task->task_fut_waiter);
1354 (void)FutureObj_traverse((FutureObj*) task, visit, arg);
1355 return 0;
1356}
1357
1358static PyObject *
1359TaskObj_get_log_destroy_pending(TaskObj *task)
1360{
1361 if (task->task_log_destroy_pending) {
1362 Py_RETURN_TRUE;
1363 }
1364 else {
1365 Py_RETURN_FALSE;
1366 }
1367}
1368
1369static int
1370TaskObj_set_log_destroy_pending(TaskObj *task, PyObject *val)
1371{
1372 int is_true = PyObject_IsTrue(val);
1373 if (is_true < 0) {
1374 return -1;
1375 }
1376 task->task_log_destroy_pending = is_true;
1377 return 0;
1378}
1379
1380static PyObject *
1381TaskObj_get_must_cancel(TaskObj *task)
1382{
1383 if (task->task_must_cancel) {
1384 Py_RETURN_TRUE;
1385 }
1386 else {
1387 Py_RETURN_FALSE;
1388 }
1389}
1390
1391static PyObject *
1392TaskObj_get_coro(TaskObj *task)
1393{
1394 if (task->task_coro) {
1395 Py_INCREF(task->task_coro);
1396 return task->task_coro;
1397 }
1398
1399 Py_RETURN_NONE;
1400}
1401
1402static PyObject *
1403TaskObj_get_fut_waiter(TaskObj *task)
1404{
1405 if (task->task_fut_waiter) {
1406 Py_INCREF(task->task_fut_waiter);
1407 return task->task_fut_waiter;
1408 }
1409
1410 Py_RETURN_NONE;
1411}
1412
1413/*[clinic input]
1414@classmethod
1415_asyncio.Task.current_task
1416
1417 loop: 'O' = NULL
1418
1419Return the currently running task in an event loop or None.
1420
1421By default the current task for the current event loop is returned.
1422
1423None is returned when called not in the context of a Task.
1424[clinic start generated code]*/
1425
1426static PyObject *
1427_asyncio_Task_current_task_impl(PyTypeObject *type, PyObject *loop)
1428/*[clinic end generated code: output=99fbe7332c516e03 input=cd784537f02cf833]*/
1429{
1430 PyObject *res;
1431
1432 if (loop == NULL) {
Victor Stinnera5ed5f02016-12-06 18:45:50 +01001433 loop = _PyObject_CallNoArg(asyncio_get_event_loop);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001434 if (loop == NULL) {
1435 return NULL;
1436 }
1437
Yury Selivanov684ef2c2016-10-28 19:01:21 -04001438 res = PyDict_GetItem(current_tasks, loop);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001439 Py_DECREF(loop);
1440 }
1441 else {
Yury Selivanov684ef2c2016-10-28 19:01:21 -04001442 res = PyDict_GetItem(current_tasks, loop);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001443 }
1444
1445 if (res == NULL) {
1446 Py_RETURN_NONE;
1447 }
1448 else {
1449 Py_INCREF(res);
1450 return res;
1451 }
1452}
1453
1454static PyObject *
1455task_all_tasks(PyObject *loop)
1456{
1457 PyObject *task;
1458 PyObject *task_loop;
1459 PyObject *set;
1460 PyObject *iter;
1461
1462 assert(loop != NULL);
1463
1464 set = PySet_New(NULL);
1465 if (set == NULL) {
1466 return NULL;
1467 }
1468
1469 iter = PyObject_GetIter(all_tasks);
1470 if (iter == NULL) {
INADA Naokic411a7d2016-10-18 11:48:14 +09001471 goto fail;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001472 }
1473
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001474 while ((task = PyIter_Next(iter))) {
1475 task_loop = PyObject_GetAttrString(task, "_loop");
1476 if (task_loop == NULL) {
1477 Py_DECREF(task);
1478 goto fail;
1479 }
1480 if (task_loop == loop) {
1481 if (PySet_Add(set, task) == -1) {
1482 Py_DECREF(task_loop);
1483 Py_DECREF(task);
1484 goto fail;
1485 }
1486 }
1487 Py_DECREF(task_loop);
1488 Py_DECREF(task);
1489 }
1490
1491 Py_DECREF(iter);
1492 return set;
1493
1494fail:
1495 Py_XDECREF(set);
1496 Py_XDECREF(iter);
1497 return NULL;
1498}
1499
1500/*[clinic input]
1501@classmethod
1502_asyncio.Task.all_tasks
1503
1504 loop: 'O' = NULL
1505
1506Return a set of all tasks for an event loop.
1507
1508By default all tasks for the current event loop are returned.
1509[clinic start generated code]*/
1510
1511static PyObject *
1512_asyncio_Task_all_tasks_impl(PyTypeObject *type, PyObject *loop)
1513/*[clinic end generated code: output=11f9b20749ccca5d input=cd64aa5f88bd5c49]*/
1514{
1515 PyObject *res;
1516
1517 if (loop == NULL) {
Victor Stinnera5ed5f02016-12-06 18:45:50 +01001518 loop = _PyObject_CallNoArg(asyncio_get_event_loop);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001519 if (loop == NULL) {
1520 return NULL;
1521 }
1522
1523 res = task_all_tasks(loop);
1524 Py_DECREF(loop);
1525 }
1526 else {
1527 res = task_all_tasks(loop);
1528 }
1529
1530 return res;
1531}
1532
1533/*[clinic input]
1534_asyncio.Task._repr_info
1535[clinic start generated code]*/
1536
1537static PyObject *
1538_asyncio_Task__repr_info_impl(TaskObj *self)
1539/*[clinic end generated code: output=6a490eb66d5ba34b input=3c6d051ed3ddec8b]*/
1540{
Victor Stinnerde4ae3d2016-12-04 22:59:09 +01001541 return PyObject_CallFunctionObjArgs(
1542 asyncio_task_repr_info_func, self, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001543}
1544
1545/*[clinic input]
1546_asyncio.Task.cancel
1547
1548Request that this task cancel itself.
1549
1550This arranges for a CancelledError to be thrown into the
1551wrapped coroutine on the next cycle through the event loop.
1552The coroutine then has a chance to clean up or even deny
1553the request using try/except/finally.
1554
1555Unlike Future.cancel, this does not guarantee that the
1556task will be cancelled: the exception might be caught and
1557acted upon, delaying cancellation of the task or preventing
1558cancellation completely. The task may also return a value or
1559raise a different exception.
1560
1561Immediately after this method is called, Task.cancelled() will
1562not return True (unless the task was already cancelled). A
1563task will be marked as cancelled when the wrapped coroutine
1564terminates with a CancelledError exception (even if cancel()
1565was not called).
1566[clinic start generated code]*/
1567
1568static PyObject *
1569_asyncio_Task_cancel_impl(TaskObj *self)
1570/*[clinic end generated code: output=6bfc0479da9d5757 input=13f9bf496695cb52]*/
1571{
1572 if (self->task_state != STATE_PENDING) {
1573 Py_RETURN_FALSE;
1574 }
1575
1576 if (self->task_fut_waiter) {
1577 PyObject *res;
1578 int is_true;
1579
1580 res = _PyObject_CallMethodId(
1581 self->task_fut_waiter, &PyId_cancel, NULL);
1582 if (res == NULL) {
1583 return NULL;
1584 }
1585
1586 is_true = PyObject_IsTrue(res);
1587 Py_DECREF(res);
1588 if (is_true < 0) {
1589 return NULL;
1590 }
1591
1592 if (is_true) {
1593 Py_RETURN_TRUE;
1594 }
1595 }
1596
1597 self->task_must_cancel = 1;
1598 Py_RETURN_TRUE;
1599}
1600
1601/*[clinic input]
1602_asyncio.Task.get_stack
1603
1604 *
1605 limit: 'O' = None
1606
1607Return the list of stack frames for this task's coroutine.
1608
1609If the coroutine is not done, this returns the stack where it is
1610suspended. If the coroutine has completed successfully or was
1611cancelled, this returns an empty list. If the coroutine was
1612terminated by an exception, this returns the list of traceback
1613frames.
1614
1615The frames are always ordered from oldest to newest.
1616
1617The optional limit gives the maximum number of frames to
1618return; by default all available frames are returned. Its
1619meaning differs depending on whether a stack or a traceback is
1620returned: the newest frames of a stack are returned, but the
1621oldest frames of a traceback are returned. (This matches the
1622behavior of the traceback module.)
1623
1624For reasons beyond our control, only one stack frame is
1625returned for a suspended coroutine.
1626[clinic start generated code]*/
1627
1628static PyObject *
1629_asyncio_Task_get_stack_impl(TaskObj *self, PyObject *limit)
1630/*[clinic end generated code: output=c9aeeeebd1e18118 input=b1920230a766d17a]*/
1631{
1632 return PyObject_CallFunctionObjArgs(
1633 asyncio_task_get_stack_func, self, limit, NULL);
1634}
1635
1636/*[clinic input]
1637_asyncio.Task.print_stack
1638
1639 *
1640 limit: 'O' = None
1641 file: 'O' = None
1642
1643Print the stack or traceback for this task's coroutine.
1644
1645This produces output similar to that of the traceback module,
1646for the frames retrieved by get_stack(). The limit argument
1647is passed to get_stack(). The file argument is an I/O stream
1648to which the output is written; by default output is written
1649to sys.stderr.
1650[clinic start generated code]*/
1651
1652static PyObject *
1653_asyncio_Task_print_stack_impl(TaskObj *self, PyObject *limit,
1654 PyObject *file)
1655/*[clinic end generated code: output=7339e10314cd3f4d input=19f1e99ab5400bc3]*/
1656{
1657 return PyObject_CallFunctionObjArgs(
1658 asyncio_task_print_stack_func, self, limit, file, NULL);
1659}
1660
1661/*[clinic input]
1662_asyncio.Task._step
1663
1664 exc: 'O' = NULL
1665[clinic start generated code]*/
1666
1667static PyObject *
1668_asyncio_Task__step_impl(TaskObj *self, PyObject *exc)
1669/*[clinic end generated code: output=7ed23f0cefd5ae42 input=ada4b2324e5370af]*/
1670{
1671 return task_step(self, exc == Py_None ? NULL : exc);
1672}
1673
1674/*[clinic input]
1675_asyncio.Task._wakeup
1676
1677 fut: 'O'
1678[clinic start generated code]*/
1679
1680static PyObject *
1681_asyncio_Task__wakeup_impl(TaskObj *self, PyObject *fut)
1682/*[clinic end generated code: output=75cb341c760fd071 input=11ee4918a5bdbf21]*/
1683{
1684 return task_wakeup(self, fut);
1685}
1686
1687static void
1688TaskObj_finalize(TaskObj *task)
1689{
1690 _Py_IDENTIFIER(call_exception_handler);
1691 _Py_IDENTIFIER(task);
1692 _Py_IDENTIFIER(message);
1693 _Py_IDENTIFIER(source_traceback);
1694
1695 PyObject *message = NULL;
1696 PyObject *context = NULL;
1697 PyObject *func = NULL;
1698 PyObject *res = NULL;
1699
1700 PyObject *error_type, *error_value, *error_traceback;
1701
1702 if (task->task_state != STATE_PENDING || !task->task_log_destroy_pending) {
1703 goto done;
1704 }
1705
1706 /* Save the current exception, if any. */
1707 PyErr_Fetch(&error_type, &error_value, &error_traceback);
1708
1709 context = PyDict_New();
1710 if (context == NULL) {
1711 goto finally;
1712 }
1713
1714 message = PyUnicode_FromString("Task was destroyed but it is pending!");
1715 if (message == NULL) {
1716 goto finally;
1717 }
1718
1719 if (_PyDict_SetItemId(context, &PyId_message, message) < 0 ||
1720 _PyDict_SetItemId(context, &PyId_task, (PyObject*)task) < 0)
1721 {
1722 goto finally;
1723 }
1724
1725 if (task->task_source_tb != NULL) {
1726 if (_PyDict_SetItemId(context, &PyId_source_traceback,
1727 task->task_source_tb) < 0)
1728 {
1729 goto finally;
1730 }
1731 }
1732
1733 func = _PyObject_GetAttrId(task->task_loop, &PyId_call_exception_handler);
1734 if (func != NULL) {
Victor Stinner7bfb42d2016-12-05 17:04:32 +01001735 res = PyObject_CallFunctionObjArgs(func, context, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001736 if (res == NULL) {
1737 PyErr_WriteUnraisable(func);
1738 }
1739 }
1740
1741finally:
1742 Py_CLEAR(context);
1743 Py_CLEAR(message);
1744 Py_CLEAR(func);
1745 Py_CLEAR(res);
1746
1747 /* Restore the saved exception. */
1748 PyErr_Restore(error_type, error_value, error_traceback);
1749
1750done:
1751 FutureObj_finalize((FutureObj*)task);
1752}
1753
1754static void TaskObj_dealloc(PyObject *); /* Needs Task_CheckExact */
1755
1756static PyMethodDef TaskType_methods[] = {
1757 _ASYNCIO_FUTURE_RESULT_METHODDEF
1758 _ASYNCIO_FUTURE_EXCEPTION_METHODDEF
1759 _ASYNCIO_FUTURE_SET_RESULT_METHODDEF
1760 _ASYNCIO_FUTURE_SET_EXCEPTION_METHODDEF
1761 _ASYNCIO_FUTURE_ADD_DONE_CALLBACK_METHODDEF
1762 _ASYNCIO_FUTURE_REMOVE_DONE_CALLBACK_METHODDEF
1763 _ASYNCIO_FUTURE_CANCELLED_METHODDEF
1764 _ASYNCIO_FUTURE_DONE_METHODDEF
1765 _ASYNCIO_TASK_CURRENT_TASK_METHODDEF
1766 _ASYNCIO_TASK_ALL_TASKS_METHODDEF
1767 _ASYNCIO_TASK_CANCEL_METHODDEF
1768 _ASYNCIO_TASK_GET_STACK_METHODDEF
1769 _ASYNCIO_TASK_PRINT_STACK_METHODDEF
1770 _ASYNCIO_TASK__WAKEUP_METHODDEF
1771 _ASYNCIO_TASK__STEP_METHODDEF
1772 _ASYNCIO_TASK__REPR_INFO_METHODDEF
1773 {NULL, NULL} /* Sentinel */
1774};
1775
1776static PyGetSetDef TaskType_getsetlist[] = {
1777 FUTURE_COMMON_GETSETLIST
1778 {"_log_destroy_pending", (getter)TaskObj_get_log_destroy_pending,
1779 (setter)TaskObj_set_log_destroy_pending, NULL},
1780 {"_must_cancel", (getter)TaskObj_get_must_cancel, NULL, NULL},
1781 {"_coro", (getter)TaskObj_get_coro, NULL, NULL},
1782 {"_fut_waiter", (getter)TaskObj_get_fut_waiter, NULL, NULL},
1783 {NULL} /* Sentinel */
1784};
1785
1786static PyTypeObject TaskType = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02001787 PyVarObject_HEAD_INIT(NULL, 0)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001788 "_asyncio.Task",
1789 sizeof(TaskObj), /* tp_basicsize */
1790 .tp_base = &FutureType,
1791 .tp_dealloc = TaskObj_dealloc,
1792 .tp_as_async = &FutureType_as_async,
1793 .tp_repr = (reprfunc)FutureObj_repr,
1794 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE
1795 | Py_TPFLAGS_HAVE_FINALIZE,
1796 .tp_doc = _asyncio_Task___init____doc__,
1797 .tp_traverse = (traverseproc)TaskObj_traverse,
1798 .tp_clear = (inquiry)TaskObj_clear,
1799 .tp_weaklistoffset = offsetof(TaskObj, task_weakreflist),
1800 .tp_iter = (getiterfunc)future_new_iter,
1801 .tp_methods = TaskType_methods,
1802 .tp_getset = TaskType_getsetlist,
1803 .tp_dictoffset = offsetof(TaskObj, dict),
1804 .tp_init = (initproc)_asyncio_Task___init__,
1805 .tp_new = PyType_GenericNew,
1806 .tp_finalize = (destructor)TaskObj_finalize,
1807};
1808
1809#define Task_CheckExact(obj) (Py_TYPE(obj) == &TaskType)
1810
1811static void
1812TaskObj_dealloc(PyObject *self)
1813{
1814 TaskObj *task = (TaskObj *)self;
1815
1816 if (Task_CheckExact(self)) {
1817 /* When fut is subclass of Task, finalizer is called from
1818 * subtype_dealloc.
1819 */
1820 if (PyObject_CallFinalizerFromDealloc(self) < 0) {
1821 // resurrected.
1822 return;
1823 }
1824 }
1825
1826 if (task->task_weakreflist != NULL) {
1827 PyObject_ClearWeakRefs(self);
1828 }
1829
1830 (void)TaskObj_clear(task);
1831 Py_TYPE(task)->tp_free(task);
1832}
1833
1834static inline PyObject *
1835task_call_wakeup(TaskObj *task, PyObject *fut)
1836{
1837 if (Task_CheckExact(task)) {
1838 return task_wakeup(task, fut);
1839 }
1840 else {
1841 /* `task` is a subclass of Task */
Victor Stinnerb6ed57d2016-12-09 14:24:02 +01001842 return _PyObject_CallMethodIdObjArgs((PyObject*)task, &PyId__wakeup,
1843 fut, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001844 }
1845}
1846
1847static inline PyObject *
1848task_call_step(TaskObj *task, PyObject *arg)
1849{
1850 if (Task_CheckExact(task)) {
1851 return task_step(task, arg);
1852 }
1853 else {
1854 /* `task` is a subclass of Task */
1855 if (arg == NULL) {
1856 arg = Py_None;
1857 }
Victor Stinnerb6ed57d2016-12-09 14:24:02 +01001858 return _PyObject_CallMethodIdObjArgs((PyObject*)task, &PyId__step,
1859 arg, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001860 }
1861}
1862
1863static int
1864task_call_step_soon(TaskObj *task, PyObject *arg)
1865{
1866 PyObject *handle;
1867
1868 PyObject *cb = TaskSendMethWrapper_new(task, arg);
1869 if (cb == NULL) {
1870 return -1;
1871 }
1872
Victor Stinnerb6ed57d2016-12-09 14:24:02 +01001873 handle = _PyObject_CallMethodIdObjArgs(task->task_loop, &PyId_call_soon,
1874 cb, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001875 Py_DECREF(cb);
1876 if (handle == NULL) {
1877 return -1;
1878 }
1879
1880 Py_DECREF(handle);
1881 return 0;
1882}
1883
1884static PyObject *
1885task_set_error_soon(TaskObj *task, PyObject *et, const char *format, ...)
1886{
1887 PyObject* msg;
1888
1889 va_list vargs;
1890#ifdef HAVE_STDARG_PROTOTYPES
1891 va_start(vargs, format);
1892#else
1893 va_start(vargs);
1894#endif
1895 msg = PyUnicode_FromFormatV(format, vargs);
1896 va_end(vargs);
1897
1898 if (msg == NULL) {
1899 return NULL;
1900 }
1901
Victor Stinnerde4ae3d2016-12-04 22:59:09 +01001902 PyObject *e = PyObject_CallFunctionObjArgs(et, msg, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001903 Py_DECREF(msg);
1904 if (e == NULL) {
1905 return NULL;
1906 }
1907
1908 if (task_call_step_soon(task, e) == -1) {
1909 Py_DECREF(e);
1910 return NULL;
1911 }
1912
1913 Py_DECREF(e);
1914 Py_RETURN_NONE;
1915}
1916
1917static PyObject *
1918task_step_impl(TaskObj *task, PyObject *exc)
1919{
1920 int res;
1921 int clear_exc = 0;
1922 PyObject *result = NULL;
1923 PyObject *coro = task->task_coro;
1924 PyObject *o;
1925
1926 if (task->task_state != STATE_PENDING) {
1927 PyErr_Format(PyExc_AssertionError,
1928 "_step(): already done: %R %R",
1929 task,
1930 exc ? exc : Py_None);
INADA Naokic411a7d2016-10-18 11:48:14 +09001931 goto fail;
1932 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001933
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001934 if (task->task_must_cancel) {
1935 assert(exc != Py_None);
1936
1937 if (exc) {
1938 /* Check if exc is a CancelledError */
1939 res = PyObject_IsInstance(exc, asyncio_CancelledError);
1940 if (res == -1) {
1941 /* An error occurred, abort */
1942 goto fail;
1943 }
1944 if (res == 0) {
1945 /* exc is not CancelledError; reset it to NULL */
1946 exc = NULL;
1947 }
1948 }
1949
1950 if (!exc) {
1951 /* exc was not a CancelledError */
Victor Stinnerf17c3de2016-12-06 18:46:19 +01001952 exc = _PyObject_CallNoArg(asyncio_CancelledError);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001953 if (!exc) {
1954 goto fail;
1955 }
1956 clear_exc = 1;
1957 }
1958
1959 task->task_must_cancel = 0;
1960 }
1961
1962 Py_CLEAR(task->task_fut_waiter);
1963
1964 if (exc == NULL) {
1965 if (PyGen_CheckExact(coro) || PyCoro_CheckExact(coro)) {
1966 result = _PyGen_Send((PyGenObject*)coro, Py_None);
1967 }
1968 else {
Victor Stinnerb6ed57d2016-12-09 14:24:02 +01001969 result = _PyObject_CallMethodIdObjArgs(coro, &PyId_send,
1970 Py_None, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001971 }
1972 }
1973 else {
Victor Stinnerb6ed57d2016-12-09 14:24:02 +01001974 result = _PyObject_CallMethodIdObjArgs(coro, &PyId_throw,
1975 exc, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001976 if (clear_exc) {
1977 /* We created 'exc' during this call */
1978 Py_CLEAR(exc);
1979 }
1980 }
1981
1982 if (result == NULL) {
1983 PyObject *et, *ev, *tb;
1984
1985 if (_PyGen_FetchStopIterationValue(&o) == 0) {
1986 /* The error is StopIteration and that means that
1987 the underlying coroutine has resolved */
1988 PyObject *res = future_set_result((FutureObj*)task, o);
1989 Py_DECREF(o);
1990 if (res == NULL) {
1991 return NULL;
1992 }
1993 Py_DECREF(res);
1994 Py_RETURN_NONE;
1995 }
1996
1997 if (PyErr_ExceptionMatches(asyncio_CancelledError)) {
1998 /* CancelledError */
1999 PyErr_Clear();
2000 return future_cancel((FutureObj*)task);
2001 }
2002
2003 /* Some other exception; pop it and call Task.set_exception() */
2004 PyErr_Fetch(&et, &ev, &tb);
2005 assert(et);
2006 if (!ev || !PyObject_TypeCheck(ev, (PyTypeObject *) et)) {
2007 PyErr_NormalizeException(&et, &ev, &tb);
2008 }
Yury Selivanovedfe8862016-12-01 11:37:47 -05002009 if (tb != NULL) {
2010 PyException_SetTraceback(ev, tb);
2011 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002012 o = future_set_exception((FutureObj*)task, ev);
2013 if (!o) {
2014 /* An exception in Task.set_exception() */
2015 Py_XDECREF(et);
2016 Py_XDECREF(tb);
2017 Py_XDECREF(ev);
2018 goto fail;
2019 }
2020 assert(o == Py_None);
2021 Py_CLEAR(o);
2022
2023 if (!PyErr_GivenExceptionMatches(et, PyExc_Exception)) {
2024 /* We've got a BaseException; re-raise it */
2025 PyErr_Restore(et, ev, tb);
2026 goto fail;
2027 }
2028
2029 Py_XDECREF(et);
2030 Py_XDECREF(tb);
2031 Py_XDECREF(ev);
2032
2033 Py_RETURN_NONE;
2034 }
2035
2036 if (result == (PyObject*)task) {
2037 /* We have a task that wants to await on itself */
2038 goto self_await;
2039 }
2040
2041 /* Check if `result` is FutureObj or TaskObj (and not a subclass) */
2042 if (Future_CheckExact(result) || Task_CheckExact(result)) {
2043 PyObject *wrapper;
2044 PyObject *res;
2045 FutureObj *fut = (FutureObj*)result;
2046
2047 /* Check if `result` future is attached to a different loop */
2048 if (fut->fut_loop != task->task_loop) {
2049 goto different_loop;
2050 }
2051
2052 if (fut->fut_blocking) {
2053 fut->fut_blocking = 0;
2054
2055 /* result.add_done_callback(task._wakeup) */
2056 wrapper = TaskWakeupMethWrapper_new(task);
2057 if (wrapper == NULL) {
2058 goto fail;
2059 }
2060 res = future_add_done_callback((FutureObj*)result, wrapper);
2061 Py_DECREF(wrapper);
2062 if (res == NULL) {
2063 goto fail;
2064 }
2065 Py_DECREF(res);
2066
2067 /* task._fut_waiter = result */
2068 task->task_fut_waiter = result; /* no incref is necessary */
2069
2070 if (task->task_must_cancel) {
2071 PyObject *r;
2072 r = future_cancel(fut);
2073 if (r == NULL) {
2074 return NULL;
2075 }
2076 if (r == Py_True) {
2077 task->task_must_cancel = 0;
2078 }
2079 Py_DECREF(r);
2080 }
2081
2082 Py_RETURN_NONE;
2083 }
2084 else {
2085 goto yield_insteadof_yf;
2086 }
2087 }
2088
2089 /* Check if `result` is a Future-compatible object */
2090 o = PyObject_GetAttrString(result, "_asyncio_future_blocking");
2091 if (o == NULL) {
2092 if (PyErr_ExceptionMatches(PyExc_AttributeError)) {
2093 PyErr_Clear();
2094 }
2095 else {
2096 goto fail;
2097 }
2098 }
2099 else {
2100 if (o == Py_None) {
2101 Py_CLEAR(o);
2102 }
2103 else {
2104 /* `result` is a Future-compatible object */
2105 PyObject *wrapper;
2106 PyObject *res;
2107
2108 int blocking = PyObject_IsTrue(o);
2109 Py_CLEAR(o);
2110 if (blocking < 0) {
2111 goto fail;
2112 }
2113
2114 /* Check if `result` future is attached to a different loop */
2115 PyObject *oloop = PyObject_GetAttrString(result, "_loop");
2116 if (oloop == NULL) {
2117 goto fail;
2118 }
2119 if (oloop != task->task_loop) {
2120 Py_DECREF(oloop);
2121 goto different_loop;
2122 }
2123 else {
2124 Py_DECREF(oloop);
2125 }
2126
2127 if (blocking) {
2128 /* result._asyncio_future_blocking = False */
2129 if (PyObject_SetAttrString(
2130 result, "_asyncio_future_blocking", Py_False) == -1) {
2131 goto fail;
2132 }
2133
2134 /* result.add_done_callback(task._wakeup) */
2135 wrapper = TaskWakeupMethWrapper_new(task);
2136 if (wrapper == NULL) {
2137 goto fail;
2138 }
Victor Stinnerb6ed57d2016-12-09 14:24:02 +01002139 res = _PyObject_CallMethodIdObjArgs(result,
2140 &PyId_add_done_callback,
2141 wrapper, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002142 Py_DECREF(wrapper);
2143 if (res == NULL) {
2144 goto fail;
2145 }
2146 Py_DECREF(res);
2147
2148 /* task._fut_waiter = result */
2149 task->task_fut_waiter = result; /* no incref is necessary */
2150
2151 if (task->task_must_cancel) {
2152 PyObject *r;
2153 int is_true;
2154 r = _PyObject_CallMethodId(result, &PyId_cancel, NULL);
2155 if (r == NULL) {
2156 return NULL;
2157 }
2158 is_true = PyObject_IsTrue(r);
2159 Py_DECREF(r);
2160 if (is_true < 0) {
2161 return NULL;
2162 }
2163 else if (is_true) {
2164 task->task_must_cancel = 0;
2165 }
2166 }
2167
2168 Py_RETURN_NONE;
2169 }
2170 else {
2171 goto yield_insteadof_yf;
2172 }
2173 }
2174 }
2175
2176 /* Check if `result` is None */
2177 if (result == Py_None) {
2178 /* Bare yield relinquishes control for one event loop iteration. */
2179 if (task_call_step_soon(task, NULL)) {
2180 goto fail;
2181 }
2182 return result;
2183 }
2184
2185 /* Check if `result` is a generator */
Victor Stinnerde4ae3d2016-12-04 22:59:09 +01002186 o = PyObject_CallFunctionObjArgs(inspect_isgenerator, result, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002187 if (o == NULL) {
2188 /* An exception in inspect.isgenerator */
2189 goto fail;
2190 }
2191 res = PyObject_IsTrue(o);
2192 Py_CLEAR(o);
2193 if (res == -1) {
2194 /* An exception while checking if 'val' is True */
2195 goto fail;
2196 }
2197 if (res == 1) {
2198 /* `result` is a generator */
2199 PyObject *ret;
2200 ret = task_set_error_soon(
2201 task, PyExc_RuntimeError,
2202 "yield was used instead of yield from for "
2203 "generator in task %R with %S", task, result);
2204 Py_DECREF(result);
2205 return ret;
2206 }
2207
2208 /* The `result` is none of the above */
2209 Py_DECREF(result);
2210 return task_set_error_soon(
2211 task, PyExc_RuntimeError, "Task got bad yield: %R", result);
2212
2213self_await:
2214 o = task_set_error_soon(
2215 task, PyExc_RuntimeError,
2216 "Task cannot await on itself: %R", task);
2217 Py_DECREF(result);
2218 return o;
2219
2220yield_insteadof_yf:
2221 o = task_set_error_soon(
2222 task, PyExc_RuntimeError,
2223 "yield was used instead of yield from "
2224 "in task %R with %R",
2225 task, result);
2226 Py_DECREF(result);
2227 return o;
2228
2229different_loop:
2230 o = task_set_error_soon(
2231 task, PyExc_RuntimeError,
2232 "Task %R got Future %R attached to a different loop",
2233 task, result);
2234 Py_DECREF(result);
2235 return o;
2236
2237fail:
2238 Py_XDECREF(result);
2239 return NULL;
2240}
2241
2242static PyObject *
2243task_step(TaskObj *task, PyObject *exc)
2244{
2245 PyObject *res;
2246 PyObject *ot;
2247
Yury Selivanov684ef2c2016-10-28 19:01:21 -04002248 if (PyDict_SetItem(current_tasks,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002249 task->task_loop, (PyObject*)task) == -1)
2250 {
2251 return NULL;
2252 }
2253
2254 res = task_step_impl(task, exc);
2255
2256 if (res == NULL) {
2257 PyObject *et, *ev, *tb;
2258 PyErr_Fetch(&et, &ev, &tb);
2259 ot = _PyDict_Pop(current_tasks, task->task_loop, NULL);
2260 if (ot == NULL) {
2261 Py_XDECREF(et);
2262 Py_XDECREF(tb);
2263 Py_XDECREF(ev);
2264 return NULL;
2265 }
2266 Py_DECREF(ot);
2267 PyErr_Restore(et, ev, tb);
2268 return NULL;
2269 }
2270 else {
2271 ot = _PyDict_Pop(current_tasks, task->task_loop, NULL);
2272 if (ot == NULL) {
2273 Py_DECREF(res);
2274 return NULL;
2275 }
2276 else {
2277 Py_DECREF(ot);
2278 return res;
2279 }
2280 }
2281}
2282
2283static PyObject *
2284task_wakeup(TaskObj *task, PyObject *o)
2285{
2286 assert(o);
2287
2288 if (Future_CheckExact(o) || Task_CheckExact(o)) {
2289 PyObject *fut_result = NULL;
2290 int res = future_get_result((FutureObj*)o, &fut_result);
2291 PyObject *result;
2292
2293 switch(res) {
2294 case -1:
2295 assert(fut_result == NULL);
2296 return NULL;
2297 case 0:
2298 Py_DECREF(fut_result);
2299 return task_call_step(task, NULL);
2300 default:
2301 assert(res == 1);
2302 result = task_call_step(task, fut_result);
2303 Py_DECREF(fut_result);
2304 return result;
2305 }
2306 }
2307
2308 PyObject *fut_result = PyObject_CallMethod(o, "result", NULL);
2309 if (fut_result == NULL) {
2310 PyObject *et, *ev, *tb;
2311 PyObject *res;
2312
2313 PyErr_Fetch(&et, &ev, &tb);
2314 if (!ev || !PyObject_TypeCheck(ev, (PyTypeObject *) et)) {
2315 PyErr_NormalizeException(&et, &ev, &tb);
2316 }
2317
2318 res = task_call_step(task, ev);
2319
2320 Py_XDECREF(et);
2321 Py_XDECREF(tb);
2322 Py_XDECREF(ev);
2323
2324 return res;
2325 }
2326 else {
2327 Py_DECREF(fut_result);
2328 return task_call_step(task, NULL);
2329 }
2330}
2331
2332
2333/*********************** Module **************************/
2334
2335
2336static void
2337module_free(void *m)
2338{
2339 Py_CLEAR(current_tasks);
2340 Py_CLEAR(all_tasks);
2341 Py_CLEAR(traceback_extract_stack);
2342 Py_CLEAR(asyncio_get_event_loop);
2343 Py_CLEAR(asyncio_future_repr_info_func);
2344 Py_CLEAR(asyncio_task_repr_info_func);
2345 Py_CLEAR(asyncio_task_get_stack_func);
2346 Py_CLEAR(asyncio_task_print_stack_func);
2347 Py_CLEAR(asyncio_InvalidStateError);
2348 Py_CLEAR(asyncio_CancelledError);
2349 Py_CLEAR(inspect_isgenerator);
2350}
2351
2352static int
2353module_init(void)
2354{
2355 PyObject *module = NULL;
2356 PyObject *cls;
2357
2358#define WITH_MOD(NAME) \
2359 Py_CLEAR(module); \
2360 module = PyImport_ImportModule(NAME); \
2361 if (module == NULL) { \
2362 return -1; \
2363 }
2364
2365#define GET_MOD_ATTR(VAR, NAME) \
2366 VAR = PyObject_GetAttrString(module, NAME); \
2367 if (VAR == NULL) { \
2368 goto fail; \
2369 }
2370
2371 WITH_MOD("asyncio.events")
2372 GET_MOD_ATTR(asyncio_get_event_loop, "get_event_loop")
2373
2374 WITH_MOD("asyncio.base_futures")
2375 GET_MOD_ATTR(asyncio_future_repr_info_func, "_future_repr_info")
2376 GET_MOD_ATTR(asyncio_InvalidStateError, "InvalidStateError")
2377 GET_MOD_ATTR(asyncio_CancelledError, "CancelledError")
2378
2379 WITH_MOD("asyncio.base_tasks")
2380 GET_MOD_ATTR(asyncio_task_repr_info_func, "_task_repr_info")
2381 GET_MOD_ATTR(asyncio_task_get_stack_func, "_task_get_stack")
2382 GET_MOD_ATTR(asyncio_task_print_stack_func, "_task_print_stack")
2383
2384 WITH_MOD("inspect")
2385 GET_MOD_ATTR(inspect_isgenerator, "isgenerator")
2386
2387 WITH_MOD("traceback")
2388 GET_MOD_ATTR(traceback_extract_stack, "extract_stack")
2389
2390 WITH_MOD("weakref")
2391 GET_MOD_ATTR(cls, "WeakSet")
Victor Stinnera5ed5f02016-12-06 18:45:50 +01002392 all_tasks = _PyObject_CallNoArg(cls);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002393 Py_CLEAR(cls);
2394 if (all_tasks == NULL) {
INADA Naokic411a7d2016-10-18 11:48:14 +09002395 goto fail;
2396 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09002397
Yury Selivanov684ef2c2016-10-28 19:01:21 -04002398 current_tasks = PyDict_New();
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002399 if (current_tasks == NULL) {
2400 goto fail;
2401 }
2402
2403 Py_CLEAR(module);
INADA Naokic411a7d2016-10-18 11:48:14 +09002404 return 0;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09002405
INADA Naokic411a7d2016-10-18 11:48:14 +09002406fail:
INADA Naokic411a7d2016-10-18 11:48:14 +09002407 Py_CLEAR(module);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002408 module_free(NULL);
INADA Naokic411a7d2016-10-18 11:48:14 +09002409 return -1;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09002410
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002411#undef WITH_MOD
2412#undef GET_MOD_ATTR
2413}
INADA Naoki9e4e38e2016-10-09 14:44:47 +09002414
INADA Naokic411a7d2016-10-18 11:48:14 +09002415PyDoc_STRVAR(module_doc, "Accelerator module for asyncio");
INADA Naoki9e4e38e2016-10-09 14:44:47 +09002416
INADA Naoki9f2ce252016-10-15 15:39:19 +09002417static struct PyModuleDef _asynciomodule = {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09002418 PyModuleDef_HEAD_INIT, /* m_base */
INADA Naoki9f2ce252016-10-15 15:39:19 +09002419 "_asyncio", /* m_name */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09002420 module_doc, /* m_doc */
2421 -1, /* m_size */
INADA Naokic411a7d2016-10-18 11:48:14 +09002422 NULL, /* m_methods */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09002423 NULL, /* m_slots */
2424 NULL, /* m_traverse */
2425 NULL, /* m_clear */
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002426 (freefunc)module_free /* m_free */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09002427};
2428
2429
2430PyMODINIT_FUNC
INADA Naoki9f2ce252016-10-15 15:39:19 +09002431PyInit__asyncio(void)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09002432{
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002433 if (module_init() < 0) {
INADA Naokic411a7d2016-10-18 11:48:14 +09002434 return NULL;
2435 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09002436 if (PyType_Ready(&FutureType) < 0) {
2437 return NULL;
2438 }
2439 if (PyType_Ready(&FutureIterType) < 0) {
2440 return NULL;
2441 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002442 if (PyType_Ready(&TaskSendMethWrapper_Type) < 0) {
2443 return NULL;
2444 }
2445 if(PyType_Ready(&TaskWakeupMethWrapper_Type) < 0) {
2446 return NULL;
2447 }
2448 if (PyType_Ready(&TaskType) < 0) {
2449 return NULL;
2450 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09002451
INADA Naoki9f2ce252016-10-15 15:39:19 +09002452 PyObject *m = PyModule_Create(&_asynciomodule);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09002453 if (m == NULL) {
2454 return NULL;
2455 }
2456
2457 Py_INCREF(&FutureType);
2458 if (PyModule_AddObject(m, "Future", (PyObject *)&FutureType) < 0) {
2459 Py_DECREF(&FutureType);
2460 return NULL;
2461 }
2462
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002463 Py_INCREF(&TaskType);
2464 if (PyModule_AddObject(m, "Task", (PyObject *)&TaskType) < 0) {
2465 Py_DECREF(&TaskType);
2466 return NULL;
2467 }
2468
INADA Naoki9e4e38e2016-10-09 14:44:47 +09002469 return m;
2470}