blob: 60136082a7eecfe9ff327bae1b3d7acfb3a66631 [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
Jeroen Demeyeraacc77f2019-05-29 20:31:52 +0200370 handle = _PyObject_Vectorcall(callable, stack, nargs, context_kwname);
Yury Selivanovf23746a2018-01-22 19:11:18 -0500371 Py_DECREF(callable);
372 }
373
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500374 if (handle == NULL) {
375 return -1;
376 }
377 Py_DECREF(handle);
378 return 0;
379}
380
381
382static inline int
383future_is_alive(FutureObj *fut)
384{
385 return fut->fut_loop != NULL;
386}
387
388
389static inline int
390future_ensure_alive(FutureObj *fut)
391{
392 if (!future_is_alive(fut)) {
393 PyErr_SetString(PyExc_RuntimeError,
394 "Future object is not initialized.");
395 return -1;
396 }
397 return 0;
398}
399
400
401#define ENSURE_FUTURE_ALIVE(fut) \
402 do { \
403 assert(Future_Check(fut) || Task_Check(fut)); \
404 if (future_ensure_alive((FutureObj*)fut)) { \
405 return NULL; \
406 } \
407 } while(0);
408
409
410static int
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400411future_schedule_callbacks(FutureObj *fut)
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900412{
413 Py_ssize_t len;
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500414 Py_ssize_t i;
415
416 if (fut->fut_callback0 != NULL) {
417 /* There's a 1st callback */
418
419 int ret = call_soon(
Yury Selivanovf23746a2018-01-22 19:11:18 -0500420 fut->fut_loop, fut->fut_callback0,
421 (PyObject *)fut, fut->fut_context0);
422
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500423 Py_CLEAR(fut->fut_callback0);
Yury Selivanovf23746a2018-01-22 19:11:18 -0500424 Py_CLEAR(fut->fut_context0);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500425 if (ret) {
426 /* If an error occurs in pure-Python implementation,
427 all callbacks are cleared. */
428 Py_CLEAR(fut->fut_callbacks);
429 return ret;
430 }
431
432 /* we called the first callback, now try calling
433 callbacks from the 'fut_callbacks' list. */
434 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900435
436 if (fut->fut_callbacks == NULL) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500437 /* No more callbacks, return. */
438 return 0;
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900439 }
440
441 len = PyList_GET_SIZE(fut->fut_callbacks);
442 if (len == 0) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500443 /* The list of callbacks was empty; clear it and return. */
444 Py_CLEAR(fut->fut_callbacks);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900445 return 0;
446 }
447
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900448 for (i = 0; i < len; i++) {
Yury Selivanovf23746a2018-01-22 19:11:18 -0500449 PyObject *cb_tup = PyList_GET_ITEM(fut->fut_callbacks, i);
450 PyObject *cb = PyTuple_GET_ITEM(cb_tup, 0);
451 PyObject *ctx = PyTuple_GET_ITEM(cb_tup, 1);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900452
Yury Selivanov994269c2018-09-27 14:55:55 -0400453 if (call_soon(fut->fut_loop, cb, (PyObject *)fut, ctx)) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500454 /* If an error occurs in pure-Python implementation,
455 all callbacks are cleared. */
456 Py_CLEAR(fut->fut_callbacks);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900457 return -1;
458 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900459 }
460
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500461 Py_CLEAR(fut->fut_callbacks);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900462 return 0;
463}
464
Oren Milmand019bc82018-02-13 12:28:33 +0200465
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900466static int
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400467future_init(FutureObj *fut, PyObject *loop)
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900468{
Serhiy Storchakabca49392017-09-03 08:10:14 +0300469 PyObject *res;
470 int is_true;
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900471 _Py_IDENTIFIER(get_debug);
472
Oren Milmand019bc82018-02-13 12:28:33 +0200473 // Same to FutureObj_clear() but not clearing fut->dict
474 Py_CLEAR(fut->fut_loop);
475 Py_CLEAR(fut->fut_callback0);
476 Py_CLEAR(fut->fut_context0);
477 Py_CLEAR(fut->fut_callbacks);
478 Py_CLEAR(fut->fut_result);
479 Py_CLEAR(fut->fut_exception);
480 Py_CLEAR(fut->fut_source_tb);
481
482 fut->fut_state = STATE_PENDING;
483 fut->fut_log_tb = 0;
484 fut->fut_blocking = 0;
485
Serhiy Storchakabca49392017-09-03 08:10:14 +0300486 if (loop == Py_None) {
Yury Selivanova70232f2017-12-13 14:49:42 -0500487 loop = get_event_loop();
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900488 if (loop == NULL) {
489 return -1;
490 }
491 }
492 else {
493 Py_INCREF(loop);
494 }
Oren Milmand019bc82018-02-13 12:28:33 +0200495 fut->fut_loop = loop;
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900496
Victor Stinnerf94d1ee2016-10-29 09:05:39 +0200497 res = _PyObject_CallMethodId(fut->fut_loop, &PyId_get_debug, NULL);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900498 if (res == NULL) {
499 return -1;
500 }
Serhiy Storchakabca49392017-09-03 08:10:14 +0300501 is_true = PyObject_IsTrue(res);
502 Py_DECREF(res);
503 if (is_true < 0) {
504 return -1;
505 }
Yury Selivanov35230d02018-05-28 11:11:31 -0400506 if (is_true && !_Py_IsFinalizing()) {
507 /* Only try to capture the traceback if the interpreter is not being
508 finalized. The original motivation to add a `_Py_IsFinalizing()`
509 call was to prevent SIGSEGV when a Future is created in a __del__
510 method, which is called during the interpreter shutdown and the
511 traceback module is already unloaded.
512 */
Oren Milmand019bc82018-02-13 12:28:33 +0200513 fut->fut_source_tb = _PyObject_CallNoArg(traceback_extract_stack);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900514 if (fut->fut_source_tb == NULL) {
515 return -1;
516 }
517 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900518
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900519 return 0;
520}
521
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900522static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400523future_set_result(FutureObj *fut, PyObject *res)
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900524{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500525 if (future_ensure_alive(fut)) {
526 return NULL;
527 }
528
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900529 if (fut->fut_state != STATE_PENDING) {
530 PyErr_SetString(asyncio_InvalidStateError, "invalid state");
531 return NULL;
532 }
533
Serhiy Storchakabca49392017-09-03 08:10:14 +0300534 assert(!fut->fut_result);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900535 Py_INCREF(res);
536 fut->fut_result = res;
537 fut->fut_state = STATE_FINISHED;
538
Yury Selivanov22feeb82018-01-24 11:31:01 -0500539 if (future_schedule_callbacks(fut) == -1) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900540 return NULL;
541 }
542 Py_RETURN_NONE;
543}
544
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900545static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400546future_set_exception(FutureObj *fut, PyObject *exc)
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900547{
548 PyObject *exc_val = NULL;
549
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900550 if (fut->fut_state != STATE_PENDING) {
551 PyErr_SetString(asyncio_InvalidStateError, "invalid state");
552 return NULL;
553 }
554
555 if (PyExceptionClass_Check(exc)) {
Victor Stinnera5ed5f02016-12-06 18:45:50 +0100556 exc_val = _PyObject_CallNoArg(exc);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900557 if (exc_val == NULL) {
558 return NULL;
559 }
Serhiy Storchakabca49392017-09-03 08:10:14 +0300560 if (fut->fut_state != STATE_PENDING) {
561 Py_DECREF(exc_val);
562 PyErr_SetString(asyncio_InvalidStateError, "invalid state");
563 return NULL;
564 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900565 }
566 else {
567 exc_val = exc;
568 Py_INCREF(exc_val);
569 }
570 if (!PyExceptionInstance_Check(exc_val)) {
571 Py_DECREF(exc_val);
572 PyErr_SetString(PyExc_TypeError, "invalid exception object");
573 return NULL;
574 }
575 if ((PyObject*)Py_TYPE(exc_val) == PyExc_StopIteration) {
576 Py_DECREF(exc_val);
577 PyErr_SetString(PyExc_TypeError,
578 "StopIteration interacts badly with generators "
579 "and cannot be raised into a Future");
580 return NULL;
581 }
582
Serhiy Storchakabca49392017-09-03 08:10:14 +0300583 assert(!fut->fut_exception);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900584 fut->fut_exception = exc_val;
585 fut->fut_state = STATE_FINISHED;
586
Yury Selivanov22feeb82018-01-24 11:31:01 -0500587 if (future_schedule_callbacks(fut) == -1) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900588 return NULL;
589 }
590
591 fut->fut_log_tb = 1;
592 Py_RETURN_NONE;
593}
594
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400595static int
596future_get_result(FutureObj *fut, PyObject **result)
597{
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400598 if (fut->fut_state == STATE_CANCELLED) {
Serhiy Storchakabca49392017-09-03 08:10:14 +0300599 PyErr_SetNone(asyncio_CancelledError);
600 return -1;
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400601 }
602
603 if (fut->fut_state != STATE_FINISHED) {
Serhiy Storchakabca49392017-09-03 08:10:14 +0300604 PyErr_SetString(asyncio_InvalidStateError, "Result is not set.");
605 return -1;
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400606 }
607
608 fut->fut_log_tb = 0;
609 if (fut->fut_exception != NULL) {
610 Py_INCREF(fut->fut_exception);
611 *result = fut->fut_exception;
612 return 1;
613 }
614
615 Py_INCREF(fut->fut_result);
616 *result = fut->fut_result;
617 return 0;
618}
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900619
620static PyObject *
Yury Selivanov994269c2018-09-27 14:55:55 -0400621future_add_done_callback(FutureObj *fut, PyObject *arg, PyObject *ctx)
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900622{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500623 if (!future_is_alive(fut)) {
624 PyErr_SetString(PyExc_RuntimeError, "uninitialized Future object");
625 return NULL;
626 }
627
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900628 if (fut->fut_state != STATE_PENDING) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500629 /* The future is done/cancelled, so schedule the callback
630 right away. */
Yury Selivanovf23746a2018-01-22 19:11:18 -0500631 if (call_soon(fut->fut_loop, arg, (PyObject*) fut, ctx)) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900632 return NULL;
633 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900634 }
635 else {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500636 /* The future is pending, add a callback.
637
638 Callbacks in the future object are stored as follows:
639
640 callback0 -- a pointer to the first callback
641 callbacks -- a list of 2nd, 3rd, ... callbacks
642
643 Invariants:
644
645 * callbacks != NULL:
646 There are some callbacks in in the list. Just
647 add the new callback to it.
648
649 * callbacks == NULL and callback0 == NULL:
650 This is the first callback. Set it to callback0.
651
652 * callbacks == NULL and callback0 != NULL:
653 This is a second callback. Initialize callbacks
654 with a new list and add the new callback to it.
655 */
656
Yury Selivanovf23746a2018-01-22 19:11:18 -0500657 if (fut->fut_callbacks == NULL && fut->fut_callback0 == NULL) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500658 Py_INCREF(arg);
659 fut->fut_callback0 = arg;
Yury Selivanovf23746a2018-01-22 19:11:18 -0500660 Py_INCREF(ctx);
661 fut->fut_context0 = ctx;
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500662 }
663 else {
Yury Selivanovf23746a2018-01-22 19:11:18 -0500664 PyObject *tup = PyTuple_New(2);
665 if (tup == NULL) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500666 return NULL;
667 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500668 Py_INCREF(arg);
Yury Selivanovf23746a2018-01-22 19:11:18 -0500669 PyTuple_SET_ITEM(tup, 0, arg);
670 Py_INCREF(ctx);
671 PyTuple_SET_ITEM(tup, 1, (PyObject *)ctx);
672
673 if (fut->fut_callbacks != NULL) {
674 int err = PyList_Append(fut->fut_callbacks, tup);
675 if (err) {
676 Py_DECREF(tup);
677 return NULL;
678 }
679 Py_DECREF(tup);
680 }
681 else {
682 fut->fut_callbacks = PyList_New(1);
683 if (fut->fut_callbacks == NULL) {
684 return NULL;
685 }
686
687 PyList_SET_ITEM(fut->fut_callbacks, 0, tup); /* borrow */
688 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900689 }
690 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500691
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900692 Py_RETURN_NONE;
693}
694
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400695static PyObject *
696future_cancel(FutureObj *fut)
697{
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +0000698 fut->fut_log_tb = 0;
699
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400700 if (fut->fut_state != STATE_PENDING) {
701 Py_RETURN_FALSE;
702 }
703 fut->fut_state = STATE_CANCELLED;
704
Yury Selivanov22feeb82018-01-24 11:31:01 -0500705 if (future_schedule_callbacks(fut) == -1) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400706 return NULL;
707 }
708
709 Py_RETURN_TRUE;
710}
711
712/*[clinic input]
713_asyncio.Future.__init__
714
715 *
Serhiy Storchakabca49392017-09-03 08:10:14 +0300716 loop: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400717
718This class is *almost* compatible with concurrent.futures.Future.
719
720 Differences:
721
722 - result() and exception() do not take a timeout argument and
723 raise an exception when the future isn't done yet.
724
725 - Callbacks registered with add_done_callback() are always called
726 via the event loop's call_soon_threadsafe().
727
728 - This class is not compatible with the wait() and as_completed()
729 methods in the concurrent.futures package.
730[clinic start generated code]*/
731
732static int
733_asyncio_Future___init___impl(FutureObj *self, PyObject *loop)
Serhiy Storchakabca49392017-09-03 08:10:14 +0300734/*[clinic end generated code: output=9ed75799eaccb5d6 input=89af317082bc0bf8]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400735
736{
737 return future_init(self, loop);
738}
739
740static int
741FutureObj_clear(FutureObj *fut)
742{
743 Py_CLEAR(fut->fut_loop);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500744 Py_CLEAR(fut->fut_callback0);
Yury Selivanovf23746a2018-01-22 19:11:18 -0500745 Py_CLEAR(fut->fut_context0);
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400746 Py_CLEAR(fut->fut_callbacks);
747 Py_CLEAR(fut->fut_result);
748 Py_CLEAR(fut->fut_exception);
749 Py_CLEAR(fut->fut_source_tb);
750 Py_CLEAR(fut->dict);
751 return 0;
752}
753
754static int
755FutureObj_traverse(FutureObj *fut, visitproc visit, void *arg)
756{
757 Py_VISIT(fut->fut_loop);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500758 Py_VISIT(fut->fut_callback0);
Yury Selivanovf23746a2018-01-22 19:11:18 -0500759 Py_VISIT(fut->fut_context0);
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400760 Py_VISIT(fut->fut_callbacks);
761 Py_VISIT(fut->fut_result);
762 Py_VISIT(fut->fut_exception);
763 Py_VISIT(fut->fut_source_tb);
764 Py_VISIT(fut->dict);
765 return 0;
766}
767
768/*[clinic input]
769_asyncio.Future.result
770
771Return the result this future represents.
772
773If the future has been cancelled, raises CancelledError. If the
774future's result isn't yet available, raises InvalidStateError. If
775the future is done and has an exception set, this exception is raised.
776[clinic start generated code]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900777
778static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400779_asyncio_Future_result_impl(FutureObj *self)
780/*[clinic end generated code: output=f35f940936a4b1e5 input=49ecf9cf5ec50dc5]*/
781{
782 PyObject *result;
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500783
784 if (!future_is_alive(self)) {
785 PyErr_SetString(asyncio_InvalidStateError,
786 "Future object is not initialized.");
787 return NULL;
788 }
789
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400790 int res = future_get_result(self, &result);
791
792 if (res == -1) {
793 return NULL;
794 }
795
796 if (res == 0) {
797 return result;
798 }
799
800 assert(res == 1);
801
802 PyErr_SetObject(PyExceptionInstance_Class(result), result);
803 Py_DECREF(result);
804 return NULL;
805}
806
807/*[clinic input]
808_asyncio.Future.exception
809
810Return the exception that was set on this future.
811
812The exception (or None if no exception was set) is returned only if
813the future is done. If the future has been cancelled, raises
814CancelledError. If the future isn't done yet, raises
815InvalidStateError.
816[clinic start generated code]*/
817
818static PyObject *
819_asyncio_Future_exception_impl(FutureObj *self)
820/*[clinic end generated code: output=88b20d4f855e0710 input=733547a70c841c68]*/
821{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500822 if (!future_is_alive(self)) {
823 PyErr_SetString(asyncio_InvalidStateError,
824 "Future object is not initialized.");
825 return NULL;
826 }
827
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400828 if (self->fut_state == STATE_CANCELLED) {
Serhiy Storchakabca49392017-09-03 08:10:14 +0300829 PyErr_SetNone(asyncio_CancelledError);
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400830 return NULL;
831 }
832
833 if (self->fut_state != STATE_FINISHED) {
Serhiy Storchakabca49392017-09-03 08:10:14 +0300834 PyErr_SetString(asyncio_InvalidStateError, "Exception is not set.");
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400835 return NULL;
836 }
837
838 if (self->fut_exception != NULL) {
839 self->fut_log_tb = 0;
840 Py_INCREF(self->fut_exception);
841 return self->fut_exception;
842 }
843
844 Py_RETURN_NONE;
845}
846
847/*[clinic input]
848_asyncio.Future.set_result
849
Yury Selivanov0cf16f92017-12-25 10:48:15 -0500850 result: object
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400851 /
852
853Mark the future done and set its result.
854
855If the future is already done when this method is called, raises
856InvalidStateError.
857[clinic start generated code]*/
858
859static PyObject *
Yury Selivanov0cf16f92017-12-25 10:48:15 -0500860_asyncio_Future_set_result(FutureObj *self, PyObject *result)
861/*[clinic end generated code: output=1ec2e6bcccd6f2ce input=8b75172c2a7b05f1]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400862{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500863 ENSURE_FUTURE_ALIVE(self)
Yury Selivanov0cf16f92017-12-25 10:48:15 -0500864 return future_set_result(self, result);
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400865}
866
867/*[clinic input]
868_asyncio.Future.set_exception
869
Serhiy Storchakabca49392017-09-03 08:10:14 +0300870 exception: object
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400871 /
872
873Mark the future done and set an exception.
874
875If the future is already done when this method is called, raises
876InvalidStateError.
877[clinic start generated code]*/
878
879static PyObject *
880_asyncio_Future_set_exception(FutureObj *self, PyObject *exception)
Serhiy Storchakabca49392017-09-03 08:10:14 +0300881/*[clinic end generated code: output=f1c1b0cd321be360 input=e45b7d7aa71cc66d]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400882{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500883 ENSURE_FUTURE_ALIVE(self)
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400884 return future_set_exception(self, exception);
885}
886
887/*[clinic input]
888_asyncio.Future.add_done_callback
889
Serhiy Storchakabca49392017-09-03 08:10:14 +0300890 fn: object
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400891 /
Yury Selivanovf23746a2018-01-22 19:11:18 -0500892 *
893 context: object = NULL
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400894
895Add a callback to be run when the future becomes done.
896
897The callback is called with a single argument - the future object. If
898the future is already done when this is called, the callback is
899scheduled with call_soon.
900[clinic start generated code]*/
901
902static PyObject *
Yury Selivanovf23746a2018-01-22 19:11:18 -0500903_asyncio_Future_add_done_callback_impl(FutureObj *self, PyObject *fn,
904 PyObject *context)
905/*[clinic end generated code: output=7ce635bbc9554c1e input=15ab0693a96e9533]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400906{
Yury Selivanovf23746a2018-01-22 19:11:18 -0500907 if (context == NULL) {
Yury Selivanov994269c2018-09-27 14:55:55 -0400908 context = PyContext_CopyCurrent();
Yury Selivanovf23746a2018-01-22 19:11:18 -0500909 if (context == NULL) {
910 return NULL;
911 }
Yury Selivanov994269c2018-09-27 14:55:55 -0400912 PyObject *res = future_add_done_callback(self, fn, context);
Yury Selivanovf23746a2018-01-22 19:11:18 -0500913 Py_DECREF(context);
914 return res;
915 }
Yury Selivanov994269c2018-09-27 14:55:55 -0400916 return future_add_done_callback(self, fn, context);
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400917}
918
919/*[clinic input]
920_asyncio.Future.remove_done_callback
921
Serhiy Storchakabca49392017-09-03 08:10:14 +0300922 fn: object
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400923 /
924
925Remove all instances of a callback from the "call when done" list.
926
927Returns the number of callbacks removed.
928[clinic start generated code]*/
929
930static PyObject *
931_asyncio_Future_remove_done_callback(FutureObj *self, PyObject *fn)
Serhiy Storchakabca49392017-09-03 08:10:14 +0300932/*[clinic end generated code: output=5ab1fb52b24ef31f input=0a43280a149d505b]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900933{
934 PyObject *newlist;
935 Py_ssize_t len, i, j=0;
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500936 Py_ssize_t cleared_callback0 = 0;
937
938 ENSURE_FUTURE_ALIVE(self)
939
940 if (self->fut_callback0 != NULL) {
941 int cmp = PyObject_RichCompareBool(fn, self->fut_callback0, Py_EQ);
942 if (cmp == -1) {
943 return NULL;
944 }
945 if (cmp == 1) {
946 /* callback0 == fn */
947 Py_CLEAR(self->fut_callback0);
Yury Selivanovf23746a2018-01-22 19:11:18 -0500948 Py_CLEAR(self->fut_context0);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500949 cleared_callback0 = 1;
950 }
951 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900952
Serhiy Storchakabca49392017-09-03 08:10:14 +0300953 if (self->fut_callbacks == NULL) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500954 return PyLong_FromSsize_t(cleared_callback0);
Serhiy Storchakabca49392017-09-03 08:10:14 +0300955 }
956
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400957 len = PyList_GET_SIZE(self->fut_callbacks);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900958 if (len == 0) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500959 Py_CLEAR(self->fut_callbacks);
960 return PyLong_FromSsize_t(cleared_callback0);
961 }
962
963 if (len == 1) {
Yury Selivanovf23746a2018-01-22 19:11:18 -0500964 PyObject *cb_tup = PyList_GET_ITEM(self->fut_callbacks, 0);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500965 int cmp = PyObject_RichCompareBool(
Yury Selivanovf23746a2018-01-22 19:11:18 -0500966 fn, PyTuple_GET_ITEM(cb_tup, 0), Py_EQ);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500967 if (cmp == -1) {
968 return NULL;
969 }
970 if (cmp == 1) {
971 /* callbacks[0] == fn */
972 Py_CLEAR(self->fut_callbacks);
973 return PyLong_FromSsize_t(1 + cleared_callback0);
974 }
975 /* callbacks[0] != fn and len(callbacks) == 1 */
976 return PyLong_FromSsize_t(cleared_callback0);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900977 }
978
979 newlist = PyList_New(len);
980 if (newlist == NULL) {
981 return NULL;
982 }
983
Yury Selivanov84af9032017-03-02 23:46:56 -0500984 for (i = 0; i < PyList_GET_SIZE(self->fut_callbacks); i++) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900985 int ret;
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400986 PyObject *item = PyList_GET_ITEM(self->fut_callbacks, i);
Serhiy Storchakabca49392017-09-03 08:10:14 +0300987 Py_INCREF(item);
Yury Selivanovf23746a2018-01-22 19:11:18 -0500988 ret = PyObject_RichCompareBool(fn, PyTuple_GET_ITEM(item, 0), Py_EQ);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900989 if (ret == 0) {
Yury Selivanov833a3b02017-07-05 13:32:03 -0400990 if (j < len) {
Yury Selivanov833a3b02017-07-05 13:32:03 -0400991 PyList_SET_ITEM(newlist, j, item);
992 j++;
Serhiy Storchakabca49392017-09-03 08:10:14 +0300993 continue;
Yury Selivanov833a3b02017-07-05 13:32:03 -0400994 }
Serhiy Storchakabca49392017-09-03 08:10:14 +0300995 ret = PyList_Append(newlist, item);
996 }
997 Py_DECREF(item);
998 if (ret < 0) {
999 goto fail;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001000 }
1001 }
1002
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001003 if (j == 0) {
1004 Py_CLEAR(self->fut_callbacks);
1005 Py_DECREF(newlist);
1006 return PyLong_FromSsize_t(len + cleared_callback0);
1007 }
1008
Serhiy Storchakabca49392017-09-03 08:10:14 +03001009 if (j < len) {
1010 Py_SIZE(newlist) = j;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001011 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03001012 j = PyList_GET_SIZE(newlist);
1013 len = PyList_GET_SIZE(self->fut_callbacks);
1014 if (j != len) {
1015 if (PyList_SetSlice(self->fut_callbacks, 0, len, newlist) < 0) {
1016 goto fail;
1017 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001018 }
1019 Py_DECREF(newlist);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001020 return PyLong_FromSsize_t(len - j + cleared_callback0);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001021
1022fail:
1023 Py_DECREF(newlist);
1024 return NULL;
1025}
1026
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001027/*[clinic input]
1028_asyncio.Future.cancel
1029
1030Cancel the future and schedule callbacks.
1031
1032If the future is already done or cancelled, return False. Otherwise,
1033change the future's state to cancelled, schedule the callbacks and
1034return True.
1035[clinic start generated code]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001036
1037static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001038_asyncio_Future_cancel_impl(FutureObj *self)
1039/*[clinic end generated code: output=e45b932ba8bd68a1 input=515709a127995109]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001040{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001041 ENSURE_FUTURE_ALIVE(self)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001042 return future_cancel(self);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001043}
1044
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001045/*[clinic input]
1046_asyncio.Future.cancelled
1047
1048Return True if the future was cancelled.
1049[clinic start generated code]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001050
1051static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001052_asyncio_Future_cancelled_impl(FutureObj *self)
1053/*[clinic end generated code: output=145197ced586357d input=943ab8b7b7b17e45]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001054{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001055 if (future_is_alive(self) && self->fut_state == STATE_CANCELLED) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001056 Py_RETURN_TRUE;
1057 }
1058 else {
1059 Py_RETURN_FALSE;
1060 }
1061}
1062
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001063/*[clinic input]
1064_asyncio.Future.done
1065
1066Return True if the future is done.
1067
1068Done means either that a result / exception are available, or that the
1069future was cancelled.
1070[clinic start generated code]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001071
1072static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001073_asyncio_Future_done_impl(FutureObj *self)
1074/*[clinic end generated code: output=244c5ac351145096 input=28d7b23fdb65d2ac]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001075{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001076 if (!future_is_alive(self) || self->fut_state == STATE_PENDING) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001077 Py_RETURN_FALSE;
1078 }
1079 else {
1080 Py_RETURN_TRUE;
1081 }
1082}
1083
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001084/*[clinic input]
1085_asyncio.Future.get_loop
1086
1087Return the event loop the Future is bound to.
1088[clinic start generated code]*/
1089
1090static PyObject *
1091_asyncio_Future_get_loop_impl(FutureObj *self)
1092/*[clinic end generated code: output=119b6ea0c9816c3f input=cba48c2136c79d1f]*/
1093{
1094 Py_INCREF(self->fut_loop);
1095 return self->fut_loop;
1096}
1097
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001098static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001099FutureObj_get_blocking(FutureObj *fut, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001100{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001101 if (future_is_alive(fut) && fut->fut_blocking) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001102 Py_RETURN_TRUE;
1103 }
1104 else {
1105 Py_RETURN_FALSE;
1106 }
1107}
1108
1109static int
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001110FutureObj_set_blocking(FutureObj *fut, PyObject *val, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001111{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001112 if (future_ensure_alive(fut)) {
1113 return -1;
1114 }
Zackery Spytz842acaa2018-12-17 07:52:45 -07001115 if (val == NULL) {
1116 PyErr_SetString(PyExc_AttributeError, "cannot delete attribute");
1117 return -1;
1118 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001119
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001120 int is_true = PyObject_IsTrue(val);
1121 if (is_true < 0) {
1122 return -1;
1123 }
1124 fut->fut_blocking = is_true;
1125 return 0;
1126}
1127
1128static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001129FutureObj_get_log_traceback(FutureObj *fut, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001130{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001131 ENSURE_FUTURE_ALIVE(fut)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001132 if (fut->fut_log_tb) {
1133 Py_RETURN_TRUE;
1134 }
1135 else {
1136 Py_RETURN_FALSE;
1137 }
1138}
1139
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +00001140static int
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001141FutureObj_set_log_traceback(FutureObj *fut, PyObject *val, void *Py_UNUSED(ignored))
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +00001142{
Zackery Spytz842acaa2018-12-17 07:52:45 -07001143 if (val == NULL) {
1144 PyErr_SetString(PyExc_AttributeError, "cannot delete attribute");
1145 return -1;
1146 }
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +00001147 int is_true = PyObject_IsTrue(val);
1148 if (is_true < 0) {
1149 return -1;
1150 }
Yury Selivanove0aef4f2017-12-25 16:16:10 -05001151 if (is_true) {
1152 PyErr_SetString(PyExc_ValueError,
1153 "_log_traceback can only be set to False");
1154 return -1;
1155 }
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +00001156 fut->fut_log_tb = is_true;
1157 return 0;
1158}
1159
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001160static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001161FutureObj_get_loop(FutureObj *fut, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001162{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001163 if (!future_is_alive(fut)) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001164 Py_RETURN_NONE;
1165 }
1166 Py_INCREF(fut->fut_loop);
1167 return fut->fut_loop;
1168}
1169
1170static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001171FutureObj_get_callbacks(FutureObj *fut, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001172{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001173 Py_ssize_t i;
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001174
1175 ENSURE_FUTURE_ALIVE(fut)
1176
Yury Selivanovf23746a2018-01-22 19:11:18 -05001177 if (fut->fut_callback0 == NULL) {
1178 if (fut->fut_callbacks == NULL) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001179 Py_RETURN_NONE;
1180 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001181
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001182 Py_INCREF(fut->fut_callbacks);
1183 return fut->fut_callbacks;
1184 }
1185
Yury Selivanovf23746a2018-01-22 19:11:18 -05001186 Py_ssize_t len = 1;
1187 if (fut->fut_callbacks != NULL) {
1188 len += PyList_GET_SIZE(fut->fut_callbacks);
1189 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001190
Yury Selivanovf23746a2018-01-22 19:11:18 -05001191
1192 PyObject *new_list = PyList_New(len);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001193 if (new_list == NULL) {
1194 return NULL;
1195 }
1196
Yury Selivanovf23746a2018-01-22 19:11:18 -05001197 PyObject *tup0 = PyTuple_New(2);
1198 if (tup0 == NULL) {
1199 Py_DECREF(new_list);
1200 return NULL;
1201 }
1202
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001203 Py_INCREF(fut->fut_callback0);
Yury Selivanovf23746a2018-01-22 19:11:18 -05001204 PyTuple_SET_ITEM(tup0, 0, fut->fut_callback0);
1205 assert(fut->fut_context0 != NULL);
1206 Py_INCREF(fut->fut_context0);
1207 PyTuple_SET_ITEM(tup0, 1, (PyObject *)fut->fut_context0);
1208
1209 PyList_SET_ITEM(new_list, 0, tup0);
1210
1211 if (fut->fut_callbacks != NULL) {
1212 for (i = 0; i < PyList_GET_SIZE(fut->fut_callbacks); i++) {
1213 PyObject *cb = PyList_GET_ITEM(fut->fut_callbacks, i);
1214 Py_INCREF(cb);
1215 PyList_SET_ITEM(new_list, i + 1, cb);
1216 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001217 }
1218
1219 return new_list;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001220}
1221
1222static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001223FutureObj_get_result(FutureObj *fut, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001224{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001225 ENSURE_FUTURE_ALIVE(fut)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001226 if (fut->fut_result == NULL) {
1227 Py_RETURN_NONE;
1228 }
1229 Py_INCREF(fut->fut_result);
1230 return fut->fut_result;
1231}
1232
1233static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001234FutureObj_get_exception(FutureObj *fut, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001235{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001236 ENSURE_FUTURE_ALIVE(fut)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001237 if (fut->fut_exception == NULL) {
1238 Py_RETURN_NONE;
1239 }
1240 Py_INCREF(fut->fut_exception);
1241 return fut->fut_exception;
1242}
1243
1244static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001245FutureObj_get_source_traceback(FutureObj *fut, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001246{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001247 if (!future_is_alive(fut) || fut->fut_source_tb == NULL) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001248 Py_RETURN_NONE;
1249 }
1250 Py_INCREF(fut->fut_source_tb);
1251 return fut->fut_source_tb;
1252}
1253
1254static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001255FutureObj_get_state(FutureObj *fut, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001256{
1257 _Py_IDENTIFIER(PENDING);
1258 _Py_IDENTIFIER(CANCELLED);
1259 _Py_IDENTIFIER(FINISHED);
1260 PyObject *ret = NULL;
1261
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001262 ENSURE_FUTURE_ALIVE(fut)
1263
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001264 switch (fut->fut_state) {
1265 case STATE_PENDING:
1266 ret = _PyUnicode_FromId(&PyId_PENDING);
1267 break;
1268 case STATE_CANCELLED:
1269 ret = _PyUnicode_FromId(&PyId_CANCELLED);
1270 break;
1271 case STATE_FINISHED:
1272 ret = _PyUnicode_FromId(&PyId_FINISHED);
1273 break;
1274 default:
1275 assert (0);
1276 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03001277 Py_XINCREF(ret);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001278 return ret;
1279}
1280
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001281/*[clinic input]
1282_asyncio.Future._repr_info
1283[clinic start generated code]*/
1284
1285static PyObject *
1286_asyncio_Future__repr_info_impl(FutureObj *self)
1287/*[clinic end generated code: output=fa69e901bd176cfb input=f21504d8e2ae1ca2]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001288{
Victor Stinnerde4ae3d2016-12-04 22:59:09 +01001289 return PyObject_CallFunctionObjArgs(
1290 asyncio_future_repr_info_func, self, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001291}
1292
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001293static PyObject *
1294FutureObj_repr(FutureObj *fut)
1295{
1296 _Py_IDENTIFIER(_repr_info);
1297
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001298 ENSURE_FUTURE_ALIVE(fut)
1299
Serhiy Storchakabca49392017-09-03 08:10:14 +03001300 PyObject *rinfo = _PyObject_CallMethodIdObjArgs((PyObject*)fut,
1301 &PyId__repr_info,
1302 NULL);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001303 if (rinfo == NULL) {
1304 return NULL;
1305 }
1306
Serhiy Storchakabca49392017-09-03 08:10:14 +03001307 PyObject *rinfo_s = PyUnicode_Join(NULL, rinfo);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001308 Py_DECREF(rinfo);
1309 if (rinfo_s == NULL) {
1310 return NULL;
1311 }
1312
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03001313 PyObject *rstr = PyUnicode_FromFormat("<%s %U>",
1314 _PyType_Name(Py_TYPE(fut)), rinfo_s);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001315 Py_DECREF(rinfo_s);
1316 return rstr;
1317}
1318
1319static void
1320FutureObj_finalize(FutureObj *fut)
1321{
1322 _Py_IDENTIFIER(call_exception_handler);
1323 _Py_IDENTIFIER(message);
1324 _Py_IDENTIFIER(exception);
1325 _Py_IDENTIFIER(future);
1326 _Py_IDENTIFIER(source_traceback);
1327
Serhiy Storchakabca49392017-09-03 08:10:14 +03001328 PyObject *error_type, *error_value, *error_traceback;
1329 PyObject *context;
Serhiy Storchakabca49392017-09-03 08:10:14 +03001330 PyObject *message = NULL;
1331 PyObject *func;
1332
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001333 if (!fut->fut_log_tb) {
1334 return;
1335 }
1336 assert(fut->fut_exception != NULL);
Serhiy Storchakabca49392017-09-03 08:10:14 +03001337 fut->fut_log_tb = 0;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001338
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001339 /* Save the current exception, if any. */
1340 PyErr_Fetch(&error_type, &error_value, &error_traceback);
1341
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001342 context = PyDict_New();
1343 if (context == NULL) {
1344 goto finally;
1345 }
1346
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001347 message = PyUnicode_FromFormat(
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03001348 "%s exception was never retrieved", _PyType_Name(Py_TYPE(fut)));
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001349 if (message == NULL) {
1350 goto finally;
1351 }
1352
1353 if (_PyDict_SetItemId(context, &PyId_message, message) < 0 ||
1354 _PyDict_SetItemId(context, &PyId_exception, fut->fut_exception) < 0 ||
1355 _PyDict_SetItemId(context, &PyId_future, (PyObject*)fut) < 0) {
1356 goto finally;
1357 }
1358 if (fut->fut_source_tb != NULL) {
1359 if (_PyDict_SetItemId(context, &PyId_source_traceback,
1360 fut->fut_source_tb) < 0) {
1361 goto finally;
1362 }
1363 }
1364
1365 func = _PyObject_GetAttrId(fut->fut_loop, &PyId_call_exception_handler);
1366 if (func != NULL) {
Serhiy Storchakabca49392017-09-03 08:10:14 +03001367 PyObject *res = PyObject_CallFunctionObjArgs(func, context, NULL);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001368 if (res == NULL) {
1369 PyErr_WriteUnraisable(func);
1370 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03001371 else {
1372 Py_DECREF(res);
1373 }
1374 Py_DECREF(func);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001375 }
1376
1377finally:
Serhiy Storchakabca49392017-09-03 08:10:14 +03001378 Py_XDECREF(context);
1379 Py_XDECREF(message);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001380
1381 /* Restore the saved exception. */
1382 PyErr_Restore(error_type, error_value, error_traceback);
1383}
1384
1385
1386static PyAsyncMethods FutureType_as_async = {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001387 (unaryfunc)future_new_iter, /* am_await */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001388 0, /* am_aiter */
1389 0 /* am_anext */
1390};
1391
1392static PyMethodDef FutureType_methods[] = {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001393 _ASYNCIO_FUTURE_RESULT_METHODDEF
1394 _ASYNCIO_FUTURE_EXCEPTION_METHODDEF
1395 _ASYNCIO_FUTURE_SET_RESULT_METHODDEF
1396 _ASYNCIO_FUTURE_SET_EXCEPTION_METHODDEF
1397 _ASYNCIO_FUTURE_ADD_DONE_CALLBACK_METHODDEF
1398 _ASYNCIO_FUTURE_REMOVE_DONE_CALLBACK_METHODDEF
1399 _ASYNCIO_FUTURE_CANCEL_METHODDEF
1400 _ASYNCIO_FUTURE_CANCELLED_METHODDEF
1401 _ASYNCIO_FUTURE_DONE_METHODDEF
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001402 _ASYNCIO_FUTURE_GET_LOOP_METHODDEF
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001403 _ASYNCIO_FUTURE__REPR_INFO_METHODDEF
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001404 {NULL, NULL} /* Sentinel */
1405};
1406
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001407#define FUTURE_COMMON_GETSETLIST \
1408 {"_state", (getter)FutureObj_get_state, NULL, NULL}, \
1409 {"_asyncio_future_blocking", (getter)FutureObj_get_blocking, \
1410 (setter)FutureObj_set_blocking, NULL}, \
1411 {"_loop", (getter)FutureObj_get_loop, NULL, NULL}, \
1412 {"_callbacks", (getter)FutureObj_get_callbacks, NULL, NULL}, \
1413 {"_result", (getter)FutureObj_get_result, NULL, NULL}, \
1414 {"_exception", (getter)FutureObj_get_exception, NULL, NULL}, \
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +00001415 {"_log_traceback", (getter)FutureObj_get_log_traceback, \
1416 (setter)FutureObj_set_log_traceback, NULL}, \
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001417 {"_source_traceback", (getter)FutureObj_get_source_traceback, NULL, NULL},
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001418
1419static PyGetSetDef FutureType_getsetlist[] = {
1420 FUTURE_COMMON_GETSETLIST
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001421 {NULL} /* Sentinel */
1422};
1423
1424static void FutureObj_dealloc(PyObject *self);
1425
1426static PyTypeObject FutureType = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02001427 PyVarObject_HEAD_INIT(NULL, 0)
INADA Naoki9f2ce252016-10-15 15:39:19 +09001428 "_asyncio.Future",
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001429 sizeof(FutureObj), /* tp_basicsize */
1430 .tp_dealloc = FutureObj_dealloc,
1431 .tp_as_async = &FutureType_as_async,
1432 .tp_repr = (reprfunc)FutureObj_repr,
1433 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE
1434 | Py_TPFLAGS_HAVE_FINALIZE,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001435 .tp_doc = _asyncio_Future___init____doc__,
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001436 .tp_traverse = (traverseproc)FutureObj_traverse,
1437 .tp_clear = (inquiry)FutureObj_clear,
1438 .tp_weaklistoffset = offsetof(FutureObj, fut_weakreflist),
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001439 .tp_iter = (getiterfunc)future_new_iter,
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001440 .tp_methods = FutureType_methods,
1441 .tp_getset = FutureType_getsetlist,
1442 .tp_dictoffset = offsetof(FutureObj, dict),
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001443 .tp_init = (initproc)_asyncio_Future___init__,
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001444 .tp_new = PyType_GenericNew,
1445 .tp_finalize = (destructor)FutureObj_finalize,
1446};
1447
1448static void
1449FutureObj_dealloc(PyObject *self)
1450{
1451 FutureObj *fut = (FutureObj *)self;
1452
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001453 if (Future_CheckExact(fut)) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001454 /* When fut is subclass of Future, finalizer is called from
1455 * subtype_dealloc.
1456 */
1457 if (PyObject_CallFinalizerFromDealloc(self) < 0) {
1458 // resurrected.
1459 return;
1460 }
1461 }
1462
Alexander Mohrde34cbe2017-08-01 23:31:07 -07001463 PyObject_GC_UnTrack(self);
1464
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001465 if (fut->fut_weakreflist != NULL) {
1466 PyObject_ClearWeakRefs(self);
1467 }
1468
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001469 (void)FutureObj_clear(fut);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001470 Py_TYPE(fut)->tp_free(fut);
1471}
1472
1473
1474/*********************** Future Iterator **************************/
1475
1476typedef struct {
1477 PyObject_HEAD
1478 FutureObj *future;
1479} futureiterobject;
1480
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001481
1482#define FI_FREELIST_MAXLEN 255
1483static futureiterobject *fi_freelist = NULL;
1484static Py_ssize_t fi_freelist_len = 0;
1485
1486
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001487static void
1488FutureIter_dealloc(futureiterobject *it)
1489{
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001490 PyObject_GC_UnTrack(it);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001491 Py_CLEAR(it->future);
1492
1493 if (fi_freelist_len < FI_FREELIST_MAXLEN) {
1494 fi_freelist_len++;
1495 it->future = (FutureObj*) fi_freelist;
1496 fi_freelist = it;
1497 }
1498 else {
1499 PyObject_GC_Del(it);
1500 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001501}
1502
1503static PyObject *
1504FutureIter_iternext(futureiterobject *it)
1505{
1506 PyObject *res;
1507 FutureObj *fut = it->future;
1508
1509 if (fut == NULL) {
1510 return NULL;
1511 }
1512
1513 if (fut->fut_state == STATE_PENDING) {
1514 if (!fut->fut_blocking) {
1515 fut->fut_blocking = 1;
1516 Py_INCREF(fut);
1517 return (PyObject *)fut;
1518 }
Yury Selivanov0cf16f92017-12-25 10:48:15 -05001519 PyErr_SetString(PyExc_RuntimeError,
1520 "await wasn't used with future");
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001521 return NULL;
1522 }
1523
Serhiy Storchakabca49392017-09-03 08:10:14 +03001524 it->future = NULL;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001525 res = _asyncio_Future_result_impl(fut);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001526 if (res != NULL) {
Serhiy Storchaka60e49aa2016-11-06 18:47:03 +02001527 /* The result of the Future is not an exception. */
Serhiy Storchakabca49392017-09-03 08:10:14 +03001528 (void)_PyGen_SetStopIterationValue(res);
Serhiy Storchaka60e49aa2016-11-06 18:47:03 +02001529 Py_DECREF(res);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001530 }
1531
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001532 Py_DECREF(fut);
1533 return NULL;
1534}
1535
1536static PyObject *
INADA Naoki74c17532016-10-25 19:00:45 +09001537FutureIter_send(futureiterobject *self, PyObject *unused)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001538{
INADA Naoki74c17532016-10-25 19:00:45 +09001539 /* Future.__iter__ doesn't care about values that are pushed to the
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03001540 * generator, it just returns self.result().
INADA Naoki74c17532016-10-25 19:00:45 +09001541 */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001542 return FutureIter_iternext(self);
1543}
1544
1545static PyObject *
1546FutureIter_throw(futureiterobject *self, PyObject *args)
1547{
Serhiy Storchakabca49392017-09-03 08:10:14 +03001548 PyObject *type, *val = NULL, *tb = NULL;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001549 if (!PyArg_ParseTuple(args, "O|OO", &type, &val, &tb))
1550 return NULL;
1551
1552 if (val == Py_None) {
1553 val = NULL;
1554 }
1555 if (tb == Py_None) {
1556 tb = NULL;
Benjamin Peterson996fc1f2016-11-14 00:15:44 -08001557 } else if (tb != NULL && !PyTraceBack_Check(tb)) {
1558 PyErr_SetString(PyExc_TypeError, "throw() third argument must be a traceback");
1559 return NULL;
1560 }
1561
1562 Py_INCREF(type);
1563 Py_XINCREF(val);
1564 Py_XINCREF(tb);
1565
1566 if (PyExceptionClass_Check(type)) {
1567 PyErr_NormalizeException(&type, &val, &tb);
Yury Selivanovedfe8862016-12-01 11:37:47 -05001568 /* No need to call PyException_SetTraceback since we'll be calling
1569 PyErr_Restore for `type`, `val`, and `tb`. */
Benjamin Peterson996fc1f2016-11-14 00:15:44 -08001570 } else if (PyExceptionInstance_Check(type)) {
1571 if (val) {
1572 PyErr_SetString(PyExc_TypeError,
1573 "instance exception may not have a separate value");
1574 goto fail;
1575 }
1576 val = type;
1577 type = PyExceptionInstance_Class(type);
1578 Py_INCREF(type);
1579 if (tb == NULL)
1580 tb = PyException_GetTraceback(val);
1581 } else {
1582 PyErr_SetString(PyExc_TypeError,
1583 "exceptions must be classes deriving BaseException or "
1584 "instances of such a class");
1585 goto fail;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001586 }
1587
1588 Py_CLEAR(self->future);
1589
Benjamin Peterson996fc1f2016-11-14 00:15:44 -08001590 PyErr_Restore(type, val, tb);
1591
Serhiy Storchakabca49392017-09-03 08:10:14 +03001592 return NULL;
Benjamin Peterson996fc1f2016-11-14 00:15:44 -08001593
1594 fail:
1595 Py_DECREF(type);
1596 Py_XDECREF(val);
1597 Py_XDECREF(tb);
1598 return NULL;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001599}
1600
1601static PyObject *
1602FutureIter_close(futureiterobject *self, PyObject *arg)
1603{
1604 Py_CLEAR(self->future);
1605 Py_RETURN_NONE;
1606}
1607
1608static int
1609FutureIter_traverse(futureiterobject *it, visitproc visit, void *arg)
1610{
1611 Py_VISIT(it->future);
1612 return 0;
1613}
1614
1615static PyMethodDef FutureIter_methods[] = {
1616 {"send", (PyCFunction)FutureIter_send, METH_O, NULL},
1617 {"throw", (PyCFunction)FutureIter_throw, METH_VARARGS, NULL},
1618 {"close", (PyCFunction)FutureIter_close, METH_NOARGS, NULL},
1619 {NULL, NULL} /* Sentinel */
1620};
1621
1622static PyTypeObject FutureIterType = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02001623 PyVarObject_HEAD_INIT(NULL, 0)
INADA Naoki9f2ce252016-10-15 15:39:19 +09001624 "_asyncio.FutureIter",
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001625 .tp_basicsize = sizeof(futureiterobject),
1626 .tp_itemsize = 0,
1627 .tp_dealloc = (destructor)FutureIter_dealloc,
1628 .tp_getattro = PyObject_GenericGetAttr,
1629 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
1630 .tp_traverse = (traverseproc)FutureIter_traverse,
1631 .tp_iter = PyObject_SelfIter,
1632 .tp_iternext = (iternextfunc)FutureIter_iternext,
1633 .tp_methods = FutureIter_methods,
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001634};
1635
1636static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001637future_new_iter(PyObject *fut)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001638{
1639 futureiterobject *it;
1640
1641 if (!PyObject_TypeCheck(fut, &FutureType)) {
1642 PyErr_BadInternalCall();
1643 return NULL;
1644 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001645
1646 ENSURE_FUTURE_ALIVE(fut)
1647
1648 if (fi_freelist_len) {
1649 fi_freelist_len--;
1650 it = fi_freelist;
1651 fi_freelist = (futureiterobject*) it->future;
1652 it->future = NULL;
1653 _Py_NewReference((PyObject*) it);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001654 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001655 else {
1656 it = PyObject_GC_New(futureiterobject, &FutureIterType);
1657 if (it == NULL) {
1658 return NULL;
1659 }
1660 }
1661
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001662 Py_INCREF(fut);
1663 it->future = (FutureObj*)fut;
INADA Naoki1be427b2016-10-11 02:12:34 +09001664 PyObject_GC_Track(it);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001665 return (PyObject*)it;
1666}
1667
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001668
1669/*********************** Task **************************/
1670
1671
1672/*[clinic input]
1673class _asyncio.Task "TaskObj *" "&Task_Type"
1674[clinic start generated code]*/
1675/*[clinic end generated code: output=da39a3ee5e6b4b0d input=719dcef0fcc03b37]*/
1676
1677static int task_call_step_soon(TaskObj *, PyObject *);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001678static PyObject * task_wakeup(TaskObj *, PyObject *);
1679static PyObject * task_step(TaskObj *, PyObject *);
1680
1681/* ----- Task._step wrapper */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001682
INADA Naokic411a7d2016-10-18 11:48:14 +09001683static int
Serhiy Storchakabca49392017-09-03 08:10:14 +03001684TaskStepMethWrapper_clear(TaskStepMethWrapper *o)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001685{
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001686 Py_CLEAR(o->sw_task);
1687 Py_CLEAR(o->sw_arg);
1688 return 0;
1689}
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001690
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001691static void
Serhiy Storchakabca49392017-09-03 08:10:14 +03001692TaskStepMethWrapper_dealloc(TaskStepMethWrapper *o)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001693{
1694 PyObject_GC_UnTrack(o);
Serhiy Storchakabca49392017-09-03 08:10:14 +03001695 (void)TaskStepMethWrapper_clear(o);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001696 Py_TYPE(o)->tp_free(o);
1697}
1698
1699static PyObject *
Serhiy Storchakabca49392017-09-03 08:10:14 +03001700TaskStepMethWrapper_call(TaskStepMethWrapper *o,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001701 PyObject *args, PyObject *kwds)
1702{
Serhiy Storchakabca49392017-09-03 08:10:14 +03001703 if (kwds != NULL && PyDict_GET_SIZE(kwds) != 0) {
1704 PyErr_SetString(PyExc_TypeError, "function takes no keyword arguments");
1705 return NULL;
1706 }
1707 if (args != NULL && PyTuple_GET_SIZE(args) != 0) {
1708 PyErr_SetString(PyExc_TypeError, "function takes no positional arguments");
1709 return NULL;
1710 }
Yury Selivanov22feeb82018-01-24 11:31:01 -05001711 return task_step(o->sw_task, o->sw_arg);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001712}
1713
1714static int
Serhiy Storchakabca49392017-09-03 08:10:14 +03001715TaskStepMethWrapper_traverse(TaskStepMethWrapper *o,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001716 visitproc visit, void *arg)
1717{
1718 Py_VISIT(o->sw_task);
1719 Py_VISIT(o->sw_arg);
1720 return 0;
1721}
1722
1723static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001724TaskStepMethWrapper_get___self__(TaskStepMethWrapper *o, void *Py_UNUSED(ignored))
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001725{
1726 if (o->sw_task) {
1727 Py_INCREF(o->sw_task);
1728 return (PyObject*)o->sw_task;
1729 }
1730 Py_RETURN_NONE;
1731}
1732
Serhiy Storchakabca49392017-09-03 08:10:14 +03001733static PyGetSetDef TaskStepMethWrapper_getsetlist[] = {
1734 {"__self__", (getter)TaskStepMethWrapper_get___self__, NULL, NULL},
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001735 {NULL} /* Sentinel */
1736};
1737
Benjamin Peterson3c8aae92018-07-05 22:39:34 -07001738static PyTypeObject TaskStepMethWrapper_Type = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02001739 PyVarObject_HEAD_INIT(NULL, 0)
Serhiy Storchakabca49392017-09-03 08:10:14 +03001740 "TaskStepMethWrapper",
1741 .tp_basicsize = sizeof(TaskStepMethWrapper),
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001742 .tp_itemsize = 0,
Serhiy Storchakabca49392017-09-03 08:10:14 +03001743 .tp_getset = TaskStepMethWrapper_getsetlist,
1744 .tp_dealloc = (destructor)TaskStepMethWrapper_dealloc,
1745 .tp_call = (ternaryfunc)TaskStepMethWrapper_call,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001746 .tp_getattro = PyObject_GenericGetAttr,
1747 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
Serhiy Storchakabca49392017-09-03 08:10:14 +03001748 .tp_traverse = (traverseproc)TaskStepMethWrapper_traverse,
1749 .tp_clear = (inquiry)TaskStepMethWrapper_clear,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001750};
1751
1752static PyObject *
Serhiy Storchakabca49392017-09-03 08:10:14 +03001753TaskStepMethWrapper_new(TaskObj *task, PyObject *arg)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001754{
Serhiy Storchakabca49392017-09-03 08:10:14 +03001755 TaskStepMethWrapper *o;
1756 o = PyObject_GC_New(TaskStepMethWrapper, &TaskStepMethWrapper_Type);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001757 if (o == NULL) {
1758 return NULL;
1759 }
1760
1761 Py_INCREF(task);
1762 o->sw_task = task;
1763
1764 Py_XINCREF(arg);
1765 o->sw_arg = arg;
1766
1767 PyObject_GC_Track(o);
1768 return (PyObject*) o;
1769}
1770
1771/* ----- Task._wakeup wrapper */
1772
1773static PyObject *
1774TaskWakeupMethWrapper_call(TaskWakeupMethWrapper *o,
1775 PyObject *args, PyObject *kwds)
1776{
1777 PyObject *fut;
1778
Serhiy Storchakabca49392017-09-03 08:10:14 +03001779 if (kwds != NULL && PyDict_GET_SIZE(kwds) != 0) {
1780 PyErr_SetString(PyExc_TypeError, "function takes no keyword arguments");
1781 return NULL;
1782 }
1783 if (!PyArg_ParseTuple(args, "O", &fut)) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001784 return NULL;
1785 }
1786
Yury Selivanov22feeb82018-01-24 11:31:01 -05001787 return task_wakeup(o->ww_task, fut);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001788}
1789
1790static int
1791TaskWakeupMethWrapper_clear(TaskWakeupMethWrapper *o)
1792{
1793 Py_CLEAR(o->ww_task);
1794 return 0;
1795}
1796
1797static int
1798TaskWakeupMethWrapper_traverse(TaskWakeupMethWrapper *o,
1799 visitproc visit, void *arg)
1800{
1801 Py_VISIT(o->ww_task);
1802 return 0;
1803}
1804
1805static void
1806TaskWakeupMethWrapper_dealloc(TaskWakeupMethWrapper *o)
1807{
1808 PyObject_GC_UnTrack(o);
1809 (void)TaskWakeupMethWrapper_clear(o);
1810 Py_TYPE(o)->tp_free(o);
1811}
1812
Benjamin Peterson3c8aae92018-07-05 22:39:34 -07001813static PyTypeObject TaskWakeupMethWrapper_Type = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02001814 PyVarObject_HEAD_INIT(NULL, 0)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001815 "TaskWakeupMethWrapper",
1816 .tp_basicsize = sizeof(TaskWakeupMethWrapper),
1817 .tp_itemsize = 0,
1818 .tp_dealloc = (destructor)TaskWakeupMethWrapper_dealloc,
1819 .tp_call = (ternaryfunc)TaskWakeupMethWrapper_call,
1820 .tp_getattro = PyObject_GenericGetAttr,
1821 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
1822 .tp_traverse = (traverseproc)TaskWakeupMethWrapper_traverse,
1823 .tp_clear = (inquiry)TaskWakeupMethWrapper_clear,
1824};
1825
1826static PyObject *
1827TaskWakeupMethWrapper_new(TaskObj *task)
1828{
1829 TaskWakeupMethWrapper *o;
1830 o = PyObject_GC_New(TaskWakeupMethWrapper, &TaskWakeupMethWrapper_Type);
1831 if (o == NULL) {
1832 return NULL;
1833 }
1834
1835 Py_INCREF(task);
1836 o->ww_task = task;
1837
1838 PyObject_GC_Track(o);
1839 return (PyObject*) o;
1840}
1841
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001842/* ----- Task introspection helpers */
1843
1844static int
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001845register_task(PyObject *task)
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001846{
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001847 _Py_IDENTIFIER(add);
1848
1849 PyObject *res = _PyObject_CallMethodIdObjArgs(
1850 all_tasks, &PyId_add, task, NULL);
1851 if (res == NULL) {
1852 return -1;
1853 }
1854 Py_DECREF(res);
1855 return 0;
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001856}
1857
1858
1859static int
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001860unregister_task(PyObject *task)
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001861{
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001862 _Py_IDENTIFIER(discard);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001863
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001864 PyObject *res = _PyObject_CallMethodIdObjArgs(
1865 all_tasks, &PyId_discard, task, NULL);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001866 if (res == NULL) {
1867 return -1;
1868 }
1869 Py_DECREF(res);
1870 return 0;
1871}
1872
1873
1874static int
1875enter_task(PyObject *loop, PyObject *task)
1876{
1877 PyObject *item;
1878 Py_hash_t hash;
1879 hash = PyObject_Hash(loop);
1880 if (hash == -1) {
1881 return -1;
1882 }
1883 item = _PyDict_GetItem_KnownHash(current_tasks, loop, hash);
1884 if (item != NULL) {
Serhiy Storchaka66553542018-05-20 16:30:31 +03001885 Py_INCREF(item);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001886 PyErr_Format(
1887 PyExc_RuntimeError,
1888 "Cannot enter into task %R while another " \
1889 "task %R is being executed.",
1890 task, item, NULL);
Serhiy Storchaka66553542018-05-20 16:30:31 +03001891 Py_DECREF(item);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001892 return -1;
1893 }
Serhiy Storchaka66553542018-05-20 16:30:31 +03001894 if (PyErr_Occurred()) {
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001895 return -1;
1896 }
Serhiy Storchaka66553542018-05-20 16:30:31 +03001897 return _PyDict_SetItem_KnownHash(current_tasks, loop, task, hash);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001898}
1899
1900
1901static int
1902leave_task(PyObject *loop, PyObject *task)
1903/*[clinic end generated code: output=0ebf6db4b858fb41 input=51296a46313d1ad8]*/
1904{
1905 PyObject *item;
1906 Py_hash_t hash;
1907 hash = PyObject_Hash(loop);
1908 if (hash == -1) {
1909 return -1;
1910 }
1911 item = _PyDict_GetItem_KnownHash(current_tasks, loop, hash);
1912 if (item != task) {
1913 if (item == NULL) {
1914 /* Not entered, replace with None */
1915 item = Py_None;
1916 }
1917 PyErr_Format(
1918 PyExc_RuntimeError,
1919 "Leaving task %R does not match the current task %R.",
1920 task, item, NULL);
1921 return -1;
1922 }
1923 return _PyDict_DelItem_KnownHash(current_tasks, loop, hash);
1924}
1925
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001926/* ----- Task */
1927
1928/*[clinic input]
1929_asyncio.Task.__init__
1930
Serhiy Storchakabca49392017-09-03 08:10:14 +03001931 coro: object
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001932 *
Serhiy Storchakabca49392017-09-03 08:10:14 +03001933 loop: object = None
Alex Grönholmcca4eec2018-08-09 00:06:47 +03001934 name: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001935
1936A coroutine wrapped in a Future.
1937[clinic start generated code]*/
1938
1939static int
Alex Grönholmcca4eec2018-08-09 00:06:47 +03001940_asyncio_Task___init___impl(TaskObj *self, PyObject *coro, PyObject *loop,
1941 PyObject *name)
1942/*[clinic end generated code: output=88b12b83d570df50 input=352a3137fe60091d]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001943{
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001944 if (future_init((FutureObj*)self, loop)) {
INADA Naokic411a7d2016-10-18 11:48:14 +09001945 return -1;
1946 }
INADA Naokic411a7d2016-10-18 11:48:14 +09001947
Yury Selivanova9d7e552017-12-19 07:18:45 -05001948 int is_coro = is_coroutine(coro);
1949 if (is_coro == -1) {
1950 return -1;
1951 }
1952 if (is_coro == 0) {
1953 self->task_log_destroy_pending = 0;
1954 PyErr_Format(PyExc_TypeError,
1955 "a coroutine was expected, got %R",
1956 coro, NULL);
1957 return -1;
Andrew Svetlovf74ef452017-12-15 07:04:38 +02001958 }
1959
Oren Milmand019bc82018-02-13 12:28:33 +02001960 Py_XSETREF(self->task_context, PyContext_CopyCurrent());
Yury Selivanovf23746a2018-01-22 19:11:18 -05001961 if (self->task_context == NULL) {
1962 return -1;
1963 }
1964
Oren Milmand019bc82018-02-13 12:28:33 +02001965 Py_CLEAR(self->task_fut_waiter);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001966 self->task_must_cancel = 0;
1967 self->task_log_destroy_pending = 1;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001968 Py_INCREF(coro);
Oren Milmand019bc82018-02-13 12:28:33 +02001969 Py_XSETREF(self->task_coro, coro);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001970
Alex Grönholmcca4eec2018-08-09 00:06:47 +03001971 if (name == Py_None) {
1972 name = PyUnicode_FromFormat("Task-%" PRIu64, ++task_name_counter);
Alex Grönholma7548232018-08-09 23:49:49 +03001973 } else if (!PyUnicode_CheckExact(name)) {
Alex Grönholmcca4eec2018-08-09 00:06:47 +03001974 name = PyObject_Str(name);
1975 } else {
1976 Py_INCREF(name);
1977 }
1978 Py_XSETREF(self->task_name, name);
1979 if (self->task_name == NULL) {
1980 return -1;
1981 }
1982
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001983 if (task_call_step_soon(self, NULL)) {
1984 return -1;
INADA Naokic411a7d2016-10-18 11:48:14 +09001985 }
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001986 return register_task((PyObject*)self);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001987}
1988
1989static int
1990TaskObj_clear(TaskObj *task)
1991{
1992 (void)FutureObj_clear((FutureObj*) task);
Yury Selivanovf23746a2018-01-22 19:11:18 -05001993 Py_CLEAR(task->task_context);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001994 Py_CLEAR(task->task_coro);
Alex Grönholmcca4eec2018-08-09 00:06:47 +03001995 Py_CLEAR(task->task_name);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001996 Py_CLEAR(task->task_fut_waiter);
1997 return 0;
1998}
1999
2000static int
2001TaskObj_traverse(TaskObj *task, visitproc visit, void *arg)
2002{
Yury Selivanovf23746a2018-01-22 19:11:18 -05002003 Py_VISIT(task->task_context);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002004 Py_VISIT(task->task_coro);
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002005 Py_VISIT(task->task_name);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002006 Py_VISIT(task->task_fut_waiter);
2007 (void)FutureObj_traverse((FutureObj*) task, visit, arg);
2008 return 0;
2009}
2010
2011static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02002012TaskObj_get_log_destroy_pending(TaskObj *task, void *Py_UNUSED(ignored))
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002013{
2014 if (task->task_log_destroy_pending) {
2015 Py_RETURN_TRUE;
2016 }
2017 else {
2018 Py_RETURN_FALSE;
2019 }
2020}
2021
2022static int
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02002023TaskObj_set_log_destroy_pending(TaskObj *task, PyObject *val, void *Py_UNUSED(ignored))
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002024{
Zackery Spytz842acaa2018-12-17 07:52:45 -07002025 if (val == NULL) {
2026 PyErr_SetString(PyExc_AttributeError, "cannot delete attribute");
2027 return -1;
2028 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002029 int is_true = PyObject_IsTrue(val);
2030 if (is_true < 0) {
2031 return -1;
2032 }
2033 task->task_log_destroy_pending = is_true;
2034 return 0;
2035}
2036
2037static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02002038TaskObj_get_must_cancel(TaskObj *task, void *Py_UNUSED(ignored))
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002039{
2040 if (task->task_must_cancel) {
2041 Py_RETURN_TRUE;
2042 }
2043 else {
2044 Py_RETURN_FALSE;
2045 }
2046}
2047
2048static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02002049TaskObj_get_coro(TaskObj *task, void *Py_UNUSED(ignored))
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002050{
2051 if (task->task_coro) {
2052 Py_INCREF(task->task_coro);
2053 return task->task_coro;
2054 }
2055
2056 Py_RETURN_NONE;
2057}
2058
2059static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02002060TaskObj_get_fut_waiter(TaskObj *task, void *Py_UNUSED(ignored))
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002061{
2062 if (task->task_fut_waiter) {
2063 Py_INCREF(task->task_fut_waiter);
2064 return task->task_fut_waiter;
2065 }
2066
2067 Py_RETURN_NONE;
2068}
2069
2070/*[clinic input]
2071@classmethod
2072_asyncio.Task.current_task
2073
Serhiy Storchakabca49392017-09-03 08:10:14 +03002074 loop: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002075
2076Return the currently running task in an event loop or None.
2077
2078By default the current task for the current event loop is returned.
2079
2080None is returned when called not in the context of a Task.
2081[clinic start generated code]*/
2082
2083static PyObject *
2084_asyncio_Task_current_task_impl(PyTypeObject *type, PyObject *loop)
Serhiy Storchakabca49392017-09-03 08:10:14 +03002085/*[clinic end generated code: output=99fbe7332c516e03 input=cd14770c5b79c7eb]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002086{
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002087 PyObject *ret;
2088 PyObject *current_task_func;
2089
Inada Naokic5c6cda2019-03-22 20:07:32 +09002090 if (PyErr_WarnEx(PyExc_DeprecationWarning,
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002091 "Task.current_task() is deprecated, " \
2092 "use asyncio.current_task() instead",
2093 1) < 0) {
2094 return NULL;
2095 }
2096
2097 current_task_func = _PyObject_GetAttrId(asyncio_mod, &PyId_current_task);
2098 if (current_task_func == NULL) {
2099 return NULL;
2100 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002101
Yury Selivanov8d26aa92017-03-02 22:16:33 -05002102 if (loop == Py_None) {
Yury Selivanova70232f2017-12-13 14:49:42 -05002103 loop = get_event_loop();
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002104 if (loop == NULL) {
Serhiy Storchaka66553542018-05-20 16:30:31 +03002105 Py_DECREF(current_task_func);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002106 return NULL;
2107 }
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002108 ret = PyObject_CallFunctionObjArgs(current_task_func, loop, NULL);
2109 Py_DECREF(current_task_func);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002110 Py_DECREF(loop);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002111 return ret;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002112 }
2113 else {
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002114 ret = PyObject_CallFunctionObjArgs(current_task_func, loop, NULL);
2115 Py_DECREF(current_task_func);
2116 return ret;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002117 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002118}
2119
2120/*[clinic input]
2121@classmethod
2122_asyncio.Task.all_tasks
2123
Serhiy Storchakabca49392017-09-03 08:10:14 +03002124 loop: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002125
2126Return a set of all tasks for an event loop.
2127
2128By default all tasks for the current event loop are returned.
2129[clinic start generated code]*/
2130
2131static PyObject *
2132_asyncio_Task_all_tasks_impl(PyTypeObject *type, PyObject *loop)
Serhiy Storchakabca49392017-09-03 08:10:14 +03002133/*[clinic end generated code: output=11f9b20749ccca5d input=497f80bc9ce726b5]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002134{
2135 PyObject *res;
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002136 PyObject *all_tasks_func;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002137
Inada Naokic5c6cda2019-03-22 20:07:32 +09002138 if (PyErr_WarnEx(PyExc_DeprecationWarning,
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002139 "Task.all_tasks() is deprecated, " \
2140 "use asyncio.all_tasks() instead",
2141 1) < 0) {
2142 return NULL;
2143 }
2144
Yury Selivanov416c1eb2018-05-28 17:54:02 -04002145 all_tasks_func = _PyObject_GetAttrId(asyncio_mod, &PyId__all_tasks_compat);
Serhiy Storchaka66553542018-05-20 16:30:31 +03002146 if (all_tasks_func == NULL) {
2147 return NULL;
2148 }
2149
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002150 res = PyObject_CallFunctionObjArgs(all_tasks_func, loop, NULL);
2151 Py_DECREF(all_tasks_func);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002152 return res;
2153}
2154
2155/*[clinic input]
2156_asyncio.Task._repr_info
2157[clinic start generated code]*/
2158
2159static PyObject *
2160_asyncio_Task__repr_info_impl(TaskObj *self)
2161/*[clinic end generated code: output=6a490eb66d5ba34b input=3c6d051ed3ddec8b]*/
2162{
Victor Stinnerde4ae3d2016-12-04 22:59:09 +01002163 return PyObject_CallFunctionObjArgs(
2164 asyncio_task_repr_info_func, self, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002165}
2166
2167/*[clinic input]
2168_asyncio.Task.cancel
2169
2170Request that this task cancel itself.
2171
2172This arranges for a CancelledError to be thrown into the
2173wrapped coroutine on the next cycle through the event loop.
2174The coroutine then has a chance to clean up or even deny
2175the request using try/except/finally.
2176
2177Unlike Future.cancel, this does not guarantee that the
2178task will be cancelled: the exception might be caught and
2179acted upon, delaying cancellation of the task or preventing
2180cancellation completely. The task may also return a value or
2181raise a different exception.
2182
2183Immediately after this method is called, Task.cancelled() will
2184not return True (unless the task was already cancelled). A
2185task will be marked as cancelled when the wrapped coroutine
2186terminates with a CancelledError exception (even if cancel()
2187was not called).
2188[clinic start generated code]*/
2189
2190static PyObject *
2191_asyncio_Task_cancel_impl(TaskObj *self)
2192/*[clinic end generated code: output=6bfc0479da9d5757 input=13f9bf496695cb52]*/
2193{
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +00002194 self->task_log_tb = 0;
2195
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002196 if (self->task_state != STATE_PENDING) {
2197 Py_RETURN_FALSE;
2198 }
2199
2200 if (self->task_fut_waiter) {
2201 PyObject *res;
2202 int is_true;
2203
2204 res = _PyObject_CallMethodId(
2205 self->task_fut_waiter, &PyId_cancel, NULL);
2206 if (res == NULL) {
2207 return NULL;
2208 }
2209
2210 is_true = PyObject_IsTrue(res);
2211 Py_DECREF(res);
2212 if (is_true < 0) {
2213 return NULL;
2214 }
2215
2216 if (is_true) {
2217 Py_RETURN_TRUE;
2218 }
2219 }
2220
2221 self->task_must_cancel = 1;
2222 Py_RETURN_TRUE;
2223}
2224
2225/*[clinic input]
2226_asyncio.Task.get_stack
2227
2228 *
Serhiy Storchakabca49392017-09-03 08:10:14 +03002229 limit: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002230
2231Return the list of stack frames for this task's coroutine.
2232
2233If the coroutine is not done, this returns the stack where it is
2234suspended. If the coroutine has completed successfully or was
2235cancelled, this returns an empty list. If the coroutine was
2236terminated by an exception, this returns the list of traceback
2237frames.
2238
2239The frames are always ordered from oldest to newest.
2240
2241The optional limit gives the maximum number of frames to
2242return; by default all available frames are returned. Its
2243meaning differs depending on whether a stack or a traceback is
2244returned: the newest frames of a stack are returned, but the
2245oldest frames of a traceback are returned. (This matches the
2246behavior of the traceback module.)
2247
2248For reasons beyond our control, only one stack frame is
2249returned for a suspended coroutine.
2250[clinic start generated code]*/
2251
2252static PyObject *
2253_asyncio_Task_get_stack_impl(TaskObj *self, PyObject *limit)
Serhiy Storchakabca49392017-09-03 08:10:14 +03002254/*[clinic end generated code: output=c9aeeeebd1e18118 input=05b323d42b809b90]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002255{
2256 return PyObject_CallFunctionObjArgs(
2257 asyncio_task_get_stack_func, self, limit, NULL);
2258}
2259
2260/*[clinic input]
2261_asyncio.Task.print_stack
2262
2263 *
Serhiy Storchakabca49392017-09-03 08:10:14 +03002264 limit: object = None
2265 file: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002266
2267Print the stack or traceback for this task's coroutine.
2268
2269This produces output similar to that of the traceback module,
2270for the frames retrieved by get_stack(). The limit argument
2271is passed to get_stack(). The file argument is an I/O stream
2272to which the output is written; by default output is written
2273to sys.stderr.
2274[clinic start generated code]*/
2275
2276static PyObject *
2277_asyncio_Task_print_stack_impl(TaskObj *self, PyObject *limit,
2278 PyObject *file)
Serhiy Storchakabca49392017-09-03 08:10:14 +03002279/*[clinic end generated code: output=7339e10314cd3f4d input=1a0352913b7fcd92]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002280{
2281 return PyObject_CallFunctionObjArgs(
2282 asyncio_task_print_stack_func, self, limit, file, NULL);
2283}
2284
2285/*[clinic input]
Yury Selivanov0cf16f92017-12-25 10:48:15 -05002286_asyncio.Task.set_result
2287
2288 result: object
2289 /
2290[clinic start generated code]*/
2291
2292static PyObject *
2293_asyncio_Task_set_result(TaskObj *self, PyObject *result)
2294/*[clinic end generated code: output=1dcae308bfcba318 input=9d1a00c07be41bab]*/
2295{
2296 PyErr_SetString(PyExc_RuntimeError,
2297 "Task does not support set_result operation");
2298 return NULL;
2299}
2300
2301/*[clinic input]
2302_asyncio.Task.set_exception
2303
2304 exception: object
2305 /
2306[clinic start generated code]*/
2307
2308static PyObject *
2309_asyncio_Task_set_exception(TaskObj *self, PyObject *exception)
2310/*[clinic end generated code: output=bc377fc28067303d input=9a8f65c83dcf893a]*/
2311{
2312 PyErr_SetString(PyExc_RuntimeError,
Andrew Svetlovfc359322017-12-30 15:40:27 +02002313 "Task does not support set_exception operation");
Yury Selivanov0cf16f92017-12-25 10:48:15 -05002314 return NULL;
2315}
2316
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002317/*[clinic input]
2318_asyncio.Task.get_name
2319[clinic start generated code]*/
2320
2321static PyObject *
2322_asyncio_Task_get_name_impl(TaskObj *self)
2323/*[clinic end generated code: output=0ecf1570c3b37a8f input=a4a6595d12f4f0f8]*/
2324{
2325 if (self->task_name) {
2326 Py_INCREF(self->task_name);
2327 return self->task_name;
2328 }
2329
2330 Py_RETURN_NONE;
2331}
2332
2333/*[clinic input]
2334_asyncio.Task.set_name
2335
2336 value: object
2337 /
2338[clinic start generated code]*/
2339
2340static PyObject *
2341_asyncio_Task_set_name(TaskObj *self, PyObject *value)
2342/*[clinic end generated code: output=138a8d51e32057d6 input=a8359b6e65f8fd31]*/
2343{
Alex Grönholma7548232018-08-09 23:49:49 +03002344 if (!PyUnicode_CheckExact(value)) {
2345 value = PyObject_Str(value);
2346 if (value == NULL) {
2347 return NULL;
2348 }
2349 } else {
2350 Py_INCREF(value);
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002351 }
2352
Alex Grönholma7548232018-08-09 23:49:49 +03002353 Py_XSETREF(self->task_name, value);
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002354 Py_RETURN_NONE;
2355}
Yury Selivanov0cf16f92017-12-25 10:48:15 -05002356
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002357static void
2358TaskObj_finalize(TaskObj *task)
2359{
2360 _Py_IDENTIFIER(call_exception_handler);
2361 _Py_IDENTIFIER(task);
2362 _Py_IDENTIFIER(message);
2363 _Py_IDENTIFIER(source_traceback);
2364
Serhiy Storchakabca49392017-09-03 08:10:14 +03002365 PyObject *context;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002366 PyObject *message = NULL;
Serhiy Storchakabca49392017-09-03 08:10:14 +03002367 PyObject *func;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002368 PyObject *error_type, *error_value, *error_traceback;
2369
2370 if (task->task_state != STATE_PENDING || !task->task_log_destroy_pending) {
2371 goto done;
2372 }
2373
2374 /* Save the current exception, if any. */
2375 PyErr_Fetch(&error_type, &error_value, &error_traceback);
2376
2377 context = PyDict_New();
2378 if (context == NULL) {
2379 goto finally;
2380 }
2381
2382 message = PyUnicode_FromString("Task was destroyed but it is pending!");
2383 if (message == NULL) {
2384 goto finally;
2385 }
2386
2387 if (_PyDict_SetItemId(context, &PyId_message, message) < 0 ||
2388 _PyDict_SetItemId(context, &PyId_task, (PyObject*)task) < 0)
2389 {
2390 goto finally;
2391 }
2392
2393 if (task->task_source_tb != NULL) {
2394 if (_PyDict_SetItemId(context, &PyId_source_traceback,
2395 task->task_source_tb) < 0)
2396 {
2397 goto finally;
2398 }
2399 }
2400
2401 func = _PyObject_GetAttrId(task->task_loop, &PyId_call_exception_handler);
2402 if (func != NULL) {
Serhiy Storchakabca49392017-09-03 08:10:14 +03002403 PyObject *res = PyObject_CallFunctionObjArgs(func, context, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002404 if (res == NULL) {
2405 PyErr_WriteUnraisable(func);
2406 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03002407 else {
2408 Py_DECREF(res);
2409 }
2410 Py_DECREF(func);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002411 }
2412
2413finally:
Serhiy Storchakabca49392017-09-03 08:10:14 +03002414 Py_XDECREF(context);
2415 Py_XDECREF(message);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002416
2417 /* Restore the saved exception. */
2418 PyErr_Restore(error_type, error_value, error_traceback);
2419
2420done:
2421 FutureObj_finalize((FutureObj*)task);
2422}
2423
2424static void TaskObj_dealloc(PyObject *); /* Needs Task_CheckExact */
2425
2426static PyMethodDef TaskType_methods[] = {
2427 _ASYNCIO_FUTURE_RESULT_METHODDEF
2428 _ASYNCIO_FUTURE_EXCEPTION_METHODDEF
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002429 _ASYNCIO_FUTURE_ADD_DONE_CALLBACK_METHODDEF
2430 _ASYNCIO_FUTURE_REMOVE_DONE_CALLBACK_METHODDEF
2431 _ASYNCIO_FUTURE_CANCELLED_METHODDEF
2432 _ASYNCIO_FUTURE_DONE_METHODDEF
Yury Selivanov0cf16f92017-12-25 10:48:15 -05002433 _ASYNCIO_TASK_SET_RESULT_METHODDEF
2434 _ASYNCIO_TASK_SET_EXCEPTION_METHODDEF
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002435 _ASYNCIO_TASK_CURRENT_TASK_METHODDEF
2436 _ASYNCIO_TASK_ALL_TASKS_METHODDEF
2437 _ASYNCIO_TASK_CANCEL_METHODDEF
2438 _ASYNCIO_TASK_GET_STACK_METHODDEF
2439 _ASYNCIO_TASK_PRINT_STACK_METHODDEF
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002440 _ASYNCIO_TASK__REPR_INFO_METHODDEF
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002441 _ASYNCIO_TASK_GET_NAME_METHODDEF
2442 _ASYNCIO_TASK_SET_NAME_METHODDEF
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002443 {NULL, NULL} /* Sentinel */
2444};
2445
2446static PyGetSetDef TaskType_getsetlist[] = {
2447 FUTURE_COMMON_GETSETLIST
2448 {"_log_destroy_pending", (getter)TaskObj_get_log_destroy_pending,
2449 (setter)TaskObj_set_log_destroy_pending, NULL},
2450 {"_must_cancel", (getter)TaskObj_get_must_cancel, NULL, NULL},
2451 {"_coro", (getter)TaskObj_get_coro, NULL, NULL},
2452 {"_fut_waiter", (getter)TaskObj_get_fut_waiter, NULL, NULL},
2453 {NULL} /* Sentinel */
2454};
2455
2456static PyTypeObject TaskType = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02002457 PyVarObject_HEAD_INIT(NULL, 0)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002458 "_asyncio.Task",
2459 sizeof(TaskObj), /* tp_basicsize */
2460 .tp_base = &FutureType,
2461 .tp_dealloc = TaskObj_dealloc,
2462 .tp_as_async = &FutureType_as_async,
2463 .tp_repr = (reprfunc)FutureObj_repr,
2464 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE
2465 | Py_TPFLAGS_HAVE_FINALIZE,
2466 .tp_doc = _asyncio_Task___init____doc__,
2467 .tp_traverse = (traverseproc)TaskObj_traverse,
2468 .tp_clear = (inquiry)TaskObj_clear,
2469 .tp_weaklistoffset = offsetof(TaskObj, task_weakreflist),
2470 .tp_iter = (getiterfunc)future_new_iter,
2471 .tp_methods = TaskType_methods,
2472 .tp_getset = TaskType_getsetlist,
2473 .tp_dictoffset = offsetof(TaskObj, dict),
2474 .tp_init = (initproc)_asyncio_Task___init__,
2475 .tp_new = PyType_GenericNew,
2476 .tp_finalize = (destructor)TaskObj_finalize,
2477};
2478
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002479static void
2480TaskObj_dealloc(PyObject *self)
2481{
2482 TaskObj *task = (TaskObj *)self;
2483
2484 if (Task_CheckExact(self)) {
2485 /* When fut is subclass of Task, finalizer is called from
2486 * subtype_dealloc.
2487 */
2488 if (PyObject_CallFinalizerFromDealloc(self) < 0) {
2489 // resurrected.
2490 return;
2491 }
2492 }
2493
Alexander Mohrde34cbe2017-08-01 23:31:07 -07002494 PyObject_GC_UnTrack(self);
2495
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002496 if (task->task_weakreflist != NULL) {
2497 PyObject_ClearWeakRefs(self);
2498 }
2499
2500 (void)TaskObj_clear(task);
2501 Py_TYPE(task)->tp_free(task);
2502}
2503
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002504static int
2505task_call_step_soon(TaskObj *task, PyObject *arg)
2506{
Serhiy Storchakabca49392017-09-03 08:10:14 +03002507 PyObject *cb = TaskStepMethWrapper_new(task, arg);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002508 if (cb == NULL) {
2509 return -1;
2510 }
2511
Yury Selivanovf23746a2018-01-22 19:11:18 -05002512 int ret = call_soon(task->task_loop, cb, NULL, task->task_context);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002513 Py_DECREF(cb);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05002514 return ret;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002515}
2516
2517static PyObject *
2518task_set_error_soon(TaskObj *task, PyObject *et, const char *format, ...)
2519{
2520 PyObject* msg;
2521
2522 va_list vargs;
2523#ifdef HAVE_STDARG_PROTOTYPES
2524 va_start(vargs, format);
2525#else
2526 va_start(vargs);
2527#endif
2528 msg = PyUnicode_FromFormatV(format, vargs);
2529 va_end(vargs);
2530
2531 if (msg == NULL) {
2532 return NULL;
2533 }
2534
Victor Stinnerde4ae3d2016-12-04 22:59:09 +01002535 PyObject *e = PyObject_CallFunctionObjArgs(et, msg, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002536 Py_DECREF(msg);
2537 if (e == NULL) {
2538 return NULL;
2539 }
2540
2541 if (task_call_step_soon(task, e) == -1) {
2542 Py_DECREF(e);
2543 return NULL;
2544 }
2545
2546 Py_DECREF(e);
2547 Py_RETURN_NONE;
2548}
2549
2550static PyObject *
2551task_step_impl(TaskObj *task, PyObject *exc)
2552{
2553 int res;
2554 int clear_exc = 0;
2555 PyObject *result = NULL;
Serhiy Storchakabca49392017-09-03 08:10:14 +03002556 PyObject *coro;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002557 PyObject *o;
2558
2559 if (task->task_state != STATE_PENDING) {
Yury Selivanov0cf16f92017-12-25 10:48:15 -05002560 PyErr_Format(asyncio_InvalidStateError,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002561 "_step(): already done: %R %R",
2562 task,
2563 exc ? exc : Py_None);
INADA Naokic411a7d2016-10-18 11:48:14 +09002564 goto fail;
2565 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09002566
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002567 if (task->task_must_cancel) {
2568 assert(exc != Py_None);
2569
2570 if (exc) {
2571 /* Check if exc is a CancelledError */
2572 res = PyObject_IsInstance(exc, asyncio_CancelledError);
2573 if (res == -1) {
2574 /* An error occurred, abort */
2575 goto fail;
2576 }
2577 if (res == 0) {
2578 /* exc is not CancelledError; reset it to NULL */
2579 exc = NULL;
2580 }
2581 }
2582
2583 if (!exc) {
2584 /* exc was not a CancelledError */
Victor Stinnerf17c3de2016-12-06 18:46:19 +01002585 exc = _PyObject_CallNoArg(asyncio_CancelledError);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002586 if (!exc) {
2587 goto fail;
2588 }
2589 clear_exc = 1;
2590 }
2591
2592 task->task_must_cancel = 0;
2593 }
2594
2595 Py_CLEAR(task->task_fut_waiter);
2596
Serhiy Storchakabca49392017-09-03 08:10:14 +03002597 coro = task->task_coro;
2598 if (coro == NULL) {
2599 PyErr_SetString(PyExc_RuntimeError, "uninitialized Task object");
2600 return NULL;
2601 }
2602
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002603 if (exc == NULL) {
2604 if (PyGen_CheckExact(coro) || PyCoro_CheckExact(coro)) {
2605 result = _PyGen_Send((PyGenObject*)coro, Py_None);
2606 }
2607 else {
Victor Stinnerb6ed57d2016-12-09 14:24:02 +01002608 result = _PyObject_CallMethodIdObjArgs(coro, &PyId_send,
2609 Py_None, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002610 }
2611 }
2612 else {
Victor Stinnerb6ed57d2016-12-09 14:24:02 +01002613 result = _PyObject_CallMethodIdObjArgs(coro, &PyId_throw,
2614 exc, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002615 if (clear_exc) {
2616 /* We created 'exc' during this call */
Serhiy Storchakabca49392017-09-03 08:10:14 +03002617 Py_DECREF(exc);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002618 }
2619 }
2620
2621 if (result == NULL) {
2622 PyObject *et, *ev, *tb;
2623
2624 if (_PyGen_FetchStopIterationValue(&o) == 0) {
2625 /* The error is StopIteration and that means that
2626 the underlying coroutine has resolved */
INADA Naoki991adca2017-05-11 21:18:38 +09002627 if (task->task_must_cancel) {
2628 // Task is cancelled right before coro stops.
2629 Py_DECREF(o);
2630 task->task_must_cancel = 0;
2631 et = asyncio_CancelledError;
2632 Py_INCREF(et);
2633 ev = NULL;
2634 tb = NULL;
2635 goto set_exception;
2636 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002637 PyObject *res = future_set_result((FutureObj*)task, o);
2638 Py_DECREF(o);
2639 if (res == NULL) {
2640 return NULL;
2641 }
2642 Py_DECREF(res);
2643 Py_RETURN_NONE;
2644 }
2645
2646 if (PyErr_ExceptionMatches(asyncio_CancelledError)) {
2647 /* CancelledError */
2648 PyErr_Clear();
2649 return future_cancel((FutureObj*)task);
2650 }
2651
2652 /* Some other exception; pop it and call Task.set_exception() */
2653 PyErr_Fetch(&et, &ev, &tb);
INADA Naoki991adca2017-05-11 21:18:38 +09002654
2655set_exception:
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002656 assert(et);
2657 if (!ev || !PyObject_TypeCheck(ev, (PyTypeObject *) et)) {
2658 PyErr_NormalizeException(&et, &ev, &tb);
2659 }
Yury Selivanovedfe8862016-12-01 11:37:47 -05002660 if (tb != NULL) {
2661 PyException_SetTraceback(ev, tb);
2662 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002663 o = future_set_exception((FutureObj*)task, ev);
2664 if (!o) {
2665 /* An exception in Task.set_exception() */
Serhiy Storchakabca49392017-09-03 08:10:14 +03002666 Py_DECREF(et);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002667 Py_XDECREF(tb);
2668 Py_XDECREF(ev);
2669 goto fail;
2670 }
2671 assert(o == Py_None);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002672 Py_DECREF(o);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002673
Yury Selivanov431b5402019-05-27 14:45:12 +02002674 if (PyErr_GivenExceptionMatches(et, PyExc_KeyboardInterrupt) ||
2675 PyErr_GivenExceptionMatches(et, PyExc_SystemExit))
2676 {
2677 /* We've got a KeyboardInterrupt or a SystemError; re-raise it */
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002678 PyErr_Restore(et, ev, tb);
2679 goto fail;
2680 }
2681
Serhiy Storchakabca49392017-09-03 08:10:14 +03002682 Py_DECREF(et);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002683 Py_XDECREF(tb);
2684 Py_XDECREF(ev);
2685
2686 Py_RETURN_NONE;
2687 }
2688
2689 if (result == (PyObject*)task) {
2690 /* We have a task that wants to await on itself */
2691 goto self_await;
2692 }
2693
2694 /* Check if `result` is FutureObj or TaskObj (and not a subclass) */
2695 if (Future_CheckExact(result) || Task_CheckExact(result)) {
2696 PyObject *wrapper;
2697 PyObject *res;
2698 FutureObj *fut = (FutureObj*)result;
2699
2700 /* Check if `result` future is attached to a different loop */
2701 if (fut->fut_loop != task->task_loop) {
2702 goto different_loop;
2703 }
2704
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002705 if (!fut->fut_blocking) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002706 goto yield_insteadof_yf;
2707 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002708
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002709 fut->fut_blocking = 0;
2710
2711 /* result.add_done_callback(task._wakeup) */
2712 wrapper = TaskWakeupMethWrapper_new(task);
2713 if (wrapper == NULL) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002714 goto fail;
2715 }
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002716 res = future_add_done_callback(
2717 (FutureObj*)result, wrapper, task->task_context);
2718 Py_DECREF(wrapper);
2719 if (res == NULL) {
2720 goto fail;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002721 }
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002722 Py_DECREF(res);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002723
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002724 /* task._fut_waiter = result */
2725 task->task_fut_waiter = result; /* no incref is necessary */
2726
2727 if (task->task_must_cancel) {
2728 PyObject *r;
Elvis Pranskevichus0c797a62018-10-03 10:30:31 -04002729 int is_true;
Serhiy Storchakaaddf8af2018-10-05 21:20:02 +03002730 r = _PyObject_CallMethodId(result, &PyId_cancel, NULL);
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002731 if (r == NULL) {
2732 return NULL;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002733 }
Elvis Pranskevichus0c797a62018-10-03 10:30:31 -04002734 is_true = PyObject_IsTrue(r);
2735 Py_DECREF(r);
2736 if (is_true < 0) {
2737 return NULL;
2738 }
2739 else if (is_true) {
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002740 task->task_must_cancel = 0;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002741 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002742 }
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002743
2744 Py_RETURN_NONE;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002745 }
2746
2747 /* Check if `result` is None */
2748 if (result == Py_None) {
2749 /* Bare yield relinquishes control for one event loop iteration. */
2750 if (task_call_step_soon(task, NULL)) {
2751 goto fail;
2752 }
2753 return result;
2754 }
2755
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002756 /* Check if `result` is a Future-compatible object */
2757 if (_PyObject_LookupAttrId(result, &PyId__asyncio_future_blocking, &o) < 0) {
2758 goto fail;
2759 }
2760 if (o != NULL && o != Py_None) {
2761 /* `result` is a Future-compatible object */
2762 PyObject *wrapper;
2763 PyObject *res;
2764
2765 int blocking = PyObject_IsTrue(o);
2766 Py_DECREF(o);
2767 if (blocking < 0) {
2768 goto fail;
2769 }
2770
2771 /* Check if `result` future is attached to a different loop */
2772 PyObject *oloop = get_future_loop(result);
2773 if (oloop == NULL) {
2774 goto fail;
2775 }
2776 if (oloop != task->task_loop) {
2777 Py_DECREF(oloop);
2778 goto different_loop;
2779 }
2780 Py_DECREF(oloop);
2781
2782 if (!blocking) {
2783 goto yield_insteadof_yf;
2784 }
2785
2786 /* result._asyncio_future_blocking = False */
2787 if (_PyObject_SetAttrId(
2788 result, &PyId__asyncio_future_blocking, Py_False) == -1) {
2789 goto fail;
2790 }
2791
2792 wrapper = TaskWakeupMethWrapper_new(task);
2793 if (wrapper == NULL) {
2794 goto fail;
2795 }
2796
2797 /* result.add_done_callback(task._wakeup) */
2798 PyObject *add_cb = _PyObject_GetAttrId(
2799 result, &PyId_add_done_callback);
2800 if (add_cb == NULL) {
2801 Py_DECREF(wrapper);
2802 goto fail;
2803 }
2804 PyObject *stack[2];
2805 stack[0] = wrapper;
2806 stack[1] = (PyObject *)task->task_context;
Jeroen Demeyeraacc77f2019-05-29 20:31:52 +02002807 res = _PyObject_Vectorcall(add_cb, stack, 1, context_kwname);
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002808 Py_DECREF(add_cb);
2809 Py_DECREF(wrapper);
2810 if (res == NULL) {
2811 goto fail;
2812 }
2813 Py_DECREF(res);
2814
2815 /* task._fut_waiter = result */
2816 task->task_fut_waiter = result; /* no incref is necessary */
2817
2818 if (task->task_must_cancel) {
2819 PyObject *r;
2820 int is_true;
2821 r = _PyObject_CallMethodId(result, &PyId_cancel, NULL);
2822 if (r == NULL) {
2823 return NULL;
2824 }
2825 is_true = PyObject_IsTrue(r);
2826 Py_DECREF(r);
2827 if (is_true < 0) {
2828 return NULL;
2829 }
2830 else if (is_true) {
2831 task->task_must_cancel = 0;
2832 }
2833 }
2834
2835 Py_RETURN_NONE;
2836 }
2837
2838 Py_XDECREF(o);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002839 /* Check if `result` is a generator */
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002840 res = PyObject_IsInstance(result, (PyObject*)&PyGen_Type);
2841 if (res < 0) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002842 goto fail;
2843 }
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002844 if (res) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002845 /* `result` is a generator */
Serhiy Storchaka66553542018-05-20 16:30:31 +03002846 o = task_set_error_soon(
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002847 task, PyExc_RuntimeError,
2848 "yield was used instead of yield from for "
Serhiy Storchaka66553542018-05-20 16:30:31 +03002849 "generator in task %R with %R", task, result);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002850 Py_DECREF(result);
Serhiy Storchaka66553542018-05-20 16:30:31 +03002851 return o;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002852 }
2853
2854 /* The `result` is none of the above */
Serhiy Storchaka66553542018-05-20 16:30:31 +03002855 o = task_set_error_soon(
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002856 task, PyExc_RuntimeError, "Task got bad yield: %R", result);
Serhiy Storchaka66553542018-05-20 16:30:31 +03002857 Py_DECREF(result);
2858 return o;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002859
2860self_await:
2861 o = task_set_error_soon(
2862 task, PyExc_RuntimeError,
2863 "Task cannot await on itself: %R", task);
2864 Py_DECREF(result);
2865 return o;
2866
2867yield_insteadof_yf:
2868 o = task_set_error_soon(
2869 task, PyExc_RuntimeError,
2870 "yield was used instead of yield from "
2871 "in task %R with %R",
2872 task, result);
2873 Py_DECREF(result);
2874 return o;
2875
2876different_loop:
2877 o = task_set_error_soon(
2878 task, PyExc_RuntimeError,
2879 "Task %R got Future %R attached to a different loop",
2880 task, result);
2881 Py_DECREF(result);
2882 return o;
2883
2884fail:
2885 Py_XDECREF(result);
2886 return NULL;
2887}
2888
2889static PyObject *
2890task_step(TaskObj *task, PyObject *exc)
2891{
2892 PyObject *res;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002893
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002894 if (enter_task(task->task_loop, (PyObject*)task) < 0) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002895 return NULL;
2896 }
2897
2898 res = task_step_impl(task, exc);
2899
2900 if (res == NULL) {
2901 PyObject *et, *ev, *tb;
2902 PyErr_Fetch(&et, &ev, &tb);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002903 leave_task(task->task_loop, (PyObject*)task);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002904 _PyErr_ChainExceptions(et, ev, tb);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002905 return NULL;
2906 }
2907 else {
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002908 if (leave_task(task->task_loop, (PyObject*)task) < 0) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002909 Py_DECREF(res);
2910 return NULL;
2911 }
2912 else {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002913 return res;
2914 }
2915 }
2916}
2917
2918static PyObject *
2919task_wakeup(TaskObj *task, PyObject *o)
2920{
Serhiy Storchakabca49392017-09-03 08:10:14 +03002921 PyObject *et, *ev, *tb;
2922 PyObject *result;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002923 assert(o);
2924
2925 if (Future_CheckExact(o) || Task_CheckExact(o)) {
2926 PyObject *fut_result = NULL;
2927 int res = future_get_result((FutureObj*)o, &fut_result);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002928
2929 switch(res) {
2930 case -1:
2931 assert(fut_result == NULL);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002932 break; /* exception raised */
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002933 case 0:
2934 Py_DECREF(fut_result);
Yury Selivanov22feeb82018-01-24 11:31:01 -05002935 return task_step(task, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002936 default:
2937 assert(res == 1);
Yury Selivanov22feeb82018-01-24 11:31:01 -05002938 result = task_step(task, fut_result);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002939 Py_DECREF(fut_result);
2940 return result;
2941 }
2942 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002943 else {
Serhiy Storchakabca49392017-09-03 08:10:14 +03002944 PyObject *fut_result = PyObject_CallMethod(o, "result", NULL);
2945 if (fut_result != NULL) {
2946 Py_DECREF(fut_result);
Yury Selivanov22feeb82018-01-24 11:31:01 -05002947 return task_step(task, NULL);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002948 }
2949 /* exception raised */
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002950 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03002951
2952 PyErr_Fetch(&et, &ev, &tb);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002953 if (!ev || !PyObject_TypeCheck(ev, (PyTypeObject *) et)) {
2954 PyErr_NormalizeException(&et, &ev, &tb);
2955 }
2956
Yury Selivanov22feeb82018-01-24 11:31:01 -05002957 result = task_step(task, ev);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002958
2959 Py_DECREF(et);
2960 Py_XDECREF(tb);
2961 Py_XDECREF(ev);
2962
2963 return result;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002964}
2965
2966
Yury Selivanova70232f2017-12-13 14:49:42 -05002967/*********************** Functions **************************/
2968
2969
2970/*[clinic input]
2971_asyncio._get_running_loop
2972
2973Return the running event loop or None.
2974
2975This is a low-level function intended to be used by event loops.
2976This function is thread-specific.
2977
2978[clinic start generated code]*/
2979
2980static PyObject *
2981_asyncio__get_running_loop_impl(PyObject *module)
2982/*[clinic end generated code: output=b4390af721411a0a input=0a21627e25a4bd43]*/
2983{
2984 PyObject *loop;
2985 if (get_running_loop(&loop)) {
2986 return NULL;
2987 }
2988 if (loop == NULL) {
2989 /* There's no currently running event loop */
2990 Py_RETURN_NONE;
2991 }
2992 return loop;
2993}
2994
2995/*[clinic input]
2996_asyncio._set_running_loop
2997 loop: 'O'
2998 /
2999
3000Set the running event loop.
3001
3002This is a low-level function intended to be used by event loops.
3003This function is thread-specific.
3004[clinic start generated code]*/
3005
3006static PyObject *
3007_asyncio__set_running_loop(PyObject *module, PyObject *loop)
3008/*[clinic end generated code: output=ae56bf7a28ca189a input=4c9720233d606604]*/
3009{
3010 if (set_running_loop(loop)) {
3011 return NULL;
3012 }
3013 Py_RETURN_NONE;
3014}
3015
3016/*[clinic input]
3017_asyncio.get_event_loop
3018
3019Return an asyncio event loop.
3020
3021When called from a coroutine or a callback (e.g. scheduled with
3022call_soon or similar API), this function will always return the
3023running event loop.
3024
3025If there is no running event loop set, the function will return
3026the result of `get_event_loop_policy().get_event_loop()` call.
3027[clinic start generated code]*/
3028
3029static PyObject *
3030_asyncio_get_event_loop_impl(PyObject *module)
3031/*[clinic end generated code: output=2a2d8b2f824c648b input=9364bf2916c8655d]*/
3032{
3033 return get_event_loop();
3034}
3035
3036/*[clinic input]
3037_asyncio.get_running_loop
3038
3039Return the running event loop. Raise a RuntimeError if there is none.
3040
3041This function is thread-specific.
3042[clinic start generated code]*/
3043
3044static PyObject *
3045_asyncio_get_running_loop_impl(PyObject *module)
3046/*[clinic end generated code: output=c247b5f9e529530e input=2a3bf02ba39f173d]*/
3047{
3048 PyObject *loop;
3049 if (get_running_loop(&loop)) {
3050 return NULL;
3051 }
3052 if (loop == NULL) {
3053 /* There's no currently running event loop */
3054 PyErr_SetString(
3055 PyExc_RuntimeError, "no running event loop");
3056 }
3057 return loop;
3058}
3059
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003060/*[clinic input]
3061_asyncio._register_task
3062
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003063 task: object
3064
3065Register a new task in asyncio as executed by loop.
3066
3067Returns None.
3068[clinic start generated code]*/
3069
3070static PyObject *
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003071_asyncio__register_task_impl(PyObject *module, PyObject *task)
3072/*[clinic end generated code: output=8672dadd69a7d4e2 input=21075aaea14dfbad]*/
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003073{
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003074 if (register_task(task) < 0) {
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003075 return NULL;
3076 }
3077 Py_RETURN_NONE;
3078}
3079
3080
3081/*[clinic input]
3082_asyncio._unregister_task
3083
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003084 task: object
3085
3086Unregister a task.
3087
3088Returns None.
3089[clinic start generated code]*/
3090
3091static PyObject *
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003092_asyncio__unregister_task_impl(PyObject *module, PyObject *task)
3093/*[clinic end generated code: output=6e5585706d568a46 input=28fb98c3975f7bdc]*/
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003094{
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003095 if (unregister_task(task) < 0) {
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003096 return NULL;
3097 }
3098 Py_RETURN_NONE;
3099}
3100
3101
3102/*[clinic input]
3103_asyncio._enter_task
3104
3105 loop: object
3106 task: object
3107
3108Enter into task execution or resume suspended task.
3109
3110Task belongs to loop.
3111
3112Returns None.
3113[clinic start generated code]*/
3114
3115static PyObject *
3116_asyncio__enter_task_impl(PyObject *module, PyObject *loop, PyObject *task)
3117/*[clinic end generated code: output=a22611c858035b73 input=de1b06dca70d8737]*/
3118{
3119 if (enter_task(loop, task) < 0) {
3120 return NULL;
3121 }
3122 Py_RETURN_NONE;
3123}
3124
3125
3126/*[clinic input]
3127_asyncio._leave_task
3128
3129 loop: object
3130 task: object
3131
3132Leave task execution or suspend a task.
3133
3134Task belongs to loop.
3135
3136Returns None.
3137[clinic start generated code]*/
3138
3139static PyObject *
3140_asyncio__leave_task_impl(PyObject *module, PyObject *loop, PyObject *task)
3141/*[clinic end generated code: output=0ebf6db4b858fb41 input=51296a46313d1ad8]*/
3142{
3143 if (leave_task(loop, task) < 0) {
3144 return NULL;
3145 }
3146 Py_RETURN_NONE;
3147}
3148
Yury Selivanova70232f2017-12-13 14:49:42 -05003149
Yury Selivanov9d411c12018-01-23 15:10:03 -05003150/*********************** PyRunningLoopHolder ********************/
3151
3152
3153static PyRunningLoopHolder *
3154new_running_loop_holder(PyObject *loop)
3155{
3156 PyRunningLoopHolder *rl = PyObject_New(
3157 PyRunningLoopHolder, &PyRunningLoopHolder_Type);
3158 if (rl == NULL) {
3159 return NULL;
3160 }
3161
3162#if defined(HAVE_GETPID) && !defined(MS_WINDOWS)
3163 rl->rl_pid = getpid();
3164#endif
3165
3166 Py_INCREF(loop);
3167 rl->rl_loop = loop;
3168
3169 return rl;
3170}
3171
3172
3173static void
3174PyRunningLoopHolder_tp_dealloc(PyRunningLoopHolder *rl)
3175{
3176 Py_CLEAR(rl->rl_loop);
3177 PyObject_Free(rl);
3178}
3179
3180
3181static PyTypeObject PyRunningLoopHolder_Type = {
3182 PyVarObject_HEAD_INIT(NULL, 0)
3183 "_RunningLoopHolder",
3184 sizeof(PyRunningLoopHolder),
3185 .tp_getattro = PyObject_GenericGetAttr,
3186 .tp_flags = Py_TPFLAGS_DEFAULT,
3187 .tp_dealloc = (destructor)PyRunningLoopHolder_tp_dealloc,
3188};
3189
3190
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003191/*********************** Module **************************/
3192
3193
3194static void
Zackery Spytze40ad792017-12-19 11:48:13 -07003195module_free_freelists(void)
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05003196{
3197 PyObject *next;
3198 PyObject *current;
3199
3200 next = (PyObject*) fi_freelist;
3201 while (next != NULL) {
3202 assert(fi_freelist_len > 0);
3203 fi_freelist_len--;
3204
3205 current = next;
3206 next = (PyObject*) ((futureiterobject*) current)->future;
3207 PyObject_GC_Del(current);
3208 }
3209 assert(fi_freelist_len == 0);
3210 fi_freelist = NULL;
3211}
3212
3213
3214static void
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003215module_free(void *m)
3216{
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003217 Py_CLEAR(asyncio_mod);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003218 Py_CLEAR(traceback_extract_stack);
3219 Py_CLEAR(asyncio_future_repr_info_func);
3220 Py_CLEAR(asyncio_get_event_loop_policy);
3221 Py_CLEAR(asyncio_iscoroutine_func);
3222 Py_CLEAR(asyncio_task_get_stack_func);
3223 Py_CLEAR(asyncio_task_print_stack_func);
3224 Py_CLEAR(asyncio_task_repr_info_func);
3225 Py_CLEAR(asyncio_InvalidStateError);
3226 Py_CLEAR(asyncio_CancelledError);
3227
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003228 Py_CLEAR(all_tasks);
Yury Selivanova9d7e552017-12-19 07:18:45 -05003229 Py_CLEAR(current_tasks);
3230 Py_CLEAR(iscoroutine_typecache);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05003231
Yury Selivanovf23746a2018-01-22 19:11:18 -05003232 Py_CLEAR(context_kwname);
3233
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05003234 module_free_freelists();
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003235}
3236
3237static int
3238module_init(void)
3239{
3240 PyObject *module = NULL;
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003241
3242 asyncio_mod = PyImport_ImportModule("asyncio");
3243 if (asyncio_mod == NULL) {
3244 goto fail;
3245 }
3246
3247 current_tasks = PyDict_New();
3248 if (current_tasks == NULL) {
3249 goto fail;
3250 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003251
Yury Selivanova9d7e552017-12-19 07:18:45 -05003252 iscoroutine_typecache = PySet_New(NULL);
3253 if (iscoroutine_typecache == NULL) {
3254 goto fail;
3255 }
3256
Yury Selivanovf23746a2018-01-22 19:11:18 -05003257
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03003258 context_kwname = Py_BuildValue("(s)", "context");
Yury Selivanovf23746a2018-01-22 19:11:18 -05003259 if (context_kwname == NULL) {
3260 goto fail;
3261 }
Yury Selivanovf23746a2018-01-22 19:11:18 -05003262
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003263#define WITH_MOD(NAME) \
3264 Py_CLEAR(module); \
3265 module = PyImport_ImportModule(NAME); \
3266 if (module == NULL) { \
Serhiy Storchakabca49392017-09-03 08:10:14 +03003267 goto fail; \
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003268 }
3269
3270#define GET_MOD_ATTR(VAR, NAME) \
3271 VAR = PyObject_GetAttrString(module, NAME); \
3272 if (VAR == NULL) { \
3273 goto fail; \
3274 }
3275
3276 WITH_MOD("asyncio.events")
Yury Selivanova70232f2017-12-13 14:49:42 -05003277 GET_MOD_ATTR(asyncio_get_event_loop_policy, "get_event_loop_policy")
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003278
3279 WITH_MOD("asyncio.base_futures")
3280 GET_MOD_ATTR(asyncio_future_repr_info_func, "_future_repr_info")
Andrew Svetlov0baa72f2018-09-11 10:13:04 -07003281
3282 WITH_MOD("asyncio.exceptions")
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003283 GET_MOD_ATTR(asyncio_InvalidStateError, "InvalidStateError")
3284 GET_MOD_ATTR(asyncio_CancelledError, "CancelledError")
3285
3286 WITH_MOD("asyncio.base_tasks")
3287 GET_MOD_ATTR(asyncio_task_repr_info_func, "_task_repr_info")
3288 GET_MOD_ATTR(asyncio_task_get_stack_func, "_task_get_stack")
3289 GET_MOD_ATTR(asyncio_task_print_stack_func, "_task_print_stack")
3290
Andrew Svetlovf74ef452017-12-15 07:04:38 +02003291 WITH_MOD("asyncio.coroutines")
3292 GET_MOD_ATTR(asyncio_iscoroutine_func, "iscoroutine")
3293
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003294 WITH_MOD("traceback")
3295 GET_MOD_ATTR(traceback_extract_stack, "extract_stack")
3296
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003297 PyObject *weak_set;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003298 WITH_MOD("weakref")
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003299 GET_MOD_ATTR(weak_set, "WeakSet");
3300 all_tasks = _PyObject_CallNoArg(weak_set);
3301 Py_CLEAR(weak_set);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003302 if (all_tasks == NULL) {
INADA Naokic411a7d2016-10-18 11:48:14 +09003303 goto fail;
3304 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003305
Serhiy Storchakabca49392017-09-03 08:10:14 +03003306 Py_DECREF(module);
INADA Naokic411a7d2016-10-18 11:48:14 +09003307 return 0;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003308
INADA Naokic411a7d2016-10-18 11:48:14 +09003309fail:
INADA Naokic411a7d2016-10-18 11:48:14 +09003310 Py_CLEAR(module);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003311 module_free(NULL);
INADA Naokic411a7d2016-10-18 11:48:14 +09003312 return -1;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003313
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003314#undef WITH_MOD
3315#undef GET_MOD_ATTR
3316}
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003317
INADA Naokic411a7d2016-10-18 11:48:14 +09003318PyDoc_STRVAR(module_doc, "Accelerator module for asyncio");
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003319
Yury Selivanova70232f2017-12-13 14:49:42 -05003320static PyMethodDef asyncio_methods[] = {
3321 _ASYNCIO_GET_EVENT_LOOP_METHODDEF
3322 _ASYNCIO_GET_RUNNING_LOOP_METHODDEF
3323 _ASYNCIO__GET_RUNNING_LOOP_METHODDEF
3324 _ASYNCIO__SET_RUNNING_LOOP_METHODDEF
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003325 _ASYNCIO__REGISTER_TASK_METHODDEF
3326 _ASYNCIO__UNREGISTER_TASK_METHODDEF
3327 _ASYNCIO__ENTER_TASK_METHODDEF
3328 _ASYNCIO__LEAVE_TASK_METHODDEF
Yury Selivanova70232f2017-12-13 14:49:42 -05003329 {NULL, NULL}
3330};
3331
INADA Naoki9f2ce252016-10-15 15:39:19 +09003332static struct PyModuleDef _asynciomodule = {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003333 PyModuleDef_HEAD_INIT, /* m_base */
INADA Naoki9f2ce252016-10-15 15:39:19 +09003334 "_asyncio", /* m_name */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003335 module_doc, /* m_doc */
3336 -1, /* m_size */
Yury Selivanova70232f2017-12-13 14:49:42 -05003337 asyncio_methods, /* m_methods */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003338 NULL, /* m_slots */
3339 NULL, /* m_traverse */
3340 NULL, /* m_clear */
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003341 (freefunc)module_free /* m_free */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003342};
3343
3344
3345PyMODINIT_FUNC
INADA Naoki9f2ce252016-10-15 15:39:19 +09003346PyInit__asyncio(void)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003347{
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003348 if (module_init() < 0) {
INADA Naokic411a7d2016-10-18 11:48:14 +09003349 return NULL;
3350 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003351 if (PyType_Ready(&FutureType) < 0) {
3352 return NULL;
3353 }
3354 if (PyType_Ready(&FutureIterType) < 0) {
3355 return NULL;
3356 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03003357 if (PyType_Ready(&TaskStepMethWrapper_Type) < 0) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003358 return NULL;
3359 }
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03003360 if (PyType_Ready(&TaskWakeupMethWrapper_Type) < 0) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003361 return NULL;
3362 }
3363 if (PyType_Ready(&TaskType) < 0) {
3364 return NULL;
3365 }
Yury Selivanov9d411c12018-01-23 15:10:03 -05003366 if (PyType_Ready(&PyRunningLoopHolder_Type) < 0) {
3367 return NULL;
3368 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003369
INADA Naoki9f2ce252016-10-15 15:39:19 +09003370 PyObject *m = PyModule_Create(&_asynciomodule);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003371 if (m == NULL) {
3372 return NULL;
3373 }
3374
3375 Py_INCREF(&FutureType);
3376 if (PyModule_AddObject(m, "Future", (PyObject *)&FutureType) < 0) {
3377 Py_DECREF(&FutureType);
3378 return NULL;
3379 }
3380
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003381 Py_INCREF(&TaskType);
3382 if (PyModule_AddObject(m, "Task", (PyObject *)&TaskType) < 0) {
3383 Py_DECREF(&TaskType);
3384 return NULL;
3385 }
3386
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003387 Py_INCREF(all_tasks);
3388 if (PyModule_AddObject(m, "_all_tasks", all_tasks) < 0) {
3389 Py_DECREF(all_tasks);
3390 return NULL;
3391 }
3392
3393 Py_INCREF(current_tasks);
3394 if (PyModule_AddObject(m, "_current_tasks", current_tasks) < 0) {
3395 Py_DECREF(current_tasks);
3396 return NULL;
3397 }
3398
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003399 return m;
3400}