blob: 0998cc103880b85383cfa4756eccb4000a57e2a0 [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__);
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +030013_Py_IDENTIFIER(_asyncio_future_blocking);
Yury Selivanova0c1ba62016-10-28 12:52:37 -040014_Py_IDENTIFIER(add_done_callback);
Yury Selivanov416c1eb2018-05-28 17:54:02 -040015_Py_IDENTIFIER(_all_tasks_compat);
INADA Naoki9e4e38e2016-10-09 14:44:47 +090016_Py_IDENTIFIER(call_soon);
Yury Selivanova0c1ba62016-10-28 12:52:37 -040017_Py_IDENTIFIER(cancel);
Andrew Svetlov44d1a592017-12-16 21:58:38 +020018_Py_IDENTIFIER(current_task);
Yury Selivanova70232f2017-12-13 14:49:42 -050019_Py_IDENTIFIER(get_event_loop);
Yury Selivanova0c1ba62016-10-28 12:52:37 -040020_Py_IDENTIFIER(send);
21_Py_IDENTIFIER(throw);
INADA Naoki9e4e38e2016-10-09 14:44:47 +090022
23
INADA Naoki9f2ce252016-10-15 15:39:19 +090024/* State of the _asyncio module */
Andrew Svetlov44d1a592017-12-16 21:58:38 +020025static PyObject *asyncio_mod;
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
Alex Grönholmcca4eec2018-08-09 00:06:47 +030040/* Counter for autogenerated Task names */
41static uint64_t task_name_counter = 0;
Andrew Svetlov44d1a592017-12-16 21:58:38 +020042
Yury Selivanovca9b36c2017-12-23 15:04:15 -050043/* WeakSet containing all alive tasks. */
44static PyObject *all_tasks;
Andrew Svetlov44d1a592017-12-16 21:58:38 +020045
46/* Dictionary containing tasks that are currently active in
47 all running event loops. {EventLoop: Task} */
Yury Selivanovca9b36c2017-12-23 15:04:15 -050048static PyObject *current_tasks;
INADA Naoki9e4e38e2016-10-09 14:44:47 +090049
Yury Selivanova9d7e552017-12-19 07:18:45 -050050/* An isinstance type cache for the 'is_coroutine()' function. */
51static PyObject *iscoroutine_typecache;
52
INADA Naoki9e4e38e2016-10-09 14:44:47 +090053
INADA Naoki9e4e38e2016-10-09 14:44:47 +090054typedef enum {
55 STATE_PENDING,
56 STATE_CANCELLED,
57 STATE_FINISHED
58} fut_state;
59
Yury Selivanova0c1ba62016-10-28 12:52:37 -040060#define FutureObj_HEAD(prefix) \
61 PyObject_HEAD \
62 PyObject *prefix##_loop; \
Yury Selivanov1b7c11f2017-12-17 20:19:47 -050063 PyObject *prefix##_callback0; \
Yury Selivanov994269c2018-09-27 14:55:55 -040064 PyObject *prefix##_context0; \
Yury Selivanova0c1ba62016-10-28 12:52:37 -040065 PyObject *prefix##_callbacks; \
66 PyObject *prefix##_exception; \
67 PyObject *prefix##_result; \
68 PyObject *prefix##_source_tb; \
69 fut_state prefix##_state; \
70 int prefix##_log_tb; \
71 int prefix##_blocking; \
72 PyObject *dict; \
73 PyObject *prefix##_weakreflist;
74
75typedef struct {
76 FutureObj_HEAD(fut)
77} FutureObj;
78
79typedef struct {
80 FutureObj_HEAD(task)
81 PyObject *task_fut_waiter;
82 PyObject *task_coro;
Alex Grönholmcca4eec2018-08-09 00:06:47 +030083 PyObject *task_name;
Yury Selivanov994269c2018-09-27 14:55:55 -040084 PyObject *task_context;
Yury Selivanova0c1ba62016-10-28 12:52:37 -040085 int task_must_cancel;
86 int task_log_destroy_pending;
87} TaskObj;
INADA Naoki9e4e38e2016-10-09 14:44:47 +090088
89typedef struct {
90 PyObject_HEAD
Yury Selivanova0c1ba62016-10-28 12:52:37 -040091 TaskObj *sw_task;
92 PyObject *sw_arg;
Serhiy Storchakabca49392017-09-03 08:10:14 +030093} TaskStepMethWrapper;
INADA Naoki9e4e38e2016-10-09 14:44:47 +090094
Yury Selivanova0c1ba62016-10-28 12:52:37 -040095typedef struct {
96 PyObject_HEAD
97 TaskObj *ww_task;
98} TaskWakeupMethWrapper;
99
Yury Selivanov9d411c12018-01-23 15:10:03 -0500100typedef struct {
101 PyObject_HEAD
102 PyObject *rl_loop;
103#if defined(HAVE_GETPID) && !defined(MS_WINDOWS)
104 pid_t rl_pid;
105#endif
106} PyRunningLoopHolder;
107
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400108
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500109static PyTypeObject FutureType;
110static PyTypeObject TaskType;
Yury Selivanov9d411c12018-01-23 15:10:03 -0500111static PyTypeObject PyRunningLoopHolder_Type;
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500112
113
114#define Future_CheckExact(obj) (Py_TYPE(obj) == &FutureType)
115#define Task_CheckExact(obj) (Py_TYPE(obj) == &TaskType)
116
117#define Future_Check(obj) PyObject_TypeCheck(obj, &FutureType)
118#define Task_Check(obj) PyObject_TypeCheck(obj, &TaskType)
119
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400120#include "clinic/_asynciomodule.c.h"
121
122
123/*[clinic input]
124class _asyncio.Future "FutureObj *" "&Future_Type"
125[clinic start generated code]*/
126/*[clinic end generated code: output=da39a3ee5e6b4b0d input=00d3e4abca711e0f]*/
127
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500128
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400129/* Get FutureIter from Future */
Yury Selivanov9d411c12018-01-23 15:10:03 -0500130static PyObject * future_new_iter(PyObject *);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900131
Yury Selivanov9d411c12018-01-23 15:10:03 -0500132static PyRunningLoopHolder * new_running_loop_holder(PyObject *);
133
Yury Selivanova70232f2017-12-13 14:49:42 -0500134
135static int
Yury Selivanova9d7e552017-12-19 07:18:45 -0500136_is_coroutine(PyObject *coro)
137{
138 /* 'coro' is not a native coroutine, call asyncio.iscoroutine()
139 to check if it's another coroutine flavour.
140
141 Do this check after 'future_init()'; in case we need to raise
142 an error, __del__ needs a properly initialized object.
143 */
144 PyObject *res = PyObject_CallFunctionObjArgs(
145 asyncio_iscoroutine_func, coro, NULL);
146 if (res == NULL) {
147 return -1;
148 }
149
150 int is_res_true = PyObject_IsTrue(res);
151 Py_DECREF(res);
152 if (is_res_true <= 0) {
153 return is_res_true;
154 }
155
Andrew Svetlov0f47fa22017-12-23 22:06:46 +0200156 if (PySet_GET_SIZE(iscoroutine_typecache) < 100) {
Yury Selivanova9d7e552017-12-19 07:18:45 -0500157 /* Just in case we don't want to cache more than 100
158 positive types. That shouldn't ever happen, unless
159 someone stressing the system on purpose.
160 */
161 if (PySet_Add(iscoroutine_typecache, (PyObject*) Py_TYPE(coro))) {
162 return -1;
163 }
164 }
165
166 return 1;
167}
168
169
170static inline int
171is_coroutine(PyObject *coro)
172{
173 if (PyCoro_CheckExact(coro)) {
174 return 1;
175 }
176
177 /* Check if `type(coro)` is in the cache.
178 Caching makes is_coroutine() function almost as fast as
179 PyCoro_CheckExact() for non-native coroutine-like objects
180 (like coroutines compiled with Cython).
181
182 asyncio.iscoroutine() has its own type caching mechanism.
183 This cache allows us to avoid the cost of even calling
184 a pure-Python function in 99.9% cases.
185 */
186 int has_it = PySet_Contains(
187 iscoroutine_typecache, (PyObject*) Py_TYPE(coro));
188 if (has_it == 0) {
189 /* type(coro) is not in iscoroutine_typecache */
190 return _is_coroutine(coro);
191 }
192
Leo Ariasc3d95082018-02-03 18:36:10 -0600193 /* either an error has occurred or
Yury Selivanova9d7e552017-12-19 07:18:45 -0500194 type(coro) is in iscoroutine_typecache
195 */
196 return has_it;
197}
198
199
Yury Selivanovca9b36c2017-12-23 15:04:15 -0500200static PyObject *
201get_future_loop(PyObject *fut)
202{
203 /* Implementation of `asyncio.futures._get_loop` */
204
205 _Py_IDENTIFIER(get_loop);
206 _Py_IDENTIFIER(_loop);
Serhiy Storchaka66553542018-05-20 16:30:31 +0300207 PyObject *getloop;
Yury Selivanovca9b36c2017-12-23 15:04:15 -0500208
209 if (Future_CheckExact(fut) || Task_CheckExact(fut)) {
210 PyObject *loop = ((FutureObj *)fut)->fut_loop;
211 Py_INCREF(loop);
212 return loop;
213 }
214
Serhiy Storchaka66553542018-05-20 16:30:31 +0300215 if (_PyObject_LookupAttrId(fut, &PyId_get_loop, &getloop) < 0) {
216 return NULL;
217 }
Yury Selivanovca9b36c2017-12-23 15:04:15 -0500218 if (getloop != NULL) {
219 PyObject *res = _PyObject_CallNoArg(getloop);
220 Py_DECREF(getloop);
221 return res;
222 }
223
224 return _PyObject_GetAttrId(fut, &PyId__loop);
225}
226
227
Yury Selivanova9d7e552017-12-19 07:18:45 -0500228static int
Yury Selivanova70232f2017-12-13 14:49:42 -0500229get_running_loop(PyObject **loop)
230{
Yury Selivanov9d411c12018-01-23 15:10:03 -0500231 PyObject *rl;
Yury Selivanova70232f2017-12-13 14:49:42 -0500232
Yury Selivanov9d411c12018-01-23 15:10:03 -0500233 PyThreadState *ts = PyThreadState_Get();
234 if (ts->id == cached_running_holder_tsid && cached_running_holder != NULL) {
235 // Fast path, check the cache.
236 rl = cached_running_holder; // borrowed
237 }
238 else {
239 if (ts->dict == NULL) {
240 goto not_found;
241 }
242
243 rl = _PyDict_GetItemIdWithError(
244 ts->dict, &PyId___asyncio_running_event_loop__); // borrowed
245 if (rl == NULL) {
246 if (PyErr_Occurred()) {
247 goto error;
248 }
249 else {
250 goto not_found;
251 }
252 }
253
254 cached_running_holder = rl; // borrowed
255 cached_running_holder_tsid = ts->id;
Yury Selivanova70232f2017-12-13 14:49:42 -0500256 }
257
Yury Selivanov9d411c12018-01-23 15:10:03 -0500258 assert(Py_TYPE(rl) == &PyRunningLoopHolder_Type);
259 PyObject *running_loop = ((PyRunningLoopHolder *)rl)->rl_loop;
Yury Selivanova70232f2017-12-13 14:49:42 -0500260
261 if (running_loop == Py_None) {
262 goto not_found;
263 }
264
Yury Selivanov9d411c12018-01-23 15:10:03 -0500265#if defined(HAVE_GETPID) && !defined(MS_WINDOWS)
266 /* On Windows there is no getpid, but there is also no os.fork(),
267 so there is no need for this check.
268 */
269 if (getpid() != ((PyRunningLoopHolder *)rl)->rl_pid) {
270 goto not_found;
Yury Selivanova70232f2017-12-13 14:49:42 -0500271 }
Yury Selivanov9d411c12018-01-23 15:10:03 -0500272#endif
Yury Selivanova70232f2017-12-13 14:49:42 -0500273
Yury Selivanov9d411c12018-01-23 15:10:03 -0500274 Py_INCREF(running_loop);
275 *loop = running_loop;
276 return 0;
Yury Selivanova70232f2017-12-13 14:49:42 -0500277
278not_found:
279 *loop = NULL;
280 return 0;
281
Yury Selivanova70232f2017-12-13 14:49:42 -0500282error:
283 *loop = NULL;
284 return -1;
285}
286
287
288static int
289set_running_loop(PyObject *loop)
290{
Yury Selivanov9d411c12018-01-23 15:10:03 -0500291 cached_running_holder = NULL;
292 cached_running_holder_tsid = 0;
Yury Selivanova70232f2017-12-13 14:49:42 -0500293
Yury Selivanov9d411c12018-01-23 15:10:03 -0500294 PyObject *ts_dict = PyThreadState_GetDict(); // borrowed
Yury Selivanova70232f2017-12-13 14:49:42 -0500295 if (ts_dict == NULL) {
296 PyErr_SetString(
297 PyExc_RuntimeError, "thread-local storage is not available");
298 return -1;
299 }
300
Yury Selivanov9d411c12018-01-23 15:10:03 -0500301 PyRunningLoopHolder *rl = new_running_loop_holder(loop);
302 if (rl == NULL) {
Yury Selivanova70232f2017-12-13 14:49:42 -0500303 return -1;
304 }
305
Yury Selivanova70232f2017-12-13 14:49:42 -0500306 if (_PyDict_SetItemId(
Yury Selivanov9d411c12018-01-23 15:10:03 -0500307 ts_dict, &PyId___asyncio_running_event_loop__, (PyObject *)rl) < 0)
308 {
309 Py_DECREF(rl); // will cleanup loop & current_pid
Yury Selivanova70232f2017-12-13 14:49:42 -0500310 return -1;
311 }
Yury Selivanov9d411c12018-01-23 15:10:03 -0500312 Py_DECREF(rl);
Yury Selivanova70232f2017-12-13 14:49:42 -0500313
314 return 0;
315}
316
317
318static PyObject *
319get_event_loop(void)
320{
321 PyObject *loop;
322 PyObject *policy;
323
324 if (get_running_loop(&loop)) {
325 return NULL;
326 }
327 if (loop != NULL) {
328 return loop;
329 }
330
331 policy = _PyObject_CallNoArg(asyncio_get_event_loop_policy);
332 if (policy == NULL) {
333 return NULL;
334 }
335
336 loop = _PyObject_CallMethodId(policy, &PyId_get_event_loop, NULL);
337 Py_DECREF(policy);
338 return loop;
339}
340
341
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900342static int
Yury Selivanov994269c2018-09-27 14:55:55 -0400343call_soon(PyObject *loop, PyObject *func, PyObject *arg, PyObject *ctx)
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500344{
345 PyObject *handle;
Yury Selivanovf23746a2018-01-22 19:11:18 -0500346 PyObject *stack[3];
347 Py_ssize_t nargs;
348
349 if (ctx == NULL) {
350 handle = _PyObject_CallMethodIdObjArgs(
351 loop, &PyId_call_soon, func, arg, NULL);
352 }
353 else {
354 /* Use FASTCALL to pass a keyword-only argument to call_soon */
355
356 PyObject *callable = _PyObject_GetAttrId(loop, &PyId_call_soon);
357 if (callable == NULL) {
358 return -1;
359 }
360
361 /* All refs in 'stack' are borrowed. */
362 nargs = 1;
363 stack[0] = func;
364 if (arg != NULL) {
365 stack[1] = arg;
366 nargs++;
367 }
368 stack[nargs] = (PyObject *)ctx;
369
370 handle = _PyObject_FastCallKeywords(
371 callable, stack, nargs, context_kwname);
372 Py_DECREF(callable);
373 }
374
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500375 if (handle == NULL) {
376 return -1;
377 }
378 Py_DECREF(handle);
379 return 0;
380}
381
382
383static inline int
384future_is_alive(FutureObj *fut)
385{
386 return fut->fut_loop != NULL;
387}
388
389
390static inline int
391future_ensure_alive(FutureObj *fut)
392{
393 if (!future_is_alive(fut)) {
394 PyErr_SetString(PyExc_RuntimeError,
395 "Future object is not initialized.");
396 return -1;
397 }
398 return 0;
399}
400
401
402#define ENSURE_FUTURE_ALIVE(fut) \
403 do { \
404 assert(Future_Check(fut) || Task_Check(fut)); \
405 if (future_ensure_alive((FutureObj*)fut)) { \
406 return NULL; \
407 } \
408 } while(0);
409
410
411static int
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400412future_schedule_callbacks(FutureObj *fut)
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900413{
414 Py_ssize_t len;
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500415 Py_ssize_t i;
416
417 if (fut->fut_callback0 != NULL) {
418 /* There's a 1st callback */
419
420 int ret = call_soon(
Yury Selivanovf23746a2018-01-22 19:11:18 -0500421 fut->fut_loop, fut->fut_callback0,
422 (PyObject *)fut, fut->fut_context0);
423
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500424 Py_CLEAR(fut->fut_callback0);
Yury Selivanovf23746a2018-01-22 19:11:18 -0500425 Py_CLEAR(fut->fut_context0);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500426 if (ret) {
427 /* If an error occurs in pure-Python implementation,
428 all callbacks are cleared. */
429 Py_CLEAR(fut->fut_callbacks);
430 return ret;
431 }
432
433 /* we called the first callback, now try calling
434 callbacks from the 'fut_callbacks' list. */
435 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900436
437 if (fut->fut_callbacks == NULL) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500438 /* No more callbacks, return. */
439 return 0;
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900440 }
441
442 len = PyList_GET_SIZE(fut->fut_callbacks);
443 if (len == 0) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500444 /* The list of callbacks was empty; clear it and return. */
445 Py_CLEAR(fut->fut_callbacks);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900446 return 0;
447 }
448
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900449 for (i = 0; i < len; i++) {
Yury Selivanovf23746a2018-01-22 19:11:18 -0500450 PyObject *cb_tup = PyList_GET_ITEM(fut->fut_callbacks, i);
451 PyObject *cb = PyTuple_GET_ITEM(cb_tup, 0);
452 PyObject *ctx = PyTuple_GET_ITEM(cb_tup, 1);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900453
Yury Selivanov994269c2018-09-27 14:55:55 -0400454 if (call_soon(fut->fut_loop, cb, (PyObject *)fut, ctx)) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500455 /* If an error occurs in pure-Python implementation,
456 all callbacks are cleared. */
457 Py_CLEAR(fut->fut_callbacks);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900458 return -1;
459 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900460 }
461
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500462 Py_CLEAR(fut->fut_callbacks);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900463 return 0;
464}
465
Oren Milmand019bc82018-02-13 12:28:33 +0200466
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900467static int
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400468future_init(FutureObj *fut, PyObject *loop)
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900469{
Serhiy Storchakabca49392017-09-03 08:10:14 +0300470 PyObject *res;
471 int is_true;
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900472 _Py_IDENTIFIER(get_debug);
473
Oren Milmand019bc82018-02-13 12:28:33 +0200474 // Same to FutureObj_clear() but not clearing fut->dict
475 Py_CLEAR(fut->fut_loop);
476 Py_CLEAR(fut->fut_callback0);
477 Py_CLEAR(fut->fut_context0);
478 Py_CLEAR(fut->fut_callbacks);
479 Py_CLEAR(fut->fut_result);
480 Py_CLEAR(fut->fut_exception);
481 Py_CLEAR(fut->fut_source_tb);
482
483 fut->fut_state = STATE_PENDING;
484 fut->fut_log_tb = 0;
485 fut->fut_blocking = 0;
486
Serhiy Storchakabca49392017-09-03 08:10:14 +0300487 if (loop == Py_None) {
Yury Selivanova70232f2017-12-13 14:49:42 -0500488 loop = get_event_loop();
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900489 if (loop == NULL) {
490 return -1;
491 }
492 }
493 else {
494 Py_INCREF(loop);
495 }
Oren Milmand019bc82018-02-13 12:28:33 +0200496 fut->fut_loop = loop;
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900497
Victor Stinnerf94d1ee2016-10-29 09:05:39 +0200498 res = _PyObject_CallMethodId(fut->fut_loop, &PyId_get_debug, NULL);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900499 if (res == NULL) {
500 return -1;
501 }
Serhiy Storchakabca49392017-09-03 08:10:14 +0300502 is_true = PyObject_IsTrue(res);
503 Py_DECREF(res);
504 if (is_true < 0) {
505 return -1;
506 }
Yury Selivanov35230d02018-05-28 11:11:31 -0400507 if (is_true && !_Py_IsFinalizing()) {
508 /* Only try to capture the traceback if the interpreter is not being
509 finalized. The original motivation to add a `_Py_IsFinalizing()`
510 call was to prevent SIGSEGV when a Future is created in a __del__
511 method, which is called during the interpreter shutdown and the
512 traceback module is already unloaded.
513 */
Oren Milmand019bc82018-02-13 12:28:33 +0200514 fut->fut_source_tb = _PyObject_CallNoArg(traceback_extract_stack);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900515 if (fut->fut_source_tb == NULL) {
516 return -1;
517 }
518 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900519
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900520 return 0;
521}
522
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900523static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400524future_set_result(FutureObj *fut, PyObject *res)
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900525{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500526 if (future_ensure_alive(fut)) {
527 return NULL;
528 }
529
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900530 if (fut->fut_state != STATE_PENDING) {
531 PyErr_SetString(asyncio_InvalidStateError, "invalid state");
532 return NULL;
533 }
534
Serhiy Storchakabca49392017-09-03 08:10:14 +0300535 assert(!fut->fut_result);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900536 Py_INCREF(res);
537 fut->fut_result = res;
538 fut->fut_state = STATE_FINISHED;
539
Yury Selivanov22feeb82018-01-24 11:31:01 -0500540 if (future_schedule_callbacks(fut) == -1) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900541 return NULL;
542 }
543 Py_RETURN_NONE;
544}
545
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900546static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400547future_set_exception(FutureObj *fut, PyObject *exc)
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900548{
549 PyObject *exc_val = NULL;
550
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900551 if (fut->fut_state != STATE_PENDING) {
552 PyErr_SetString(asyncio_InvalidStateError, "invalid state");
553 return NULL;
554 }
555
556 if (PyExceptionClass_Check(exc)) {
Victor Stinnera5ed5f02016-12-06 18:45:50 +0100557 exc_val = _PyObject_CallNoArg(exc);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900558 if (exc_val == NULL) {
559 return NULL;
560 }
Serhiy Storchakabca49392017-09-03 08:10:14 +0300561 if (fut->fut_state != STATE_PENDING) {
562 Py_DECREF(exc_val);
563 PyErr_SetString(asyncio_InvalidStateError, "invalid state");
564 return NULL;
565 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900566 }
567 else {
568 exc_val = exc;
569 Py_INCREF(exc_val);
570 }
571 if (!PyExceptionInstance_Check(exc_val)) {
572 Py_DECREF(exc_val);
573 PyErr_SetString(PyExc_TypeError, "invalid exception object");
574 return NULL;
575 }
576 if ((PyObject*)Py_TYPE(exc_val) == PyExc_StopIteration) {
577 Py_DECREF(exc_val);
578 PyErr_SetString(PyExc_TypeError,
579 "StopIteration interacts badly with generators "
580 "and cannot be raised into a Future");
581 return NULL;
582 }
583
Serhiy Storchakabca49392017-09-03 08:10:14 +0300584 assert(!fut->fut_exception);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900585 fut->fut_exception = exc_val;
586 fut->fut_state = STATE_FINISHED;
587
Yury Selivanov22feeb82018-01-24 11:31:01 -0500588 if (future_schedule_callbacks(fut) == -1) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900589 return NULL;
590 }
591
592 fut->fut_log_tb = 1;
593 Py_RETURN_NONE;
594}
595
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400596static int
597future_get_result(FutureObj *fut, PyObject **result)
598{
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400599 if (fut->fut_state == STATE_CANCELLED) {
Serhiy Storchakabca49392017-09-03 08:10:14 +0300600 PyErr_SetNone(asyncio_CancelledError);
601 return -1;
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400602 }
603
604 if (fut->fut_state != STATE_FINISHED) {
Serhiy Storchakabca49392017-09-03 08:10:14 +0300605 PyErr_SetString(asyncio_InvalidStateError, "Result is not set.");
606 return -1;
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400607 }
608
609 fut->fut_log_tb = 0;
610 if (fut->fut_exception != NULL) {
611 Py_INCREF(fut->fut_exception);
612 *result = fut->fut_exception;
613 return 1;
614 }
615
616 Py_INCREF(fut->fut_result);
617 *result = fut->fut_result;
618 return 0;
619}
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900620
621static PyObject *
Yury Selivanov994269c2018-09-27 14:55:55 -0400622future_add_done_callback(FutureObj *fut, PyObject *arg, PyObject *ctx)
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900623{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500624 if (!future_is_alive(fut)) {
625 PyErr_SetString(PyExc_RuntimeError, "uninitialized Future object");
626 return NULL;
627 }
628
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900629 if (fut->fut_state != STATE_PENDING) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500630 /* The future is done/cancelled, so schedule the callback
631 right away. */
Yury Selivanovf23746a2018-01-22 19:11:18 -0500632 if (call_soon(fut->fut_loop, arg, (PyObject*) fut, ctx)) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900633 return NULL;
634 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900635 }
636 else {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500637 /* The future is pending, add a callback.
638
639 Callbacks in the future object are stored as follows:
640
641 callback0 -- a pointer to the first callback
642 callbacks -- a list of 2nd, 3rd, ... callbacks
643
644 Invariants:
645
646 * callbacks != NULL:
647 There are some callbacks in in the list. Just
648 add the new callback to it.
649
650 * callbacks == NULL and callback0 == NULL:
651 This is the first callback. Set it to callback0.
652
653 * callbacks == NULL and callback0 != NULL:
654 This is a second callback. Initialize callbacks
655 with a new list and add the new callback to it.
656 */
657
Yury Selivanovf23746a2018-01-22 19:11:18 -0500658 if (fut->fut_callbacks == NULL && fut->fut_callback0 == NULL) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500659 Py_INCREF(arg);
660 fut->fut_callback0 = arg;
Yury Selivanovf23746a2018-01-22 19:11:18 -0500661 Py_INCREF(ctx);
662 fut->fut_context0 = ctx;
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500663 }
664 else {
Yury Selivanovf23746a2018-01-22 19:11:18 -0500665 PyObject *tup = PyTuple_New(2);
666 if (tup == NULL) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500667 return NULL;
668 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500669 Py_INCREF(arg);
Yury Selivanovf23746a2018-01-22 19:11:18 -0500670 PyTuple_SET_ITEM(tup, 0, arg);
671 Py_INCREF(ctx);
672 PyTuple_SET_ITEM(tup, 1, (PyObject *)ctx);
673
674 if (fut->fut_callbacks != NULL) {
675 int err = PyList_Append(fut->fut_callbacks, tup);
676 if (err) {
677 Py_DECREF(tup);
678 return NULL;
679 }
680 Py_DECREF(tup);
681 }
682 else {
683 fut->fut_callbacks = PyList_New(1);
684 if (fut->fut_callbacks == NULL) {
685 return NULL;
686 }
687
688 PyList_SET_ITEM(fut->fut_callbacks, 0, tup); /* borrow */
689 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900690 }
691 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500692
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900693 Py_RETURN_NONE;
694}
695
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400696static PyObject *
697future_cancel(FutureObj *fut)
698{
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +0000699 fut->fut_log_tb = 0;
700
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400701 if (fut->fut_state != STATE_PENDING) {
702 Py_RETURN_FALSE;
703 }
704 fut->fut_state = STATE_CANCELLED;
705
Yury Selivanov22feeb82018-01-24 11:31:01 -0500706 if (future_schedule_callbacks(fut) == -1) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400707 return NULL;
708 }
709
710 Py_RETURN_TRUE;
711}
712
713/*[clinic input]
714_asyncio.Future.__init__
715
716 *
Serhiy Storchakabca49392017-09-03 08:10:14 +0300717 loop: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400718
719This class is *almost* compatible with concurrent.futures.Future.
720
721 Differences:
722
723 - result() and exception() do not take a timeout argument and
724 raise an exception when the future isn't done yet.
725
726 - Callbacks registered with add_done_callback() are always called
727 via the event loop's call_soon_threadsafe().
728
729 - This class is not compatible with the wait() and as_completed()
730 methods in the concurrent.futures package.
731[clinic start generated code]*/
732
733static int
734_asyncio_Future___init___impl(FutureObj *self, PyObject *loop)
Serhiy Storchakabca49392017-09-03 08:10:14 +0300735/*[clinic end generated code: output=9ed75799eaccb5d6 input=89af317082bc0bf8]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400736
737{
738 return future_init(self, loop);
739}
740
741static int
742FutureObj_clear(FutureObj *fut)
743{
744 Py_CLEAR(fut->fut_loop);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500745 Py_CLEAR(fut->fut_callback0);
Yury Selivanovf23746a2018-01-22 19:11:18 -0500746 Py_CLEAR(fut->fut_context0);
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400747 Py_CLEAR(fut->fut_callbacks);
748 Py_CLEAR(fut->fut_result);
749 Py_CLEAR(fut->fut_exception);
750 Py_CLEAR(fut->fut_source_tb);
751 Py_CLEAR(fut->dict);
752 return 0;
753}
754
755static int
756FutureObj_traverse(FutureObj *fut, visitproc visit, void *arg)
757{
758 Py_VISIT(fut->fut_loop);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500759 Py_VISIT(fut->fut_callback0);
Yury Selivanovf23746a2018-01-22 19:11:18 -0500760 Py_VISIT(fut->fut_context0);
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400761 Py_VISIT(fut->fut_callbacks);
762 Py_VISIT(fut->fut_result);
763 Py_VISIT(fut->fut_exception);
764 Py_VISIT(fut->fut_source_tb);
765 Py_VISIT(fut->dict);
766 return 0;
767}
768
769/*[clinic input]
770_asyncio.Future.result
771
772Return the result this future represents.
773
774If the future has been cancelled, raises CancelledError. If the
775future's result isn't yet available, raises InvalidStateError. If
776the future is done and has an exception set, this exception is raised.
777[clinic start generated code]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900778
779static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400780_asyncio_Future_result_impl(FutureObj *self)
781/*[clinic end generated code: output=f35f940936a4b1e5 input=49ecf9cf5ec50dc5]*/
782{
783 PyObject *result;
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500784
785 if (!future_is_alive(self)) {
786 PyErr_SetString(asyncio_InvalidStateError,
787 "Future object is not initialized.");
788 return NULL;
789 }
790
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400791 int res = future_get_result(self, &result);
792
793 if (res == -1) {
794 return NULL;
795 }
796
797 if (res == 0) {
798 return result;
799 }
800
801 assert(res == 1);
802
803 PyErr_SetObject(PyExceptionInstance_Class(result), result);
804 Py_DECREF(result);
805 return NULL;
806}
807
808/*[clinic input]
809_asyncio.Future.exception
810
811Return the exception that was set on this future.
812
813The exception (or None if no exception was set) is returned only if
814the future is done. If the future has been cancelled, raises
815CancelledError. If the future isn't done yet, raises
816InvalidStateError.
817[clinic start generated code]*/
818
819static PyObject *
820_asyncio_Future_exception_impl(FutureObj *self)
821/*[clinic end generated code: output=88b20d4f855e0710 input=733547a70c841c68]*/
822{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500823 if (!future_is_alive(self)) {
824 PyErr_SetString(asyncio_InvalidStateError,
825 "Future object is not initialized.");
826 return NULL;
827 }
828
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400829 if (self->fut_state == STATE_CANCELLED) {
Serhiy Storchakabca49392017-09-03 08:10:14 +0300830 PyErr_SetNone(asyncio_CancelledError);
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400831 return NULL;
832 }
833
834 if (self->fut_state != STATE_FINISHED) {
Serhiy Storchakabca49392017-09-03 08:10:14 +0300835 PyErr_SetString(asyncio_InvalidStateError, "Exception is not set.");
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400836 return NULL;
837 }
838
839 if (self->fut_exception != NULL) {
840 self->fut_log_tb = 0;
841 Py_INCREF(self->fut_exception);
842 return self->fut_exception;
843 }
844
845 Py_RETURN_NONE;
846}
847
848/*[clinic input]
849_asyncio.Future.set_result
850
Yury Selivanov0cf16f92017-12-25 10:48:15 -0500851 result: object
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400852 /
853
854Mark the future done and set its result.
855
856If the future is already done when this method is called, raises
857InvalidStateError.
858[clinic start generated code]*/
859
860static PyObject *
Yury Selivanov0cf16f92017-12-25 10:48:15 -0500861_asyncio_Future_set_result(FutureObj *self, PyObject *result)
862/*[clinic end generated code: output=1ec2e6bcccd6f2ce input=8b75172c2a7b05f1]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400863{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500864 ENSURE_FUTURE_ALIVE(self)
Yury Selivanov0cf16f92017-12-25 10:48:15 -0500865 return future_set_result(self, result);
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400866}
867
868/*[clinic input]
869_asyncio.Future.set_exception
870
Serhiy Storchakabca49392017-09-03 08:10:14 +0300871 exception: object
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400872 /
873
874Mark the future done and set an exception.
875
876If the future is already done when this method is called, raises
877InvalidStateError.
878[clinic start generated code]*/
879
880static PyObject *
881_asyncio_Future_set_exception(FutureObj *self, PyObject *exception)
Serhiy Storchakabca49392017-09-03 08:10:14 +0300882/*[clinic end generated code: output=f1c1b0cd321be360 input=e45b7d7aa71cc66d]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400883{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500884 ENSURE_FUTURE_ALIVE(self)
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400885 return future_set_exception(self, exception);
886}
887
888/*[clinic input]
889_asyncio.Future.add_done_callback
890
Serhiy Storchakabca49392017-09-03 08:10:14 +0300891 fn: object
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400892 /
Yury Selivanovf23746a2018-01-22 19:11:18 -0500893 *
894 context: object = NULL
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400895
896Add a callback to be run when the future becomes done.
897
898The callback is called with a single argument - the future object. If
899the future is already done when this is called, the callback is
900scheduled with call_soon.
901[clinic start generated code]*/
902
903static PyObject *
Yury Selivanovf23746a2018-01-22 19:11:18 -0500904_asyncio_Future_add_done_callback_impl(FutureObj *self, PyObject *fn,
905 PyObject *context)
906/*[clinic end generated code: output=7ce635bbc9554c1e input=15ab0693a96e9533]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400907{
Yury Selivanovf23746a2018-01-22 19:11:18 -0500908 if (context == NULL) {
Yury Selivanov994269c2018-09-27 14:55:55 -0400909 context = PyContext_CopyCurrent();
Yury Selivanovf23746a2018-01-22 19:11:18 -0500910 if (context == NULL) {
911 return NULL;
912 }
Yury Selivanov994269c2018-09-27 14:55:55 -0400913 PyObject *res = future_add_done_callback(self, fn, context);
Yury Selivanovf23746a2018-01-22 19:11:18 -0500914 Py_DECREF(context);
915 return res;
916 }
Yury Selivanov994269c2018-09-27 14:55:55 -0400917 return future_add_done_callback(self, fn, context);
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400918}
919
920/*[clinic input]
921_asyncio.Future.remove_done_callback
922
Serhiy Storchakabca49392017-09-03 08:10:14 +0300923 fn: object
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400924 /
925
926Remove all instances of a callback from the "call when done" list.
927
928Returns the number of callbacks removed.
929[clinic start generated code]*/
930
931static PyObject *
932_asyncio_Future_remove_done_callback(FutureObj *self, PyObject *fn)
Serhiy Storchakabca49392017-09-03 08:10:14 +0300933/*[clinic end generated code: output=5ab1fb52b24ef31f input=0a43280a149d505b]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900934{
935 PyObject *newlist;
936 Py_ssize_t len, i, j=0;
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500937 Py_ssize_t cleared_callback0 = 0;
938
939 ENSURE_FUTURE_ALIVE(self)
940
941 if (self->fut_callback0 != NULL) {
942 int cmp = PyObject_RichCompareBool(fn, self->fut_callback0, Py_EQ);
943 if (cmp == -1) {
944 return NULL;
945 }
946 if (cmp == 1) {
947 /* callback0 == fn */
948 Py_CLEAR(self->fut_callback0);
Yury Selivanovf23746a2018-01-22 19:11:18 -0500949 Py_CLEAR(self->fut_context0);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500950 cleared_callback0 = 1;
951 }
952 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900953
Serhiy Storchakabca49392017-09-03 08:10:14 +0300954 if (self->fut_callbacks == NULL) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500955 return PyLong_FromSsize_t(cleared_callback0);
Serhiy Storchakabca49392017-09-03 08:10:14 +0300956 }
957
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400958 len = PyList_GET_SIZE(self->fut_callbacks);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900959 if (len == 0) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500960 Py_CLEAR(self->fut_callbacks);
961 return PyLong_FromSsize_t(cleared_callback0);
962 }
963
964 if (len == 1) {
Yury Selivanovf23746a2018-01-22 19:11:18 -0500965 PyObject *cb_tup = PyList_GET_ITEM(self->fut_callbacks, 0);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500966 int cmp = PyObject_RichCompareBool(
Yury Selivanovf23746a2018-01-22 19:11:18 -0500967 fn, PyTuple_GET_ITEM(cb_tup, 0), Py_EQ);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500968 if (cmp == -1) {
969 return NULL;
970 }
971 if (cmp == 1) {
972 /* callbacks[0] == fn */
973 Py_CLEAR(self->fut_callbacks);
974 return PyLong_FromSsize_t(1 + cleared_callback0);
975 }
976 /* callbacks[0] != fn and len(callbacks) == 1 */
977 return PyLong_FromSsize_t(cleared_callback0);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900978 }
979
980 newlist = PyList_New(len);
981 if (newlist == NULL) {
982 return NULL;
983 }
984
Yury Selivanov84af9032017-03-02 23:46:56 -0500985 for (i = 0; i < PyList_GET_SIZE(self->fut_callbacks); i++) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900986 int ret;
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400987 PyObject *item = PyList_GET_ITEM(self->fut_callbacks, i);
Serhiy Storchakabca49392017-09-03 08:10:14 +0300988 Py_INCREF(item);
Yury Selivanovf23746a2018-01-22 19:11:18 -0500989 ret = PyObject_RichCompareBool(fn, PyTuple_GET_ITEM(item, 0), Py_EQ);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900990 if (ret == 0) {
Yury Selivanov833a3b02017-07-05 13:32:03 -0400991 if (j < len) {
Yury Selivanov833a3b02017-07-05 13:32:03 -0400992 PyList_SET_ITEM(newlist, j, item);
993 j++;
Serhiy Storchakabca49392017-09-03 08:10:14 +0300994 continue;
Yury Selivanov833a3b02017-07-05 13:32:03 -0400995 }
Serhiy Storchakabca49392017-09-03 08:10:14 +0300996 ret = PyList_Append(newlist, item);
997 }
998 Py_DECREF(item);
999 if (ret < 0) {
1000 goto fail;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001001 }
1002 }
1003
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001004 if (j == 0) {
1005 Py_CLEAR(self->fut_callbacks);
1006 Py_DECREF(newlist);
1007 return PyLong_FromSsize_t(len + cleared_callback0);
1008 }
1009
Serhiy Storchakabca49392017-09-03 08:10:14 +03001010 if (j < len) {
1011 Py_SIZE(newlist) = j;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001012 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03001013 j = PyList_GET_SIZE(newlist);
1014 len = PyList_GET_SIZE(self->fut_callbacks);
1015 if (j != len) {
1016 if (PyList_SetSlice(self->fut_callbacks, 0, len, newlist) < 0) {
1017 goto fail;
1018 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001019 }
1020 Py_DECREF(newlist);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001021 return PyLong_FromSsize_t(len - j + cleared_callback0);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001022
1023fail:
1024 Py_DECREF(newlist);
1025 return NULL;
1026}
1027
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001028/*[clinic input]
1029_asyncio.Future.cancel
1030
1031Cancel the future and schedule callbacks.
1032
1033If the future is already done or cancelled, return False. Otherwise,
1034change the future's state to cancelled, schedule the callbacks and
1035return True.
1036[clinic start generated code]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001037
1038static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001039_asyncio_Future_cancel_impl(FutureObj *self)
1040/*[clinic end generated code: output=e45b932ba8bd68a1 input=515709a127995109]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001041{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001042 ENSURE_FUTURE_ALIVE(self)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001043 return future_cancel(self);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001044}
1045
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001046/*[clinic input]
1047_asyncio.Future.cancelled
1048
1049Return True if the future was cancelled.
1050[clinic start generated code]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001051
1052static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001053_asyncio_Future_cancelled_impl(FutureObj *self)
1054/*[clinic end generated code: output=145197ced586357d input=943ab8b7b7b17e45]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001055{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001056 if (future_is_alive(self) && self->fut_state == STATE_CANCELLED) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001057 Py_RETURN_TRUE;
1058 }
1059 else {
1060 Py_RETURN_FALSE;
1061 }
1062}
1063
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001064/*[clinic input]
1065_asyncio.Future.done
1066
1067Return True if the future is done.
1068
1069Done means either that a result / exception are available, or that the
1070future was cancelled.
1071[clinic start generated code]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001072
1073static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001074_asyncio_Future_done_impl(FutureObj *self)
1075/*[clinic end generated code: output=244c5ac351145096 input=28d7b23fdb65d2ac]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001076{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001077 if (!future_is_alive(self) || self->fut_state == STATE_PENDING) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001078 Py_RETURN_FALSE;
1079 }
1080 else {
1081 Py_RETURN_TRUE;
1082 }
1083}
1084
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001085/*[clinic input]
1086_asyncio.Future.get_loop
1087
1088Return the event loop the Future is bound to.
1089[clinic start generated code]*/
1090
1091static PyObject *
1092_asyncio_Future_get_loop_impl(FutureObj *self)
1093/*[clinic end generated code: output=119b6ea0c9816c3f input=cba48c2136c79d1f]*/
1094{
1095 Py_INCREF(self->fut_loop);
1096 return self->fut_loop;
1097}
1098
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001099static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001100FutureObj_get_blocking(FutureObj *fut, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001101{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001102 if (future_is_alive(fut) && fut->fut_blocking) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001103 Py_RETURN_TRUE;
1104 }
1105 else {
1106 Py_RETURN_FALSE;
1107 }
1108}
1109
1110static int
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001111FutureObj_set_blocking(FutureObj *fut, PyObject *val, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001112{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001113 if (future_ensure_alive(fut)) {
1114 return -1;
1115 }
1116
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001117 int is_true = PyObject_IsTrue(val);
1118 if (is_true < 0) {
1119 return -1;
1120 }
1121 fut->fut_blocking = is_true;
1122 return 0;
1123}
1124
1125static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001126FutureObj_get_log_traceback(FutureObj *fut, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001127{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001128 ENSURE_FUTURE_ALIVE(fut)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001129 if (fut->fut_log_tb) {
1130 Py_RETURN_TRUE;
1131 }
1132 else {
1133 Py_RETURN_FALSE;
1134 }
1135}
1136
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +00001137static int
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001138FutureObj_set_log_traceback(FutureObj *fut, PyObject *val, void *Py_UNUSED(ignored))
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +00001139{
1140 int is_true = PyObject_IsTrue(val);
1141 if (is_true < 0) {
1142 return -1;
1143 }
Yury Selivanove0aef4f2017-12-25 16:16:10 -05001144 if (is_true) {
1145 PyErr_SetString(PyExc_ValueError,
1146 "_log_traceback can only be set to False");
1147 return -1;
1148 }
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +00001149 fut->fut_log_tb = is_true;
1150 return 0;
1151}
1152
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001153static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001154FutureObj_get_loop(FutureObj *fut, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001155{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001156 if (!future_is_alive(fut)) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001157 Py_RETURN_NONE;
1158 }
1159 Py_INCREF(fut->fut_loop);
1160 return fut->fut_loop;
1161}
1162
1163static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001164FutureObj_get_callbacks(FutureObj *fut, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001165{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001166 Py_ssize_t i;
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001167
1168 ENSURE_FUTURE_ALIVE(fut)
1169
Yury Selivanovf23746a2018-01-22 19:11:18 -05001170 if (fut->fut_callback0 == NULL) {
1171 if (fut->fut_callbacks == NULL) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001172 Py_RETURN_NONE;
1173 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001174
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001175 Py_INCREF(fut->fut_callbacks);
1176 return fut->fut_callbacks;
1177 }
1178
Yury Selivanovf23746a2018-01-22 19:11:18 -05001179 Py_ssize_t len = 1;
1180 if (fut->fut_callbacks != NULL) {
1181 len += PyList_GET_SIZE(fut->fut_callbacks);
1182 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001183
Yury Selivanovf23746a2018-01-22 19:11:18 -05001184
1185 PyObject *new_list = PyList_New(len);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001186 if (new_list == NULL) {
1187 return NULL;
1188 }
1189
Yury Selivanovf23746a2018-01-22 19:11:18 -05001190 PyObject *tup0 = PyTuple_New(2);
1191 if (tup0 == NULL) {
1192 Py_DECREF(new_list);
1193 return NULL;
1194 }
1195
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001196 Py_INCREF(fut->fut_callback0);
Yury Selivanovf23746a2018-01-22 19:11:18 -05001197 PyTuple_SET_ITEM(tup0, 0, fut->fut_callback0);
1198 assert(fut->fut_context0 != NULL);
1199 Py_INCREF(fut->fut_context0);
1200 PyTuple_SET_ITEM(tup0, 1, (PyObject *)fut->fut_context0);
1201
1202 PyList_SET_ITEM(new_list, 0, tup0);
1203
1204 if (fut->fut_callbacks != NULL) {
1205 for (i = 0; i < PyList_GET_SIZE(fut->fut_callbacks); i++) {
1206 PyObject *cb = PyList_GET_ITEM(fut->fut_callbacks, i);
1207 Py_INCREF(cb);
1208 PyList_SET_ITEM(new_list, i + 1, cb);
1209 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001210 }
1211
1212 return new_list;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001213}
1214
1215static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001216FutureObj_get_result(FutureObj *fut, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001217{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001218 ENSURE_FUTURE_ALIVE(fut)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001219 if (fut->fut_result == NULL) {
1220 Py_RETURN_NONE;
1221 }
1222 Py_INCREF(fut->fut_result);
1223 return fut->fut_result;
1224}
1225
1226static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001227FutureObj_get_exception(FutureObj *fut, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001228{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001229 ENSURE_FUTURE_ALIVE(fut)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001230 if (fut->fut_exception == NULL) {
1231 Py_RETURN_NONE;
1232 }
1233 Py_INCREF(fut->fut_exception);
1234 return fut->fut_exception;
1235}
1236
1237static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001238FutureObj_get_source_traceback(FutureObj *fut, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001239{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001240 if (!future_is_alive(fut) || fut->fut_source_tb == NULL) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001241 Py_RETURN_NONE;
1242 }
1243 Py_INCREF(fut->fut_source_tb);
1244 return fut->fut_source_tb;
1245}
1246
1247static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001248FutureObj_get_state(FutureObj *fut, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001249{
1250 _Py_IDENTIFIER(PENDING);
1251 _Py_IDENTIFIER(CANCELLED);
1252 _Py_IDENTIFIER(FINISHED);
1253 PyObject *ret = NULL;
1254
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001255 ENSURE_FUTURE_ALIVE(fut)
1256
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001257 switch (fut->fut_state) {
1258 case STATE_PENDING:
1259 ret = _PyUnicode_FromId(&PyId_PENDING);
1260 break;
1261 case STATE_CANCELLED:
1262 ret = _PyUnicode_FromId(&PyId_CANCELLED);
1263 break;
1264 case STATE_FINISHED:
1265 ret = _PyUnicode_FromId(&PyId_FINISHED);
1266 break;
1267 default:
1268 assert (0);
1269 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03001270 Py_XINCREF(ret);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001271 return ret;
1272}
1273
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001274/*[clinic input]
1275_asyncio.Future._repr_info
1276[clinic start generated code]*/
1277
1278static PyObject *
1279_asyncio_Future__repr_info_impl(FutureObj *self)
1280/*[clinic end generated code: output=fa69e901bd176cfb input=f21504d8e2ae1ca2]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001281{
Victor Stinnerde4ae3d2016-12-04 22:59:09 +01001282 return PyObject_CallFunctionObjArgs(
1283 asyncio_future_repr_info_func, self, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001284}
1285
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001286static PyObject *
1287FutureObj_repr(FutureObj *fut)
1288{
1289 _Py_IDENTIFIER(_repr_info);
1290
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001291 ENSURE_FUTURE_ALIVE(fut)
1292
Serhiy Storchakabca49392017-09-03 08:10:14 +03001293 PyObject *rinfo = _PyObject_CallMethodIdObjArgs((PyObject*)fut,
1294 &PyId__repr_info,
1295 NULL);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001296 if (rinfo == NULL) {
1297 return NULL;
1298 }
1299
Serhiy Storchakabca49392017-09-03 08:10:14 +03001300 PyObject *rinfo_s = PyUnicode_Join(NULL, rinfo);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001301 Py_DECREF(rinfo);
1302 if (rinfo_s == NULL) {
1303 return NULL;
1304 }
1305
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03001306 PyObject *rstr = PyUnicode_FromFormat("<%s %U>",
1307 _PyType_Name(Py_TYPE(fut)), rinfo_s);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001308 Py_DECREF(rinfo_s);
1309 return rstr;
1310}
1311
1312static void
1313FutureObj_finalize(FutureObj *fut)
1314{
1315 _Py_IDENTIFIER(call_exception_handler);
1316 _Py_IDENTIFIER(message);
1317 _Py_IDENTIFIER(exception);
1318 _Py_IDENTIFIER(future);
1319 _Py_IDENTIFIER(source_traceback);
1320
Serhiy Storchakabca49392017-09-03 08:10:14 +03001321 PyObject *error_type, *error_value, *error_traceback;
1322 PyObject *context;
Serhiy Storchakabca49392017-09-03 08:10:14 +03001323 PyObject *message = NULL;
1324 PyObject *func;
1325
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001326 if (!fut->fut_log_tb) {
1327 return;
1328 }
1329 assert(fut->fut_exception != NULL);
Serhiy Storchakabca49392017-09-03 08:10:14 +03001330 fut->fut_log_tb = 0;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001331
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001332 /* Save the current exception, if any. */
1333 PyErr_Fetch(&error_type, &error_value, &error_traceback);
1334
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001335 context = PyDict_New();
1336 if (context == NULL) {
1337 goto finally;
1338 }
1339
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001340 message = PyUnicode_FromFormat(
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03001341 "%s exception was never retrieved", _PyType_Name(Py_TYPE(fut)));
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001342 if (message == NULL) {
1343 goto finally;
1344 }
1345
1346 if (_PyDict_SetItemId(context, &PyId_message, message) < 0 ||
1347 _PyDict_SetItemId(context, &PyId_exception, fut->fut_exception) < 0 ||
1348 _PyDict_SetItemId(context, &PyId_future, (PyObject*)fut) < 0) {
1349 goto finally;
1350 }
1351 if (fut->fut_source_tb != NULL) {
1352 if (_PyDict_SetItemId(context, &PyId_source_traceback,
1353 fut->fut_source_tb) < 0) {
1354 goto finally;
1355 }
1356 }
1357
1358 func = _PyObject_GetAttrId(fut->fut_loop, &PyId_call_exception_handler);
1359 if (func != NULL) {
Serhiy Storchakabca49392017-09-03 08:10:14 +03001360 PyObject *res = PyObject_CallFunctionObjArgs(func, context, NULL);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001361 if (res == NULL) {
1362 PyErr_WriteUnraisable(func);
1363 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03001364 else {
1365 Py_DECREF(res);
1366 }
1367 Py_DECREF(func);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001368 }
1369
1370finally:
Serhiy Storchakabca49392017-09-03 08:10:14 +03001371 Py_XDECREF(context);
1372 Py_XDECREF(message);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001373
1374 /* Restore the saved exception. */
1375 PyErr_Restore(error_type, error_value, error_traceback);
1376}
1377
1378
1379static PyAsyncMethods FutureType_as_async = {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001380 (unaryfunc)future_new_iter, /* am_await */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001381 0, /* am_aiter */
1382 0 /* am_anext */
1383};
1384
1385static PyMethodDef FutureType_methods[] = {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001386 _ASYNCIO_FUTURE_RESULT_METHODDEF
1387 _ASYNCIO_FUTURE_EXCEPTION_METHODDEF
1388 _ASYNCIO_FUTURE_SET_RESULT_METHODDEF
1389 _ASYNCIO_FUTURE_SET_EXCEPTION_METHODDEF
1390 _ASYNCIO_FUTURE_ADD_DONE_CALLBACK_METHODDEF
1391 _ASYNCIO_FUTURE_REMOVE_DONE_CALLBACK_METHODDEF
1392 _ASYNCIO_FUTURE_CANCEL_METHODDEF
1393 _ASYNCIO_FUTURE_CANCELLED_METHODDEF
1394 _ASYNCIO_FUTURE_DONE_METHODDEF
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001395 _ASYNCIO_FUTURE_GET_LOOP_METHODDEF
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001396 _ASYNCIO_FUTURE__REPR_INFO_METHODDEF
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001397 {NULL, NULL} /* Sentinel */
1398};
1399
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001400#define FUTURE_COMMON_GETSETLIST \
1401 {"_state", (getter)FutureObj_get_state, NULL, NULL}, \
1402 {"_asyncio_future_blocking", (getter)FutureObj_get_blocking, \
1403 (setter)FutureObj_set_blocking, NULL}, \
1404 {"_loop", (getter)FutureObj_get_loop, NULL, NULL}, \
1405 {"_callbacks", (getter)FutureObj_get_callbacks, NULL, NULL}, \
1406 {"_result", (getter)FutureObj_get_result, NULL, NULL}, \
1407 {"_exception", (getter)FutureObj_get_exception, NULL, NULL}, \
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +00001408 {"_log_traceback", (getter)FutureObj_get_log_traceback, \
1409 (setter)FutureObj_set_log_traceback, NULL}, \
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001410 {"_source_traceback", (getter)FutureObj_get_source_traceback, NULL, NULL},
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001411
1412static PyGetSetDef FutureType_getsetlist[] = {
1413 FUTURE_COMMON_GETSETLIST
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001414 {NULL} /* Sentinel */
1415};
1416
1417static void FutureObj_dealloc(PyObject *self);
1418
1419static PyTypeObject FutureType = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02001420 PyVarObject_HEAD_INIT(NULL, 0)
INADA Naoki9f2ce252016-10-15 15:39:19 +09001421 "_asyncio.Future",
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001422 sizeof(FutureObj), /* tp_basicsize */
1423 .tp_dealloc = FutureObj_dealloc,
1424 .tp_as_async = &FutureType_as_async,
1425 .tp_repr = (reprfunc)FutureObj_repr,
1426 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE
1427 | Py_TPFLAGS_HAVE_FINALIZE,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001428 .tp_doc = _asyncio_Future___init____doc__,
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001429 .tp_traverse = (traverseproc)FutureObj_traverse,
1430 .tp_clear = (inquiry)FutureObj_clear,
1431 .tp_weaklistoffset = offsetof(FutureObj, fut_weakreflist),
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001432 .tp_iter = (getiterfunc)future_new_iter,
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001433 .tp_methods = FutureType_methods,
1434 .tp_getset = FutureType_getsetlist,
1435 .tp_dictoffset = offsetof(FutureObj, dict),
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001436 .tp_init = (initproc)_asyncio_Future___init__,
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001437 .tp_new = PyType_GenericNew,
1438 .tp_finalize = (destructor)FutureObj_finalize,
1439};
1440
1441static void
1442FutureObj_dealloc(PyObject *self)
1443{
1444 FutureObj *fut = (FutureObj *)self;
1445
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001446 if (Future_CheckExact(fut)) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001447 /* When fut is subclass of Future, finalizer is called from
1448 * subtype_dealloc.
1449 */
1450 if (PyObject_CallFinalizerFromDealloc(self) < 0) {
1451 // resurrected.
1452 return;
1453 }
1454 }
1455
Alexander Mohrde34cbe2017-08-01 23:31:07 -07001456 PyObject_GC_UnTrack(self);
1457
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001458 if (fut->fut_weakreflist != NULL) {
1459 PyObject_ClearWeakRefs(self);
1460 }
1461
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001462 (void)FutureObj_clear(fut);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001463 Py_TYPE(fut)->tp_free(fut);
1464}
1465
1466
1467/*********************** Future Iterator **************************/
1468
1469typedef struct {
1470 PyObject_HEAD
1471 FutureObj *future;
1472} futureiterobject;
1473
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001474
1475#define FI_FREELIST_MAXLEN 255
1476static futureiterobject *fi_freelist = NULL;
1477static Py_ssize_t fi_freelist_len = 0;
1478
1479
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001480static void
1481FutureIter_dealloc(futureiterobject *it)
1482{
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001483 PyObject_GC_UnTrack(it);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001484 Py_CLEAR(it->future);
1485
1486 if (fi_freelist_len < FI_FREELIST_MAXLEN) {
1487 fi_freelist_len++;
1488 it->future = (FutureObj*) fi_freelist;
1489 fi_freelist = it;
1490 }
1491 else {
1492 PyObject_GC_Del(it);
1493 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001494}
1495
1496static PyObject *
1497FutureIter_iternext(futureiterobject *it)
1498{
1499 PyObject *res;
1500 FutureObj *fut = it->future;
1501
1502 if (fut == NULL) {
1503 return NULL;
1504 }
1505
1506 if (fut->fut_state == STATE_PENDING) {
1507 if (!fut->fut_blocking) {
1508 fut->fut_blocking = 1;
1509 Py_INCREF(fut);
1510 return (PyObject *)fut;
1511 }
Yury Selivanov0cf16f92017-12-25 10:48:15 -05001512 PyErr_SetString(PyExc_RuntimeError,
1513 "await wasn't used with future");
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001514 return NULL;
1515 }
1516
Serhiy Storchakabca49392017-09-03 08:10:14 +03001517 it->future = NULL;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001518 res = _asyncio_Future_result_impl(fut);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001519 if (res != NULL) {
Serhiy Storchaka60e49aa2016-11-06 18:47:03 +02001520 /* The result of the Future is not an exception. */
Serhiy Storchakabca49392017-09-03 08:10:14 +03001521 (void)_PyGen_SetStopIterationValue(res);
Serhiy Storchaka60e49aa2016-11-06 18:47:03 +02001522 Py_DECREF(res);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001523 }
1524
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001525 Py_DECREF(fut);
1526 return NULL;
1527}
1528
1529static PyObject *
INADA Naoki74c17532016-10-25 19:00:45 +09001530FutureIter_send(futureiterobject *self, PyObject *unused)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001531{
INADA Naoki74c17532016-10-25 19:00:45 +09001532 /* Future.__iter__ doesn't care about values that are pushed to the
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03001533 * generator, it just returns self.result().
INADA Naoki74c17532016-10-25 19:00:45 +09001534 */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001535 return FutureIter_iternext(self);
1536}
1537
1538static PyObject *
1539FutureIter_throw(futureiterobject *self, PyObject *args)
1540{
Serhiy Storchakabca49392017-09-03 08:10:14 +03001541 PyObject *type, *val = NULL, *tb = NULL;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001542 if (!PyArg_ParseTuple(args, "O|OO", &type, &val, &tb))
1543 return NULL;
1544
1545 if (val == Py_None) {
1546 val = NULL;
1547 }
1548 if (tb == Py_None) {
1549 tb = NULL;
Benjamin Peterson996fc1f2016-11-14 00:15:44 -08001550 } else if (tb != NULL && !PyTraceBack_Check(tb)) {
1551 PyErr_SetString(PyExc_TypeError, "throw() third argument must be a traceback");
1552 return NULL;
1553 }
1554
1555 Py_INCREF(type);
1556 Py_XINCREF(val);
1557 Py_XINCREF(tb);
1558
1559 if (PyExceptionClass_Check(type)) {
1560 PyErr_NormalizeException(&type, &val, &tb);
Yury Selivanovedfe8862016-12-01 11:37:47 -05001561 /* No need to call PyException_SetTraceback since we'll be calling
1562 PyErr_Restore for `type`, `val`, and `tb`. */
Benjamin Peterson996fc1f2016-11-14 00:15:44 -08001563 } else if (PyExceptionInstance_Check(type)) {
1564 if (val) {
1565 PyErr_SetString(PyExc_TypeError,
1566 "instance exception may not have a separate value");
1567 goto fail;
1568 }
1569 val = type;
1570 type = PyExceptionInstance_Class(type);
1571 Py_INCREF(type);
1572 if (tb == NULL)
1573 tb = PyException_GetTraceback(val);
1574 } else {
1575 PyErr_SetString(PyExc_TypeError,
1576 "exceptions must be classes deriving BaseException or "
1577 "instances of such a class");
1578 goto fail;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001579 }
1580
1581 Py_CLEAR(self->future);
1582
Benjamin Peterson996fc1f2016-11-14 00:15:44 -08001583 PyErr_Restore(type, val, tb);
1584
Serhiy Storchakabca49392017-09-03 08:10:14 +03001585 return NULL;
Benjamin Peterson996fc1f2016-11-14 00:15:44 -08001586
1587 fail:
1588 Py_DECREF(type);
1589 Py_XDECREF(val);
1590 Py_XDECREF(tb);
1591 return NULL;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001592}
1593
1594static PyObject *
1595FutureIter_close(futureiterobject *self, PyObject *arg)
1596{
1597 Py_CLEAR(self->future);
1598 Py_RETURN_NONE;
1599}
1600
1601static int
1602FutureIter_traverse(futureiterobject *it, visitproc visit, void *arg)
1603{
1604 Py_VISIT(it->future);
1605 return 0;
1606}
1607
1608static PyMethodDef FutureIter_methods[] = {
1609 {"send", (PyCFunction)FutureIter_send, METH_O, NULL},
1610 {"throw", (PyCFunction)FutureIter_throw, METH_VARARGS, NULL},
1611 {"close", (PyCFunction)FutureIter_close, METH_NOARGS, NULL},
1612 {NULL, NULL} /* Sentinel */
1613};
1614
1615static PyTypeObject FutureIterType = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02001616 PyVarObject_HEAD_INIT(NULL, 0)
INADA Naoki9f2ce252016-10-15 15:39:19 +09001617 "_asyncio.FutureIter",
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001618 .tp_basicsize = sizeof(futureiterobject),
1619 .tp_itemsize = 0,
1620 .tp_dealloc = (destructor)FutureIter_dealloc,
1621 .tp_getattro = PyObject_GenericGetAttr,
1622 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
1623 .tp_traverse = (traverseproc)FutureIter_traverse,
1624 .tp_iter = PyObject_SelfIter,
1625 .tp_iternext = (iternextfunc)FutureIter_iternext,
1626 .tp_methods = FutureIter_methods,
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001627};
1628
1629static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001630future_new_iter(PyObject *fut)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001631{
1632 futureiterobject *it;
1633
1634 if (!PyObject_TypeCheck(fut, &FutureType)) {
1635 PyErr_BadInternalCall();
1636 return NULL;
1637 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001638
1639 ENSURE_FUTURE_ALIVE(fut)
1640
1641 if (fi_freelist_len) {
1642 fi_freelist_len--;
1643 it = fi_freelist;
1644 fi_freelist = (futureiterobject*) it->future;
1645 it->future = NULL;
1646 _Py_NewReference((PyObject*) it);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001647 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001648 else {
1649 it = PyObject_GC_New(futureiterobject, &FutureIterType);
1650 if (it == NULL) {
1651 return NULL;
1652 }
1653 }
1654
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001655 Py_INCREF(fut);
1656 it->future = (FutureObj*)fut;
INADA Naoki1be427b2016-10-11 02:12:34 +09001657 PyObject_GC_Track(it);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001658 return (PyObject*)it;
1659}
1660
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001661
1662/*********************** Task **************************/
1663
1664
1665/*[clinic input]
1666class _asyncio.Task "TaskObj *" "&Task_Type"
1667[clinic start generated code]*/
1668/*[clinic end generated code: output=da39a3ee5e6b4b0d input=719dcef0fcc03b37]*/
1669
1670static int task_call_step_soon(TaskObj *, PyObject *);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001671static PyObject * task_wakeup(TaskObj *, PyObject *);
1672static PyObject * task_step(TaskObj *, PyObject *);
1673
1674/* ----- Task._step wrapper */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001675
INADA Naokic411a7d2016-10-18 11:48:14 +09001676static int
Serhiy Storchakabca49392017-09-03 08:10:14 +03001677TaskStepMethWrapper_clear(TaskStepMethWrapper *o)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001678{
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001679 Py_CLEAR(o->sw_task);
1680 Py_CLEAR(o->sw_arg);
1681 return 0;
1682}
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001683
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001684static void
Serhiy Storchakabca49392017-09-03 08:10:14 +03001685TaskStepMethWrapper_dealloc(TaskStepMethWrapper *o)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001686{
1687 PyObject_GC_UnTrack(o);
Serhiy Storchakabca49392017-09-03 08:10:14 +03001688 (void)TaskStepMethWrapper_clear(o);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001689 Py_TYPE(o)->tp_free(o);
1690}
1691
1692static PyObject *
Serhiy Storchakabca49392017-09-03 08:10:14 +03001693TaskStepMethWrapper_call(TaskStepMethWrapper *o,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001694 PyObject *args, PyObject *kwds)
1695{
Serhiy Storchakabca49392017-09-03 08:10:14 +03001696 if (kwds != NULL && PyDict_GET_SIZE(kwds) != 0) {
1697 PyErr_SetString(PyExc_TypeError, "function takes no keyword arguments");
1698 return NULL;
1699 }
1700 if (args != NULL && PyTuple_GET_SIZE(args) != 0) {
1701 PyErr_SetString(PyExc_TypeError, "function takes no positional arguments");
1702 return NULL;
1703 }
Yury Selivanov22feeb82018-01-24 11:31:01 -05001704 return task_step(o->sw_task, o->sw_arg);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001705}
1706
1707static int
Serhiy Storchakabca49392017-09-03 08:10:14 +03001708TaskStepMethWrapper_traverse(TaskStepMethWrapper *o,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001709 visitproc visit, void *arg)
1710{
1711 Py_VISIT(o->sw_task);
1712 Py_VISIT(o->sw_arg);
1713 return 0;
1714}
1715
1716static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001717TaskStepMethWrapper_get___self__(TaskStepMethWrapper *o, void *Py_UNUSED(ignored))
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001718{
1719 if (o->sw_task) {
1720 Py_INCREF(o->sw_task);
1721 return (PyObject*)o->sw_task;
1722 }
1723 Py_RETURN_NONE;
1724}
1725
Serhiy Storchakabca49392017-09-03 08:10:14 +03001726static PyGetSetDef TaskStepMethWrapper_getsetlist[] = {
1727 {"__self__", (getter)TaskStepMethWrapper_get___self__, NULL, NULL},
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001728 {NULL} /* Sentinel */
1729};
1730
Benjamin Peterson3c8aae92018-07-05 22:39:34 -07001731static PyTypeObject TaskStepMethWrapper_Type = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02001732 PyVarObject_HEAD_INIT(NULL, 0)
Serhiy Storchakabca49392017-09-03 08:10:14 +03001733 "TaskStepMethWrapper",
1734 .tp_basicsize = sizeof(TaskStepMethWrapper),
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001735 .tp_itemsize = 0,
Serhiy Storchakabca49392017-09-03 08:10:14 +03001736 .tp_getset = TaskStepMethWrapper_getsetlist,
1737 .tp_dealloc = (destructor)TaskStepMethWrapper_dealloc,
1738 .tp_call = (ternaryfunc)TaskStepMethWrapper_call,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001739 .tp_getattro = PyObject_GenericGetAttr,
1740 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
Serhiy Storchakabca49392017-09-03 08:10:14 +03001741 .tp_traverse = (traverseproc)TaskStepMethWrapper_traverse,
1742 .tp_clear = (inquiry)TaskStepMethWrapper_clear,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001743};
1744
1745static PyObject *
Serhiy Storchakabca49392017-09-03 08:10:14 +03001746TaskStepMethWrapper_new(TaskObj *task, PyObject *arg)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001747{
Serhiy Storchakabca49392017-09-03 08:10:14 +03001748 TaskStepMethWrapper *o;
1749 o = PyObject_GC_New(TaskStepMethWrapper, &TaskStepMethWrapper_Type);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001750 if (o == NULL) {
1751 return NULL;
1752 }
1753
1754 Py_INCREF(task);
1755 o->sw_task = task;
1756
1757 Py_XINCREF(arg);
1758 o->sw_arg = arg;
1759
1760 PyObject_GC_Track(o);
1761 return (PyObject*) o;
1762}
1763
1764/* ----- Task._wakeup wrapper */
1765
1766static PyObject *
1767TaskWakeupMethWrapper_call(TaskWakeupMethWrapper *o,
1768 PyObject *args, PyObject *kwds)
1769{
1770 PyObject *fut;
1771
Serhiy Storchakabca49392017-09-03 08:10:14 +03001772 if (kwds != NULL && PyDict_GET_SIZE(kwds) != 0) {
1773 PyErr_SetString(PyExc_TypeError, "function takes no keyword arguments");
1774 return NULL;
1775 }
1776 if (!PyArg_ParseTuple(args, "O", &fut)) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001777 return NULL;
1778 }
1779
Yury Selivanov22feeb82018-01-24 11:31:01 -05001780 return task_wakeup(o->ww_task, fut);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001781}
1782
1783static int
1784TaskWakeupMethWrapper_clear(TaskWakeupMethWrapper *o)
1785{
1786 Py_CLEAR(o->ww_task);
1787 return 0;
1788}
1789
1790static int
1791TaskWakeupMethWrapper_traverse(TaskWakeupMethWrapper *o,
1792 visitproc visit, void *arg)
1793{
1794 Py_VISIT(o->ww_task);
1795 return 0;
1796}
1797
1798static void
1799TaskWakeupMethWrapper_dealloc(TaskWakeupMethWrapper *o)
1800{
1801 PyObject_GC_UnTrack(o);
1802 (void)TaskWakeupMethWrapper_clear(o);
1803 Py_TYPE(o)->tp_free(o);
1804}
1805
Benjamin Peterson3c8aae92018-07-05 22:39:34 -07001806static PyTypeObject TaskWakeupMethWrapper_Type = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02001807 PyVarObject_HEAD_INIT(NULL, 0)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001808 "TaskWakeupMethWrapper",
1809 .tp_basicsize = sizeof(TaskWakeupMethWrapper),
1810 .tp_itemsize = 0,
1811 .tp_dealloc = (destructor)TaskWakeupMethWrapper_dealloc,
1812 .tp_call = (ternaryfunc)TaskWakeupMethWrapper_call,
1813 .tp_getattro = PyObject_GenericGetAttr,
1814 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
1815 .tp_traverse = (traverseproc)TaskWakeupMethWrapper_traverse,
1816 .tp_clear = (inquiry)TaskWakeupMethWrapper_clear,
1817};
1818
1819static PyObject *
1820TaskWakeupMethWrapper_new(TaskObj *task)
1821{
1822 TaskWakeupMethWrapper *o;
1823 o = PyObject_GC_New(TaskWakeupMethWrapper, &TaskWakeupMethWrapper_Type);
1824 if (o == NULL) {
1825 return NULL;
1826 }
1827
1828 Py_INCREF(task);
1829 o->ww_task = task;
1830
1831 PyObject_GC_Track(o);
1832 return (PyObject*) o;
1833}
1834
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001835/* ----- Task introspection helpers */
1836
1837static int
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001838register_task(PyObject *task)
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001839{
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001840 _Py_IDENTIFIER(add);
1841
1842 PyObject *res = _PyObject_CallMethodIdObjArgs(
1843 all_tasks, &PyId_add, task, NULL);
1844 if (res == NULL) {
1845 return -1;
1846 }
1847 Py_DECREF(res);
1848 return 0;
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001849}
1850
1851
1852static int
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001853unregister_task(PyObject *task)
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001854{
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001855 _Py_IDENTIFIER(discard);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001856
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001857 PyObject *res = _PyObject_CallMethodIdObjArgs(
1858 all_tasks, &PyId_discard, task, NULL);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001859 if (res == NULL) {
1860 return -1;
1861 }
1862 Py_DECREF(res);
1863 return 0;
1864}
1865
1866
1867static int
1868enter_task(PyObject *loop, PyObject *task)
1869{
1870 PyObject *item;
1871 Py_hash_t hash;
1872 hash = PyObject_Hash(loop);
1873 if (hash == -1) {
1874 return -1;
1875 }
1876 item = _PyDict_GetItem_KnownHash(current_tasks, loop, hash);
1877 if (item != NULL) {
Serhiy Storchaka66553542018-05-20 16:30:31 +03001878 Py_INCREF(item);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001879 PyErr_Format(
1880 PyExc_RuntimeError,
1881 "Cannot enter into task %R while another " \
1882 "task %R is being executed.",
1883 task, item, NULL);
Serhiy Storchaka66553542018-05-20 16:30:31 +03001884 Py_DECREF(item);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001885 return -1;
1886 }
Serhiy Storchaka66553542018-05-20 16:30:31 +03001887 if (PyErr_Occurred()) {
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001888 return -1;
1889 }
Serhiy Storchaka66553542018-05-20 16:30:31 +03001890 return _PyDict_SetItem_KnownHash(current_tasks, loop, task, hash);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001891}
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
Alex Grönholmcca4eec2018-08-09 00:06:47 +03001927 name: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001928
1929A coroutine wrapped in a Future.
1930[clinic start generated code]*/
1931
1932static int
Alex Grönholmcca4eec2018-08-09 00:06:47 +03001933_asyncio_Task___init___impl(TaskObj *self, PyObject *coro, PyObject *loop,
1934 PyObject *name)
1935/*[clinic end generated code: output=88b12b83d570df50 input=352a3137fe60091d]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001936{
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001937 if (future_init((FutureObj*)self, loop)) {
INADA Naokic411a7d2016-10-18 11:48:14 +09001938 return -1;
1939 }
INADA Naokic411a7d2016-10-18 11:48:14 +09001940
Yury Selivanova9d7e552017-12-19 07:18:45 -05001941 int is_coro = is_coroutine(coro);
1942 if (is_coro == -1) {
1943 return -1;
1944 }
1945 if (is_coro == 0) {
1946 self->task_log_destroy_pending = 0;
1947 PyErr_Format(PyExc_TypeError,
1948 "a coroutine was expected, got %R",
1949 coro, NULL);
1950 return -1;
Andrew Svetlovf74ef452017-12-15 07:04:38 +02001951 }
1952
Oren Milmand019bc82018-02-13 12:28:33 +02001953 Py_XSETREF(self->task_context, PyContext_CopyCurrent());
Yury Selivanovf23746a2018-01-22 19:11:18 -05001954 if (self->task_context == NULL) {
1955 return -1;
1956 }
1957
Oren Milmand019bc82018-02-13 12:28:33 +02001958 Py_CLEAR(self->task_fut_waiter);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001959 self->task_must_cancel = 0;
1960 self->task_log_destroy_pending = 1;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001961 Py_INCREF(coro);
Oren Milmand019bc82018-02-13 12:28:33 +02001962 Py_XSETREF(self->task_coro, coro);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001963
Alex Grönholmcca4eec2018-08-09 00:06:47 +03001964 if (name == Py_None) {
1965 name = PyUnicode_FromFormat("Task-%" PRIu64, ++task_name_counter);
Alex Grönholma7548232018-08-09 23:49:49 +03001966 } else if (!PyUnicode_CheckExact(name)) {
Alex Grönholmcca4eec2018-08-09 00:06:47 +03001967 name = PyObject_Str(name);
1968 } else {
1969 Py_INCREF(name);
1970 }
1971 Py_XSETREF(self->task_name, name);
1972 if (self->task_name == NULL) {
1973 return -1;
1974 }
1975
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001976 if (task_call_step_soon(self, NULL)) {
1977 return -1;
INADA Naokic411a7d2016-10-18 11:48:14 +09001978 }
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001979 return register_task((PyObject*)self);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001980}
1981
1982static int
1983TaskObj_clear(TaskObj *task)
1984{
1985 (void)FutureObj_clear((FutureObj*) task);
Yury Selivanovf23746a2018-01-22 19:11:18 -05001986 Py_CLEAR(task->task_context);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001987 Py_CLEAR(task->task_coro);
Alex Grönholmcca4eec2018-08-09 00:06:47 +03001988 Py_CLEAR(task->task_name);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001989 Py_CLEAR(task->task_fut_waiter);
1990 return 0;
1991}
1992
1993static int
1994TaskObj_traverse(TaskObj *task, visitproc visit, void *arg)
1995{
Yury Selivanovf23746a2018-01-22 19:11:18 -05001996 Py_VISIT(task->task_context);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001997 Py_VISIT(task->task_coro);
Alex Grönholmcca4eec2018-08-09 00:06:47 +03001998 Py_VISIT(task->task_name);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001999 Py_VISIT(task->task_fut_waiter);
2000 (void)FutureObj_traverse((FutureObj*) task, visit, arg);
2001 return 0;
2002}
2003
2004static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02002005TaskObj_get_log_destroy_pending(TaskObj *task, void *Py_UNUSED(ignored))
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002006{
2007 if (task->task_log_destroy_pending) {
2008 Py_RETURN_TRUE;
2009 }
2010 else {
2011 Py_RETURN_FALSE;
2012 }
2013}
2014
2015static int
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02002016TaskObj_set_log_destroy_pending(TaskObj *task, PyObject *val, void *Py_UNUSED(ignored))
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002017{
2018 int is_true = PyObject_IsTrue(val);
2019 if (is_true < 0) {
2020 return -1;
2021 }
2022 task->task_log_destroy_pending = is_true;
2023 return 0;
2024}
2025
2026static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02002027TaskObj_get_must_cancel(TaskObj *task, void *Py_UNUSED(ignored))
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002028{
2029 if (task->task_must_cancel) {
2030 Py_RETURN_TRUE;
2031 }
2032 else {
2033 Py_RETURN_FALSE;
2034 }
2035}
2036
2037static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02002038TaskObj_get_coro(TaskObj *task, void *Py_UNUSED(ignored))
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002039{
2040 if (task->task_coro) {
2041 Py_INCREF(task->task_coro);
2042 return task->task_coro;
2043 }
2044
2045 Py_RETURN_NONE;
2046}
2047
2048static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02002049TaskObj_get_fut_waiter(TaskObj *task, void *Py_UNUSED(ignored))
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002050{
2051 if (task->task_fut_waiter) {
2052 Py_INCREF(task->task_fut_waiter);
2053 return task->task_fut_waiter;
2054 }
2055
2056 Py_RETURN_NONE;
2057}
2058
2059/*[clinic input]
2060@classmethod
2061_asyncio.Task.current_task
2062
Serhiy Storchakabca49392017-09-03 08:10:14 +03002063 loop: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002064
2065Return the currently running task in an event loop or None.
2066
2067By default the current task for the current event loop is returned.
2068
2069None is returned when called not in the context of a Task.
2070[clinic start generated code]*/
2071
2072static PyObject *
2073_asyncio_Task_current_task_impl(PyTypeObject *type, PyObject *loop)
Serhiy Storchakabca49392017-09-03 08:10:14 +03002074/*[clinic end generated code: output=99fbe7332c516e03 input=cd14770c5b79c7eb]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002075{
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002076 PyObject *ret;
2077 PyObject *current_task_func;
2078
2079 if (PyErr_WarnEx(PyExc_PendingDeprecationWarning,
2080 "Task.current_task() is deprecated, " \
2081 "use asyncio.current_task() instead",
2082 1) < 0) {
2083 return NULL;
2084 }
2085
2086 current_task_func = _PyObject_GetAttrId(asyncio_mod, &PyId_current_task);
2087 if (current_task_func == NULL) {
2088 return NULL;
2089 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002090
Yury Selivanov8d26aa92017-03-02 22:16:33 -05002091 if (loop == Py_None) {
Yury Selivanova70232f2017-12-13 14:49:42 -05002092 loop = get_event_loop();
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002093 if (loop == NULL) {
Serhiy Storchaka66553542018-05-20 16:30:31 +03002094 Py_DECREF(current_task_func);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002095 return NULL;
2096 }
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002097 ret = PyObject_CallFunctionObjArgs(current_task_func, loop, NULL);
2098 Py_DECREF(current_task_func);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002099 Py_DECREF(loop);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002100 return ret;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002101 }
2102 else {
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002103 ret = PyObject_CallFunctionObjArgs(current_task_func, loop, NULL);
2104 Py_DECREF(current_task_func);
2105 return ret;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002106 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002107}
2108
2109/*[clinic input]
2110@classmethod
2111_asyncio.Task.all_tasks
2112
Serhiy Storchakabca49392017-09-03 08:10:14 +03002113 loop: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002114
2115Return a set of all tasks for an event loop.
2116
2117By default all tasks for the current event loop are returned.
2118[clinic start generated code]*/
2119
2120static PyObject *
2121_asyncio_Task_all_tasks_impl(PyTypeObject *type, PyObject *loop)
Serhiy Storchakabca49392017-09-03 08:10:14 +03002122/*[clinic end generated code: output=11f9b20749ccca5d input=497f80bc9ce726b5]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002123{
2124 PyObject *res;
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002125 PyObject *all_tasks_func;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002126
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002127 if (PyErr_WarnEx(PyExc_PendingDeprecationWarning,
2128 "Task.all_tasks() is deprecated, " \
2129 "use asyncio.all_tasks() instead",
2130 1) < 0) {
2131 return NULL;
2132 }
2133
Yury Selivanov416c1eb2018-05-28 17:54:02 -04002134 all_tasks_func = _PyObject_GetAttrId(asyncio_mod, &PyId__all_tasks_compat);
Serhiy Storchaka66553542018-05-20 16:30:31 +03002135 if (all_tasks_func == NULL) {
2136 return NULL;
2137 }
2138
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002139 res = PyObject_CallFunctionObjArgs(all_tasks_func, loop, NULL);
2140 Py_DECREF(all_tasks_func);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002141 return res;
2142}
2143
2144/*[clinic input]
2145_asyncio.Task._repr_info
2146[clinic start generated code]*/
2147
2148static PyObject *
2149_asyncio_Task__repr_info_impl(TaskObj *self)
2150/*[clinic end generated code: output=6a490eb66d5ba34b input=3c6d051ed3ddec8b]*/
2151{
Victor Stinnerde4ae3d2016-12-04 22:59:09 +01002152 return PyObject_CallFunctionObjArgs(
2153 asyncio_task_repr_info_func, self, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002154}
2155
2156/*[clinic input]
2157_asyncio.Task.cancel
2158
2159Request that this task cancel itself.
2160
2161This arranges for a CancelledError to be thrown into the
2162wrapped coroutine on the next cycle through the event loop.
2163The coroutine then has a chance to clean up or even deny
2164the request using try/except/finally.
2165
2166Unlike Future.cancel, this does not guarantee that the
2167task will be cancelled: the exception might be caught and
2168acted upon, delaying cancellation of the task or preventing
2169cancellation completely. The task may also return a value or
2170raise a different exception.
2171
2172Immediately after this method is called, Task.cancelled() will
2173not return True (unless the task was already cancelled). A
2174task will be marked as cancelled when the wrapped coroutine
2175terminates with a CancelledError exception (even if cancel()
2176was not called).
2177[clinic start generated code]*/
2178
2179static PyObject *
2180_asyncio_Task_cancel_impl(TaskObj *self)
2181/*[clinic end generated code: output=6bfc0479da9d5757 input=13f9bf496695cb52]*/
2182{
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +00002183 self->task_log_tb = 0;
2184
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002185 if (self->task_state != STATE_PENDING) {
2186 Py_RETURN_FALSE;
2187 }
2188
2189 if (self->task_fut_waiter) {
2190 PyObject *res;
2191 int is_true;
2192
2193 res = _PyObject_CallMethodId(
2194 self->task_fut_waiter, &PyId_cancel, NULL);
2195 if (res == NULL) {
2196 return NULL;
2197 }
2198
2199 is_true = PyObject_IsTrue(res);
2200 Py_DECREF(res);
2201 if (is_true < 0) {
2202 return NULL;
2203 }
2204
2205 if (is_true) {
2206 Py_RETURN_TRUE;
2207 }
2208 }
2209
2210 self->task_must_cancel = 1;
2211 Py_RETURN_TRUE;
2212}
2213
2214/*[clinic input]
2215_asyncio.Task.get_stack
2216
2217 *
Serhiy Storchakabca49392017-09-03 08:10:14 +03002218 limit: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002219
2220Return the list of stack frames for this task's coroutine.
2221
2222If the coroutine is not done, this returns the stack where it is
2223suspended. If the coroutine has completed successfully or was
2224cancelled, this returns an empty list. If the coroutine was
2225terminated by an exception, this returns the list of traceback
2226frames.
2227
2228The frames are always ordered from oldest to newest.
2229
2230The optional limit gives the maximum number of frames to
2231return; by default all available frames are returned. Its
2232meaning differs depending on whether a stack or a traceback is
2233returned: the newest frames of a stack are returned, but the
2234oldest frames of a traceback are returned. (This matches the
2235behavior of the traceback module.)
2236
2237For reasons beyond our control, only one stack frame is
2238returned for a suspended coroutine.
2239[clinic start generated code]*/
2240
2241static PyObject *
2242_asyncio_Task_get_stack_impl(TaskObj *self, PyObject *limit)
Serhiy Storchakabca49392017-09-03 08:10:14 +03002243/*[clinic end generated code: output=c9aeeeebd1e18118 input=05b323d42b809b90]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002244{
2245 return PyObject_CallFunctionObjArgs(
2246 asyncio_task_get_stack_func, self, limit, NULL);
2247}
2248
2249/*[clinic input]
2250_asyncio.Task.print_stack
2251
2252 *
Serhiy Storchakabca49392017-09-03 08:10:14 +03002253 limit: object = None
2254 file: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002255
2256Print the stack or traceback for this task's coroutine.
2257
2258This produces output similar to that of the traceback module,
2259for the frames retrieved by get_stack(). The limit argument
2260is passed to get_stack(). The file argument is an I/O stream
2261to which the output is written; by default output is written
2262to sys.stderr.
2263[clinic start generated code]*/
2264
2265static PyObject *
2266_asyncio_Task_print_stack_impl(TaskObj *self, PyObject *limit,
2267 PyObject *file)
Serhiy Storchakabca49392017-09-03 08:10:14 +03002268/*[clinic end generated code: output=7339e10314cd3f4d input=1a0352913b7fcd92]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002269{
2270 return PyObject_CallFunctionObjArgs(
2271 asyncio_task_print_stack_func, self, limit, file, NULL);
2272}
2273
2274/*[clinic input]
Yury Selivanov0cf16f92017-12-25 10:48:15 -05002275_asyncio.Task.set_result
2276
2277 result: object
2278 /
2279[clinic start generated code]*/
2280
2281static PyObject *
2282_asyncio_Task_set_result(TaskObj *self, PyObject *result)
2283/*[clinic end generated code: output=1dcae308bfcba318 input=9d1a00c07be41bab]*/
2284{
2285 PyErr_SetString(PyExc_RuntimeError,
2286 "Task does not support set_result operation");
2287 return NULL;
2288}
2289
2290/*[clinic input]
2291_asyncio.Task.set_exception
2292
2293 exception: object
2294 /
2295[clinic start generated code]*/
2296
2297static PyObject *
2298_asyncio_Task_set_exception(TaskObj *self, PyObject *exception)
2299/*[clinic end generated code: output=bc377fc28067303d input=9a8f65c83dcf893a]*/
2300{
2301 PyErr_SetString(PyExc_RuntimeError,
Andrew Svetlovfc359322017-12-30 15:40:27 +02002302 "Task does not support set_exception operation");
Yury Selivanov0cf16f92017-12-25 10:48:15 -05002303 return NULL;
2304}
2305
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002306/*[clinic input]
2307_asyncio.Task.get_name
2308[clinic start generated code]*/
2309
2310static PyObject *
2311_asyncio_Task_get_name_impl(TaskObj *self)
2312/*[clinic end generated code: output=0ecf1570c3b37a8f input=a4a6595d12f4f0f8]*/
2313{
2314 if (self->task_name) {
2315 Py_INCREF(self->task_name);
2316 return self->task_name;
2317 }
2318
2319 Py_RETURN_NONE;
2320}
2321
2322/*[clinic input]
2323_asyncio.Task.set_name
2324
2325 value: object
2326 /
2327[clinic start generated code]*/
2328
2329static PyObject *
2330_asyncio_Task_set_name(TaskObj *self, PyObject *value)
2331/*[clinic end generated code: output=138a8d51e32057d6 input=a8359b6e65f8fd31]*/
2332{
Alex Grönholma7548232018-08-09 23:49:49 +03002333 if (!PyUnicode_CheckExact(value)) {
2334 value = PyObject_Str(value);
2335 if (value == NULL) {
2336 return NULL;
2337 }
2338 } else {
2339 Py_INCREF(value);
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002340 }
2341
Alex Grönholma7548232018-08-09 23:49:49 +03002342 Py_XSETREF(self->task_name, value);
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002343 Py_RETURN_NONE;
2344}
Yury Selivanov0cf16f92017-12-25 10:48:15 -05002345
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002346static void
2347TaskObj_finalize(TaskObj *task)
2348{
2349 _Py_IDENTIFIER(call_exception_handler);
2350 _Py_IDENTIFIER(task);
2351 _Py_IDENTIFIER(message);
2352 _Py_IDENTIFIER(source_traceback);
2353
Serhiy Storchakabca49392017-09-03 08:10:14 +03002354 PyObject *context;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002355 PyObject *message = NULL;
Serhiy Storchakabca49392017-09-03 08:10:14 +03002356 PyObject *func;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002357 PyObject *error_type, *error_value, *error_traceback;
2358
2359 if (task->task_state != STATE_PENDING || !task->task_log_destroy_pending) {
2360 goto done;
2361 }
2362
2363 /* Save the current exception, if any. */
2364 PyErr_Fetch(&error_type, &error_value, &error_traceback);
2365
2366 context = PyDict_New();
2367 if (context == NULL) {
2368 goto finally;
2369 }
2370
2371 message = PyUnicode_FromString("Task was destroyed but it is pending!");
2372 if (message == NULL) {
2373 goto finally;
2374 }
2375
2376 if (_PyDict_SetItemId(context, &PyId_message, message) < 0 ||
2377 _PyDict_SetItemId(context, &PyId_task, (PyObject*)task) < 0)
2378 {
2379 goto finally;
2380 }
2381
2382 if (task->task_source_tb != NULL) {
2383 if (_PyDict_SetItemId(context, &PyId_source_traceback,
2384 task->task_source_tb) < 0)
2385 {
2386 goto finally;
2387 }
2388 }
2389
2390 func = _PyObject_GetAttrId(task->task_loop, &PyId_call_exception_handler);
2391 if (func != NULL) {
Serhiy Storchakabca49392017-09-03 08:10:14 +03002392 PyObject *res = PyObject_CallFunctionObjArgs(func, context, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002393 if (res == NULL) {
2394 PyErr_WriteUnraisable(func);
2395 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03002396 else {
2397 Py_DECREF(res);
2398 }
2399 Py_DECREF(func);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002400 }
2401
2402finally:
Serhiy Storchakabca49392017-09-03 08:10:14 +03002403 Py_XDECREF(context);
2404 Py_XDECREF(message);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002405
2406 /* Restore the saved exception. */
2407 PyErr_Restore(error_type, error_value, error_traceback);
2408
2409done:
2410 FutureObj_finalize((FutureObj*)task);
2411}
2412
2413static void TaskObj_dealloc(PyObject *); /* Needs Task_CheckExact */
2414
2415static PyMethodDef TaskType_methods[] = {
2416 _ASYNCIO_FUTURE_RESULT_METHODDEF
2417 _ASYNCIO_FUTURE_EXCEPTION_METHODDEF
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002418 _ASYNCIO_FUTURE_ADD_DONE_CALLBACK_METHODDEF
2419 _ASYNCIO_FUTURE_REMOVE_DONE_CALLBACK_METHODDEF
2420 _ASYNCIO_FUTURE_CANCELLED_METHODDEF
2421 _ASYNCIO_FUTURE_DONE_METHODDEF
Yury Selivanov0cf16f92017-12-25 10:48:15 -05002422 _ASYNCIO_TASK_SET_RESULT_METHODDEF
2423 _ASYNCIO_TASK_SET_EXCEPTION_METHODDEF
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002424 _ASYNCIO_TASK_CURRENT_TASK_METHODDEF
2425 _ASYNCIO_TASK_ALL_TASKS_METHODDEF
2426 _ASYNCIO_TASK_CANCEL_METHODDEF
2427 _ASYNCIO_TASK_GET_STACK_METHODDEF
2428 _ASYNCIO_TASK_PRINT_STACK_METHODDEF
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002429 _ASYNCIO_TASK__REPR_INFO_METHODDEF
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002430 _ASYNCIO_TASK_GET_NAME_METHODDEF
2431 _ASYNCIO_TASK_SET_NAME_METHODDEF
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002432 {NULL, NULL} /* Sentinel */
2433};
2434
2435static PyGetSetDef TaskType_getsetlist[] = {
2436 FUTURE_COMMON_GETSETLIST
2437 {"_log_destroy_pending", (getter)TaskObj_get_log_destroy_pending,
2438 (setter)TaskObj_set_log_destroy_pending, NULL},
2439 {"_must_cancel", (getter)TaskObj_get_must_cancel, NULL, NULL},
2440 {"_coro", (getter)TaskObj_get_coro, NULL, NULL},
2441 {"_fut_waiter", (getter)TaskObj_get_fut_waiter, NULL, NULL},
2442 {NULL} /* Sentinel */
2443};
2444
2445static PyTypeObject TaskType = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02002446 PyVarObject_HEAD_INIT(NULL, 0)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002447 "_asyncio.Task",
2448 sizeof(TaskObj), /* tp_basicsize */
2449 .tp_base = &FutureType,
2450 .tp_dealloc = TaskObj_dealloc,
2451 .tp_as_async = &FutureType_as_async,
2452 .tp_repr = (reprfunc)FutureObj_repr,
2453 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE
2454 | Py_TPFLAGS_HAVE_FINALIZE,
2455 .tp_doc = _asyncio_Task___init____doc__,
2456 .tp_traverse = (traverseproc)TaskObj_traverse,
2457 .tp_clear = (inquiry)TaskObj_clear,
2458 .tp_weaklistoffset = offsetof(TaskObj, task_weakreflist),
2459 .tp_iter = (getiterfunc)future_new_iter,
2460 .tp_methods = TaskType_methods,
2461 .tp_getset = TaskType_getsetlist,
2462 .tp_dictoffset = offsetof(TaskObj, dict),
2463 .tp_init = (initproc)_asyncio_Task___init__,
2464 .tp_new = PyType_GenericNew,
2465 .tp_finalize = (destructor)TaskObj_finalize,
2466};
2467
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002468static void
2469TaskObj_dealloc(PyObject *self)
2470{
2471 TaskObj *task = (TaskObj *)self;
2472
2473 if (Task_CheckExact(self)) {
2474 /* When fut is subclass of Task, finalizer is called from
2475 * subtype_dealloc.
2476 */
2477 if (PyObject_CallFinalizerFromDealloc(self) < 0) {
2478 // resurrected.
2479 return;
2480 }
2481 }
2482
Alexander Mohrde34cbe2017-08-01 23:31:07 -07002483 PyObject_GC_UnTrack(self);
2484
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002485 if (task->task_weakreflist != NULL) {
2486 PyObject_ClearWeakRefs(self);
2487 }
2488
2489 (void)TaskObj_clear(task);
2490 Py_TYPE(task)->tp_free(task);
2491}
2492
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002493static int
2494task_call_step_soon(TaskObj *task, PyObject *arg)
2495{
Serhiy Storchakabca49392017-09-03 08:10:14 +03002496 PyObject *cb = TaskStepMethWrapper_new(task, arg);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002497 if (cb == NULL) {
2498 return -1;
2499 }
2500
Yury Selivanovf23746a2018-01-22 19:11:18 -05002501 int ret = call_soon(task->task_loop, cb, NULL, task->task_context);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002502 Py_DECREF(cb);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05002503 return ret;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002504}
2505
2506static PyObject *
2507task_set_error_soon(TaskObj *task, PyObject *et, const char *format, ...)
2508{
2509 PyObject* msg;
2510
2511 va_list vargs;
2512#ifdef HAVE_STDARG_PROTOTYPES
2513 va_start(vargs, format);
2514#else
2515 va_start(vargs);
2516#endif
2517 msg = PyUnicode_FromFormatV(format, vargs);
2518 va_end(vargs);
2519
2520 if (msg == NULL) {
2521 return NULL;
2522 }
2523
Victor Stinnerde4ae3d2016-12-04 22:59:09 +01002524 PyObject *e = PyObject_CallFunctionObjArgs(et, msg, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002525 Py_DECREF(msg);
2526 if (e == NULL) {
2527 return NULL;
2528 }
2529
2530 if (task_call_step_soon(task, e) == -1) {
2531 Py_DECREF(e);
2532 return NULL;
2533 }
2534
2535 Py_DECREF(e);
2536 Py_RETURN_NONE;
2537}
2538
2539static PyObject *
2540task_step_impl(TaskObj *task, PyObject *exc)
2541{
2542 int res;
2543 int clear_exc = 0;
2544 PyObject *result = NULL;
Serhiy Storchakabca49392017-09-03 08:10:14 +03002545 PyObject *coro;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002546 PyObject *o;
2547
2548 if (task->task_state != STATE_PENDING) {
Yury Selivanov0cf16f92017-12-25 10:48:15 -05002549 PyErr_Format(asyncio_InvalidStateError,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002550 "_step(): already done: %R %R",
2551 task,
2552 exc ? exc : Py_None);
INADA Naokic411a7d2016-10-18 11:48:14 +09002553 goto fail;
2554 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09002555
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002556 if (task->task_must_cancel) {
2557 assert(exc != Py_None);
2558
2559 if (exc) {
2560 /* Check if exc is a CancelledError */
2561 res = PyObject_IsInstance(exc, asyncio_CancelledError);
2562 if (res == -1) {
2563 /* An error occurred, abort */
2564 goto fail;
2565 }
2566 if (res == 0) {
2567 /* exc is not CancelledError; reset it to NULL */
2568 exc = NULL;
2569 }
2570 }
2571
2572 if (!exc) {
2573 /* exc was not a CancelledError */
Victor Stinnerf17c3de2016-12-06 18:46:19 +01002574 exc = _PyObject_CallNoArg(asyncio_CancelledError);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002575 if (!exc) {
2576 goto fail;
2577 }
2578 clear_exc = 1;
2579 }
2580
2581 task->task_must_cancel = 0;
2582 }
2583
2584 Py_CLEAR(task->task_fut_waiter);
2585
Serhiy Storchakabca49392017-09-03 08:10:14 +03002586 coro = task->task_coro;
2587 if (coro == NULL) {
2588 PyErr_SetString(PyExc_RuntimeError, "uninitialized Task object");
2589 return NULL;
2590 }
2591
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002592 if (exc == NULL) {
2593 if (PyGen_CheckExact(coro) || PyCoro_CheckExact(coro)) {
2594 result = _PyGen_Send((PyGenObject*)coro, Py_None);
2595 }
2596 else {
Victor Stinnerb6ed57d2016-12-09 14:24:02 +01002597 result = _PyObject_CallMethodIdObjArgs(coro, &PyId_send,
2598 Py_None, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002599 }
2600 }
2601 else {
Victor Stinnerb6ed57d2016-12-09 14:24:02 +01002602 result = _PyObject_CallMethodIdObjArgs(coro, &PyId_throw,
2603 exc, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002604 if (clear_exc) {
2605 /* We created 'exc' during this call */
Serhiy Storchakabca49392017-09-03 08:10:14 +03002606 Py_DECREF(exc);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002607 }
2608 }
2609
2610 if (result == NULL) {
2611 PyObject *et, *ev, *tb;
2612
2613 if (_PyGen_FetchStopIterationValue(&o) == 0) {
2614 /* The error is StopIteration and that means that
2615 the underlying coroutine has resolved */
INADA Naoki991adca2017-05-11 21:18:38 +09002616 if (task->task_must_cancel) {
2617 // Task is cancelled right before coro stops.
2618 Py_DECREF(o);
2619 task->task_must_cancel = 0;
2620 et = asyncio_CancelledError;
2621 Py_INCREF(et);
2622 ev = NULL;
2623 tb = NULL;
2624 goto set_exception;
2625 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002626 PyObject *res = future_set_result((FutureObj*)task, o);
2627 Py_DECREF(o);
2628 if (res == NULL) {
2629 return NULL;
2630 }
2631 Py_DECREF(res);
2632 Py_RETURN_NONE;
2633 }
2634
2635 if (PyErr_ExceptionMatches(asyncio_CancelledError)) {
2636 /* CancelledError */
2637 PyErr_Clear();
2638 return future_cancel((FutureObj*)task);
2639 }
2640
2641 /* Some other exception; pop it and call Task.set_exception() */
2642 PyErr_Fetch(&et, &ev, &tb);
INADA Naoki991adca2017-05-11 21:18:38 +09002643
2644set_exception:
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002645 assert(et);
2646 if (!ev || !PyObject_TypeCheck(ev, (PyTypeObject *) et)) {
2647 PyErr_NormalizeException(&et, &ev, &tb);
2648 }
Yury Selivanovedfe8862016-12-01 11:37:47 -05002649 if (tb != NULL) {
2650 PyException_SetTraceback(ev, tb);
2651 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002652 o = future_set_exception((FutureObj*)task, ev);
2653 if (!o) {
2654 /* An exception in Task.set_exception() */
Serhiy Storchakabca49392017-09-03 08:10:14 +03002655 Py_DECREF(et);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002656 Py_XDECREF(tb);
2657 Py_XDECREF(ev);
2658 goto fail;
2659 }
2660 assert(o == Py_None);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002661 Py_DECREF(o);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002662
2663 if (!PyErr_GivenExceptionMatches(et, PyExc_Exception)) {
2664 /* We've got a BaseException; re-raise it */
2665 PyErr_Restore(et, ev, tb);
2666 goto fail;
2667 }
2668
Serhiy Storchakabca49392017-09-03 08:10:14 +03002669 Py_DECREF(et);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002670 Py_XDECREF(tb);
2671 Py_XDECREF(ev);
2672
2673 Py_RETURN_NONE;
2674 }
2675
2676 if (result == (PyObject*)task) {
2677 /* We have a task that wants to await on itself */
2678 goto self_await;
2679 }
2680
2681 /* Check if `result` is FutureObj or TaskObj (and not a subclass) */
2682 if (Future_CheckExact(result) || Task_CheckExact(result)) {
2683 PyObject *wrapper;
2684 PyObject *res;
2685 FutureObj *fut = (FutureObj*)result;
2686
2687 /* Check if `result` future is attached to a different loop */
2688 if (fut->fut_loop != task->task_loop) {
2689 goto different_loop;
2690 }
2691
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002692 if (!fut->fut_blocking) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002693 goto yield_insteadof_yf;
2694 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002695
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002696 fut->fut_blocking = 0;
2697
2698 /* result.add_done_callback(task._wakeup) */
2699 wrapper = TaskWakeupMethWrapper_new(task);
2700 if (wrapper == NULL) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002701 goto fail;
2702 }
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002703 res = future_add_done_callback(
2704 (FutureObj*)result, wrapper, task->task_context);
2705 Py_DECREF(wrapper);
2706 if (res == NULL) {
2707 goto fail;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002708 }
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002709 Py_DECREF(res);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002710
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002711 /* task._fut_waiter = result */
2712 task->task_fut_waiter = result; /* no incref is necessary */
2713
2714 if (task->task_must_cancel) {
2715 PyObject *r;
Elvis Pranskevichus0c797a62018-10-03 10:30:31 -04002716 int is_true;
Serhiy Storchakaaddf8af2018-10-05 21:20:02 +03002717 r = _PyObject_CallMethodId(result, &PyId_cancel, NULL);
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002718 if (r == NULL) {
2719 return NULL;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002720 }
Elvis Pranskevichus0c797a62018-10-03 10:30:31 -04002721 is_true = PyObject_IsTrue(r);
2722 Py_DECREF(r);
2723 if (is_true < 0) {
2724 return NULL;
2725 }
2726 else if (is_true) {
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002727 task->task_must_cancel = 0;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002728 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002729 }
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002730
2731 Py_RETURN_NONE;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002732 }
2733
2734 /* Check if `result` is None */
2735 if (result == Py_None) {
2736 /* Bare yield relinquishes control for one event loop iteration. */
2737 if (task_call_step_soon(task, NULL)) {
2738 goto fail;
2739 }
2740 return result;
2741 }
2742
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002743 /* Check if `result` is a Future-compatible object */
2744 if (_PyObject_LookupAttrId(result, &PyId__asyncio_future_blocking, &o) < 0) {
2745 goto fail;
2746 }
2747 if (o != NULL && o != Py_None) {
2748 /* `result` is a Future-compatible object */
2749 PyObject *wrapper;
2750 PyObject *res;
2751
2752 int blocking = PyObject_IsTrue(o);
2753 Py_DECREF(o);
2754 if (blocking < 0) {
2755 goto fail;
2756 }
2757
2758 /* Check if `result` future is attached to a different loop */
2759 PyObject *oloop = get_future_loop(result);
2760 if (oloop == NULL) {
2761 goto fail;
2762 }
2763 if (oloop != task->task_loop) {
2764 Py_DECREF(oloop);
2765 goto different_loop;
2766 }
2767 Py_DECREF(oloop);
2768
2769 if (!blocking) {
2770 goto yield_insteadof_yf;
2771 }
2772
2773 /* result._asyncio_future_blocking = False */
2774 if (_PyObject_SetAttrId(
2775 result, &PyId__asyncio_future_blocking, Py_False) == -1) {
2776 goto fail;
2777 }
2778
2779 wrapper = TaskWakeupMethWrapper_new(task);
2780 if (wrapper == NULL) {
2781 goto fail;
2782 }
2783
2784 /* result.add_done_callback(task._wakeup) */
2785 PyObject *add_cb = _PyObject_GetAttrId(
2786 result, &PyId_add_done_callback);
2787 if (add_cb == NULL) {
2788 Py_DECREF(wrapper);
2789 goto fail;
2790 }
2791 PyObject *stack[2];
2792 stack[0] = wrapper;
2793 stack[1] = (PyObject *)task->task_context;
2794 res = _PyObject_FastCallKeywords(
2795 add_cb, stack, 1, context_kwname);
2796 Py_DECREF(add_cb);
2797 Py_DECREF(wrapper);
2798 if (res == NULL) {
2799 goto fail;
2800 }
2801 Py_DECREF(res);
2802
2803 /* task._fut_waiter = result */
2804 task->task_fut_waiter = result; /* no incref is necessary */
2805
2806 if (task->task_must_cancel) {
2807 PyObject *r;
2808 int is_true;
2809 r = _PyObject_CallMethodId(result, &PyId_cancel, NULL);
2810 if (r == NULL) {
2811 return NULL;
2812 }
2813 is_true = PyObject_IsTrue(r);
2814 Py_DECREF(r);
2815 if (is_true < 0) {
2816 return NULL;
2817 }
2818 else if (is_true) {
2819 task->task_must_cancel = 0;
2820 }
2821 }
2822
2823 Py_RETURN_NONE;
2824 }
2825
2826 Py_XDECREF(o);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002827 /* Check if `result` is a generator */
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002828 res = PyObject_IsInstance(result, (PyObject*)&PyGen_Type);
2829 if (res < 0) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002830 goto fail;
2831 }
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002832 if (res) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002833 /* `result` is a generator */
Serhiy Storchaka66553542018-05-20 16:30:31 +03002834 o = task_set_error_soon(
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002835 task, PyExc_RuntimeError,
2836 "yield was used instead of yield from for "
Serhiy Storchaka66553542018-05-20 16:30:31 +03002837 "generator in task %R with %R", task, result);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002838 Py_DECREF(result);
Serhiy Storchaka66553542018-05-20 16:30:31 +03002839 return o;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002840 }
2841
2842 /* The `result` is none of the above */
Serhiy Storchaka66553542018-05-20 16:30:31 +03002843 o = task_set_error_soon(
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002844 task, PyExc_RuntimeError, "Task got bad yield: %R", result);
Serhiy Storchaka66553542018-05-20 16:30:31 +03002845 Py_DECREF(result);
2846 return o;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002847
2848self_await:
2849 o = task_set_error_soon(
2850 task, PyExc_RuntimeError,
2851 "Task cannot await on itself: %R", task);
2852 Py_DECREF(result);
2853 return o;
2854
2855yield_insteadof_yf:
2856 o = task_set_error_soon(
2857 task, PyExc_RuntimeError,
2858 "yield was used instead of yield from "
2859 "in task %R with %R",
2860 task, result);
2861 Py_DECREF(result);
2862 return o;
2863
2864different_loop:
2865 o = task_set_error_soon(
2866 task, PyExc_RuntimeError,
2867 "Task %R got Future %R attached to a different loop",
2868 task, result);
2869 Py_DECREF(result);
2870 return o;
2871
2872fail:
2873 Py_XDECREF(result);
2874 return NULL;
2875}
2876
2877static PyObject *
2878task_step(TaskObj *task, PyObject *exc)
2879{
2880 PyObject *res;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002881
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002882 if (enter_task(task->task_loop, (PyObject*)task) < 0) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002883 return NULL;
2884 }
2885
2886 res = task_step_impl(task, exc);
2887
2888 if (res == NULL) {
2889 PyObject *et, *ev, *tb;
2890 PyErr_Fetch(&et, &ev, &tb);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002891 leave_task(task->task_loop, (PyObject*)task);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002892 _PyErr_ChainExceptions(et, ev, tb);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002893 return NULL;
2894 }
2895 else {
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002896 if (leave_task(task->task_loop, (PyObject*)task) < 0) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002897 Py_DECREF(res);
2898 return NULL;
2899 }
2900 else {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002901 return res;
2902 }
2903 }
2904}
2905
2906static PyObject *
2907task_wakeup(TaskObj *task, PyObject *o)
2908{
Serhiy Storchakabca49392017-09-03 08:10:14 +03002909 PyObject *et, *ev, *tb;
2910 PyObject *result;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002911 assert(o);
2912
2913 if (Future_CheckExact(o) || Task_CheckExact(o)) {
2914 PyObject *fut_result = NULL;
2915 int res = future_get_result((FutureObj*)o, &fut_result);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002916
2917 switch(res) {
2918 case -1:
2919 assert(fut_result == NULL);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002920 break; /* exception raised */
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002921 case 0:
2922 Py_DECREF(fut_result);
Yury Selivanov22feeb82018-01-24 11:31:01 -05002923 return task_step(task, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002924 default:
2925 assert(res == 1);
Yury Selivanov22feeb82018-01-24 11:31:01 -05002926 result = task_step(task, fut_result);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002927 Py_DECREF(fut_result);
2928 return result;
2929 }
2930 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002931 else {
Serhiy Storchakabca49392017-09-03 08:10:14 +03002932 PyObject *fut_result = PyObject_CallMethod(o, "result", NULL);
2933 if (fut_result != NULL) {
2934 Py_DECREF(fut_result);
Yury Selivanov22feeb82018-01-24 11:31:01 -05002935 return task_step(task, NULL);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002936 }
2937 /* exception raised */
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002938 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03002939
2940 PyErr_Fetch(&et, &ev, &tb);
2941 if (!PyErr_GivenExceptionMatches(et, PyExc_Exception)) {
2942 /* We've got a BaseException; re-raise it */
2943 PyErr_Restore(et, ev, tb);
2944 return NULL;
2945 }
2946 if (!ev || !PyObject_TypeCheck(ev, (PyTypeObject *) et)) {
2947 PyErr_NormalizeException(&et, &ev, &tb);
2948 }
2949
Yury Selivanov22feeb82018-01-24 11:31:01 -05002950 result = task_step(task, ev);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002951
2952 Py_DECREF(et);
2953 Py_XDECREF(tb);
2954 Py_XDECREF(ev);
2955
2956 return result;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002957}
2958
2959
Yury Selivanova70232f2017-12-13 14:49:42 -05002960/*********************** Functions **************************/
2961
2962
2963/*[clinic input]
2964_asyncio._get_running_loop
2965
2966Return the running event loop or None.
2967
2968This is a low-level function intended to be used by event loops.
2969This function is thread-specific.
2970
2971[clinic start generated code]*/
2972
2973static PyObject *
2974_asyncio__get_running_loop_impl(PyObject *module)
2975/*[clinic end generated code: output=b4390af721411a0a input=0a21627e25a4bd43]*/
2976{
2977 PyObject *loop;
2978 if (get_running_loop(&loop)) {
2979 return NULL;
2980 }
2981 if (loop == NULL) {
2982 /* There's no currently running event loop */
2983 Py_RETURN_NONE;
2984 }
2985 return loop;
2986}
2987
2988/*[clinic input]
2989_asyncio._set_running_loop
2990 loop: 'O'
2991 /
2992
2993Set the running event loop.
2994
2995This is a low-level function intended to be used by event loops.
2996This function is thread-specific.
2997[clinic start generated code]*/
2998
2999static PyObject *
3000_asyncio__set_running_loop(PyObject *module, PyObject *loop)
3001/*[clinic end generated code: output=ae56bf7a28ca189a input=4c9720233d606604]*/
3002{
3003 if (set_running_loop(loop)) {
3004 return NULL;
3005 }
3006 Py_RETURN_NONE;
3007}
3008
3009/*[clinic input]
3010_asyncio.get_event_loop
3011
3012Return an asyncio event loop.
3013
3014When called from a coroutine or a callback (e.g. scheduled with
3015call_soon or similar API), this function will always return the
3016running event loop.
3017
3018If there is no running event loop set, the function will return
3019the result of `get_event_loop_policy().get_event_loop()` call.
3020[clinic start generated code]*/
3021
3022static PyObject *
3023_asyncio_get_event_loop_impl(PyObject *module)
3024/*[clinic end generated code: output=2a2d8b2f824c648b input=9364bf2916c8655d]*/
3025{
3026 return get_event_loop();
3027}
3028
3029/*[clinic input]
3030_asyncio.get_running_loop
3031
3032Return the running event loop. Raise a RuntimeError if there is none.
3033
3034This function is thread-specific.
3035[clinic start generated code]*/
3036
3037static PyObject *
3038_asyncio_get_running_loop_impl(PyObject *module)
3039/*[clinic end generated code: output=c247b5f9e529530e input=2a3bf02ba39f173d]*/
3040{
3041 PyObject *loop;
3042 if (get_running_loop(&loop)) {
3043 return NULL;
3044 }
3045 if (loop == NULL) {
3046 /* There's no currently running event loop */
3047 PyErr_SetString(
3048 PyExc_RuntimeError, "no running event loop");
3049 }
3050 return loop;
3051}
3052
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003053/*[clinic input]
3054_asyncio._register_task
3055
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003056 task: object
3057
3058Register a new task in asyncio as executed by loop.
3059
3060Returns None.
3061[clinic start generated code]*/
3062
3063static PyObject *
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003064_asyncio__register_task_impl(PyObject *module, PyObject *task)
3065/*[clinic end generated code: output=8672dadd69a7d4e2 input=21075aaea14dfbad]*/
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003066{
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003067 if (register_task(task) < 0) {
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003068 return NULL;
3069 }
3070 Py_RETURN_NONE;
3071}
3072
3073
3074/*[clinic input]
3075_asyncio._unregister_task
3076
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003077 task: object
3078
3079Unregister a task.
3080
3081Returns None.
3082[clinic start generated code]*/
3083
3084static PyObject *
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003085_asyncio__unregister_task_impl(PyObject *module, PyObject *task)
3086/*[clinic end generated code: output=6e5585706d568a46 input=28fb98c3975f7bdc]*/
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003087{
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003088 if (unregister_task(task) < 0) {
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003089 return NULL;
3090 }
3091 Py_RETURN_NONE;
3092}
3093
3094
3095/*[clinic input]
3096_asyncio._enter_task
3097
3098 loop: object
3099 task: object
3100
3101Enter into task execution or resume suspended task.
3102
3103Task belongs to loop.
3104
3105Returns None.
3106[clinic start generated code]*/
3107
3108static PyObject *
3109_asyncio__enter_task_impl(PyObject *module, PyObject *loop, PyObject *task)
3110/*[clinic end generated code: output=a22611c858035b73 input=de1b06dca70d8737]*/
3111{
3112 if (enter_task(loop, task) < 0) {
3113 return NULL;
3114 }
3115 Py_RETURN_NONE;
3116}
3117
3118
3119/*[clinic input]
3120_asyncio._leave_task
3121
3122 loop: object
3123 task: object
3124
3125Leave task execution or suspend a task.
3126
3127Task belongs to loop.
3128
3129Returns None.
3130[clinic start generated code]*/
3131
3132static PyObject *
3133_asyncio__leave_task_impl(PyObject *module, PyObject *loop, PyObject *task)
3134/*[clinic end generated code: output=0ebf6db4b858fb41 input=51296a46313d1ad8]*/
3135{
3136 if (leave_task(loop, task) < 0) {
3137 return NULL;
3138 }
3139 Py_RETURN_NONE;
3140}
3141
Yury Selivanova70232f2017-12-13 14:49:42 -05003142
Yury Selivanov9d411c12018-01-23 15:10:03 -05003143/*********************** PyRunningLoopHolder ********************/
3144
3145
3146static PyRunningLoopHolder *
3147new_running_loop_holder(PyObject *loop)
3148{
3149 PyRunningLoopHolder *rl = PyObject_New(
3150 PyRunningLoopHolder, &PyRunningLoopHolder_Type);
3151 if (rl == NULL) {
3152 return NULL;
3153 }
3154
3155#if defined(HAVE_GETPID) && !defined(MS_WINDOWS)
3156 rl->rl_pid = getpid();
3157#endif
3158
3159 Py_INCREF(loop);
3160 rl->rl_loop = loop;
3161
3162 return rl;
3163}
3164
3165
3166static void
3167PyRunningLoopHolder_tp_dealloc(PyRunningLoopHolder *rl)
3168{
3169 Py_CLEAR(rl->rl_loop);
3170 PyObject_Free(rl);
3171}
3172
3173
3174static PyTypeObject PyRunningLoopHolder_Type = {
3175 PyVarObject_HEAD_INIT(NULL, 0)
3176 "_RunningLoopHolder",
3177 sizeof(PyRunningLoopHolder),
3178 .tp_getattro = PyObject_GenericGetAttr,
3179 .tp_flags = Py_TPFLAGS_DEFAULT,
3180 .tp_dealloc = (destructor)PyRunningLoopHolder_tp_dealloc,
3181};
3182
3183
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003184/*********************** Module **************************/
3185
3186
3187static void
Zackery Spytze40ad792017-12-19 11:48:13 -07003188module_free_freelists(void)
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05003189{
3190 PyObject *next;
3191 PyObject *current;
3192
3193 next = (PyObject*) fi_freelist;
3194 while (next != NULL) {
3195 assert(fi_freelist_len > 0);
3196 fi_freelist_len--;
3197
3198 current = next;
3199 next = (PyObject*) ((futureiterobject*) current)->future;
3200 PyObject_GC_Del(current);
3201 }
3202 assert(fi_freelist_len == 0);
3203 fi_freelist = NULL;
3204}
3205
3206
3207static void
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003208module_free(void *m)
3209{
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003210 Py_CLEAR(asyncio_mod);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003211 Py_CLEAR(traceback_extract_stack);
3212 Py_CLEAR(asyncio_future_repr_info_func);
3213 Py_CLEAR(asyncio_get_event_loop_policy);
3214 Py_CLEAR(asyncio_iscoroutine_func);
3215 Py_CLEAR(asyncio_task_get_stack_func);
3216 Py_CLEAR(asyncio_task_print_stack_func);
3217 Py_CLEAR(asyncio_task_repr_info_func);
3218 Py_CLEAR(asyncio_InvalidStateError);
3219 Py_CLEAR(asyncio_CancelledError);
3220
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003221 Py_CLEAR(all_tasks);
Yury Selivanova9d7e552017-12-19 07:18:45 -05003222 Py_CLEAR(current_tasks);
3223 Py_CLEAR(iscoroutine_typecache);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05003224
Yury Selivanovf23746a2018-01-22 19:11:18 -05003225 Py_CLEAR(context_kwname);
3226
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05003227 module_free_freelists();
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003228}
3229
3230static int
3231module_init(void)
3232{
3233 PyObject *module = NULL;
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003234
3235 asyncio_mod = PyImport_ImportModule("asyncio");
3236 if (asyncio_mod == NULL) {
3237 goto fail;
3238 }
3239
3240 current_tasks = PyDict_New();
3241 if (current_tasks == NULL) {
3242 goto fail;
3243 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003244
Yury Selivanova9d7e552017-12-19 07:18:45 -05003245 iscoroutine_typecache = PySet_New(NULL);
3246 if (iscoroutine_typecache == NULL) {
3247 goto fail;
3248 }
3249
Yury Selivanovf23746a2018-01-22 19:11:18 -05003250
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03003251 context_kwname = Py_BuildValue("(s)", "context");
Yury Selivanovf23746a2018-01-22 19:11:18 -05003252 if (context_kwname == NULL) {
3253 goto fail;
3254 }
Yury Selivanovf23746a2018-01-22 19:11:18 -05003255
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003256#define WITH_MOD(NAME) \
3257 Py_CLEAR(module); \
3258 module = PyImport_ImportModule(NAME); \
3259 if (module == NULL) { \
Serhiy Storchakabca49392017-09-03 08:10:14 +03003260 goto fail; \
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003261 }
3262
3263#define GET_MOD_ATTR(VAR, NAME) \
3264 VAR = PyObject_GetAttrString(module, NAME); \
3265 if (VAR == NULL) { \
3266 goto fail; \
3267 }
3268
3269 WITH_MOD("asyncio.events")
Yury Selivanova70232f2017-12-13 14:49:42 -05003270 GET_MOD_ATTR(asyncio_get_event_loop_policy, "get_event_loop_policy")
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003271
3272 WITH_MOD("asyncio.base_futures")
3273 GET_MOD_ATTR(asyncio_future_repr_info_func, "_future_repr_info")
Andrew Svetlov0baa72f2018-09-11 10:13:04 -07003274
3275 WITH_MOD("asyncio.exceptions")
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003276 GET_MOD_ATTR(asyncio_InvalidStateError, "InvalidStateError")
3277 GET_MOD_ATTR(asyncio_CancelledError, "CancelledError")
3278
3279 WITH_MOD("asyncio.base_tasks")
3280 GET_MOD_ATTR(asyncio_task_repr_info_func, "_task_repr_info")
3281 GET_MOD_ATTR(asyncio_task_get_stack_func, "_task_get_stack")
3282 GET_MOD_ATTR(asyncio_task_print_stack_func, "_task_print_stack")
3283
Andrew Svetlovf74ef452017-12-15 07:04:38 +02003284 WITH_MOD("asyncio.coroutines")
3285 GET_MOD_ATTR(asyncio_iscoroutine_func, "iscoroutine")
3286
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003287 WITH_MOD("traceback")
3288 GET_MOD_ATTR(traceback_extract_stack, "extract_stack")
3289
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003290 PyObject *weak_set;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003291 WITH_MOD("weakref")
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003292 GET_MOD_ATTR(weak_set, "WeakSet");
3293 all_tasks = _PyObject_CallNoArg(weak_set);
3294 Py_CLEAR(weak_set);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003295 if (all_tasks == NULL) {
INADA Naokic411a7d2016-10-18 11:48:14 +09003296 goto fail;
3297 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003298
Serhiy Storchakabca49392017-09-03 08:10:14 +03003299 Py_DECREF(module);
INADA Naokic411a7d2016-10-18 11:48:14 +09003300 return 0;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003301
INADA Naokic411a7d2016-10-18 11:48:14 +09003302fail:
INADA Naokic411a7d2016-10-18 11:48:14 +09003303 Py_CLEAR(module);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003304 module_free(NULL);
INADA Naokic411a7d2016-10-18 11:48:14 +09003305 return -1;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003306
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003307#undef WITH_MOD
3308#undef GET_MOD_ATTR
3309}
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003310
INADA Naokic411a7d2016-10-18 11:48:14 +09003311PyDoc_STRVAR(module_doc, "Accelerator module for asyncio");
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003312
Yury Selivanova70232f2017-12-13 14:49:42 -05003313static PyMethodDef asyncio_methods[] = {
3314 _ASYNCIO_GET_EVENT_LOOP_METHODDEF
3315 _ASYNCIO_GET_RUNNING_LOOP_METHODDEF
3316 _ASYNCIO__GET_RUNNING_LOOP_METHODDEF
3317 _ASYNCIO__SET_RUNNING_LOOP_METHODDEF
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003318 _ASYNCIO__REGISTER_TASK_METHODDEF
3319 _ASYNCIO__UNREGISTER_TASK_METHODDEF
3320 _ASYNCIO__ENTER_TASK_METHODDEF
3321 _ASYNCIO__LEAVE_TASK_METHODDEF
Yury Selivanova70232f2017-12-13 14:49:42 -05003322 {NULL, NULL}
3323};
3324
INADA Naoki9f2ce252016-10-15 15:39:19 +09003325static struct PyModuleDef _asynciomodule = {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003326 PyModuleDef_HEAD_INIT, /* m_base */
INADA Naoki9f2ce252016-10-15 15:39:19 +09003327 "_asyncio", /* m_name */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003328 module_doc, /* m_doc */
3329 -1, /* m_size */
Yury Selivanova70232f2017-12-13 14:49:42 -05003330 asyncio_methods, /* m_methods */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003331 NULL, /* m_slots */
3332 NULL, /* m_traverse */
3333 NULL, /* m_clear */
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003334 (freefunc)module_free /* m_free */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003335};
3336
3337
3338PyMODINIT_FUNC
INADA Naoki9f2ce252016-10-15 15:39:19 +09003339PyInit__asyncio(void)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003340{
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003341 if (module_init() < 0) {
INADA Naokic411a7d2016-10-18 11:48:14 +09003342 return NULL;
3343 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003344 if (PyType_Ready(&FutureType) < 0) {
3345 return NULL;
3346 }
3347 if (PyType_Ready(&FutureIterType) < 0) {
3348 return NULL;
3349 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03003350 if (PyType_Ready(&TaskStepMethWrapper_Type) < 0) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003351 return NULL;
3352 }
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03003353 if (PyType_Ready(&TaskWakeupMethWrapper_Type) < 0) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003354 return NULL;
3355 }
3356 if (PyType_Ready(&TaskType) < 0) {
3357 return NULL;
3358 }
Yury Selivanov9d411c12018-01-23 15:10:03 -05003359 if (PyType_Ready(&PyRunningLoopHolder_Type) < 0) {
3360 return NULL;
3361 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003362
INADA Naoki9f2ce252016-10-15 15:39:19 +09003363 PyObject *m = PyModule_Create(&_asynciomodule);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003364 if (m == NULL) {
3365 return NULL;
3366 }
3367
3368 Py_INCREF(&FutureType);
3369 if (PyModule_AddObject(m, "Future", (PyObject *)&FutureType) < 0) {
3370 Py_DECREF(&FutureType);
3371 return NULL;
3372 }
3373
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003374 Py_INCREF(&TaskType);
3375 if (PyModule_AddObject(m, "Task", (PyObject *)&TaskType) < 0) {
3376 Py_DECREF(&TaskType);
3377 return NULL;
3378 }
3379
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003380 Py_INCREF(all_tasks);
3381 if (PyModule_AddObject(m, "_all_tasks", all_tasks) < 0) {
3382 Py_DECREF(all_tasks);
3383 return NULL;
3384 }
3385
3386 Py_INCREF(current_tasks);
3387 if (PyModule_AddObject(m, "_current_tasks", current_tasks) < 0) {
3388 Py_DECREF(current_tasks);
3389 return NULL;
3390 }
3391
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003392 return m;
3393}