blob: d66cc4cf0a5f5f0b1fcc99fecba9b71484938c3e [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 Selivanova70232f2017-12-13 14:49:42 -050012_Py_IDENTIFIER(__asyncio_running_event_loop__);
Yury Selivanova0c1ba62016-10-28 12:52:37 -040013_Py_IDENTIFIER(add_done_callback);
Andrew Svetlov44d1a592017-12-16 21:58:38 +020014_Py_IDENTIFIER(all_tasks);
INADA Naoki9e4e38e2016-10-09 14:44:47 +090015_Py_IDENTIFIER(call_soon);
Yury Selivanova0c1ba62016-10-28 12:52:37 -040016_Py_IDENTIFIER(cancel);
Andrew Svetlov44d1a592017-12-16 21:58:38 +020017_Py_IDENTIFIER(current_task);
Yury Selivanova70232f2017-12-13 14:49:42 -050018_Py_IDENTIFIER(get_event_loop);
Yury Selivanova0c1ba62016-10-28 12:52:37 -040019_Py_IDENTIFIER(send);
20_Py_IDENTIFIER(throw);
INADA Naoki9e4e38e2016-10-09 14:44:47 +090021
22
INADA Naoki9f2ce252016-10-15 15:39:19 +090023/* State of the _asyncio module */
Andrew Svetlov44d1a592017-12-16 21:58:38 +020024static PyObject *asyncio_mod;
Yury Selivanova0c1ba62016-10-28 12:52:37 -040025static PyObject *inspect_isgenerator;
Andrew Svetlov44d1a592017-12-16 21:58:38 +020026static PyObject *traceback_extract_stack;
27static PyObject *asyncio_get_event_loop_policy;
28static PyObject *asyncio_future_repr_info_func;
29static PyObject *asyncio_iscoroutine_func;
30static PyObject *asyncio_task_get_stack_func;
31static PyObject *asyncio_task_print_stack_func;
32static PyObject *asyncio_task_repr_info_func;
33static PyObject *asyncio_InvalidStateError;
34static PyObject *asyncio_CancelledError;
Yury Selivanovf23746a2018-01-22 19:11:18 -050035static PyObject *context_kwname;
Andrew Svetlov44d1a592017-12-16 21:58:38 +020036
Yury Selivanov9d411c12018-01-23 15:10:03 -050037static PyObject *cached_running_holder;
38static volatile uint64_t cached_running_holder_tsid;
39
Andrew Svetlov44d1a592017-12-16 21:58:38 +020040
Yury Selivanovca9b36c2017-12-23 15:04:15 -050041/* WeakSet containing all alive tasks. */
42static PyObject *all_tasks;
Andrew Svetlov44d1a592017-12-16 21:58:38 +020043
44/* Dictionary containing tasks that are currently active in
45 all running event loops. {EventLoop: Task} */
Yury Selivanovca9b36c2017-12-23 15:04:15 -050046static PyObject *current_tasks;
INADA Naoki9e4e38e2016-10-09 14:44:47 +090047
Yury Selivanova9d7e552017-12-19 07:18:45 -050048/* An isinstance type cache for the 'is_coroutine()' function. */
49static PyObject *iscoroutine_typecache;
50
INADA Naoki9e4e38e2016-10-09 14:44:47 +090051
INADA Naoki9e4e38e2016-10-09 14:44:47 +090052typedef enum {
53 STATE_PENDING,
54 STATE_CANCELLED,
55 STATE_FINISHED
56} fut_state;
57
Yury Selivanova0c1ba62016-10-28 12:52:37 -040058#define FutureObj_HEAD(prefix) \
59 PyObject_HEAD \
60 PyObject *prefix##_loop; \
Yury Selivanov1b7c11f2017-12-17 20:19:47 -050061 PyObject *prefix##_callback0; \
Yury Selivanovf23746a2018-01-22 19:11:18 -050062 PyContext *prefix##_context0; \
Yury Selivanova0c1ba62016-10-28 12:52:37 -040063 PyObject *prefix##_callbacks; \
64 PyObject *prefix##_exception; \
65 PyObject *prefix##_result; \
66 PyObject *prefix##_source_tb; \
67 fut_state prefix##_state; \
68 int prefix##_log_tb; \
69 int prefix##_blocking; \
70 PyObject *dict; \
71 PyObject *prefix##_weakreflist;
72
73typedef struct {
74 FutureObj_HEAD(fut)
75} FutureObj;
76
77typedef struct {
78 FutureObj_HEAD(task)
79 PyObject *task_fut_waiter;
80 PyObject *task_coro;
Yury Selivanovf23746a2018-01-22 19:11:18 -050081 PyContext *task_context;
Yury Selivanova0c1ba62016-10-28 12:52:37 -040082 int task_must_cancel;
83 int task_log_destroy_pending;
84} TaskObj;
INADA Naoki9e4e38e2016-10-09 14:44:47 +090085
86typedef struct {
87 PyObject_HEAD
Yury Selivanova0c1ba62016-10-28 12:52:37 -040088 TaskObj *sw_task;
89 PyObject *sw_arg;
Serhiy Storchakabca49392017-09-03 08:10:14 +030090} TaskStepMethWrapper;
INADA Naoki9e4e38e2016-10-09 14:44:47 +090091
Yury Selivanova0c1ba62016-10-28 12:52:37 -040092typedef struct {
93 PyObject_HEAD
94 TaskObj *ww_task;
95} TaskWakeupMethWrapper;
96
Yury Selivanov9d411c12018-01-23 15:10:03 -050097typedef struct {
98 PyObject_HEAD
99 PyObject *rl_loop;
100#if defined(HAVE_GETPID) && !defined(MS_WINDOWS)
101 pid_t rl_pid;
102#endif
103} PyRunningLoopHolder;
104
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400105
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500106static PyTypeObject FutureType;
107static PyTypeObject TaskType;
Yury Selivanov9d411c12018-01-23 15:10:03 -0500108static PyTypeObject PyRunningLoopHolder_Type;
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500109
110
111#define Future_CheckExact(obj) (Py_TYPE(obj) == &FutureType)
112#define Task_CheckExact(obj) (Py_TYPE(obj) == &TaskType)
113
114#define Future_Check(obj) PyObject_TypeCheck(obj, &FutureType)
115#define Task_Check(obj) PyObject_TypeCheck(obj, &TaskType)
116
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400117#include "clinic/_asynciomodule.c.h"
118
119
120/*[clinic input]
121class _asyncio.Future "FutureObj *" "&Future_Type"
122[clinic start generated code]*/
123/*[clinic end generated code: output=da39a3ee5e6b4b0d input=00d3e4abca711e0f]*/
124
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500125
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400126/* Get FutureIter from Future */
Yury Selivanov9d411c12018-01-23 15:10:03 -0500127static PyObject * future_new_iter(PyObject *);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900128
Yury Selivanov9d411c12018-01-23 15:10:03 -0500129static PyRunningLoopHolder * new_running_loop_holder(PyObject *);
130
Yury Selivanova70232f2017-12-13 14:49:42 -0500131
132static int
Yury Selivanova9d7e552017-12-19 07:18:45 -0500133_is_coroutine(PyObject *coro)
134{
135 /* 'coro' is not a native coroutine, call asyncio.iscoroutine()
136 to check if it's another coroutine flavour.
137
138 Do this check after 'future_init()'; in case we need to raise
139 an error, __del__ needs a properly initialized object.
140 */
141 PyObject *res = PyObject_CallFunctionObjArgs(
142 asyncio_iscoroutine_func, coro, NULL);
143 if (res == NULL) {
144 return -1;
145 }
146
147 int is_res_true = PyObject_IsTrue(res);
148 Py_DECREF(res);
149 if (is_res_true <= 0) {
150 return is_res_true;
151 }
152
Andrew Svetlov0f47fa22017-12-23 22:06:46 +0200153 if (PySet_GET_SIZE(iscoroutine_typecache) < 100) {
Yury Selivanova9d7e552017-12-19 07:18:45 -0500154 /* Just in case we don't want to cache more than 100
155 positive types. That shouldn't ever happen, unless
156 someone stressing the system on purpose.
157 */
158 if (PySet_Add(iscoroutine_typecache, (PyObject*) Py_TYPE(coro))) {
159 return -1;
160 }
161 }
162
163 return 1;
164}
165
166
167static inline int
168is_coroutine(PyObject *coro)
169{
170 if (PyCoro_CheckExact(coro)) {
171 return 1;
172 }
173
174 /* Check if `type(coro)` is in the cache.
175 Caching makes is_coroutine() function almost as fast as
176 PyCoro_CheckExact() for non-native coroutine-like objects
177 (like coroutines compiled with Cython).
178
179 asyncio.iscoroutine() has its own type caching mechanism.
180 This cache allows us to avoid the cost of even calling
181 a pure-Python function in 99.9% cases.
182 */
183 int has_it = PySet_Contains(
184 iscoroutine_typecache, (PyObject*) Py_TYPE(coro));
185 if (has_it == 0) {
186 /* type(coro) is not in iscoroutine_typecache */
187 return _is_coroutine(coro);
188 }
189
Miss Islington (bot)e86db342018-02-03 17:41:43 -0800190 /* either an error has occurred or
Yury Selivanova9d7e552017-12-19 07:18:45 -0500191 type(coro) is in iscoroutine_typecache
192 */
193 return has_it;
194}
195
196
Yury Selivanovca9b36c2017-12-23 15:04:15 -0500197static PyObject *
198get_future_loop(PyObject *fut)
199{
200 /* Implementation of `asyncio.futures._get_loop` */
201
202 _Py_IDENTIFIER(get_loop);
203 _Py_IDENTIFIER(_loop);
204
205 if (Future_CheckExact(fut) || Task_CheckExact(fut)) {
206 PyObject *loop = ((FutureObj *)fut)->fut_loop;
207 Py_INCREF(loop);
208 return loop;
209 }
210
211 PyObject *getloop = _PyObject_GetAttrId(fut, &PyId_get_loop);
212 if (getloop != NULL) {
213 PyObject *res = _PyObject_CallNoArg(getloop);
214 Py_DECREF(getloop);
215 return res;
216 }
217
Yury Selivanov719ccbc2017-12-23 16:29:26 -0500218 PyErr_Clear();
Yury Selivanovca9b36c2017-12-23 15:04:15 -0500219 return _PyObject_GetAttrId(fut, &PyId__loop);
220}
221
222
Yury Selivanova9d7e552017-12-19 07:18:45 -0500223static int
Yury Selivanova70232f2017-12-13 14:49:42 -0500224get_running_loop(PyObject **loop)
225{
Yury Selivanov9d411c12018-01-23 15:10:03 -0500226 PyObject *rl;
Yury Selivanova70232f2017-12-13 14:49:42 -0500227
Yury Selivanov9d411c12018-01-23 15:10:03 -0500228 PyThreadState *ts = PyThreadState_Get();
229 if (ts->id == cached_running_holder_tsid && cached_running_holder != NULL) {
230 // Fast path, check the cache.
231 rl = cached_running_holder; // borrowed
232 }
233 else {
234 if (ts->dict == NULL) {
235 goto not_found;
236 }
237
238 rl = _PyDict_GetItemIdWithError(
239 ts->dict, &PyId___asyncio_running_event_loop__); // borrowed
240 if (rl == NULL) {
241 if (PyErr_Occurred()) {
242 goto error;
243 }
244 else {
245 goto not_found;
246 }
247 }
248
249 cached_running_holder = rl; // borrowed
250 cached_running_holder_tsid = ts->id;
Yury Selivanova70232f2017-12-13 14:49:42 -0500251 }
252
Yury Selivanov9d411c12018-01-23 15:10:03 -0500253 assert(Py_TYPE(rl) == &PyRunningLoopHolder_Type);
254 PyObject *running_loop = ((PyRunningLoopHolder *)rl)->rl_loop;
Yury Selivanova70232f2017-12-13 14:49:42 -0500255
256 if (running_loop == Py_None) {
257 goto not_found;
258 }
259
Yury Selivanov9d411c12018-01-23 15:10:03 -0500260#if defined(HAVE_GETPID) && !defined(MS_WINDOWS)
261 /* On Windows there is no getpid, but there is also no os.fork(),
262 so there is no need for this check.
263 */
264 if (getpid() != ((PyRunningLoopHolder *)rl)->rl_pid) {
265 goto not_found;
Yury Selivanova70232f2017-12-13 14:49:42 -0500266 }
Yury Selivanov9d411c12018-01-23 15:10:03 -0500267#endif
Yury Selivanova70232f2017-12-13 14:49:42 -0500268
Yury Selivanov9d411c12018-01-23 15:10:03 -0500269 Py_INCREF(running_loop);
270 *loop = running_loop;
271 return 0;
Yury Selivanova70232f2017-12-13 14:49:42 -0500272
273not_found:
274 *loop = NULL;
275 return 0;
276
Yury Selivanova70232f2017-12-13 14:49:42 -0500277error:
278 *loop = NULL;
279 return -1;
280}
281
282
283static int
284set_running_loop(PyObject *loop)
285{
Yury Selivanov9d411c12018-01-23 15:10:03 -0500286 cached_running_holder = NULL;
287 cached_running_holder_tsid = 0;
Yury Selivanova70232f2017-12-13 14:49:42 -0500288
Yury Selivanov9d411c12018-01-23 15:10:03 -0500289 PyObject *ts_dict = PyThreadState_GetDict(); // borrowed
Yury Selivanova70232f2017-12-13 14:49:42 -0500290 if (ts_dict == NULL) {
291 PyErr_SetString(
292 PyExc_RuntimeError, "thread-local storage is not available");
293 return -1;
294 }
295
Yury Selivanov9d411c12018-01-23 15:10:03 -0500296 PyRunningLoopHolder *rl = new_running_loop_holder(loop);
297 if (rl == NULL) {
Yury Selivanova70232f2017-12-13 14:49:42 -0500298 return -1;
299 }
300
Yury Selivanova70232f2017-12-13 14:49:42 -0500301 if (_PyDict_SetItemId(
Yury Selivanov9d411c12018-01-23 15:10:03 -0500302 ts_dict, &PyId___asyncio_running_event_loop__, (PyObject *)rl) < 0)
303 {
304 Py_DECREF(rl); // will cleanup loop & current_pid
Yury Selivanova70232f2017-12-13 14:49:42 -0500305 return -1;
306 }
Yury Selivanov9d411c12018-01-23 15:10:03 -0500307 Py_DECREF(rl);
Yury Selivanova70232f2017-12-13 14:49:42 -0500308
309 return 0;
310}
311
312
313static PyObject *
314get_event_loop(void)
315{
316 PyObject *loop;
317 PyObject *policy;
318
319 if (get_running_loop(&loop)) {
320 return NULL;
321 }
322 if (loop != NULL) {
323 return loop;
324 }
325
326 policy = _PyObject_CallNoArg(asyncio_get_event_loop_policy);
327 if (policy == NULL) {
328 return NULL;
329 }
330
331 loop = _PyObject_CallMethodId(policy, &PyId_get_event_loop, NULL);
332 Py_DECREF(policy);
333 return loop;
334}
335
336
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900337static int
Yury Selivanovf23746a2018-01-22 19:11:18 -0500338call_soon(PyObject *loop, PyObject *func, PyObject *arg, PyContext *ctx)
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500339{
340 PyObject *handle;
Yury Selivanovf23746a2018-01-22 19:11:18 -0500341 PyObject *stack[3];
342 Py_ssize_t nargs;
343
344 if (ctx == NULL) {
345 handle = _PyObject_CallMethodIdObjArgs(
346 loop, &PyId_call_soon, func, arg, NULL);
347 }
348 else {
349 /* Use FASTCALL to pass a keyword-only argument to call_soon */
350
351 PyObject *callable = _PyObject_GetAttrId(loop, &PyId_call_soon);
352 if (callable == NULL) {
353 return -1;
354 }
355
356 /* All refs in 'stack' are borrowed. */
357 nargs = 1;
358 stack[0] = func;
359 if (arg != NULL) {
360 stack[1] = arg;
361 nargs++;
362 }
363 stack[nargs] = (PyObject *)ctx;
364
365 handle = _PyObject_FastCallKeywords(
366 callable, stack, nargs, context_kwname);
367 Py_DECREF(callable);
368 }
369
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500370 if (handle == NULL) {
371 return -1;
372 }
373 Py_DECREF(handle);
374 return 0;
375}
376
377
378static inline int
379future_is_alive(FutureObj *fut)
380{
381 return fut->fut_loop != NULL;
382}
383
384
385static inline int
386future_ensure_alive(FutureObj *fut)
387{
388 if (!future_is_alive(fut)) {
389 PyErr_SetString(PyExc_RuntimeError,
390 "Future object is not initialized.");
391 return -1;
392 }
393 return 0;
394}
395
396
397#define ENSURE_FUTURE_ALIVE(fut) \
398 do { \
399 assert(Future_Check(fut) || Task_Check(fut)); \
400 if (future_ensure_alive((FutureObj*)fut)) { \
401 return NULL; \
402 } \
403 } while(0);
404
405
406static int
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400407future_schedule_callbacks(FutureObj *fut)
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900408{
409 Py_ssize_t len;
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500410 Py_ssize_t i;
411
412 if (fut->fut_callback0 != NULL) {
413 /* There's a 1st callback */
414
415 int ret = call_soon(
Yury Selivanovf23746a2018-01-22 19:11:18 -0500416 fut->fut_loop, fut->fut_callback0,
417 (PyObject *)fut, fut->fut_context0);
418
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500419 Py_CLEAR(fut->fut_callback0);
Yury Selivanovf23746a2018-01-22 19:11:18 -0500420 Py_CLEAR(fut->fut_context0);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500421 if (ret) {
422 /* If an error occurs in pure-Python implementation,
423 all callbacks are cleared. */
424 Py_CLEAR(fut->fut_callbacks);
425 return ret;
426 }
427
428 /* we called the first callback, now try calling
429 callbacks from the 'fut_callbacks' list. */
430 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900431
432 if (fut->fut_callbacks == NULL) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500433 /* No more callbacks, return. */
434 return 0;
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900435 }
436
437 len = PyList_GET_SIZE(fut->fut_callbacks);
438 if (len == 0) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500439 /* The list of callbacks was empty; clear it and return. */
440 Py_CLEAR(fut->fut_callbacks);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900441 return 0;
442 }
443
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900444 for (i = 0; i < len; i++) {
Yury Selivanovf23746a2018-01-22 19:11:18 -0500445 PyObject *cb_tup = PyList_GET_ITEM(fut->fut_callbacks, i);
446 PyObject *cb = PyTuple_GET_ITEM(cb_tup, 0);
447 PyObject *ctx = PyTuple_GET_ITEM(cb_tup, 1);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900448
Yury Selivanovf23746a2018-01-22 19:11:18 -0500449 if (call_soon(fut->fut_loop, cb, (PyObject *)fut, (PyContext *)ctx)) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500450 /* If an error occurs in pure-Python implementation,
451 all callbacks are cleared. */
452 Py_CLEAR(fut->fut_callbacks);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900453 return -1;
454 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900455 }
456
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500457 Py_CLEAR(fut->fut_callbacks);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900458 return 0;
459}
460
Miss Islington (bot)ef20abe2018-02-13 03:32:18 -0800461
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900462static int
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400463future_init(FutureObj *fut, PyObject *loop)
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900464{
Serhiy Storchakabca49392017-09-03 08:10:14 +0300465 PyObject *res;
466 int is_true;
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900467 _Py_IDENTIFIER(get_debug);
468
Miss Islington (bot)ef20abe2018-02-13 03:32:18 -0800469 // Same to FutureObj_clear() but not clearing fut->dict
470 Py_CLEAR(fut->fut_loop);
471 Py_CLEAR(fut->fut_callback0);
472 Py_CLEAR(fut->fut_context0);
473 Py_CLEAR(fut->fut_callbacks);
474 Py_CLEAR(fut->fut_result);
475 Py_CLEAR(fut->fut_exception);
476 Py_CLEAR(fut->fut_source_tb);
477
478 fut->fut_state = STATE_PENDING;
479 fut->fut_log_tb = 0;
480 fut->fut_blocking = 0;
481
Serhiy Storchakabca49392017-09-03 08:10:14 +0300482 if (loop == Py_None) {
Yury Selivanova70232f2017-12-13 14:49:42 -0500483 loop = get_event_loop();
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900484 if (loop == NULL) {
485 return -1;
486 }
487 }
488 else {
489 Py_INCREF(loop);
490 }
Miss Islington (bot)ef20abe2018-02-13 03:32:18 -0800491 fut->fut_loop = loop;
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900492
Victor Stinnerf94d1ee2016-10-29 09:05:39 +0200493 res = _PyObject_CallMethodId(fut->fut_loop, &PyId_get_debug, NULL);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900494 if (res == NULL) {
495 return -1;
496 }
Serhiy Storchakabca49392017-09-03 08:10:14 +0300497 is_true = PyObject_IsTrue(res);
498 Py_DECREF(res);
499 if (is_true < 0) {
500 return -1;
501 }
502 if (is_true) {
Miss Islington (bot)ef20abe2018-02-13 03:32:18 -0800503 fut->fut_source_tb = _PyObject_CallNoArg(traceback_extract_stack);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900504 if (fut->fut_source_tb == NULL) {
505 return -1;
506 }
507 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900508
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900509 return 0;
510}
511
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900512static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400513future_set_result(FutureObj *fut, PyObject *res)
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900514{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500515 if (future_ensure_alive(fut)) {
516 return NULL;
517 }
518
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900519 if (fut->fut_state != STATE_PENDING) {
520 PyErr_SetString(asyncio_InvalidStateError, "invalid state");
521 return NULL;
522 }
523
Serhiy Storchakabca49392017-09-03 08:10:14 +0300524 assert(!fut->fut_result);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900525 Py_INCREF(res);
526 fut->fut_result = res;
527 fut->fut_state = STATE_FINISHED;
528
Yury Selivanov22feeb82018-01-24 11:31:01 -0500529 if (future_schedule_callbacks(fut) == -1) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900530 return NULL;
531 }
532 Py_RETURN_NONE;
533}
534
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900535static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400536future_set_exception(FutureObj *fut, PyObject *exc)
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900537{
538 PyObject *exc_val = NULL;
539
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900540 if (fut->fut_state != STATE_PENDING) {
541 PyErr_SetString(asyncio_InvalidStateError, "invalid state");
542 return NULL;
543 }
544
545 if (PyExceptionClass_Check(exc)) {
Victor Stinnera5ed5f02016-12-06 18:45:50 +0100546 exc_val = _PyObject_CallNoArg(exc);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900547 if (exc_val == NULL) {
548 return NULL;
549 }
Serhiy Storchakabca49392017-09-03 08:10:14 +0300550 if (fut->fut_state != STATE_PENDING) {
551 Py_DECREF(exc_val);
552 PyErr_SetString(asyncio_InvalidStateError, "invalid state");
553 return NULL;
554 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900555 }
556 else {
557 exc_val = exc;
558 Py_INCREF(exc_val);
559 }
560 if (!PyExceptionInstance_Check(exc_val)) {
561 Py_DECREF(exc_val);
562 PyErr_SetString(PyExc_TypeError, "invalid exception object");
563 return NULL;
564 }
565 if ((PyObject*)Py_TYPE(exc_val) == PyExc_StopIteration) {
566 Py_DECREF(exc_val);
567 PyErr_SetString(PyExc_TypeError,
568 "StopIteration interacts badly with generators "
569 "and cannot be raised into a Future");
570 return NULL;
571 }
572
Serhiy Storchakabca49392017-09-03 08:10:14 +0300573 assert(!fut->fut_exception);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900574 fut->fut_exception = exc_val;
575 fut->fut_state = STATE_FINISHED;
576
Yury Selivanov22feeb82018-01-24 11:31:01 -0500577 if (future_schedule_callbacks(fut) == -1) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900578 return NULL;
579 }
580
581 fut->fut_log_tb = 1;
582 Py_RETURN_NONE;
583}
584
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400585static int
586future_get_result(FutureObj *fut, PyObject **result)
587{
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400588 if (fut->fut_state == STATE_CANCELLED) {
Serhiy Storchakabca49392017-09-03 08:10:14 +0300589 PyErr_SetNone(asyncio_CancelledError);
590 return -1;
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400591 }
592
593 if (fut->fut_state != STATE_FINISHED) {
Serhiy Storchakabca49392017-09-03 08:10:14 +0300594 PyErr_SetString(asyncio_InvalidStateError, "Result is not set.");
595 return -1;
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400596 }
597
598 fut->fut_log_tb = 0;
599 if (fut->fut_exception != NULL) {
600 Py_INCREF(fut->fut_exception);
601 *result = fut->fut_exception;
602 return 1;
603 }
604
605 Py_INCREF(fut->fut_result);
606 *result = fut->fut_result;
607 return 0;
608}
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900609
610static PyObject *
Yury Selivanovf23746a2018-01-22 19:11:18 -0500611future_add_done_callback(FutureObj *fut, PyObject *arg, PyContext *ctx)
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900612{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500613 if (!future_is_alive(fut)) {
614 PyErr_SetString(PyExc_RuntimeError, "uninitialized Future object");
615 return NULL;
616 }
617
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900618 if (fut->fut_state != STATE_PENDING) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500619 /* The future is done/cancelled, so schedule the callback
620 right away. */
Yury Selivanovf23746a2018-01-22 19:11:18 -0500621 if (call_soon(fut->fut_loop, arg, (PyObject*) fut, ctx)) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900622 return NULL;
623 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900624 }
625 else {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500626 /* The future is pending, add a callback.
627
628 Callbacks in the future object are stored as follows:
629
630 callback0 -- a pointer to the first callback
631 callbacks -- a list of 2nd, 3rd, ... callbacks
632
633 Invariants:
634
635 * callbacks != NULL:
636 There are some callbacks in in the list. Just
637 add the new callback to it.
638
639 * callbacks == NULL and callback0 == NULL:
640 This is the first callback. Set it to callback0.
641
642 * callbacks == NULL and callback0 != NULL:
643 This is a second callback. Initialize callbacks
644 with a new list and add the new callback to it.
645 */
646
Yury Selivanovf23746a2018-01-22 19:11:18 -0500647 if (fut->fut_callbacks == NULL && fut->fut_callback0 == NULL) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500648 Py_INCREF(arg);
649 fut->fut_callback0 = arg;
Yury Selivanovf23746a2018-01-22 19:11:18 -0500650 Py_INCREF(ctx);
651 fut->fut_context0 = ctx;
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500652 }
653 else {
Yury Selivanovf23746a2018-01-22 19:11:18 -0500654 PyObject *tup = PyTuple_New(2);
655 if (tup == NULL) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500656 return NULL;
657 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500658 Py_INCREF(arg);
Yury Selivanovf23746a2018-01-22 19:11:18 -0500659 PyTuple_SET_ITEM(tup, 0, arg);
660 Py_INCREF(ctx);
661 PyTuple_SET_ITEM(tup, 1, (PyObject *)ctx);
662
663 if (fut->fut_callbacks != NULL) {
664 int err = PyList_Append(fut->fut_callbacks, tup);
665 if (err) {
666 Py_DECREF(tup);
667 return NULL;
668 }
669 Py_DECREF(tup);
670 }
671 else {
672 fut->fut_callbacks = PyList_New(1);
673 if (fut->fut_callbacks == NULL) {
674 return NULL;
675 }
676
677 PyList_SET_ITEM(fut->fut_callbacks, 0, tup); /* borrow */
678 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900679 }
680 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500681
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900682 Py_RETURN_NONE;
683}
684
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400685static PyObject *
686future_cancel(FutureObj *fut)
687{
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +0000688 fut->fut_log_tb = 0;
689
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400690 if (fut->fut_state != STATE_PENDING) {
691 Py_RETURN_FALSE;
692 }
693 fut->fut_state = STATE_CANCELLED;
694
Yury Selivanov22feeb82018-01-24 11:31:01 -0500695 if (future_schedule_callbacks(fut) == -1) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400696 return NULL;
697 }
698
699 Py_RETURN_TRUE;
700}
701
702/*[clinic input]
703_asyncio.Future.__init__
704
705 *
Serhiy Storchakabca49392017-09-03 08:10:14 +0300706 loop: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400707
708This class is *almost* compatible with concurrent.futures.Future.
709
710 Differences:
711
712 - result() and exception() do not take a timeout argument and
713 raise an exception when the future isn't done yet.
714
715 - Callbacks registered with add_done_callback() are always called
716 via the event loop's call_soon_threadsafe().
717
718 - This class is not compatible with the wait() and as_completed()
719 methods in the concurrent.futures package.
720[clinic start generated code]*/
721
722static int
723_asyncio_Future___init___impl(FutureObj *self, PyObject *loop)
Serhiy Storchakabca49392017-09-03 08:10:14 +0300724/*[clinic end generated code: output=9ed75799eaccb5d6 input=89af317082bc0bf8]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400725
726{
727 return future_init(self, loop);
728}
729
730static int
731FutureObj_clear(FutureObj *fut)
732{
733 Py_CLEAR(fut->fut_loop);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500734 Py_CLEAR(fut->fut_callback0);
Yury Selivanovf23746a2018-01-22 19:11:18 -0500735 Py_CLEAR(fut->fut_context0);
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400736 Py_CLEAR(fut->fut_callbacks);
737 Py_CLEAR(fut->fut_result);
738 Py_CLEAR(fut->fut_exception);
739 Py_CLEAR(fut->fut_source_tb);
740 Py_CLEAR(fut->dict);
741 return 0;
742}
743
744static int
745FutureObj_traverse(FutureObj *fut, visitproc visit, void *arg)
746{
747 Py_VISIT(fut->fut_loop);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500748 Py_VISIT(fut->fut_callback0);
Yury Selivanovf23746a2018-01-22 19:11:18 -0500749 Py_VISIT(fut->fut_context0);
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400750 Py_VISIT(fut->fut_callbacks);
751 Py_VISIT(fut->fut_result);
752 Py_VISIT(fut->fut_exception);
753 Py_VISIT(fut->fut_source_tb);
754 Py_VISIT(fut->dict);
755 return 0;
756}
757
758/*[clinic input]
759_asyncio.Future.result
760
761Return the result this future represents.
762
763If the future has been cancelled, raises CancelledError. If the
764future's result isn't yet available, raises InvalidStateError. If
765the future is done and has an exception set, this exception is raised.
766[clinic start generated code]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900767
768static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400769_asyncio_Future_result_impl(FutureObj *self)
770/*[clinic end generated code: output=f35f940936a4b1e5 input=49ecf9cf5ec50dc5]*/
771{
772 PyObject *result;
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500773
774 if (!future_is_alive(self)) {
775 PyErr_SetString(asyncio_InvalidStateError,
776 "Future object is not initialized.");
777 return NULL;
778 }
779
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400780 int res = future_get_result(self, &result);
781
782 if (res == -1) {
783 return NULL;
784 }
785
786 if (res == 0) {
787 return result;
788 }
789
790 assert(res == 1);
791
792 PyErr_SetObject(PyExceptionInstance_Class(result), result);
793 Py_DECREF(result);
794 return NULL;
795}
796
797/*[clinic input]
798_asyncio.Future.exception
799
800Return the exception that was set on this future.
801
802The exception (or None if no exception was set) is returned only if
803the future is done. If the future has been cancelled, raises
804CancelledError. If the future isn't done yet, raises
805InvalidStateError.
806[clinic start generated code]*/
807
808static PyObject *
809_asyncio_Future_exception_impl(FutureObj *self)
810/*[clinic end generated code: output=88b20d4f855e0710 input=733547a70c841c68]*/
811{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500812 if (!future_is_alive(self)) {
813 PyErr_SetString(asyncio_InvalidStateError,
814 "Future object is not initialized.");
815 return NULL;
816 }
817
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400818 if (self->fut_state == STATE_CANCELLED) {
Serhiy Storchakabca49392017-09-03 08:10:14 +0300819 PyErr_SetNone(asyncio_CancelledError);
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400820 return NULL;
821 }
822
823 if (self->fut_state != STATE_FINISHED) {
Serhiy Storchakabca49392017-09-03 08:10:14 +0300824 PyErr_SetString(asyncio_InvalidStateError, "Exception is not set.");
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400825 return NULL;
826 }
827
828 if (self->fut_exception != NULL) {
829 self->fut_log_tb = 0;
830 Py_INCREF(self->fut_exception);
831 return self->fut_exception;
832 }
833
834 Py_RETURN_NONE;
835}
836
837/*[clinic input]
838_asyncio.Future.set_result
839
Yury Selivanov0cf16f92017-12-25 10:48:15 -0500840 result: object
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400841 /
842
843Mark the future done and set its result.
844
845If the future is already done when this method is called, raises
846InvalidStateError.
847[clinic start generated code]*/
848
849static PyObject *
Yury Selivanov0cf16f92017-12-25 10:48:15 -0500850_asyncio_Future_set_result(FutureObj *self, PyObject *result)
851/*[clinic end generated code: output=1ec2e6bcccd6f2ce input=8b75172c2a7b05f1]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400852{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500853 ENSURE_FUTURE_ALIVE(self)
Yury Selivanov0cf16f92017-12-25 10:48:15 -0500854 return future_set_result(self, result);
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400855}
856
857/*[clinic input]
858_asyncio.Future.set_exception
859
Serhiy Storchakabca49392017-09-03 08:10:14 +0300860 exception: object
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400861 /
862
863Mark the future done and set an exception.
864
865If the future is already done when this method is called, raises
866InvalidStateError.
867[clinic start generated code]*/
868
869static PyObject *
870_asyncio_Future_set_exception(FutureObj *self, PyObject *exception)
Serhiy Storchakabca49392017-09-03 08:10:14 +0300871/*[clinic end generated code: output=f1c1b0cd321be360 input=e45b7d7aa71cc66d]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400872{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500873 ENSURE_FUTURE_ALIVE(self)
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400874 return future_set_exception(self, exception);
875}
876
877/*[clinic input]
878_asyncio.Future.add_done_callback
879
Serhiy Storchakabca49392017-09-03 08:10:14 +0300880 fn: object
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400881 /
Yury Selivanovf23746a2018-01-22 19:11:18 -0500882 *
883 context: object = NULL
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400884
885Add a callback to be run when the future becomes done.
886
887The callback is called with a single argument - the future object. If
888the future is already done when this is called, the callback is
889scheduled with call_soon.
890[clinic start generated code]*/
891
892static PyObject *
Yury Selivanovf23746a2018-01-22 19:11:18 -0500893_asyncio_Future_add_done_callback_impl(FutureObj *self, PyObject *fn,
894 PyObject *context)
895/*[clinic end generated code: output=7ce635bbc9554c1e input=15ab0693a96e9533]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400896{
Yury Selivanovf23746a2018-01-22 19:11:18 -0500897 if (context == NULL) {
898 context = (PyObject *)PyContext_CopyCurrent();
899 if (context == NULL) {
900 return NULL;
901 }
902 PyObject *res = future_add_done_callback(
903 self, fn, (PyContext *)context);
904 Py_DECREF(context);
905 return res;
906 }
907 return future_add_done_callback(self, fn, (PyContext *)context);
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400908}
909
910/*[clinic input]
911_asyncio.Future.remove_done_callback
912
Serhiy Storchakabca49392017-09-03 08:10:14 +0300913 fn: object
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400914 /
915
916Remove all instances of a callback from the "call when done" list.
917
918Returns the number of callbacks removed.
919[clinic start generated code]*/
920
921static PyObject *
922_asyncio_Future_remove_done_callback(FutureObj *self, PyObject *fn)
Serhiy Storchakabca49392017-09-03 08:10:14 +0300923/*[clinic end generated code: output=5ab1fb52b24ef31f input=0a43280a149d505b]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900924{
925 PyObject *newlist;
926 Py_ssize_t len, i, j=0;
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500927 Py_ssize_t cleared_callback0 = 0;
928
929 ENSURE_FUTURE_ALIVE(self)
930
931 if (self->fut_callback0 != NULL) {
932 int cmp = PyObject_RichCompareBool(fn, self->fut_callback0, Py_EQ);
933 if (cmp == -1) {
934 return NULL;
935 }
936 if (cmp == 1) {
937 /* callback0 == fn */
938 Py_CLEAR(self->fut_callback0);
Yury Selivanovf23746a2018-01-22 19:11:18 -0500939 Py_CLEAR(self->fut_context0);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500940 cleared_callback0 = 1;
941 }
942 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900943
Serhiy Storchakabca49392017-09-03 08:10:14 +0300944 if (self->fut_callbacks == NULL) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500945 return PyLong_FromSsize_t(cleared_callback0);
Serhiy Storchakabca49392017-09-03 08:10:14 +0300946 }
947
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400948 len = PyList_GET_SIZE(self->fut_callbacks);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900949 if (len == 0) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500950 Py_CLEAR(self->fut_callbacks);
951 return PyLong_FromSsize_t(cleared_callback0);
952 }
953
954 if (len == 1) {
Yury Selivanovf23746a2018-01-22 19:11:18 -0500955 PyObject *cb_tup = PyList_GET_ITEM(self->fut_callbacks, 0);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500956 int cmp = PyObject_RichCompareBool(
Yury Selivanovf23746a2018-01-22 19:11:18 -0500957 fn, PyTuple_GET_ITEM(cb_tup, 0), Py_EQ);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500958 if (cmp == -1) {
959 return NULL;
960 }
961 if (cmp == 1) {
962 /* callbacks[0] == fn */
963 Py_CLEAR(self->fut_callbacks);
964 return PyLong_FromSsize_t(1 + cleared_callback0);
965 }
966 /* callbacks[0] != fn and len(callbacks) == 1 */
967 return PyLong_FromSsize_t(cleared_callback0);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900968 }
969
970 newlist = PyList_New(len);
971 if (newlist == NULL) {
972 return NULL;
973 }
974
Yury Selivanov84af9032017-03-02 23:46:56 -0500975 for (i = 0; i < PyList_GET_SIZE(self->fut_callbacks); i++) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900976 int ret;
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400977 PyObject *item = PyList_GET_ITEM(self->fut_callbacks, i);
Serhiy Storchakabca49392017-09-03 08:10:14 +0300978 Py_INCREF(item);
Yury Selivanovf23746a2018-01-22 19:11:18 -0500979 ret = PyObject_RichCompareBool(fn, PyTuple_GET_ITEM(item, 0), Py_EQ);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900980 if (ret == 0) {
Yury Selivanov833a3b02017-07-05 13:32:03 -0400981 if (j < len) {
Yury Selivanov833a3b02017-07-05 13:32:03 -0400982 PyList_SET_ITEM(newlist, j, item);
983 j++;
Serhiy Storchakabca49392017-09-03 08:10:14 +0300984 continue;
Yury Selivanov833a3b02017-07-05 13:32:03 -0400985 }
Serhiy Storchakabca49392017-09-03 08:10:14 +0300986 ret = PyList_Append(newlist, item);
987 }
988 Py_DECREF(item);
989 if (ret < 0) {
990 goto fail;
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900991 }
992 }
993
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500994 if (j == 0) {
995 Py_CLEAR(self->fut_callbacks);
996 Py_DECREF(newlist);
997 return PyLong_FromSsize_t(len + cleared_callback0);
998 }
999
Serhiy Storchakabca49392017-09-03 08:10:14 +03001000 if (j < len) {
1001 Py_SIZE(newlist) = j;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001002 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03001003 j = PyList_GET_SIZE(newlist);
1004 len = PyList_GET_SIZE(self->fut_callbacks);
1005 if (j != len) {
1006 if (PyList_SetSlice(self->fut_callbacks, 0, len, newlist) < 0) {
1007 goto fail;
1008 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001009 }
1010 Py_DECREF(newlist);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001011 return PyLong_FromSsize_t(len - j + cleared_callback0);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001012
1013fail:
1014 Py_DECREF(newlist);
1015 return NULL;
1016}
1017
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001018/*[clinic input]
1019_asyncio.Future.cancel
1020
1021Cancel the future and schedule callbacks.
1022
1023If the future is already done or cancelled, return False. Otherwise,
1024change the future's state to cancelled, schedule the callbacks and
1025return True.
1026[clinic start generated code]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001027
1028static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001029_asyncio_Future_cancel_impl(FutureObj *self)
1030/*[clinic end generated code: output=e45b932ba8bd68a1 input=515709a127995109]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001031{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001032 ENSURE_FUTURE_ALIVE(self)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001033 return future_cancel(self);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001034}
1035
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001036/*[clinic input]
1037_asyncio.Future.cancelled
1038
1039Return True if the future was cancelled.
1040[clinic start generated code]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001041
1042static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001043_asyncio_Future_cancelled_impl(FutureObj *self)
1044/*[clinic end generated code: output=145197ced586357d input=943ab8b7b7b17e45]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001045{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001046 if (future_is_alive(self) && self->fut_state == STATE_CANCELLED) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001047 Py_RETURN_TRUE;
1048 }
1049 else {
1050 Py_RETURN_FALSE;
1051 }
1052}
1053
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001054/*[clinic input]
1055_asyncio.Future.done
1056
1057Return True if the future is done.
1058
1059Done means either that a result / exception are available, or that the
1060future was cancelled.
1061[clinic start generated code]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001062
1063static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001064_asyncio_Future_done_impl(FutureObj *self)
1065/*[clinic end generated code: output=244c5ac351145096 input=28d7b23fdb65d2ac]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001066{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001067 if (!future_is_alive(self) || self->fut_state == STATE_PENDING) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001068 Py_RETURN_FALSE;
1069 }
1070 else {
1071 Py_RETURN_TRUE;
1072 }
1073}
1074
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001075/*[clinic input]
1076_asyncio.Future.get_loop
1077
1078Return the event loop the Future is bound to.
1079[clinic start generated code]*/
1080
1081static PyObject *
1082_asyncio_Future_get_loop_impl(FutureObj *self)
1083/*[clinic end generated code: output=119b6ea0c9816c3f input=cba48c2136c79d1f]*/
1084{
1085 Py_INCREF(self->fut_loop);
1086 return self->fut_loop;
1087}
1088
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001089static PyObject *
1090FutureObj_get_blocking(FutureObj *fut)
1091{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001092 if (future_is_alive(fut) && fut->fut_blocking) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001093 Py_RETURN_TRUE;
1094 }
1095 else {
1096 Py_RETURN_FALSE;
1097 }
1098}
1099
1100static int
1101FutureObj_set_blocking(FutureObj *fut, PyObject *val)
1102{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001103 if (future_ensure_alive(fut)) {
1104 return -1;
1105 }
1106
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001107 int is_true = PyObject_IsTrue(val);
1108 if (is_true < 0) {
1109 return -1;
1110 }
1111 fut->fut_blocking = is_true;
1112 return 0;
1113}
1114
1115static PyObject *
1116FutureObj_get_log_traceback(FutureObj *fut)
1117{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001118 ENSURE_FUTURE_ALIVE(fut)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001119 if (fut->fut_log_tb) {
1120 Py_RETURN_TRUE;
1121 }
1122 else {
1123 Py_RETURN_FALSE;
1124 }
1125}
1126
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +00001127static int
1128FutureObj_set_log_traceback(FutureObj *fut, PyObject *val)
1129{
1130 int is_true = PyObject_IsTrue(val);
1131 if (is_true < 0) {
1132 return -1;
1133 }
Yury Selivanove0aef4f2017-12-25 16:16:10 -05001134 if (is_true) {
1135 PyErr_SetString(PyExc_ValueError,
1136 "_log_traceback can only be set to False");
1137 return -1;
1138 }
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +00001139 fut->fut_log_tb = is_true;
1140 return 0;
1141}
1142
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001143static PyObject *
1144FutureObj_get_loop(FutureObj *fut)
1145{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001146 if (!future_is_alive(fut)) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001147 Py_RETURN_NONE;
1148 }
1149 Py_INCREF(fut->fut_loop);
1150 return fut->fut_loop;
1151}
1152
1153static PyObject *
1154FutureObj_get_callbacks(FutureObj *fut)
1155{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001156 Py_ssize_t i;
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001157
1158 ENSURE_FUTURE_ALIVE(fut)
1159
Yury Selivanovf23746a2018-01-22 19:11:18 -05001160 if (fut->fut_callback0 == NULL) {
1161 if (fut->fut_callbacks == NULL) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001162 Py_RETURN_NONE;
1163 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001164
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001165 Py_INCREF(fut->fut_callbacks);
1166 return fut->fut_callbacks;
1167 }
1168
Yury Selivanovf23746a2018-01-22 19:11:18 -05001169 Py_ssize_t len = 1;
1170 if (fut->fut_callbacks != NULL) {
1171 len += PyList_GET_SIZE(fut->fut_callbacks);
1172 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001173
Yury Selivanovf23746a2018-01-22 19:11:18 -05001174
1175 PyObject *new_list = PyList_New(len);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001176 if (new_list == NULL) {
1177 return NULL;
1178 }
1179
Yury Selivanovf23746a2018-01-22 19:11:18 -05001180 PyObject *tup0 = PyTuple_New(2);
1181 if (tup0 == NULL) {
1182 Py_DECREF(new_list);
1183 return NULL;
1184 }
1185
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001186 Py_INCREF(fut->fut_callback0);
Yury Selivanovf23746a2018-01-22 19:11:18 -05001187 PyTuple_SET_ITEM(tup0, 0, fut->fut_callback0);
1188 assert(fut->fut_context0 != NULL);
1189 Py_INCREF(fut->fut_context0);
1190 PyTuple_SET_ITEM(tup0, 1, (PyObject *)fut->fut_context0);
1191
1192 PyList_SET_ITEM(new_list, 0, tup0);
1193
1194 if (fut->fut_callbacks != NULL) {
1195 for (i = 0; i < PyList_GET_SIZE(fut->fut_callbacks); i++) {
1196 PyObject *cb = PyList_GET_ITEM(fut->fut_callbacks, i);
1197 Py_INCREF(cb);
1198 PyList_SET_ITEM(new_list, i + 1, cb);
1199 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001200 }
1201
1202 return new_list;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001203}
1204
1205static PyObject *
1206FutureObj_get_result(FutureObj *fut)
1207{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001208 ENSURE_FUTURE_ALIVE(fut)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001209 if (fut->fut_result == NULL) {
1210 Py_RETURN_NONE;
1211 }
1212 Py_INCREF(fut->fut_result);
1213 return fut->fut_result;
1214}
1215
1216static PyObject *
1217FutureObj_get_exception(FutureObj *fut)
1218{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001219 ENSURE_FUTURE_ALIVE(fut)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001220 if (fut->fut_exception == NULL) {
1221 Py_RETURN_NONE;
1222 }
1223 Py_INCREF(fut->fut_exception);
1224 return fut->fut_exception;
1225}
1226
1227static PyObject *
1228FutureObj_get_source_traceback(FutureObj *fut)
1229{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001230 if (!future_is_alive(fut) || fut->fut_source_tb == NULL) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001231 Py_RETURN_NONE;
1232 }
1233 Py_INCREF(fut->fut_source_tb);
1234 return fut->fut_source_tb;
1235}
1236
1237static PyObject *
1238FutureObj_get_state(FutureObj *fut)
1239{
1240 _Py_IDENTIFIER(PENDING);
1241 _Py_IDENTIFIER(CANCELLED);
1242 _Py_IDENTIFIER(FINISHED);
1243 PyObject *ret = NULL;
1244
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001245 ENSURE_FUTURE_ALIVE(fut)
1246
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001247 switch (fut->fut_state) {
1248 case STATE_PENDING:
1249 ret = _PyUnicode_FromId(&PyId_PENDING);
1250 break;
1251 case STATE_CANCELLED:
1252 ret = _PyUnicode_FromId(&PyId_CANCELLED);
1253 break;
1254 case STATE_FINISHED:
1255 ret = _PyUnicode_FromId(&PyId_FINISHED);
1256 break;
1257 default:
1258 assert (0);
1259 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03001260 Py_XINCREF(ret);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001261 return ret;
1262}
1263
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001264/*[clinic input]
1265_asyncio.Future._repr_info
1266[clinic start generated code]*/
1267
1268static PyObject *
1269_asyncio_Future__repr_info_impl(FutureObj *self)
1270/*[clinic end generated code: output=fa69e901bd176cfb input=f21504d8e2ae1ca2]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001271{
Victor Stinnerde4ae3d2016-12-04 22:59:09 +01001272 return PyObject_CallFunctionObjArgs(
1273 asyncio_future_repr_info_func, self, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001274}
1275
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001276static PyObject *
1277FutureObj_repr(FutureObj *fut)
1278{
1279 _Py_IDENTIFIER(_repr_info);
1280
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001281 ENSURE_FUTURE_ALIVE(fut)
1282
Serhiy Storchakabca49392017-09-03 08:10:14 +03001283 PyObject *rinfo = _PyObject_CallMethodIdObjArgs((PyObject*)fut,
1284 &PyId__repr_info,
1285 NULL);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001286 if (rinfo == NULL) {
1287 return NULL;
1288 }
1289
Serhiy Storchakabca49392017-09-03 08:10:14 +03001290 PyObject *rinfo_s = PyUnicode_Join(NULL, rinfo);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001291 Py_DECREF(rinfo);
1292 if (rinfo_s == NULL) {
1293 return NULL;
1294 }
1295
1296 PyObject *rstr = NULL;
1297 PyObject *type_name = PyObject_GetAttrString((PyObject*)Py_TYPE(fut),
1298 "__name__");
1299 if (type_name != NULL) {
Serhiy Storchakabca49392017-09-03 08:10:14 +03001300 rstr = PyUnicode_FromFormat("<%S %U>", type_name, rinfo_s);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001301 Py_DECREF(type_name);
1302 }
1303 Py_DECREF(rinfo_s);
1304 return rstr;
1305}
1306
1307static void
1308FutureObj_finalize(FutureObj *fut)
1309{
1310 _Py_IDENTIFIER(call_exception_handler);
1311 _Py_IDENTIFIER(message);
1312 _Py_IDENTIFIER(exception);
1313 _Py_IDENTIFIER(future);
1314 _Py_IDENTIFIER(source_traceback);
1315
Serhiy Storchakabca49392017-09-03 08:10:14 +03001316 PyObject *error_type, *error_value, *error_traceback;
1317 PyObject *context;
1318 PyObject *type_name;
1319 PyObject *message = NULL;
1320 PyObject *func;
1321
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001322 if (!fut->fut_log_tb) {
1323 return;
1324 }
1325 assert(fut->fut_exception != NULL);
Serhiy Storchakabca49392017-09-03 08:10:14 +03001326 fut->fut_log_tb = 0;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001327
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001328 /* Save the current exception, if any. */
1329 PyErr_Fetch(&error_type, &error_value, &error_traceback);
1330
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001331 context = PyDict_New();
1332 if (context == NULL) {
1333 goto finally;
1334 }
1335
1336 type_name = PyObject_GetAttrString((PyObject*)Py_TYPE(fut), "__name__");
1337 if (type_name == NULL) {
1338 goto finally;
1339 }
1340
1341 message = PyUnicode_FromFormat(
1342 "%S exception was never retrieved", type_name);
Serhiy Storchakabca49392017-09-03 08:10:14 +03001343 Py_DECREF(type_name);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001344 if (message == NULL) {
1345 goto finally;
1346 }
1347
1348 if (_PyDict_SetItemId(context, &PyId_message, message) < 0 ||
1349 _PyDict_SetItemId(context, &PyId_exception, fut->fut_exception) < 0 ||
1350 _PyDict_SetItemId(context, &PyId_future, (PyObject*)fut) < 0) {
1351 goto finally;
1352 }
1353 if (fut->fut_source_tb != NULL) {
1354 if (_PyDict_SetItemId(context, &PyId_source_traceback,
1355 fut->fut_source_tb) < 0) {
1356 goto finally;
1357 }
1358 }
1359
1360 func = _PyObject_GetAttrId(fut->fut_loop, &PyId_call_exception_handler);
1361 if (func != NULL) {
Serhiy Storchakabca49392017-09-03 08:10:14 +03001362 PyObject *res = PyObject_CallFunctionObjArgs(func, context, NULL);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001363 if (res == NULL) {
1364 PyErr_WriteUnraisable(func);
1365 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03001366 else {
1367 Py_DECREF(res);
1368 }
1369 Py_DECREF(func);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001370 }
1371
1372finally:
Serhiy Storchakabca49392017-09-03 08:10:14 +03001373 Py_XDECREF(context);
1374 Py_XDECREF(message);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001375
1376 /* Restore the saved exception. */
1377 PyErr_Restore(error_type, error_value, error_traceback);
1378}
1379
1380
1381static PyAsyncMethods FutureType_as_async = {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001382 (unaryfunc)future_new_iter, /* am_await */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001383 0, /* am_aiter */
1384 0 /* am_anext */
1385};
1386
1387static PyMethodDef FutureType_methods[] = {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001388 _ASYNCIO_FUTURE_RESULT_METHODDEF
1389 _ASYNCIO_FUTURE_EXCEPTION_METHODDEF
1390 _ASYNCIO_FUTURE_SET_RESULT_METHODDEF
1391 _ASYNCIO_FUTURE_SET_EXCEPTION_METHODDEF
1392 _ASYNCIO_FUTURE_ADD_DONE_CALLBACK_METHODDEF
1393 _ASYNCIO_FUTURE_REMOVE_DONE_CALLBACK_METHODDEF
1394 _ASYNCIO_FUTURE_CANCEL_METHODDEF
1395 _ASYNCIO_FUTURE_CANCELLED_METHODDEF
1396 _ASYNCIO_FUTURE_DONE_METHODDEF
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001397 _ASYNCIO_FUTURE_GET_LOOP_METHODDEF
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001398 _ASYNCIO_FUTURE__REPR_INFO_METHODDEF
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001399 {NULL, NULL} /* Sentinel */
1400};
1401
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001402#define FUTURE_COMMON_GETSETLIST \
1403 {"_state", (getter)FutureObj_get_state, NULL, NULL}, \
1404 {"_asyncio_future_blocking", (getter)FutureObj_get_blocking, \
1405 (setter)FutureObj_set_blocking, NULL}, \
1406 {"_loop", (getter)FutureObj_get_loop, NULL, NULL}, \
1407 {"_callbacks", (getter)FutureObj_get_callbacks, NULL, NULL}, \
1408 {"_result", (getter)FutureObj_get_result, NULL, NULL}, \
1409 {"_exception", (getter)FutureObj_get_exception, NULL, NULL}, \
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +00001410 {"_log_traceback", (getter)FutureObj_get_log_traceback, \
1411 (setter)FutureObj_set_log_traceback, NULL}, \
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001412 {"_source_traceback", (getter)FutureObj_get_source_traceback, NULL, NULL},
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001413
1414static PyGetSetDef FutureType_getsetlist[] = {
1415 FUTURE_COMMON_GETSETLIST
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001416 {NULL} /* Sentinel */
1417};
1418
1419static void FutureObj_dealloc(PyObject *self);
1420
1421static PyTypeObject FutureType = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02001422 PyVarObject_HEAD_INIT(NULL, 0)
INADA Naoki9f2ce252016-10-15 15:39:19 +09001423 "_asyncio.Future",
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001424 sizeof(FutureObj), /* tp_basicsize */
1425 .tp_dealloc = FutureObj_dealloc,
1426 .tp_as_async = &FutureType_as_async,
1427 .tp_repr = (reprfunc)FutureObj_repr,
1428 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE
1429 | Py_TPFLAGS_HAVE_FINALIZE,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001430 .tp_doc = _asyncio_Future___init____doc__,
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001431 .tp_traverse = (traverseproc)FutureObj_traverse,
1432 .tp_clear = (inquiry)FutureObj_clear,
1433 .tp_weaklistoffset = offsetof(FutureObj, fut_weakreflist),
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001434 .tp_iter = (getiterfunc)future_new_iter,
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001435 .tp_methods = FutureType_methods,
1436 .tp_getset = FutureType_getsetlist,
1437 .tp_dictoffset = offsetof(FutureObj, dict),
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001438 .tp_init = (initproc)_asyncio_Future___init__,
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001439 .tp_new = PyType_GenericNew,
1440 .tp_finalize = (destructor)FutureObj_finalize,
1441};
1442
1443static void
1444FutureObj_dealloc(PyObject *self)
1445{
1446 FutureObj *fut = (FutureObj *)self;
1447
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001448 if (Future_CheckExact(fut)) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001449 /* When fut is subclass of Future, finalizer is called from
1450 * subtype_dealloc.
1451 */
1452 if (PyObject_CallFinalizerFromDealloc(self) < 0) {
1453 // resurrected.
1454 return;
1455 }
1456 }
1457
Alexander Mohrde34cbe2017-08-01 23:31:07 -07001458 PyObject_GC_UnTrack(self);
1459
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001460 if (fut->fut_weakreflist != NULL) {
1461 PyObject_ClearWeakRefs(self);
1462 }
1463
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001464 (void)FutureObj_clear(fut);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001465 Py_TYPE(fut)->tp_free(fut);
1466}
1467
1468
1469/*********************** Future Iterator **************************/
1470
1471typedef struct {
1472 PyObject_HEAD
1473 FutureObj *future;
1474} futureiterobject;
1475
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001476
1477#define FI_FREELIST_MAXLEN 255
1478static futureiterobject *fi_freelist = NULL;
1479static Py_ssize_t fi_freelist_len = 0;
1480
1481
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001482static void
1483FutureIter_dealloc(futureiterobject *it)
1484{
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001485 PyObject_GC_UnTrack(it);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001486 Py_CLEAR(it->future);
1487
1488 if (fi_freelist_len < FI_FREELIST_MAXLEN) {
1489 fi_freelist_len++;
1490 it->future = (FutureObj*) fi_freelist;
1491 fi_freelist = it;
1492 }
1493 else {
1494 PyObject_GC_Del(it);
1495 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001496}
1497
1498static PyObject *
1499FutureIter_iternext(futureiterobject *it)
1500{
1501 PyObject *res;
1502 FutureObj *fut = it->future;
1503
1504 if (fut == NULL) {
1505 return NULL;
1506 }
1507
1508 if (fut->fut_state == STATE_PENDING) {
1509 if (!fut->fut_blocking) {
1510 fut->fut_blocking = 1;
1511 Py_INCREF(fut);
1512 return (PyObject *)fut;
1513 }
Yury Selivanov0cf16f92017-12-25 10:48:15 -05001514 PyErr_SetString(PyExc_RuntimeError,
1515 "await wasn't used with future");
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001516 return NULL;
1517 }
1518
Serhiy Storchakabca49392017-09-03 08:10:14 +03001519 it->future = NULL;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001520 res = _asyncio_Future_result_impl(fut);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001521 if (res != NULL) {
Serhiy Storchaka60e49aa2016-11-06 18:47:03 +02001522 /* The result of the Future is not an exception. */
Serhiy Storchakabca49392017-09-03 08:10:14 +03001523 (void)_PyGen_SetStopIterationValue(res);
Serhiy Storchaka60e49aa2016-11-06 18:47:03 +02001524 Py_DECREF(res);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001525 }
1526
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001527 Py_DECREF(fut);
1528 return NULL;
1529}
1530
1531static PyObject *
INADA Naoki74c17532016-10-25 19:00:45 +09001532FutureIter_send(futureiterobject *self, PyObject *unused)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001533{
INADA Naoki74c17532016-10-25 19:00:45 +09001534 /* Future.__iter__ doesn't care about values that are pushed to the
1535 * generator, it just returns "self.result().
1536 */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001537 return FutureIter_iternext(self);
1538}
1539
1540static PyObject *
1541FutureIter_throw(futureiterobject *self, PyObject *args)
1542{
Serhiy Storchakabca49392017-09-03 08:10:14 +03001543 PyObject *type, *val = NULL, *tb = NULL;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001544 if (!PyArg_ParseTuple(args, "O|OO", &type, &val, &tb))
1545 return NULL;
1546
1547 if (val == Py_None) {
1548 val = NULL;
1549 }
1550 if (tb == Py_None) {
1551 tb = NULL;
Benjamin Peterson996fc1f2016-11-14 00:15:44 -08001552 } else if (tb != NULL && !PyTraceBack_Check(tb)) {
1553 PyErr_SetString(PyExc_TypeError, "throw() third argument must be a traceback");
1554 return NULL;
1555 }
1556
1557 Py_INCREF(type);
1558 Py_XINCREF(val);
1559 Py_XINCREF(tb);
1560
1561 if (PyExceptionClass_Check(type)) {
1562 PyErr_NormalizeException(&type, &val, &tb);
Yury Selivanovedfe8862016-12-01 11:37:47 -05001563 /* No need to call PyException_SetTraceback since we'll be calling
1564 PyErr_Restore for `type`, `val`, and `tb`. */
Benjamin Peterson996fc1f2016-11-14 00:15:44 -08001565 } else if (PyExceptionInstance_Check(type)) {
1566 if (val) {
1567 PyErr_SetString(PyExc_TypeError,
1568 "instance exception may not have a separate value");
1569 goto fail;
1570 }
1571 val = type;
1572 type = PyExceptionInstance_Class(type);
1573 Py_INCREF(type);
1574 if (tb == NULL)
1575 tb = PyException_GetTraceback(val);
1576 } else {
1577 PyErr_SetString(PyExc_TypeError,
1578 "exceptions must be classes deriving BaseException or "
1579 "instances of such a class");
1580 goto fail;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001581 }
1582
1583 Py_CLEAR(self->future);
1584
Benjamin Peterson996fc1f2016-11-14 00:15:44 -08001585 PyErr_Restore(type, val, tb);
1586
Serhiy Storchakabca49392017-09-03 08:10:14 +03001587 return NULL;
Benjamin Peterson996fc1f2016-11-14 00:15:44 -08001588
1589 fail:
1590 Py_DECREF(type);
1591 Py_XDECREF(val);
1592 Py_XDECREF(tb);
1593 return NULL;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001594}
1595
1596static PyObject *
1597FutureIter_close(futureiterobject *self, PyObject *arg)
1598{
1599 Py_CLEAR(self->future);
1600 Py_RETURN_NONE;
1601}
1602
1603static int
1604FutureIter_traverse(futureiterobject *it, visitproc visit, void *arg)
1605{
1606 Py_VISIT(it->future);
1607 return 0;
1608}
1609
1610static PyMethodDef FutureIter_methods[] = {
1611 {"send", (PyCFunction)FutureIter_send, METH_O, NULL},
1612 {"throw", (PyCFunction)FutureIter_throw, METH_VARARGS, NULL},
1613 {"close", (PyCFunction)FutureIter_close, METH_NOARGS, NULL},
1614 {NULL, NULL} /* Sentinel */
1615};
1616
1617static PyTypeObject FutureIterType = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02001618 PyVarObject_HEAD_INIT(NULL, 0)
INADA Naoki9f2ce252016-10-15 15:39:19 +09001619 "_asyncio.FutureIter",
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001620 .tp_basicsize = sizeof(futureiterobject),
1621 .tp_itemsize = 0,
1622 .tp_dealloc = (destructor)FutureIter_dealloc,
1623 .tp_getattro = PyObject_GenericGetAttr,
1624 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
1625 .tp_traverse = (traverseproc)FutureIter_traverse,
1626 .tp_iter = PyObject_SelfIter,
1627 .tp_iternext = (iternextfunc)FutureIter_iternext,
1628 .tp_methods = FutureIter_methods,
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001629};
1630
1631static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001632future_new_iter(PyObject *fut)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001633{
1634 futureiterobject *it;
1635
1636 if (!PyObject_TypeCheck(fut, &FutureType)) {
1637 PyErr_BadInternalCall();
1638 return NULL;
1639 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001640
1641 ENSURE_FUTURE_ALIVE(fut)
1642
1643 if (fi_freelist_len) {
1644 fi_freelist_len--;
1645 it = fi_freelist;
1646 fi_freelist = (futureiterobject*) it->future;
1647 it->future = NULL;
1648 _Py_NewReference((PyObject*) it);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001649 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001650 else {
1651 it = PyObject_GC_New(futureiterobject, &FutureIterType);
1652 if (it == NULL) {
1653 return NULL;
1654 }
1655 }
1656
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001657 Py_INCREF(fut);
1658 it->future = (FutureObj*)fut;
INADA Naoki1be427b2016-10-11 02:12:34 +09001659 PyObject_GC_Track(it);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001660 return (PyObject*)it;
1661}
1662
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001663
1664/*********************** Task **************************/
1665
1666
1667/*[clinic input]
1668class _asyncio.Task "TaskObj *" "&Task_Type"
1669[clinic start generated code]*/
1670/*[clinic end generated code: output=da39a3ee5e6b4b0d input=719dcef0fcc03b37]*/
1671
1672static int task_call_step_soon(TaskObj *, PyObject *);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001673static PyObject * task_wakeup(TaskObj *, PyObject *);
1674static PyObject * task_step(TaskObj *, PyObject *);
1675
1676/* ----- Task._step wrapper */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001677
INADA Naokic411a7d2016-10-18 11:48:14 +09001678static int
Serhiy Storchakabca49392017-09-03 08:10:14 +03001679TaskStepMethWrapper_clear(TaskStepMethWrapper *o)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001680{
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001681 Py_CLEAR(o->sw_task);
1682 Py_CLEAR(o->sw_arg);
1683 return 0;
1684}
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001685
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001686static void
Serhiy Storchakabca49392017-09-03 08:10:14 +03001687TaskStepMethWrapper_dealloc(TaskStepMethWrapper *o)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001688{
1689 PyObject_GC_UnTrack(o);
Serhiy Storchakabca49392017-09-03 08:10:14 +03001690 (void)TaskStepMethWrapper_clear(o);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001691 Py_TYPE(o)->tp_free(o);
1692}
1693
1694static PyObject *
Serhiy Storchakabca49392017-09-03 08:10:14 +03001695TaskStepMethWrapper_call(TaskStepMethWrapper *o,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001696 PyObject *args, PyObject *kwds)
1697{
Serhiy Storchakabca49392017-09-03 08:10:14 +03001698 if (kwds != NULL && PyDict_GET_SIZE(kwds) != 0) {
1699 PyErr_SetString(PyExc_TypeError, "function takes no keyword arguments");
1700 return NULL;
1701 }
1702 if (args != NULL && PyTuple_GET_SIZE(args) != 0) {
1703 PyErr_SetString(PyExc_TypeError, "function takes no positional arguments");
1704 return NULL;
1705 }
Yury Selivanov22feeb82018-01-24 11:31:01 -05001706 return task_step(o->sw_task, o->sw_arg);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001707}
1708
1709static int
Serhiy Storchakabca49392017-09-03 08:10:14 +03001710TaskStepMethWrapper_traverse(TaskStepMethWrapper *o,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001711 visitproc visit, void *arg)
1712{
1713 Py_VISIT(o->sw_task);
1714 Py_VISIT(o->sw_arg);
1715 return 0;
1716}
1717
1718static PyObject *
Serhiy Storchakabca49392017-09-03 08:10:14 +03001719TaskStepMethWrapper_get___self__(TaskStepMethWrapper *o)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001720{
1721 if (o->sw_task) {
1722 Py_INCREF(o->sw_task);
1723 return (PyObject*)o->sw_task;
1724 }
1725 Py_RETURN_NONE;
1726}
1727
Serhiy Storchakabca49392017-09-03 08:10:14 +03001728static PyGetSetDef TaskStepMethWrapper_getsetlist[] = {
1729 {"__self__", (getter)TaskStepMethWrapper_get___self__, NULL, NULL},
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001730 {NULL} /* Sentinel */
1731};
1732
Serhiy Storchakabca49392017-09-03 08:10:14 +03001733PyTypeObject TaskStepMethWrapper_Type = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02001734 PyVarObject_HEAD_INIT(NULL, 0)
Serhiy Storchakabca49392017-09-03 08:10:14 +03001735 "TaskStepMethWrapper",
1736 .tp_basicsize = sizeof(TaskStepMethWrapper),
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001737 .tp_itemsize = 0,
Serhiy Storchakabca49392017-09-03 08:10:14 +03001738 .tp_getset = TaskStepMethWrapper_getsetlist,
1739 .tp_dealloc = (destructor)TaskStepMethWrapper_dealloc,
1740 .tp_call = (ternaryfunc)TaskStepMethWrapper_call,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001741 .tp_getattro = PyObject_GenericGetAttr,
1742 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
Serhiy Storchakabca49392017-09-03 08:10:14 +03001743 .tp_traverse = (traverseproc)TaskStepMethWrapper_traverse,
1744 .tp_clear = (inquiry)TaskStepMethWrapper_clear,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001745};
1746
1747static PyObject *
Serhiy Storchakabca49392017-09-03 08:10:14 +03001748TaskStepMethWrapper_new(TaskObj *task, PyObject *arg)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001749{
Serhiy Storchakabca49392017-09-03 08:10:14 +03001750 TaskStepMethWrapper *o;
1751 o = PyObject_GC_New(TaskStepMethWrapper, &TaskStepMethWrapper_Type);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001752 if (o == NULL) {
1753 return NULL;
1754 }
1755
1756 Py_INCREF(task);
1757 o->sw_task = task;
1758
1759 Py_XINCREF(arg);
1760 o->sw_arg = arg;
1761
1762 PyObject_GC_Track(o);
1763 return (PyObject*) o;
1764}
1765
1766/* ----- Task._wakeup wrapper */
1767
1768static PyObject *
1769TaskWakeupMethWrapper_call(TaskWakeupMethWrapper *o,
1770 PyObject *args, PyObject *kwds)
1771{
1772 PyObject *fut;
1773
Serhiy Storchakabca49392017-09-03 08:10:14 +03001774 if (kwds != NULL && PyDict_GET_SIZE(kwds) != 0) {
1775 PyErr_SetString(PyExc_TypeError, "function takes no keyword arguments");
1776 return NULL;
1777 }
1778 if (!PyArg_ParseTuple(args, "O", &fut)) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001779 return NULL;
1780 }
1781
Yury Selivanov22feeb82018-01-24 11:31:01 -05001782 return task_wakeup(o->ww_task, fut);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001783}
1784
1785static int
1786TaskWakeupMethWrapper_clear(TaskWakeupMethWrapper *o)
1787{
1788 Py_CLEAR(o->ww_task);
1789 return 0;
1790}
1791
1792static int
1793TaskWakeupMethWrapper_traverse(TaskWakeupMethWrapper *o,
1794 visitproc visit, void *arg)
1795{
1796 Py_VISIT(o->ww_task);
1797 return 0;
1798}
1799
1800static void
1801TaskWakeupMethWrapper_dealloc(TaskWakeupMethWrapper *o)
1802{
1803 PyObject_GC_UnTrack(o);
1804 (void)TaskWakeupMethWrapper_clear(o);
1805 Py_TYPE(o)->tp_free(o);
1806}
1807
1808PyTypeObject TaskWakeupMethWrapper_Type = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02001809 PyVarObject_HEAD_INIT(NULL, 0)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001810 "TaskWakeupMethWrapper",
1811 .tp_basicsize = sizeof(TaskWakeupMethWrapper),
1812 .tp_itemsize = 0,
1813 .tp_dealloc = (destructor)TaskWakeupMethWrapper_dealloc,
1814 .tp_call = (ternaryfunc)TaskWakeupMethWrapper_call,
1815 .tp_getattro = PyObject_GenericGetAttr,
1816 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
1817 .tp_traverse = (traverseproc)TaskWakeupMethWrapper_traverse,
1818 .tp_clear = (inquiry)TaskWakeupMethWrapper_clear,
1819};
1820
1821static PyObject *
1822TaskWakeupMethWrapper_new(TaskObj *task)
1823{
1824 TaskWakeupMethWrapper *o;
1825 o = PyObject_GC_New(TaskWakeupMethWrapper, &TaskWakeupMethWrapper_Type);
1826 if (o == NULL) {
1827 return NULL;
1828 }
1829
1830 Py_INCREF(task);
1831 o->ww_task = task;
1832
1833 PyObject_GC_Track(o);
1834 return (PyObject*) o;
1835}
1836
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001837/* ----- Task introspection helpers */
1838
1839static int
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001840register_task(PyObject *task)
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001841{
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001842 _Py_IDENTIFIER(add);
1843
1844 PyObject *res = _PyObject_CallMethodIdObjArgs(
1845 all_tasks, &PyId_add, task, NULL);
1846 if (res == NULL) {
1847 return -1;
1848 }
1849 Py_DECREF(res);
1850 return 0;
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001851}
1852
1853
1854static int
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001855unregister_task(PyObject *task)
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001856{
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001857 _Py_IDENTIFIER(discard);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001858
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001859 PyObject *res = _PyObject_CallMethodIdObjArgs(
1860 all_tasks, &PyId_discard, task, NULL);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001861 if (res == NULL) {
1862 return -1;
1863 }
1864 Py_DECREF(res);
1865 return 0;
1866}
1867
1868
1869static int
1870enter_task(PyObject *loop, PyObject *task)
1871{
1872 PyObject *item;
1873 Py_hash_t hash;
1874 hash = PyObject_Hash(loop);
1875 if (hash == -1) {
1876 return -1;
1877 }
1878 item = _PyDict_GetItem_KnownHash(current_tasks, loop, hash);
1879 if (item != NULL) {
1880 PyErr_Format(
1881 PyExc_RuntimeError,
1882 "Cannot enter into task %R while another " \
1883 "task %R is being executed.",
1884 task, item, NULL);
1885 return -1;
1886 }
1887 if (_PyDict_SetItem_KnownHash(current_tasks, loop, task, hash) < 0) {
1888 return -1;
1889 }
1890 return 0;
1891}
1892
1893
1894static int
1895leave_task(PyObject *loop, PyObject *task)
1896/*[clinic end generated code: output=0ebf6db4b858fb41 input=51296a46313d1ad8]*/
1897{
1898 PyObject *item;
1899 Py_hash_t hash;
1900 hash = PyObject_Hash(loop);
1901 if (hash == -1) {
1902 return -1;
1903 }
1904 item = _PyDict_GetItem_KnownHash(current_tasks, loop, hash);
1905 if (item != task) {
1906 if (item == NULL) {
1907 /* Not entered, replace with None */
1908 item = Py_None;
1909 }
1910 PyErr_Format(
1911 PyExc_RuntimeError,
1912 "Leaving task %R does not match the current task %R.",
1913 task, item, NULL);
1914 return -1;
1915 }
1916 return _PyDict_DelItem_KnownHash(current_tasks, loop, hash);
1917}
1918
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001919/* ----- Task */
1920
1921/*[clinic input]
1922_asyncio.Task.__init__
1923
Serhiy Storchakabca49392017-09-03 08:10:14 +03001924 coro: object
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001925 *
Serhiy Storchakabca49392017-09-03 08:10:14 +03001926 loop: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001927
1928A coroutine wrapped in a Future.
1929[clinic start generated code]*/
1930
1931static int
1932_asyncio_Task___init___impl(TaskObj *self, PyObject *coro, PyObject *loop)
Serhiy Storchakabca49392017-09-03 08:10:14 +03001933/*[clinic end generated code: output=9f24774c2287fc2f input=8d132974b049593e]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001934{
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001935 if (future_init((FutureObj*)self, loop)) {
INADA Naokic411a7d2016-10-18 11:48:14 +09001936 return -1;
1937 }
INADA Naokic411a7d2016-10-18 11:48:14 +09001938
Yury Selivanova9d7e552017-12-19 07:18:45 -05001939 int is_coro = is_coroutine(coro);
1940 if (is_coro == -1) {
1941 return -1;
1942 }
1943 if (is_coro == 0) {
1944 self->task_log_destroy_pending = 0;
1945 PyErr_Format(PyExc_TypeError,
1946 "a coroutine was expected, got %R",
1947 coro, NULL);
1948 return -1;
Andrew Svetlovf74ef452017-12-15 07:04:38 +02001949 }
1950
Miss Islington (bot)ef20abe2018-02-13 03:32:18 -08001951 Py_XSETREF(self->task_context, PyContext_CopyCurrent());
Yury Selivanovf23746a2018-01-22 19:11:18 -05001952 if (self->task_context == NULL) {
1953 return -1;
1954 }
1955
Miss Islington (bot)ef20abe2018-02-13 03:32:18 -08001956 Py_CLEAR(self->task_fut_waiter);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001957 self->task_must_cancel = 0;
1958 self->task_log_destroy_pending = 1;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001959 Py_INCREF(coro);
Miss Islington (bot)ef20abe2018-02-13 03:32:18 -08001960 Py_XSETREF(self->task_coro, coro);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001961
1962 if (task_call_step_soon(self, NULL)) {
1963 return -1;
INADA Naokic411a7d2016-10-18 11:48:14 +09001964 }
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001965 return register_task((PyObject*)self);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001966}
1967
1968static int
1969TaskObj_clear(TaskObj *task)
1970{
1971 (void)FutureObj_clear((FutureObj*) task);
Yury Selivanovf23746a2018-01-22 19:11:18 -05001972 Py_CLEAR(task->task_context);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001973 Py_CLEAR(task->task_coro);
1974 Py_CLEAR(task->task_fut_waiter);
1975 return 0;
1976}
1977
1978static int
1979TaskObj_traverse(TaskObj *task, visitproc visit, void *arg)
1980{
Yury Selivanovf23746a2018-01-22 19:11:18 -05001981 Py_VISIT(task->task_context);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001982 Py_VISIT(task->task_coro);
1983 Py_VISIT(task->task_fut_waiter);
1984 (void)FutureObj_traverse((FutureObj*) task, visit, arg);
1985 return 0;
1986}
1987
1988static PyObject *
1989TaskObj_get_log_destroy_pending(TaskObj *task)
1990{
1991 if (task->task_log_destroy_pending) {
1992 Py_RETURN_TRUE;
1993 }
1994 else {
1995 Py_RETURN_FALSE;
1996 }
1997}
1998
1999static int
2000TaskObj_set_log_destroy_pending(TaskObj *task, PyObject *val)
2001{
2002 int is_true = PyObject_IsTrue(val);
2003 if (is_true < 0) {
2004 return -1;
2005 }
2006 task->task_log_destroy_pending = is_true;
2007 return 0;
2008}
2009
2010static PyObject *
2011TaskObj_get_must_cancel(TaskObj *task)
2012{
2013 if (task->task_must_cancel) {
2014 Py_RETURN_TRUE;
2015 }
2016 else {
2017 Py_RETURN_FALSE;
2018 }
2019}
2020
2021static PyObject *
2022TaskObj_get_coro(TaskObj *task)
2023{
2024 if (task->task_coro) {
2025 Py_INCREF(task->task_coro);
2026 return task->task_coro;
2027 }
2028
2029 Py_RETURN_NONE;
2030}
2031
2032static PyObject *
2033TaskObj_get_fut_waiter(TaskObj *task)
2034{
2035 if (task->task_fut_waiter) {
2036 Py_INCREF(task->task_fut_waiter);
2037 return task->task_fut_waiter;
2038 }
2039
2040 Py_RETURN_NONE;
2041}
2042
2043/*[clinic input]
2044@classmethod
2045_asyncio.Task.current_task
2046
Serhiy Storchakabca49392017-09-03 08:10:14 +03002047 loop: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002048
2049Return the currently running task in an event loop or None.
2050
2051By default the current task for the current event loop is returned.
2052
2053None is returned when called not in the context of a Task.
2054[clinic start generated code]*/
2055
2056static PyObject *
2057_asyncio_Task_current_task_impl(PyTypeObject *type, PyObject *loop)
Serhiy Storchakabca49392017-09-03 08:10:14 +03002058/*[clinic end generated code: output=99fbe7332c516e03 input=cd14770c5b79c7eb]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002059{
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002060 PyObject *ret;
2061 PyObject *current_task_func;
2062
2063 if (PyErr_WarnEx(PyExc_PendingDeprecationWarning,
2064 "Task.current_task() is deprecated, " \
2065 "use asyncio.current_task() instead",
2066 1) < 0) {
2067 return NULL;
2068 }
2069
2070 current_task_func = _PyObject_GetAttrId(asyncio_mod, &PyId_current_task);
2071 if (current_task_func == NULL) {
2072 return NULL;
2073 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002074
Yury Selivanov8d26aa92017-03-02 22:16:33 -05002075 if (loop == Py_None) {
Yury Selivanova70232f2017-12-13 14:49:42 -05002076 loop = get_event_loop();
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002077 if (loop == NULL) {
2078 return NULL;
2079 }
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002080 ret = PyObject_CallFunctionObjArgs(current_task_func, loop, NULL);
2081 Py_DECREF(current_task_func);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002082 Py_DECREF(loop);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002083 return ret;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002084 }
2085 else {
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002086 ret = PyObject_CallFunctionObjArgs(current_task_func, loop, NULL);
2087 Py_DECREF(current_task_func);
2088 return ret;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002089 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002090}
2091
2092/*[clinic input]
2093@classmethod
2094_asyncio.Task.all_tasks
2095
Serhiy Storchakabca49392017-09-03 08:10:14 +03002096 loop: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002097
2098Return a set of all tasks for an event loop.
2099
2100By default all tasks for the current event loop are returned.
2101[clinic start generated code]*/
2102
2103static PyObject *
2104_asyncio_Task_all_tasks_impl(PyTypeObject *type, PyObject *loop)
Serhiy Storchakabca49392017-09-03 08:10:14 +03002105/*[clinic end generated code: output=11f9b20749ccca5d input=497f80bc9ce726b5]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002106{
2107 PyObject *res;
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002108 PyObject *all_tasks_func;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002109
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002110 all_tasks_func = _PyObject_GetAttrId(asyncio_mod, &PyId_all_tasks);
2111 if (all_tasks_func == NULL) {
2112 return NULL;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002113 }
2114
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002115 if (PyErr_WarnEx(PyExc_PendingDeprecationWarning,
2116 "Task.all_tasks() is deprecated, " \
2117 "use asyncio.all_tasks() instead",
2118 1) < 0) {
2119 return NULL;
2120 }
2121
2122 res = PyObject_CallFunctionObjArgs(all_tasks_func, loop, NULL);
2123 Py_DECREF(all_tasks_func);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002124 return res;
2125}
2126
2127/*[clinic input]
2128_asyncio.Task._repr_info
2129[clinic start generated code]*/
2130
2131static PyObject *
2132_asyncio_Task__repr_info_impl(TaskObj *self)
2133/*[clinic end generated code: output=6a490eb66d5ba34b input=3c6d051ed3ddec8b]*/
2134{
Victor Stinnerde4ae3d2016-12-04 22:59:09 +01002135 return PyObject_CallFunctionObjArgs(
2136 asyncio_task_repr_info_func, self, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002137}
2138
2139/*[clinic input]
2140_asyncio.Task.cancel
2141
2142Request that this task cancel itself.
2143
2144This arranges for a CancelledError to be thrown into the
2145wrapped coroutine on the next cycle through the event loop.
2146The coroutine then has a chance to clean up or even deny
2147the request using try/except/finally.
2148
2149Unlike Future.cancel, this does not guarantee that the
2150task will be cancelled: the exception might be caught and
2151acted upon, delaying cancellation of the task or preventing
2152cancellation completely. The task may also return a value or
2153raise a different exception.
2154
2155Immediately after this method is called, Task.cancelled() will
2156not return True (unless the task was already cancelled). A
2157task will be marked as cancelled when the wrapped coroutine
2158terminates with a CancelledError exception (even if cancel()
2159was not called).
2160[clinic start generated code]*/
2161
2162static PyObject *
2163_asyncio_Task_cancel_impl(TaskObj *self)
2164/*[clinic end generated code: output=6bfc0479da9d5757 input=13f9bf496695cb52]*/
2165{
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +00002166 self->task_log_tb = 0;
2167
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002168 if (self->task_state != STATE_PENDING) {
2169 Py_RETURN_FALSE;
2170 }
2171
2172 if (self->task_fut_waiter) {
2173 PyObject *res;
2174 int is_true;
2175
2176 res = _PyObject_CallMethodId(
2177 self->task_fut_waiter, &PyId_cancel, NULL);
2178 if (res == NULL) {
2179 return NULL;
2180 }
2181
2182 is_true = PyObject_IsTrue(res);
2183 Py_DECREF(res);
2184 if (is_true < 0) {
2185 return NULL;
2186 }
2187
2188 if (is_true) {
2189 Py_RETURN_TRUE;
2190 }
2191 }
2192
2193 self->task_must_cancel = 1;
2194 Py_RETURN_TRUE;
2195}
2196
2197/*[clinic input]
2198_asyncio.Task.get_stack
2199
2200 *
Serhiy Storchakabca49392017-09-03 08:10:14 +03002201 limit: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002202
2203Return the list of stack frames for this task's coroutine.
2204
2205If the coroutine is not done, this returns the stack where it is
2206suspended. If the coroutine has completed successfully or was
2207cancelled, this returns an empty list. If the coroutine was
2208terminated by an exception, this returns the list of traceback
2209frames.
2210
2211The frames are always ordered from oldest to newest.
2212
2213The optional limit gives the maximum number of frames to
2214return; by default all available frames are returned. Its
2215meaning differs depending on whether a stack or a traceback is
2216returned: the newest frames of a stack are returned, but the
2217oldest frames of a traceback are returned. (This matches the
2218behavior of the traceback module.)
2219
2220For reasons beyond our control, only one stack frame is
2221returned for a suspended coroutine.
2222[clinic start generated code]*/
2223
2224static PyObject *
2225_asyncio_Task_get_stack_impl(TaskObj *self, PyObject *limit)
Serhiy Storchakabca49392017-09-03 08:10:14 +03002226/*[clinic end generated code: output=c9aeeeebd1e18118 input=05b323d42b809b90]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002227{
2228 return PyObject_CallFunctionObjArgs(
2229 asyncio_task_get_stack_func, self, limit, NULL);
2230}
2231
2232/*[clinic input]
2233_asyncio.Task.print_stack
2234
2235 *
Serhiy Storchakabca49392017-09-03 08:10:14 +03002236 limit: object = None
2237 file: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002238
2239Print the stack or traceback for this task's coroutine.
2240
2241This produces output similar to that of the traceback module,
2242for the frames retrieved by get_stack(). The limit argument
2243is passed to get_stack(). The file argument is an I/O stream
2244to which the output is written; by default output is written
2245to sys.stderr.
2246[clinic start generated code]*/
2247
2248static PyObject *
2249_asyncio_Task_print_stack_impl(TaskObj *self, PyObject *limit,
2250 PyObject *file)
Serhiy Storchakabca49392017-09-03 08:10:14 +03002251/*[clinic end generated code: output=7339e10314cd3f4d input=1a0352913b7fcd92]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002252{
2253 return PyObject_CallFunctionObjArgs(
2254 asyncio_task_print_stack_func, self, limit, file, NULL);
2255}
2256
2257/*[clinic input]
Yury Selivanov0cf16f92017-12-25 10:48:15 -05002258_asyncio.Task.set_result
2259
2260 result: object
2261 /
2262[clinic start generated code]*/
2263
2264static PyObject *
2265_asyncio_Task_set_result(TaskObj *self, PyObject *result)
2266/*[clinic end generated code: output=1dcae308bfcba318 input=9d1a00c07be41bab]*/
2267{
2268 PyErr_SetString(PyExc_RuntimeError,
2269 "Task does not support set_result operation");
2270 return NULL;
2271}
2272
2273/*[clinic input]
2274_asyncio.Task.set_exception
2275
2276 exception: object
2277 /
2278[clinic start generated code]*/
2279
2280static PyObject *
2281_asyncio_Task_set_exception(TaskObj *self, PyObject *exception)
2282/*[clinic end generated code: output=bc377fc28067303d input=9a8f65c83dcf893a]*/
2283{
2284 PyErr_SetString(PyExc_RuntimeError,
Andrew Svetlovfc359322017-12-30 15:40:27 +02002285 "Task does not support set_exception operation");
Yury Selivanov0cf16f92017-12-25 10:48:15 -05002286 return NULL;
2287}
2288
2289
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002290static void
2291TaskObj_finalize(TaskObj *task)
2292{
2293 _Py_IDENTIFIER(call_exception_handler);
2294 _Py_IDENTIFIER(task);
2295 _Py_IDENTIFIER(message);
2296 _Py_IDENTIFIER(source_traceback);
2297
Serhiy Storchakabca49392017-09-03 08:10:14 +03002298 PyObject *context;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002299 PyObject *message = NULL;
Serhiy Storchakabca49392017-09-03 08:10:14 +03002300 PyObject *func;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002301 PyObject *error_type, *error_value, *error_traceback;
2302
2303 if (task->task_state != STATE_PENDING || !task->task_log_destroy_pending) {
2304 goto done;
2305 }
2306
2307 /* Save the current exception, if any. */
2308 PyErr_Fetch(&error_type, &error_value, &error_traceback);
2309
2310 context = PyDict_New();
2311 if (context == NULL) {
2312 goto finally;
2313 }
2314
2315 message = PyUnicode_FromString("Task was destroyed but it is pending!");
2316 if (message == NULL) {
2317 goto finally;
2318 }
2319
2320 if (_PyDict_SetItemId(context, &PyId_message, message) < 0 ||
2321 _PyDict_SetItemId(context, &PyId_task, (PyObject*)task) < 0)
2322 {
2323 goto finally;
2324 }
2325
2326 if (task->task_source_tb != NULL) {
2327 if (_PyDict_SetItemId(context, &PyId_source_traceback,
2328 task->task_source_tb) < 0)
2329 {
2330 goto finally;
2331 }
2332 }
2333
2334 func = _PyObject_GetAttrId(task->task_loop, &PyId_call_exception_handler);
2335 if (func != NULL) {
Serhiy Storchakabca49392017-09-03 08:10:14 +03002336 PyObject *res = PyObject_CallFunctionObjArgs(func, context, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002337 if (res == NULL) {
2338 PyErr_WriteUnraisable(func);
2339 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03002340 else {
2341 Py_DECREF(res);
2342 }
2343 Py_DECREF(func);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002344 }
2345
2346finally:
Serhiy Storchakabca49392017-09-03 08:10:14 +03002347 Py_XDECREF(context);
2348 Py_XDECREF(message);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002349
2350 /* Restore the saved exception. */
2351 PyErr_Restore(error_type, error_value, error_traceback);
2352
2353done:
2354 FutureObj_finalize((FutureObj*)task);
2355}
2356
2357static void TaskObj_dealloc(PyObject *); /* Needs Task_CheckExact */
2358
2359static PyMethodDef TaskType_methods[] = {
2360 _ASYNCIO_FUTURE_RESULT_METHODDEF
2361 _ASYNCIO_FUTURE_EXCEPTION_METHODDEF
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002362 _ASYNCIO_FUTURE_ADD_DONE_CALLBACK_METHODDEF
2363 _ASYNCIO_FUTURE_REMOVE_DONE_CALLBACK_METHODDEF
2364 _ASYNCIO_FUTURE_CANCELLED_METHODDEF
2365 _ASYNCIO_FUTURE_DONE_METHODDEF
Yury Selivanov0cf16f92017-12-25 10:48:15 -05002366 _ASYNCIO_TASK_SET_RESULT_METHODDEF
2367 _ASYNCIO_TASK_SET_EXCEPTION_METHODDEF
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002368 _ASYNCIO_TASK_CURRENT_TASK_METHODDEF
2369 _ASYNCIO_TASK_ALL_TASKS_METHODDEF
2370 _ASYNCIO_TASK_CANCEL_METHODDEF
2371 _ASYNCIO_TASK_GET_STACK_METHODDEF
2372 _ASYNCIO_TASK_PRINT_STACK_METHODDEF
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002373 _ASYNCIO_TASK__REPR_INFO_METHODDEF
2374 {NULL, NULL} /* Sentinel */
2375};
2376
2377static PyGetSetDef TaskType_getsetlist[] = {
2378 FUTURE_COMMON_GETSETLIST
2379 {"_log_destroy_pending", (getter)TaskObj_get_log_destroy_pending,
2380 (setter)TaskObj_set_log_destroy_pending, NULL},
2381 {"_must_cancel", (getter)TaskObj_get_must_cancel, NULL, NULL},
2382 {"_coro", (getter)TaskObj_get_coro, NULL, NULL},
2383 {"_fut_waiter", (getter)TaskObj_get_fut_waiter, NULL, NULL},
2384 {NULL} /* Sentinel */
2385};
2386
2387static PyTypeObject TaskType = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02002388 PyVarObject_HEAD_INIT(NULL, 0)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002389 "_asyncio.Task",
2390 sizeof(TaskObj), /* tp_basicsize */
2391 .tp_base = &FutureType,
2392 .tp_dealloc = TaskObj_dealloc,
2393 .tp_as_async = &FutureType_as_async,
2394 .tp_repr = (reprfunc)FutureObj_repr,
2395 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE
2396 | Py_TPFLAGS_HAVE_FINALIZE,
2397 .tp_doc = _asyncio_Task___init____doc__,
2398 .tp_traverse = (traverseproc)TaskObj_traverse,
2399 .tp_clear = (inquiry)TaskObj_clear,
2400 .tp_weaklistoffset = offsetof(TaskObj, task_weakreflist),
2401 .tp_iter = (getiterfunc)future_new_iter,
2402 .tp_methods = TaskType_methods,
2403 .tp_getset = TaskType_getsetlist,
2404 .tp_dictoffset = offsetof(TaskObj, dict),
2405 .tp_init = (initproc)_asyncio_Task___init__,
2406 .tp_new = PyType_GenericNew,
2407 .tp_finalize = (destructor)TaskObj_finalize,
2408};
2409
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002410static void
2411TaskObj_dealloc(PyObject *self)
2412{
2413 TaskObj *task = (TaskObj *)self;
2414
2415 if (Task_CheckExact(self)) {
2416 /* When fut is subclass of Task, finalizer is called from
2417 * subtype_dealloc.
2418 */
2419 if (PyObject_CallFinalizerFromDealloc(self) < 0) {
2420 // resurrected.
2421 return;
2422 }
2423 }
2424
Alexander Mohrde34cbe2017-08-01 23:31:07 -07002425 PyObject_GC_UnTrack(self);
2426
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002427 if (task->task_weakreflist != NULL) {
2428 PyObject_ClearWeakRefs(self);
2429 }
2430
2431 (void)TaskObj_clear(task);
2432 Py_TYPE(task)->tp_free(task);
2433}
2434
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002435static int
2436task_call_step_soon(TaskObj *task, PyObject *arg)
2437{
Serhiy Storchakabca49392017-09-03 08:10:14 +03002438 PyObject *cb = TaskStepMethWrapper_new(task, arg);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002439 if (cb == NULL) {
2440 return -1;
2441 }
2442
Yury Selivanovf23746a2018-01-22 19:11:18 -05002443 int ret = call_soon(task->task_loop, cb, NULL, task->task_context);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002444 Py_DECREF(cb);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05002445 return ret;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002446}
2447
2448static PyObject *
2449task_set_error_soon(TaskObj *task, PyObject *et, const char *format, ...)
2450{
2451 PyObject* msg;
2452
2453 va_list vargs;
2454#ifdef HAVE_STDARG_PROTOTYPES
2455 va_start(vargs, format);
2456#else
2457 va_start(vargs);
2458#endif
2459 msg = PyUnicode_FromFormatV(format, vargs);
2460 va_end(vargs);
2461
2462 if (msg == NULL) {
2463 return NULL;
2464 }
2465
Victor Stinnerde4ae3d2016-12-04 22:59:09 +01002466 PyObject *e = PyObject_CallFunctionObjArgs(et, msg, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002467 Py_DECREF(msg);
2468 if (e == NULL) {
2469 return NULL;
2470 }
2471
2472 if (task_call_step_soon(task, e) == -1) {
2473 Py_DECREF(e);
2474 return NULL;
2475 }
2476
2477 Py_DECREF(e);
2478 Py_RETURN_NONE;
2479}
2480
2481static PyObject *
2482task_step_impl(TaskObj *task, PyObject *exc)
2483{
2484 int res;
2485 int clear_exc = 0;
2486 PyObject *result = NULL;
Serhiy Storchakabca49392017-09-03 08:10:14 +03002487 PyObject *coro;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002488 PyObject *o;
2489
2490 if (task->task_state != STATE_PENDING) {
Yury Selivanov0cf16f92017-12-25 10:48:15 -05002491 PyErr_Format(asyncio_InvalidStateError,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002492 "_step(): already done: %R %R",
2493 task,
2494 exc ? exc : Py_None);
INADA Naokic411a7d2016-10-18 11:48:14 +09002495 goto fail;
2496 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09002497
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002498 if (task->task_must_cancel) {
2499 assert(exc != Py_None);
2500
2501 if (exc) {
2502 /* Check if exc is a CancelledError */
2503 res = PyObject_IsInstance(exc, asyncio_CancelledError);
2504 if (res == -1) {
2505 /* An error occurred, abort */
2506 goto fail;
2507 }
2508 if (res == 0) {
2509 /* exc is not CancelledError; reset it to NULL */
2510 exc = NULL;
2511 }
2512 }
2513
2514 if (!exc) {
2515 /* exc was not a CancelledError */
Victor Stinnerf17c3de2016-12-06 18:46:19 +01002516 exc = _PyObject_CallNoArg(asyncio_CancelledError);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002517 if (!exc) {
2518 goto fail;
2519 }
2520 clear_exc = 1;
2521 }
2522
2523 task->task_must_cancel = 0;
2524 }
2525
2526 Py_CLEAR(task->task_fut_waiter);
2527
Serhiy Storchakabca49392017-09-03 08:10:14 +03002528 coro = task->task_coro;
2529 if (coro == NULL) {
2530 PyErr_SetString(PyExc_RuntimeError, "uninitialized Task object");
2531 return NULL;
2532 }
2533
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002534 if (exc == NULL) {
2535 if (PyGen_CheckExact(coro) || PyCoro_CheckExact(coro)) {
2536 result = _PyGen_Send((PyGenObject*)coro, Py_None);
2537 }
2538 else {
Victor Stinnerb6ed57d2016-12-09 14:24:02 +01002539 result = _PyObject_CallMethodIdObjArgs(coro, &PyId_send,
2540 Py_None, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002541 }
2542 }
2543 else {
Victor Stinnerb6ed57d2016-12-09 14:24:02 +01002544 result = _PyObject_CallMethodIdObjArgs(coro, &PyId_throw,
2545 exc, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002546 if (clear_exc) {
2547 /* We created 'exc' during this call */
Serhiy Storchakabca49392017-09-03 08:10:14 +03002548 Py_DECREF(exc);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002549 }
2550 }
2551
2552 if (result == NULL) {
2553 PyObject *et, *ev, *tb;
2554
2555 if (_PyGen_FetchStopIterationValue(&o) == 0) {
2556 /* The error is StopIteration and that means that
2557 the underlying coroutine has resolved */
INADA Naoki991adca2017-05-11 21:18:38 +09002558 if (task->task_must_cancel) {
2559 // Task is cancelled right before coro stops.
2560 Py_DECREF(o);
2561 task->task_must_cancel = 0;
2562 et = asyncio_CancelledError;
2563 Py_INCREF(et);
2564 ev = NULL;
2565 tb = NULL;
2566 goto set_exception;
2567 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002568 PyObject *res = future_set_result((FutureObj*)task, o);
2569 Py_DECREF(o);
2570 if (res == NULL) {
2571 return NULL;
2572 }
2573 Py_DECREF(res);
2574 Py_RETURN_NONE;
2575 }
2576
2577 if (PyErr_ExceptionMatches(asyncio_CancelledError)) {
2578 /* CancelledError */
2579 PyErr_Clear();
2580 return future_cancel((FutureObj*)task);
2581 }
2582
2583 /* Some other exception; pop it and call Task.set_exception() */
2584 PyErr_Fetch(&et, &ev, &tb);
INADA Naoki991adca2017-05-11 21:18:38 +09002585
2586set_exception:
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002587 assert(et);
2588 if (!ev || !PyObject_TypeCheck(ev, (PyTypeObject *) et)) {
2589 PyErr_NormalizeException(&et, &ev, &tb);
2590 }
Yury Selivanovedfe8862016-12-01 11:37:47 -05002591 if (tb != NULL) {
2592 PyException_SetTraceback(ev, tb);
2593 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002594 o = future_set_exception((FutureObj*)task, ev);
2595 if (!o) {
2596 /* An exception in Task.set_exception() */
Serhiy Storchakabca49392017-09-03 08:10:14 +03002597 Py_DECREF(et);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002598 Py_XDECREF(tb);
2599 Py_XDECREF(ev);
2600 goto fail;
2601 }
2602 assert(o == Py_None);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002603 Py_DECREF(o);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002604
2605 if (!PyErr_GivenExceptionMatches(et, PyExc_Exception)) {
2606 /* We've got a BaseException; re-raise it */
2607 PyErr_Restore(et, ev, tb);
2608 goto fail;
2609 }
2610
Serhiy Storchakabca49392017-09-03 08:10:14 +03002611 Py_DECREF(et);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002612 Py_XDECREF(tb);
2613 Py_XDECREF(ev);
2614
2615 Py_RETURN_NONE;
2616 }
2617
2618 if (result == (PyObject*)task) {
2619 /* We have a task that wants to await on itself */
2620 goto self_await;
2621 }
2622
2623 /* Check if `result` is FutureObj or TaskObj (and not a subclass) */
2624 if (Future_CheckExact(result) || Task_CheckExact(result)) {
2625 PyObject *wrapper;
2626 PyObject *res;
2627 FutureObj *fut = (FutureObj*)result;
2628
2629 /* Check if `result` future is attached to a different loop */
2630 if (fut->fut_loop != task->task_loop) {
2631 goto different_loop;
2632 }
2633
2634 if (fut->fut_blocking) {
2635 fut->fut_blocking = 0;
2636
2637 /* result.add_done_callback(task._wakeup) */
2638 wrapper = TaskWakeupMethWrapper_new(task);
2639 if (wrapper == NULL) {
2640 goto fail;
2641 }
Yury Selivanovf23746a2018-01-22 19:11:18 -05002642 res = future_add_done_callback(
2643 (FutureObj*)result, wrapper, task->task_context);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002644 Py_DECREF(wrapper);
2645 if (res == NULL) {
2646 goto fail;
2647 }
2648 Py_DECREF(res);
2649
2650 /* task._fut_waiter = result */
2651 task->task_fut_waiter = result; /* no incref is necessary */
2652
2653 if (task->task_must_cancel) {
2654 PyObject *r;
2655 r = future_cancel(fut);
2656 if (r == NULL) {
2657 return NULL;
2658 }
2659 if (r == Py_True) {
2660 task->task_must_cancel = 0;
2661 }
2662 Py_DECREF(r);
2663 }
2664
2665 Py_RETURN_NONE;
2666 }
2667 else {
2668 goto yield_insteadof_yf;
2669 }
2670 }
2671
2672 /* Check if `result` is a Future-compatible object */
2673 o = PyObject_GetAttrString(result, "_asyncio_future_blocking");
2674 if (o == NULL) {
2675 if (PyErr_ExceptionMatches(PyExc_AttributeError)) {
2676 PyErr_Clear();
2677 }
2678 else {
2679 goto fail;
2680 }
2681 }
2682 else {
2683 if (o == Py_None) {
Serhiy Storchakabca49392017-09-03 08:10:14 +03002684 Py_DECREF(o);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002685 }
2686 else {
2687 /* `result` is a Future-compatible object */
2688 PyObject *wrapper;
2689 PyObject *res;
2690
2691 int blocking = PyObject_IsTrue(o);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002692 Py_DECREF(o);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002693 if (blocking < 0) {
2694 goto fail;
2695 }
2696
2697 /* Check if `result` future is attached to a different loop */
Yury Selivanovca9b36c2017-12-23 15:04:15 -05002698 PyObject *oloop = get_future_loop(result);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002699 if (oloop == NULL) {
2700 goto fail;
2701 }
2702 if (oloop != task->task_loop) {
2703 Py_DECREF(oloop);
2704 goto different_loop;
2705 }
2706 else {
2707 Py_DECREF(oloop);
2708 }
2709
2710 if (blocking) {
2711 /* result._asyncio_future_blocking = False */
2712 if (PyObject_SetAttrString(
2713 result, "_asyncio_future_blocking", Py_False) == -1) {
2714 goto fail;
2715 }
2716
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002717 wrapper = TaskWakeupMethWrapper_new(task);
2718 if (wrapper == NULL) {
2719 goto fail;
2720 }
Yury Selivanovf23746a2018-01-22 19:11:18 -05002721
2722 /* result.add_done_callback(task._wakeup) */
2723 PyObject *add_cb = _PyObject_GetAttrId(
2724 result, &PyId_add_done_callback);
2725 if (add_cb == NULL) {
2726 goto fail;
2727 }
2728 PyObject *stack[2];
2729 stack[0] = wrapper;
2730 stack[1] = (PyObject *)task->task_context;
2731 res = _PyObject_FastCallKeywords(
2732 add_cb, stack, 1, context_kwname);
2733 Py_DECREF(add_cb);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002734 Py_DECREF(wrapper);
2735 if (res == NULL) {
2736 goto fail;
2737 }
2738 Py_DECREF(res);
2739
2740 /* task._fut_waiter = result */
2741 task->task_fut_waiter = result; /* no incref is necessary */
2742
2743 if (task->task_must_cancel) {
2744 PyObject *r;
2745 int is_true;
2746 r = _PyObject_CallMethodId(result, &PyId_cancel, NULL);
2747 if (r == NULL) {
2748 return NULL;
2749 }
2750 is_true = PyObject_IsTrue(r);
2751 Py_DECREF(r);
2752 if (is_true < 0) {
2753 return NULL;
2754 }
2755 else if (is_true) {
2756 task->task_must_cancel = 0;
2757 }
2758 }
2759
2760 Py_RETURN_NONE;
2761 }
2762 else {
2763 goto yield_insteadof_yf;
2764 }
2765 }
2766 }
2767
2768 /* Check if `result` is None */
2769 if (result == Py_None) {
2770 /* Bare yield relinquishes control for one event loop iteration. */
2771 if (task_call_step_soon(task, NULL)) {
2772 goto fail;
2773 }
2774 return result;
2775 }
2776
2777 /* Check if `result` is a generator */
Victor Stinnerde4ae3d2016-12-04 22:59:09 +01002778 o = PyObject_CallFunctionObjArgs(inspect_isgenerator, result, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002779 if (o == NULL) {
2780 /* An exception in inspect.isgenerator */
2781 goto fail;
2782 }
2783 res = PyObject_IsTrue(o);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002784 Py_DECREF(o);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002785 if (res == -1) {
2786 /* An exception while checking if 'val' is True */
2787 goto fail;
2788 }
2789 if (res == 1) {
2790 /* `result` is a generator */
2791 PyObject *ret;
2792 ret = task_set_error_soon(
2793 task, PyExc_RuntimeError,
2794 "yield was used instead of yield from for "
2795 "generator in task %R with %S", task, result);
2796 Py_DECREF(result);
2797 return ret;
2798 }
2799
2800 /* The `result` is none of the above */
2801 Py_DECREF(result);
2802 return task_set_error_soon(
2803 task, PyExc_RuntimeError, "Task got bad yield: %R", result);
2804
2805self_await:
2806 o = task_set_error_soon(
2807 task, PyExc_RuntimeError,
2808 "Task cannot await on itself: %R", task);
2809 Py_DECREF(result);
2810 return o;
2811
2812yield_insteadof_yf:
2813 o = task_set_error_soon(
2814 task, PyExc_RuntimeError,
2815 "yield was used instead of yield from "
2816 "in task %R with %R",
2817 task, result);
2818 Py_DECREF(result);
2819 return o;
2820
2821different_loop:
2822 o = task_set_error_soon(
2823 task, PyExc_RuntimeError,
2824 "Task %R got Future %R attached to a different loop",
2825 task, result);
2826 Py_DECREF(result);
2827 return o;
2828
2829fail:
2830 Py_XDECREF(result);
2831 return NULL;
2832}
2833
2834static PyObject *
2835task_step(TaskObj *task, PyObject *exc)
2836{
2837 PyObject *res;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002838
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002839 if (enter_task(task->task_loop, (PyObject*)task) < 0) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002840 return NULL;
2841 }
2842
2843 res = task_step_impl(task, exc);
2844
2845 if (res == NULL) {
2846 PyObject *et, *ev, *tb;
2847 PyErr_Fetch(&et, &ev, &tb);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002848 leave_task(task->task_loop, (PyObject*)task);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002849 _PyErr_ChainExceptions(et, ev, tb);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002850 return NULL;
2851 }
2852 else {
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002853 if(leave_task(task->task_loop, (PyObject*)task) < 0) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002854 Py_DECREF(res);
2855 return NULL;
2856 }
2857 else {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002858 return res;
2859 }
2860 }
2861}
2862
2863static PyObject *
2864task_wakeup(TaskObj *task, PyObject *o)
2865{
Serhiy Storchakabca49392017-09-03 08:10:14 +03002866 PyObject *et, *ev, *tb;
2867 PyObject *result;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002868 assert(o);
2869
2870 if (Future_CheckExact(o) || Task_CheckExact(o)) {
2871 PyObject *fut_result = NULL;
2872 int res = future_get_result((FutureObj*)o, &fut_result);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002873
2874 switch(res) {
2875 case -1:
2876 assert(fut_result == NULL);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002877 break; /* exception raised */
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002878 case 0:
2879 Py_DECREF(fut_result);
Yury Selivanov22feeb82018-01-24 11:31:01 -05002880 return task_step(task, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002881 default:
2882 assert(res == 1);
Yury Selivanov22feeb82018-01-24 11:31:01 -05002883 result = task_step(task, fut_result);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002884 Py_DECREF(fut_result);
2885 return result;
2886 }
2887 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002888 else {
Serhiy Storchakabca49392017-09-03 08:10:14 +03002889 PyObject *fut_result = PyObject_CallMethod(o, "result", NULL);
2890 if (fut_result != NULL) {
2891 Py_DECREF(fut_result);
Yury Selivanov22feeb82018-01-24 11:31:01 -05002892 return task_step(task, NULL);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002893 }
2894 /* exception raised */
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002895 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03002896
2897 PyErr_Fetch(&et, &ev, &tb);
2898 if (!PyErr_GivenExceptionMatches(et, PyExc_Exception)) {
2899 /* We've got a BaseException; re-raise it */
2900 PyErr_Restore(et, ev, tb);
2901 return NULL;
2902 }
2903 if (!ev || !PyObject_TypeCheck(ev, (PyTypeObject *) et)) {
2904 PyErr_NormalizeException(&et, &ev, &tb);
2905 }
2906
Yury Selivanov22feeb82018-01-24 11:31:01 -05002907 result = task_step(task, ev);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002908
2909 Py_DECREF(et);
2910 Py_XDECREF(tb);
2911 Py_XDECREF(ev);
2912
2913 return result;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002914}
2915
2916
Yury Selivanova70232f2017-12-13 14:49:42 -05002917/*********************** Functions **************************/
2918
2919
2920/*[clinic input]
2921_asyncio._get_running_loop
2922
2923Return the running event loop or None.
2924
2925This is a low-level function intended to be used by event loops.
2926This function is thread-specific.
2927
2928[clinic start generated code]*/
2929
2930static PyObject *
2931_asyncio__get_running_loop_impl(PyObject *module)
2932/*[clinic end generated code: output=b4390af721411a0a input=0a21627e25a4bd43]*/
2933{
2934 PyObject *loop;
2935 if (get_running_loop(&loop)) {
2936 return NULL;
2937 }
2938 if (loop == NULL) {
2939 /* There's no currently running event loop */
2940 Py_RETURN_NONE;
2941 }
2942 return loop;
2943}
2944
2945/*[clinic input]
2946_asyncio._set_running_loop
2947 loop: 'O'
2948 /
2949
2950Set the running event loop.
2951
2952This is a low-level function intended to be used by event loops.
2953This function is thread-specific.
2954[clinic start generated code]*/
2955
2956static PyObject *
2957_asyncio__set_running_loop(PyObject *module, PyObject *loop)
2958/*[clinic end generated code: output=ae56bf7a28ca189a input=4c9720233d606604]*/
2959{
2960 if (set_running_loop(loop)) {
2961 return NULL;
2962 }
2963 Py_RETURN_NONE;
2964}
2965
2966/*[clinic input]
2967_asyncio.get_event_loop
2968
2969Return an asyncio event loop.
2970
2971When called from a coroutine or a callback (e.g. scheduled with
2972call_soon or similar API), this function will always return the
2973running event loop.
2974
2975If there is no running event loop set, the function will return
2976the result of `get_event_loop_policy().get_event_loop()` call.
2977[clinic start generated code]*/
2978
2979static PyObject *
2980_asyncio_get_event_loop_impl(PyObject *module)
2981/*[clinic end generated code: output=2a2d8b2f824c648b input=9364bf2916c8655d]*/
2982{
2983 return get_event_loop();
2984}
2985
2986/*[clinic input]
2987_asyncio.get_running_loop
2988
2989Return the running event loop. Raise a RuntimeError if there is none.
2990
2991This function is thread-specific.
2992[clinic start generated code]*/
2993
2994static PyObject *
2995_asyncio_get_running_loop_impl(PyObject *module)
2996/*[clinic end generated code: output=c247b5f9e529530e input=2a3bf02ba39f173d]*/
2997{
2998 PyObject *loop;
2999 if (get_running_loop(&loop)) {
3000 return NULL;
3001 }
3002 if (loop == NULL) {
3003 /* There's no currently running event loop */
3004 PyErr_SetString(
3005 PyExc_RuntimeError, "no running event loop");
3006 }
3007 return loop;
3008}
3009
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003010/*[clinic input]
3011_asyncio._register_task
3012
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003013 task: object
3014
3015Register a new task in asyncio as executed by loop.
3016
3017Returns None.
3018[clinic start generated code]*/
3019
3020static PyObject *
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003021_asyncio__register_task_impl(PyObject *module, PyObject *task)
3022/*[clinic end generated code: output=8672dadd69a7d4e2 input=21075aaea14dfbad]*/
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003023{
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003024 if (register_task(task) < 0) {
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003025 return NULL;
3026 }
3027 Py_RETURN_NONE;
3028}
3029
3030
3031/*[clinic input]
3032_asyncio._unregister_task
3033
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003034 task: object
3035
3036Unregister a task.
3037
3038Returns None.
3039[clinic start generated code]*/
3040
3041static PyObject *
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003042_asyncio__unregister_task_impl(PyObject *module, PyObject *task)
3043/*[clinic end generated code: output=6e5585706d568a46 input=28fb98c3975f7bdc]*/
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003044{
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003045 if (unregister_task(task) < 0) {
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003046 return NULL;
3047 }
3048 Py_RETURN_NONE;
3049}
3050
3051
3052/*[clinic input]
3053_asyncio._enter_task
3054
3055 loop: object
3056 task: object
3057
3058Enter into task execution or resume suspended task.
3059
3060Task belongs to loop.
3061
3062Returns None.
3063[clinic start generated code]*/
3064
3065static PyObject *
3066_asyncio__enter_task_impl(PyObject *module, PyObject *loop, PyObject *task)
3067/*[clinic end generated code: output=a22611c858035b73 input=de1b06dca70d8737]*/
3068{
3069 if (enter_task(loop, task) < 0) {
3070 return NULL;
3071 }
3072 Py_RETURN_NONE;
3073}
3074
3075
3076/*[clinic input]
3077_asyncio._leave_task
3078
3079 loop: object
3080 task: object
3081
3082Leave task execution or suspend a task.
3083
3084Task belongs to loop.
3085
3086Returns None.
3087[clinic start generated code]*/
3088
3089static PyObject *
3090_asyncio__leave_task_impl(PyObject *module, PyObject *loop, PyObject *task)
3091/*[clinic end generated code: output=0ebf6db4b858fb41 input=51296a46313d1ad8]*/
3092{
3093 if (leave_task(loop, task) < 0) {
3094 return NULL;
3095 }
3096 Py_RETURN_NONE;
3097}
3098
Yury Selivanova70232f2017-12-13 14:49:42 -05003099
Yury Selivanov9d411c12018-01-23 15:10:03 -05003100/*********************** PyRunningLoopHolder ********************/
3101
3102
3103static PyRunningLoopHolder *
3104new_running_loop_holder(PyObject *loop)
3105{
3106 PyRunningLoopHolder *rl = PyObject_New(
3107 PyRunningLoopHolder, &PyRunningLoopHolder_Type);
3108 if (rl == NULL) {
3109 return NULL;
3110 }
3111
3112#if defined(HAVE_GETPID) && !defined(MS_WINDOWS)
3113 rl->rl_pid = getpid();
3114#endif
3115
3116 Py_INCREF(loop);
3117 rl->rl_loop = loop;
3118
3119 return rl;
3120}
3121
3122
3123static void
3124PyRunningLoopHolder_tp_dealloc(PyRunningLoopHolder *rl)
3125{
3126 Py_CLEAR(rl->rl_loop);
3127 PyObject_Free(rl);
3128}
3129
3130
3131static PyTypeObject PyRunningLoopHolder_Type = {
3132 PyVarObject_HEAD_INIT(NULL, 0)
3133 "_RunningLoopHolder",
3134 sizeof(PyRunningLoopHolder),
3135 .tp_getattro = PyObject_GenericGetAttr,
3136 .tp_flags = Py_TPFLAGS_DEFAULT,
3137 .tp_dealloc = (destructor)PyRunningLoopHolder_tp_dealloc,
3138};
3139
3140
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003141/*********************** Module **************************/
3142
3143
3144static void
Zackery Spytze40ad792017-12-19 11:48:13 -07003145module_free_freelists(void)
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05003146{
3147 PyObject *next;
3148 PyObject *current;
3149
3150 next = (PyObject*) fi_freelist;
3151 while (next != NULL) {
3152 assert(fi_freelist_len > 0);
3153 fi_freelist_len--;
3154
3155 current = next;
3156 next = (PyObject*) ((futureiterobject*) current)->future;
3157 PyObject_GC_Del(current);
3158 }
3159 assert(fi_freelist_len == 0);
3160 fi_freelist = NULL;
3161}
3162
3163
3164static void
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003165module_free(void *m)
3166{
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003167 Py_CLEAR(asyncio_mod);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003168 Py_CLEAR(inspect_isgenerator);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003169 Py_CLEAR(traceback_extract_stack);
3170 Py_CLEAR(asyncio_future_repr_info_func);
3171 Py_CLEAR(asyncio_get_event_loop_policy);
3172 Py_CLEAR(asyncio_iscoroutine_func);
3173 Py_CLEAR(asyncio_task_get_stack_func);
3174 Py_CLEAR(asyncio_task_print_stack_func);
3175 Py_CLEAR(asyncio_task_repr_info_func);
3176 Py_CLEAR(asyncio_InvalidStateError);
3177 Py_CLEAR(asyncio_CancelledError);
3178
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003179 Py_CLEAR(all_tasks);
Yury Selivanova9d7e552017-12-19 07:18:45 -05003180 Py_CLEAR(current_tasks);
3181 Py_CLEAR(iscoroutine_typecache);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05003182
Yury Selivanovf23746a2018-01-22 19:11:18 -05003183 Py_CLEAR(context_kwname);
3184
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05003185 module_free_freelists();
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003186}
3187
3188static int
3189module_init(void)
3190{
3191 PyObject *module = NULL;
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003192
3193 asyncio_mod = PyImport_ImportModule("asyncio");
3194 if (asyncio_mod == NULL) {
3195 goto fail;
3196 }
3197
3198 current_tasks = PyDict_New();
3199 if (current_tasks == NULL) {
3200 goto fail;
3201 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003202
Yury Selivanova9d7e552017-12-19 07:18:45 -05003203 iscoroutine_typecache = PySet_New(NULL);
3204 if (iscoroutine_typecache == NULL) {
3205 goto fail;
3206 }
3207
Yury Selivanovf23746a2018-01-22 19:11:18 -05003208
3209 context_kwname = PyTuple_New(1);
3210 if (context_kwname == NULL) {
3211 goto fail;
3212 }
3213 PyObject *context_str = PyUnicode_FromString("context");
3214 if (context_str == NULL) {
3215 goto fail;
3216 }
3217 PyTuple_SET_ITEM(context_kwname, 0, context_str);
3218
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003219#define WITH_MOD(NAME) \
3220 Py_CLEAR(module); \
3221 module = PyImport_ImportModule(NAME); \
3222 if (module == NULL) { \
Serhiy Storchakabca49392017-09-03 08:10:14 +03003223 goto fail; \
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003224 }
3225
3226#define GET_MOD_ATTR(VAR, NAME) \
3227 VAR = PyObject_GetAttrString(module, NAME); \
3228 if (VAR == NULL) { \
3229 goto fail; \
3230 }
3231
3232 WITH_MOD("asyncio.events")
Yury Selivanova70232f2017-12-13 14:49:42 -05003233 GET_MOD_ATTR(asyncio_get_event_loop_policy, "get_event_loop_policy")
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003234
3235 WITH_MOD("asyncio.base_futures")
3236 GET_MOD_ATTR(asyncio_future_repr_info_func, "_future_repr_info")
3237 GET_MOD_ATTR(asyncio_InvalidStateError, "InvalidStateError")
3238 GET_MOD_ATTR(asyncio_CancelledError, "CancelledError")
3239
3240 WITH_MOD("asyncio.base_tasks")
3241 GET_MOD_ATTR(asyncio_task_repr_info_func, "_task_repr_info")
3242 GET_MOD_ATTR(asyncio_task_get_stack_func, "_task_get_stack")
3243 GET_MOD_ATTR(asyncio_task_print_stack_func, "_task_print_stack")
3244
Andrew Svetlovf74ef452017-12-15 07:04:38 +02003245 WITH_MOD("asyncio.coroutines")
3246 GET_MOD_ATTR(asyncio_iscoroutine_func, "iscoroutine")
3247
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003248 WITH_MOD("inspect")
3249 GET_MOD_ATTR(inspect_isgenerator, "isgenerator")
3250
3251 WITH_MOD("traceback")
3252 GET_MOD_ATTR(traceback_extract_stack, "extract_stack")
3253
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003254 PyObject *weak_set;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003255 WITH_MOD("weakref")
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003256 GET_MOD_ATTR(weak_set, "WeakSet");
3257 all_tasks = _PyObject_CallNoArg(weak_set);
3258 Py_CLEAR(weak_set);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003259 if (all_tasks == NULL) {
INADA Naokic411a7d2016-10-18 11:48:14 +09003260 goto fail;
3261 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003262
Serhiy Storchakabca49392017-09-03 08:10:14 +03003263 Py_DECREF(module);
INADA Naokic411a7d2016-10-18 11:48:14 +09003264 return 0;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003265
INADA Naokic411a7d2016-10-18 11:48:14 +09003266fail:
INADA Naokic411a7d2016-10-18 11:48:14 +09003267 Py_CLEAR(module);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003268 module_free(NULL);
INADA Naokic411a7d2016-10-18 11:48:14 +09003269 return -1;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003270
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003271#undef WITH_MOD
3272#undef GET_MOD_ATTR
3273}
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003274
INADA Naokic411a7d2016-10-18 11:48:14 +09003275PyDoc_STRVAR(module_doc, "Accelerator module for asyncio");
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003276
Yury Selivanova70232f2017-12-13 14:49:42 -05003277static PyMethodDef asyncio_methods[] = {
3278 _ASYNCIO_GET_EVENT_LOOP_METHODDEF
3279 _ASYNCIO_GET_RUNNING_LOOP_METHODDEF
3280 _ASYNCIO__GET_RUNNING_LOOP_METHODDEF
3281 _ASYNCIO__SET_RUNNING_LOOP_METHODDEF
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003282 _ASYNCIO__REGISTER_TASK_METHODDEF
3283 _ASYNCIO__UNREGISTER_TASK_METHODDEF
3284 _ASYNCIO__ENTER_TASK_METHODDEF
3285 _ASYNCIO__LEAVE_TASK_METHODDEF
Yury Selivanova70232f2017-12-13 14:49:42 -05003286 {NULL, NULL}
3287};
3288
INADA Naoki9f2ce252016-10-15 15:39:19 +09003289static struct PyModuleDef _asynciomodule = {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003290 PyModuleDef_HEAD_INIT, /* m_base */
INADA Naoki9f2ce252016-10-15 15:39:19 +09003291 "_asyncio", /* m_name */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003292 module_doc, /* m_doc */
3293 -1, /* m_size */
Yury Selivanova70232f2017-12-13 14:49:42 -05003294 asyncio_methods, /* m_methods */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003295 NULL, /* m_slots */
3296 NULL, /* m_traverse */
3297 NULL, /* m_clear */
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003298 (freefunc)module_free /* m_free */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003299};
3300
3301
3302PyMODINIT_FUNC
INADA Naoki9f2ce252016-10-15 15:39:19 +09003303PyInit__asyncio(void)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003304{
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003305 if (module_init() < 0) {
INADA Naokic411a7d2016-10-18 11:48:14 +09003306 return NULL;
3307 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003308 if (PyType_Ready(&FutureType) < 0) {
3309 return NULL;
3310 }
3311 if (PyType_Ready(&FutureIterType) < 0) {
3312 return NULL;
3313 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03003314 if (PyType_Ready(&TaskStepMethWrapper_Type) < 0) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003315 return NULL;
3316 }
3317 if(PyType_Ready(&TaskWakeupMethWrapper_Type) < 0) {
3318 return NULL;
3319 }
3320 if (PyType_Ready(&TaskType) < 0) {
3321 return NULL;
3322 }
Yury Selivanov9d411c12018-01-23 15:10:03 -05003323 if (PyType_Ready(&PyRunningLoopHolder_Type) < 0) {
3324 return NULL;
3325 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003326
INADA Naoki9f2ce252016-10-15 15:39:19 +09003327 PyObject *m = PyModule_Create(&_asynciomodule);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003328 if (m == NULL) {
3329 return NULL;
3330 }
3331
3332 Py_INCREF(&FutureType);
3333 if (PyModule_AddObject(m, "Future", (PyObject *)&FutureType) < 0) {
3334 Py_DECREF(&FutureType);
3335 return NULL;
3336 }
3337
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003338 Py_INCREF(&TaskType);
3339 if (PyModule_AddObject(m, "Task", (PyObject *)&TaskType) < 0) {
3340 Py_DECREF(&TaskType);
3341 return NULL;
3342 }
3343
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003344 Py_INCREF(all_tasks);
3345 if (PyModule_AddObject(m, "_all_tasks", all_tasks) < 0) {
3346 Py_DECREF(all_tasks);
3347 return NULL;
3348 }
3349
3350 Py_INCREF(current_tasks);
3351 if (PyModule_AddObject(m, "_current_tasks", current_tasks) < 0) {
3352 Py_DECREF(current_tasks);
3353 return NULL;
3354 }
3355
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003356 return m;
3357}