blob: f9037c279ac9c34b8679ffbbbc4d1750ce3670bf [file] [log] [blame]
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001#include "Python.h"
2#include "structmember.h"
3
4
Yury Selivanova0c1ba62016-10-28 12:52:37 -04005/*[clinic input]
6module _asyncio
7[clinic start generated code]*/
8/*[clinic end generated code: output=da39a3ee5e6b4b0d input=8fd17862aa989c69]*/
9
10
INADA Naoki9e4e38e2016-10-09 14:44:47 +090011/* identifiers used from some functions */
Yury Selivanova70232f2017-12-13 14:49:42 -050012_Py_IDENTIFIER(__asyncio_running_event_loop__);
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +030013_Py_IDENTIFIER(_asyncio_future_blocking);
Yury Selivanova0c1ba62016-10-28 12:52:37 -040014_Py_IDENTIFIER(add_done_callback);
Yury Selivanov416c1eb2018-05-28 17:54:02 -040015_Py_IDENTIFIER(_all_tasks_compat);
INADA Naoki9e4e38e2016-10-09 14:44:47 +090016_Py_IDENTIFIER(call_soon);
Yury Selivanova0c1ba62016-10-28 12:52:37 -040017_Py_IDENTIFIER(cancel);
Andrew Svetlov44d1a592017-12-16 21:58:38 +020018_Py_IDENTIFIER(current_task);
Yury Selivanova70232f2017-12-13 14:49:42 -050019_Py_IDENTIFIER(get_event_loop);
Yury Selivanova0c1ba62016-10-28 12:52:37 -040020_Py_IDENTIFIER(send);
21_Py_IDENTIFIER(throw);
INADA Naoki9e4e38e2016-10-09 14:44:47 +090022
23
INADA Naoki9f2ce252016-10-15 15:39:19 +090024/* State of the _asyncio module */
Andrew Svetlov44d1a592017-12-16 21:58:38 +020025static PyObject *asyncio_mod;
Andrew Svetlov44d1a592017-12-16 21:58:38 +020026static PyObject *traceback_extract_stack;
27static PyObject *asyncio_get_event_loop_policy;
28static PyObject *asyncio_future_repr_info_func;
29static PyObject *asyncio_iscoroutine_func;
30static PyObject *asyncio_task_get_stack_func;
31static PyObject *asyncio_task_print_stack_func;
32static PyObject *asyncio_task_repr_info_func;
33static PyObject *asyncio_InvalidStateError;
34static PyObject *asyncio_CancelledError;
Yury Selivanovf23746a2018-01-22 19:11:18 -050035static PyObject *context_kwname;
Andrew Svetlov44d1a592017-12-16 21:58:38 +020036
Yury Selivanov9d411c12018-01-23 15:10:03 -050037static PyObject *cached_running_holder;
38static volatile uint64_t cached_running_holder_tsid;
39
Alex Grönholmcca4eec2018-08-09 00:06:47 +030040/* Counter for autogenerated Task names */
41static uint64_t task_name_counter = 0;
Andrew Svetlov44d1a592017-12-16 21:58:38 +020042
Yury Selivanovca9b36c2017-12-23 15:04:15 -050043/* WeakSet containing all alive tasks. */
44static PyObject *all_tasks;
Andrew Svetlov44d1a592017-12-16 21:58:38 +020045
46/* Dictionary containing tasks that are currently active in
47 all running event loops. {EventLoop: Task} */
Yury Selivanovca9b36c2017-12-23 15:04:15 -050048static PyObject *current_tasks;
INADA Naoki9e4e38e2016-10-09 14:44:47 +090049
Yury Selivanova9d7e552017-12-19 07:18:45 -050050/* An isinstance type cache for the 'is_coroutine()' function. */
51static PyObject *iscoroutine_typecache;
52
INADA Naoki9e4e38e2016-10-09 14:44:47 +090053
INADA Naoki9e4e38e2016-10-09 14:44:47 +090054typedef enum {
55 STATE_PENDING,
56 STATE_CANCELLED,
57 STATE_FINISHED
58} fut_state;
59
Yury Selivanova0c1ba62016-10-28 12:52:37 -040060#define FutureObj_HEAD(prefix) \
61 PyObject_HEAD \
62 PyObject *prefix##_loop; \
Yury Selivanov1b7c11f2017-12-17 20:19:47 -050063 PyObject *prefix##_callback0; \
Yury Selivanov994269c2018-09-27 14:55:55 -040064 PyObject *prefix##_context0; \
Yury Selivanova0c1ba62016-10-28 12:52:37 -040065 PyObject *prefix##_callbacks; \
66 PyObject *prefix##_exception; \
67 PyObject *prefix##_result; \
68 PyObject *prefix##_source_tb; \
69 fut_state prefix##_state; \
70 int prefix##_log_tb; \
71 int prefix##_blocking; \
72 PyObject *dict; \
73 PyObject *prefix##_weakreflist;
74
75typedef struct {
76 FutureObj_HEAD(fut)
77} FutureObj;
78
79typedef struct {
80 FutureObj_HEAD(task)
81 PyObject *task_fut_waiter;
82 PyObject *task_coro;
Alex Grönholmcca4eec2018-08-09 00:06:47 +030083 PyObject *task_name;
Yury Selivanov994269c2018-09-27 14:55:55 -040084 PyObject *task_context;
Yury Selivanova0c1ba62016-10-28 12:52:37 -040085 int task_must_cancel;
86 int task_log_destroy_pending;
87} TaskObj;
INADA Naoki9e4e38e2016-10-09 14:44:47 +090088
89typedef struct {
90 PyObject_HEAD
Yury Selivanova0c1ba62016-10-28 12:52:37 -040091 TaskObj *sw_task;
92 PyObject *sw_arg;
Serhiy Storchakabca49392017-09-03 08:10:14 +030093} TaskStepMethWrapper;
INADA Naoki9e4e38e2016-10-09 14:44:47 +090094
Yury Selivanova0c1ba62016-10-28 12:52:37 -040095typedef struct {
96 PyObject_HEAD
97 TaskObj *ww_task;
98} TaskWakeupMethWrapper;
99
Yury Selivanov9d411c12018-01-23 15:10:03 -0500100typedef struct {
101 PyObject_HEAD
102 PyObject *rl_loop;
103#if defined(HAVE_GETPID) && !defined(MS_WINDOWS)
104 pid_t rl_pid;
105#endif
106} PyRunningLoopHolder;
107
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400108
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500109static PyTypeObject FutureType;
110static PyTypeObject TaskType;
Yury Selivanov9d411c12018-01-23 15:10:03 -0500111static PyTypeObject PyRunningLoopHolder_Type;
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500112
113
114#define Future_CheckExact(obj) (Py_TYPE(obj) == &FutureType)
115#define Task_CheckExact(obj) (Py_TYPE(obj) == &TaskType)
116
117#define Future_Check(obj) PyObject_TypeCheck(obj, &FutureType)
118#define Task_Check(obj) PyObject_TypeCheck(obj, &TaskType)
119
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400120#include "clinic/_asynciomodule.c.h"
121
122
123/*[clinic input]
124class _asyncio.Future "FutureObj *" "&Future_Type"
125[clinic start generated code]*/
126/*[clinic end generated code: output=da39a3ee5e6b4b0d input=00d3e4abca711e0f]*/
127
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500128
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400129/* Get FutureIter from Future */
Yury Selivanov9d411c12018-01-23 15:10:03 -0500130static PyObject * future_new_iter(PyObject *);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900131
Yury Selivanov9d411c12018-01-23 15:10:03 -0500132static PyRunningLoopHolder * new_running_loop_holder(PyObject *);
133
Yury Selivanova70232f2017-12-13 14:49:42 -0500134
135static int
Yury Selivanova9d7e552017-12-19 07:18:45 -0500136_is_coroutine(PyObject *coro)
137{
138 /* 'coro' is not a native coroutine, call asyncio.iscoroutine()
139 to check if it's another coroutine flavour.
140
141 Do this check after 'future_init()'; in case we need to raise
142 an error, __del__ needs a properly initialized object.
143 */
144 PyObject *res = PyObject_CallFunctionObjArgs(
145 asyncio_iscoroutine_func, coro, NULL);
146 if (res == NULL) {
147 return -1;
148 }
149
150 int is_res_true = PyObject_IsTrue(res);
151 Py_DECREF(res);
152 if (is_res_true <= 0) {
153 return is_res_true;
154 }
155
Andrew Svetlov0f47fa22017-12-23 22:06:46 +0200156 if (PySet_GET_SIZE(iscoroutine_typecache) < 100) {
Yury Selivanova9d7e552017-12-19 07:18:45 -0500157 /* Just in case we don't want to cache more than 100
158 positive types. That shouldn't ever happen, unless
159 someone stressing the system on purpose.
160 */
161 if (PySet_Add(iscoroutine_typecache, (PyObject*) Py_TYPE(coro))) {
162 return -1;
163 }
164 }
165
166 return 1;
167}
168
169
170static inline int
171is_coroutine(PyObject *coro)
172{
173 if (PyCoro_CheckExact(coro)) {
174 return 1;
175 }
176
177 /* Check if `type(coro)` is in the cache.
178 Caching makes is_coroutine() function almost as fast as
179 PyCoro_CheckExact() for non-native coroutine-like objects
180 (like coroutines compiled with Cython).
181
182 asyncio.iscoroutine() has its own type caching mechanism.
183 This cache allows us to avoid the cost of even calling
184 a pure-Python function in 99.9% cases.
185 */
186 int has_it = PySet_Contains(
187 iscoroutine_typecache, (PyObject*) Py_TYPE(coro));
188 if (has_it == 0) {
189 /* type(coro) is not in iscoroutine_typecache */
190 return _is_coroutine(coro);
191 }
192
Leo Ariasc3d95082018-02-03 18:36:10 -0600193 /* either an error has occurred or
Yury Selivanova9d7e552017-12-19 07:18:45 -0500194 type(coro) is in iscoroutine_typecache
195 */
196 return has_it;
197}
198
199
Yury Selivanovca9b36c2017-12-23 15:04:15 -0500200static PyObject *
201get_future_loop(PyObject *fut)
202{
203 /* Implementation of `asyncio.futures._get_loop` */
204
205 _Py_IDENTIFIER(get_loop);
206 _Py_IDENTIFIER(_loop);
Serhiy Storchaka66553542018-05-20 16:30:31 +0300207 PyObject *getloop;
Yury Selivanovca9b36c2017-12-23 15:04:15 -0500208
209 if (Future_CheckExact(fut) || Task_CheckExact(fut)) {
210 PyObject *loop = ((FutureObj *)fut)->fut_loop;
211 Py_INCREF(loop);
212 return loop;
213 }
214
Serhiy Storchaka66553542018-05-20 16:30:31 +0300215 if (_PyObject_LookupAttrId(fut, &PyId_get_loop, &getloop) < 0) {
216 return NULL;
217 }
Yury Selivanovca9b36c2017-12-23 15:04:15 -0500218 if (getloop != NULL) {
219 PyObject *res = _PyObject_CallNoArg(getloop);
220 Py_DECREF(getloop);
221 return res;
222 }
223
224 return _PyObject_GetAttrId(fut, &PyId__loop);
225}
226
227
Yury Selivanova9d7e552017-12-19 07:18:45 -0500228static int
Yury Selivanova70232f2017-12-13 14:49:42 -0500229get_running_loop(PyObject **loop)
230{
Yury Selivanov9d411c12018-01-23 15:10:03 -0500231 PyObject *rl;
Yury Selivanova70232f2017-12-13 14:49:42 -0500232
Yury Selivanov9d411c12018-01-23 15:10:03 -0500233 PyThreadState *ts = PyThreadState_Get();
234 if (ts->id == cached_running_holder_tsid && cached_running_holder != NULL) {
235 // Fast path, check the cache.
236 rl = cached_running_holder; // borrowed
237 }
238 else {
239 if (ts->dict == NULL) {
240 goto not_found;
241 }
242
243 rl = _PyDict_GetItemIdWithError(
244 ts->dict, &PyId___asyncio_running_event_loop__); // borrowed
245 if (rl == NULL) {
246 if (PyErr_Occurred()) {
247 goto error;
248 }
249 else {
250 goto not_found;
251 }
252 }
253
254 cached_running_holder = rl; // borrowed
255 cached_running_holder_tsid = ts->id;
Yury Selivanova70232f2017-12-13 14:49:42 -0500256 }
257
Yury Selivanov9d411c12018-01-23 15:10:03 -0500258 assert(Py_TYPE(rl) == &PyRunningLoopHolder_Type);
259 PyObject *running_loop = ((PyRunningLoopHolder *)rl)->rl_loop;
Yury Selivanova70232f2017-12-13 14:49:42 -0500260
261 if (running_loop == Py_None) {
262 goto not_found;
263 }
264
Yury Selivanov9d411c12018-01-23 15:10:03 -0500265#if defined(HAVE_GETPID) && !defined(MS_WINDOWS)
266 /* On Windows there is no getpid, but there is also no os.fork(),
267 so there is no need for this check.
268 */
269 if (getpid() != ((PyRunningLoopHolder *)rl)->rl_pid) {
270 goto not_found;
Yury Selivanova70232f2017-12-13 14:49:42 -0500271 }
Yury Selivanov9d411c12018-01-23 15:10:03 -0500272#endif
Yury Selivanova70232f2017-12-13 14:49:42 -0500273
Yury Selivanov9d411c12018-01-23 15:10:03 -0500274 Py_INCREF(running_loop);
275 *loop = running_loop;
276 return 0;
Yury Selivanova70232f2017-12-13 14:49:42 -0500277
278not_found:
279 *loop = NULL;
280 return 0;
281
Yury Selivanova70232f2017-12-13 14:49:42 -0500282error:
283 *loop = NULL;
284 return -1;
285}
286
287
288static int
289set_running_loop(PyObject *loop)
290{
Yury Selivanov9d411c12018-01-23 15:10:03 -0500291 cached_running_holder = NULL;
292 cached_running_holder_tsid = 0;
Yury Selivanova70232f2017-12-13 14:49:42 -0500293
Yury Selivanov9d411c12018-01-23 15:10:03 -0500294 PyObject *ts_dict = PyThreadState_GetDict(); // borrowed
Yury Selivanova70232f2017-12-13 14:49:42 -0500295 if (ts_dict == NULL) {
296 PyErr_SetString(
297 PyExc_RuntimeError, "thread-local storage is not available");
298 return -1;
299 }
300
Yury Selivanov9d411c12018-01-23 15:10:03 -0500301 PyRunningLoopHolder *rl = new_running_loop_holder(loop);
302 if (rl == NULL) {
Yury Selivanova70232f2017-12-13 14:49:42 -0500303 return -1;
304 }
305
Yury Selivanova70232f2017-12-13 14:49:42 -0500306 if (_PyDict_SetItemId(
Yury Selivanov9d411c12018-01-23 15:10:03 -0500307 ts_dict, &PyId___asyncio_running_event_loop__, (PyObject *)rl) < 0)
308 {
309 Py_DECREF(rl); // will cleanup loop & current_pid
Yury Selivanova70232f2017-12-13 14:49:42 -0500310 return -1;
311 }
Yury Selivanov9d411c12018-01-23 15:10:03 -0500312 Py_DECREF(rl);
Yury Selivanova70232f2017-12-13 14:49:42 -0500313
314 return 0;
315}
316
317
318static PyObject *
319get_event_loop(void)
320{
321 PyObject *loop;
322 PyObject *policy;
323
324 if (get_running_loop(&loop)) {
325 return NULL;
326 }
327 if (loop != NULL) {
328 return loop;
329 }
330
331 policy = _PyObject_CallNoArg(asyncio_get_event_loop_policy);
332 if (policy == NULL) {
333 return NULL;
334 }
335
336 loop = _PyObject_CallMethodId(policy, &PyId_get_event_loop, NULL);
337 Py_DECREF(policy);
338 return loop;
339}
340
341
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900342static int
Yury Selivanov994269c2018-09-27 14:55:55 -0400343call_soon(PyObject *loop, PyObject *func, PyObject *arg, PyObject *ctx)
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500344{
345 PyObject *handle;
Yury Selivanovf23746a2018-01-22 19:11:18 -0500346 PyObject *stack[3];
347 Py_ssize_t nargs;
348
349 if (ctx == NULL) {
350 handle = _PyObject_CallMethodIdObjArgs(
351 loop, &PyId_call_soon, func, arg, NULL);
352 }
353 else {
354 /* Use FASTCALL to pass a keyword-only argument to call_soon */
355
356 PyObject *callable = _PyObject_GetAttrId(loop, &PyId_call_soon);
357 if (callable == NULL) {
358 return -1;
359 }
360
361 /* All refs in 'stack' are borrowed. */
362 nargs = 1;
363 stack[0] = func;
364 if (arg != NULL) {
365 stack[1] = arg;
366 nargs++;
367 }
368 stack[nargs] = (PyObject *)ctx;
369
370 handle = _PyObject_FastCallKeywords(
371 callable, stack, nargs, context_kwname);
372 Py_DECREF(callable);
373 }
374
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500375 if (handle == NULL) {
376 return -1;
377 }
378 Py_DECREF(handle);
379 return 0;
380}
381
382
383static inline int
384future_is_alive(FutureObj *fut)
385{
386 return fut->fut_loop != NULL;
387}
388
389
390static inline int
391future_ensure_alive(FutureObj *fut)
392{
393 if (!future_is_alive(fut)) {
394 PyErr_SetString(PyExc_RuntimeError,
395 "Future object is not initialized.");
396 return -1;
397 }
398 return 0;
399}
400
401
402#define ENSURE_FUTURE_ALIVE(fut) \
403 do { \
404 assert(Future_Check(fut) || Task_Check(fut)); \
405 if (future_ensure_alive((FutureObj*)fut)) { \
406 return NULL; \
407 } \
408 } while(0);
409
410
411static int
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400412future_schedule_callbacks(FutureObj *fut)
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900413{
414 Py_ssize_t len;
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500415 Py_ssize_t i;
416
417 if (fut->fut_callback0 != NULL) {
418 /* There's a 1st callback */
419
420 int ret = call_soon(
Yury Selivanovf23746a2018-01-22 19:11:18 -0500421 fut->fut_loop, fut->fut_callback0,
422 (PyObject *)fut, fut->fut_context0);
423
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500424 Py_CLEAR(fut->fut_callback0);
Yury Selivanovf23746a2018-01-22 19:11:18 -0500425 Py_CLEAR(fut->fut_context0);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500426 if (ret) {
427 /* If an error occurs in pure-Python implementation,
428 all callbacks are cleared. */
429 Py_CLEAR(fut->fut_callbacks);
430 return ret;
431 }
432
433 /* we called the first callback, now try calling
434 callbacks from the 'fut_callbacks' list. */
435 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900436
437 if (fut->fut_callbacks == NULL) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500438 /* No more callbacks, return. */
439 return 0;
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900440 }
441
442 len = PyList_GET_SIZE(fut->fut_callbacks);
443 if (len == 0) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500444 /* The list of callbacks was empty; clear it and return. */
445 Py_CLEAR(fut->fut_callbacks);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900446 return 0;
447 }
448
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900449 for (i = 0; i < len; i++) {
Yury Selivanovf23746a2018-01-22 19:11:18 -0500450 PyObject *cb_tup = PyList_GET_ITEM(fut->fut_callbacks, i);
451 PyObject *cb = PyTuple_GET_ITEM(cb_tup, 0);
452 PyObject *ctx = PyTuple_GET_ITEM(cb_tup, 1);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900453
Yury Selivanov994269c2018-09-27 14:55:55 -0400454 if (call_soon(fut->fut_loop, cb, (PyObject *)fut, ctx)) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500455 /* If an error occurs in pure-Python implementation,
456 all callbacks are cleared. */
457 Py_CLEAR(fut->fut_callbacks);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900458 return -1;
459 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900460 }
461
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500462 Py_CLEAR(fut->fut_callbacks);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900463 return 0;
464}
465
Oren Milmand019bc82018-02-13 12:28:33 +0200466
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900467static int
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400468future_init(FutureObj *fut, PyObject *loop)
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900469{
Serhiy Storchakabca49392017-09-03 08:10:14 +0300470 PyObject *res;
471 int is_true;
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900472 _Py_IDENTIFIER(get_debug);
473
Oren Milmand019bc82018-02-13 12:28:33 +0200474 // Same to FutureObj_clear() but not clearing fut->dict
475 Py_CLEAR(fut->fut_loop);
476 Py_CLEAR(fut->fut_callback0);
477 Py_CLEAR(fut->fut_context0);
478 Py_CLEAR(fut->fut_callbacks);
479 Py_CLEAR(fut->fut_result);
480 Py_CLEAR(fut->fut_exception);
481 Py_CLEAR(fut->fut_source_tb);
482
483 fut->fut_state = STATE_PENDING;
484 fut->fut_log_tb = 0;
485 fut->fut_blocking = 0;
486
Serhiy Storchakabca49392017-09-03 08:10:14 +0300487 if (loop == Py_None) {
Yury Selivanova70232f2017-12-13 14:49:42 -0500488 loop = get_event_loop();
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900489 if (loop == NULL) {
490 return -1;
491 }
492 }
493 else {
494 Py_INCREF(loop);
495 }
Oren Milmand019bc82018-02-13 12:28:33 +0200496 fut->fut_loop = loop;
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900497
Victor Stinnerf94d1ee2016-10-29 09:05:39 +0200498 res = _PyObject_CallMethodId(fut->fut_loop, &PyId_get_debug, NULL);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900499 if (res == NULL) {
500 return -1;
501 }
Serhiy Storchakabca49392017-09-03 08:10:14 +0300502 is_true = PyObject_IsTrue(res);
503 Py_DECREF(res);
504 if (is_true < 0) {
505 return -1;
506 }
Yury Selivanov35230d02018-05-28 11:11:31 -0400507 if (is_true && !_Py_IsFinalizing()) {
508 /* Only try to capture the traceback if the interpreter is not being
509 finalized. The original motivation to add a `_Py_IsFinalizing()`
510 call was to prevent SIGSEGV when a Future is created in a __del__
511 method, which is called during the interpreter shutdown and the
512 traceback module is already unloaded.
513 */
Oren Milmand019bc82018-02-13 12:28:33 +0200514 fut->fut_source_tb = _PyObject_CallNoArg(traceback_extract_stack);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900515 if (fut->fut_source_tb == NULL) {
516 return -1;
517 }
518 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900519
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900520 return 0;
521}
522
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900523static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400524future_set_result(FutureObj *fut, PyObject *res)
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900525{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500526 if (future_ensure_alive(fut)) {
527 return NULL;
528 }
529
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900530 if (fut->fut_state != STATE_PENDING) {
531 PyErr_SetString(asyncio_InvalidStateError, "invalid state");
532 return NULL;
533 }
534
Serhiy Storchakabca49392017-09-03 08:10:14 +0300535 assert(!fut->fut_result);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900536 Py_INCREF(res);
537 fut->fut_result = res;
538 fut->fut_state = STATE_FINISHED;
539
Yury Selivanov22feeb82018-01-24 11:31:01 -0500540 if (future_schedule_callbacks(fut) == -1) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900541 return NULL;
542 }
543 Py_RETURN_NONE;
544}
545
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900546static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400547future_set_exception(FutureObj *fut, PyObject *exc)
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900548{
549 PyObject *exc_val = NULL;
550
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900551 if (fut->fut_state != STATE_PENDING) {
552 PyErr_SetString(asyncio_InvalidStateError, "invalid state");
553 return NULL;
554 }
555
556 if (PyExceptionClass_Check(exc)) {
Victor Stinnera5ed5f02016-12-06 18:45:50 +0100557 exc_val = _PyObject_CallNoArg(exc);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900558 if (exc_val == NULL) {
559 return NULL;
560 }
Serhiy Storchakabca49392017-09-03 08:10:14 +0300561 if (fut->fut_state != STATE_PENDING) {
562 Py_DECREF(exc_val);
563 PyErr_SetString(asyncio_InvalidStateError, "invalid state");
564 return NULL;
565 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900566 }
567 else {
568 exc_val = exc;
569 Py_INCREF(exc_val);
570 }
571 if (!PyExceptionInstance_Check(exc_val)) {
572 Py_DECREF(exc_val);
573 PyErr_SetString(PyExc_TypeError, "invalid exception object");
574 return NULL;
575 }
576 if ((PyObject*)Py_TYPE(exc_val) == PyExc_StopIteration) {
577 Py_DECREF(exc_val);
578 PyErr_SetString(PyExc_TypeError,
579 "StopIteration interacts badly with generators "
580 "and cannot be raised into a Future");
581 return NULL;
582 }
583
Serhiy Storchakabca49392017-09-03 08:10:14 +0300584 assert(!fut->fut_exception);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900585 fut->fut_exception = exc_val;
586 fut->fut_state = STATE_FINISHED;
587
Yury Selivanov22feeb82018-01-24 11:31:01 -0500588 if (future_schedule_callbacks(fut) == -1) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900589 return NULL;
590 }
591
592 fut->fut_log_tb = 1;
593 Py_RETURN_NONE;
594}
595
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400596static int
597future_get_result(FutureObj *fut, PyObject **result)
598{
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400599 if (fut->fut_state == STATE_CANCELLED) {
Serhiy Storchakabca49392017-09-03 08:10:14 +0300600 PyErr_SetNone(asyncio_CancelledError);
601 return -1;
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400602 }
603
604 if (fut->fut_state != STATE_FINISHED) {
Serhiy Storchakabca49392017-09-03 08:10:14 +0300605 PyErr_SetString(asyncio_InvalidStateError, "Result is not set.");
606 return -1;
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400607 }
608
609 fut->fut_log_tb = 0;
610 if (fut->fut_exception != NULL) {
611 Py_INCREF(fut->fut_exception);
612 *result = fut->fut_exception;
613 return 1;
614 }
615
616 Py_INCREF(fut->fut_result);
617 *result = fut->fut_result;
618 return 0;
619}
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900620
621static PyObject *
Yury Selivanov994269c2018-09-27 14:55:55 -0400622future_add_done_callback(FutureObj *fut, PyObject *arg, PyObject *ctx)
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900623{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500624 if (!future_is_alive(fut)) {
625 PyErr_SetString(PyExc_RuntimeError, "uninitialized Future object");
626 return NULL;
627 }
628
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900629 if (fut->fut_state != STATE_PENDING) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500630 /* The future is done/cancelled, so schedule the callback
631 right away. */
Yury Selivanovf23746a2018-01-22 19:11:18 -0500632 if (call_soon(fut->fut_loop, arg, (PyObject*) fut, ctx)) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900633 return NULL;
634 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900635 }
636 else {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500637 /* The future is pending, add a callback.
638
639 Callbacks in the future object are stored as follows:
640
641 callback0 -- a pointer to the first callback
642 callbacks -- a list of 2nd, 3rd, ... callbacks
643
644 Invariants:
645
646 * callbacks != NULL:
647 There are some callbacks in in the list. Just
648 add the new callback to it.
649
650 * callbacks == NULL and callback0 == NULL:
651 This is the first callback. Set it to callback0.
652
653 * callbacks == NULL and callback0 != NULL:
654 This is a second callback. Initialize callbacks
655 with a new list and add the new callback to it.
656 */
657
Yury Selivanovf23746a2018-01-22 19:11:18 -0500658 if (fut->fut_callbacks == NULL && fut->fut_callback0 == NULL) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500659 Py_INCREF(arg);
660 fut->fut_callback0 = arg;
Yury Selivanovf23746a2018-01-22 19:11:18 -0500661 Py_INCREF(ctx);
662 fut->fut_context0 = ctx;
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500663 }
664 else {
Yury Selivanovf23746a2018-01-22 19:11:18 -0500665 PyObject *tup = PyTuple_New(2);
666 if (tup == NULL) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500667 return NULL;
668 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500669 Py_INCREF(arg);
Yury Selivanovf23746a2018-01-22 19:11:18 -0500670 PyTuple_SET_ITEM(tup, 0, arg);
671 Py_INCREF(ctx);
672 PyTuple_SET_ITEM(tup, 1, (PyObject *)ctx);
673
674 if (fut->fut_callbacks != NULL) {
675 int err = PyList_Append(fut->fut_callbacks, tup);
676 if (err) {
677 Py_DECREF(tup);
678 return NULL;
679 }
680 Py_DECREF(tup);
681 }
682 else {
683 fut->fut_callbacks = PyList_New(1);
684 if (fut->fut_callbacks == NULL) {
685 return NULL;
686 }
687
688 PyList_SET_ITEM(fut->fut_callbacks, 0, tup); /* borrow */
689 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900690 }
691 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500692
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900693 Py_RETURN_NONE;
694}
695
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400696static PyObject *
697future_cancel(FutureObj *fut)
698{
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +0000699 fut->fut_log_tb = 0;
700
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400701 if (fut->fut_state != STATE_PENDING) {
702 Py_RETURN_FALSE;
703 }
704 fut->fut_state = STATE_CANCELLED;
705
Yury Selivanov22feeb82018-01-24 11:31:01 -0500706 if (future_schedule_callbacks(fut) == -1) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400707 return NULL;
708 }
709
710 Py_RETURN_TRUE;
711}
712
713/*[clinic input]
714_asyncio.Future.__init__
715
716 *
Serhiy Storchakabca49392017-09-03 08:10:14 +0300717 loop: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400718
719This class is *almost* compatible with concurrent.futures.Future.
720
721 Differences:
722
723 - result() and exception() do not take a timeout argument and
724 raise an exception when the future isn't done yet.
725
726 - Callbacks registered with add_done_callback() are always called
727 via the event loop's call_soon_threadsafe().
728
729 - This class is not compatible with the wait() and as_completed()
730 methods in the concurrent.futures package.
731[clinic start generated code]*/
732
733static int
734_asyncio_Future___init___impl(FutureObj *self, PyObject *loop)
Serhiy Storchakabca49392017-09-03 08:10:14 +0300735/*[clinic end generated code: output=9ed75799eaccb5d6 input=89af317082bc0bf8]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400736
737{
738 return future_init(self, loop);
739}
740
741static int
742FutureObj_clear(FutureObj *fut)
743{
744 Py_CLEAR(fut->fut_loop);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500745 Py_CLEAR(fut->fut_callback0);
Yury Selivanovf23746a2018-01-22 19:11:18 -0500746 Py_CLEAR(fut->fut_context0);
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400747 Py_CLEAR(fut->fut_callbacks);
748 Py_CLEAR(fut->fut_result);
749 Py_CLEAR(fut->fut_exception);
750 Py_CLEAR(fut->fut_source_tb);
751 Py_CLEAR(fut->dict);
752 return 0;
753}
754
755static int
756FutureObj_traverse(FutureObj *fut, visitproc visit, void *arg)
757{
758 Py_VISIT(fut->fut_loop);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500759 Py_VISIT(fut->fut_callback0);
Yury Selivanovf23746a2018-01-22 19:11:18 -0500760 Py_VISIT(fut->fut_context0);
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400761 Py_VISIT(fut->fut_callbacks);
762 Py_VISIT(fut->fut_result);
763 Py_VISIT(fut->fut_exception);
764 Py_VISIT(fut->fut_source_tb);
765 Py_VISIT(fut->dict);
766 return 0;
767}
768
769/*[clinic input]
770_asyncio.Future.result
771
772Return the result this future represents.
773
774If the future has been cancelled, raises CancelledError. If the
775future's result isn't yet available, raises InvalidStateError. If
776the future is done and has an exception set, this exception is raised.
777[clinic start generated code]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900778
779static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400780_asyncio_Future_result_impl(FutureObj *self)
781/*[clinic end generated code: output=f35f940936a4b1e5 input=49ecf9cf5ec50dc5]*/
782{
783 PyObject *result;
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500784
785 if (!future_is_alive(self)) {
786 PyErr_SetString(asyncio_InvalidStateError,
787 "Future object is not initialized.");
788 return NULL;
789 }
790
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400791 int res = future_get_result(self, &result);
792
793 if (res == -1) {
794 return NULL;
795 }
796
797 if (res == 0) {
798 return result;
799 }
800
801 assert(res == 1);
802
803 PyErr_SetObject(PyExceptionInstance_Class(result), result);
804 Py_DECREF(result);
805 return NULL;
806}
807
808/*[clinic input]
809_asyncio.Future.exception
810
811Return the exception that was set on this future.
812
813The exception (or None if no exception was set) is returned only if
814the future is done. If the future has been cancelled, raises
815CancelledError. If the future isn't done yet, raises
816InvalidStateError.
817[clinic start generated code]*/
818
819static PyObject *
820_asyncio_Future_exception_impl(FutureObj *self)
821/*[clinic end generated code: output=88b20d4f855e0710 input=733547a70c841c68]*/
822{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500823 if (!future_is_alive(self)) {
824 PyErr_SetString(asyncio_InvalidStateError,
825 "Future object is not initialized.");
826 return NULL;
827 }
828
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400829 if (self->fut_state == STATE_CANCELLED) {
Serhiy Storchakabca49392017-09-03 08:10:14 +0300830 PyErr_SetNone(asyncio_CancelledError);
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400831 return NULL;
832 }
833
834 if (self->fut_state != STATE_FINISHED) {
Serhiy Storchakabca49392017-09-03 08:10:14 +0300835 PyErr_SetString(asyncio_InvalidStateError, "Exception is not set.");
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400836 return NULL;
837 }
838
839 if (self->fut_exception != NULL) {
840 self->fut_log_tb = 0;
841 Py_INCREF(self->fut_exception);
842 return self->fut_exception;
843 }
844
845 Py_RETURN_NONE;
846}
847
848/*[clinic input]
849_asyncio.Future.set_result
850
Yury Selivanov0cf16f92017-12-25 10:48:15 -0500851 result: object
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400852 /
853
854Mark the future done and set its result.
855
856If the future is already done when this method is called, raises
857InvalidStateError.
858[clinic start generated code]*/
859
860static PyObject *
Yury Selivanov0cf16f92017-12-25 10:48:15 -0500861_asyncio_Future_set_result(FutureObj *self, PyObject *result)
862/*[clinic end generated code: output=1ec2e6bcccd6f2ce input=8b75172c2a7b05f1]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400863{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500864 ENSURE_FUTURE_ALIVE(self)
Yury Selivanov0cf16f92017-12-25 10:48:15 -0500865 return future_set_result(self, result);
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400866}
867
868/*[clinic input]
869_asyncio.Future.set_exception
870
Serhiy Storchakabca49392017-09-03 08:10:14 +0300871 exception: object
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400872 /
873
874Mark the future done and set an exception.
875
876If the future is already done when this method is called, raises
877InvalidStateError.
878[clinic start generated code]*/
879
880static PyObject *
881_asyncio_Future_set_exception(FutureObj *self, PyObject *exception)
Serhiy Storchakabca49392017-09-03 08:10:14 +0300882/*[clinic end generated code: output=f1c1b0cd321be360 input=e45b7d7aa71cc66d]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400883{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500884 ENSURE_FUTURE_ALIVE(self)
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400885 return future_set_exception(self, exception);
886}
887
888/*[clinic input]
889_asyncio.Future.add_done_callback
890
Serhiy Storchakabca49392017-09-03 08:10:14 +0300891 fn: object
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400892 /
Yury Selivanovf23746a2018-01-22 19:11:18 -0500893 *
894 context: object = NULL
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400895
896Add a callback to be run when the future becomes done.
897
898The callback is called with a single argument - the future object. If
899the future is already done when this is called, the callback is
900scheduled with call_soon.
901[clinic start generated code]*/
902
903static PyObject *
Yury Selivanovf23746a2018-01-22 19:11:18 -0500904_asyncio_Future_add_done_callback_impl(FutureObj *self, PyObject *fn,
905 PyObject *context)
906/*[clinic end generated code: output=7ce635bbc9554c1e input=15ab0693a96e9533]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400907{
Yury Selivanovf23746a2018-01-22 19:11:18 -0500908 if (context == NULL) {
Yury Selivanov994269c2018-09-27 14:55:55 -0400909 context = PyContext_CopyCurrent();
Yury Selivanovf23746a2018-01-22 19:11:18 -0500910 if (context == NULL) {
911 return NULL;
912 }
Yury Selivanov994269c2018-09-27 14:55:55 -0400913 PyObject *res = future_add_done_callback(self, fn, context);
Yury Selivanovf23746a2018-01-22 19:11:18 -0500914 Py_DECREF(context);
915 return res;
916 }
Yury Selivanov994269c2018-09-27 14:55:55 -0400917 return future_add_done_callback(self, fn, context);
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400918}
919
920/*[clinic input]
921_asyncio.Future.remove_done_callback
922
Serhiy Storchakabca49392017-09-03 08:10:14 +0300923 fn: object
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400924 /
925
926Remove all instances of a callback from the "call when done" list.
927
928Returns the number of callbacks removed.
929[clinic start generated code]*/
930
931static PyObject *
932_asyncio_Future_remove_done_callback(FutureObj *self, PyObject *fn)
Serhiy Storchakabca49392017-09-03 08:10:14 +0300933/*[clinic end generated code: output=5ab1fb52b24ef31f input=0a43280a149d505b]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900934{
935 PyObject *newlist;
936 Py_ssize_t len, i, j=0;
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500937 Py_ssize_t cleared_callback0 = 0;
938
939 ENSURE_FUTURE_ALIVE(self)
940
941 if (self->fut_callback0 != NULL) {
942 int cmp = PyObject_RichCompareBool(fn, self->fut_callback0, Py_EQ);
943 if (cmp == -1) {
944 return NULL;
945 }
946 if (cmp == 1) {
947 /* callback0 == fn */
948 Py_CLEAR(self->fut_callback0);
Yury Selivanovf23746a2018-01-22 19:11:18 -0500949 Py_CLEAR(self->fut_context0);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500950 cleared_callback0 = 1;
951 }
952 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900953
Serhiy Storchakabca49392017-09-03 08:10:14 +0300954 if (self->fut_callbacks == NULL) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500955 return PyLong_FromSsize_t(cleared_callback0);
Serhiy Storchakabca49392017-09-03 08:10:14 +0300956 }
957
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400958 len = PyList_GET_SIZE(self->fut_callbacks);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900959 if (len == 0) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500960 Py_CLEAR(self->fut_callbacks);
961 return PyLong_FromSsize_t(cleared_callback0);
962 }
963
964 if (len == 1) {
Yury Selivanovf23746a2018-01-22 19:11:18 -0500965 PyObject *cb_tup = PyList_GET_ITEM(self->fut_callbacks, 0);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500966 int cmp = PyObject_RichCompareBool(
Yury Selivanovf23746a2018-01-22 19:11:18 -0500967 fn, PyTuple_GET_ITEM(cb_tup, 0), Py_EQ);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500968 if (cmp == -1) {
969 return NULL;
970 }
971 if (cmp == 1) {
972 /* callbacks[0] == fn */
973 Py_CLEAR(self->fut_callbacks);
974 return PyLong_FromSsize_t(1 + cleared_callback0);
975 }
976 /* callbacks[0] != fn and len(callbacks) == 1 */
977 return PyLong_FromSsize_t(cleared_callback0);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900978 }
979
980 newlist = PyList_New(len);
981 if (newlist == NULL) {
982 return NULL;
983 }
984
Yury Selivanov84af9032017-03-02 23:46:56 -0500985 for (i = 0; i < PyList_GET_SIZE(self->fut_callbacks); i++) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900986 int ret;
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400987 PyObject *item = PyList_GET_ITEM(self->fut_callbacks, i);
Serhiy Storchakabca49392017-09-03 08:10:14 +0300988 Py_INCREF(item);
Yury Selivanovf23746a2018-01-22 19:11:18 -0500989 ret = PyObject_RichCompareBool(fn, PyTuple_GET_ITEM(item, 0), Py_EQ);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900990 if (ret == 0) {
Yury Selivanov833a3b02017-07-05 13:32:03 -0400991 if (j < len) {
Yury Selivanov833a3b02017-07-05 13:32:03 -0400992 PyList_SET_ITEM(newlist, j, item);
993 j++;
Serhiy Storchakabca49392017-09-03 08:10:14 +0300994 continue;
Yury Selivanov833a3b02017-07-05 13:32:03 -0400995 }
Serhiy Storchakabca49392017-09-03 08:10:14 +0300996 ret = PyList_Append(newlist, item);
997 }
998 Py_DECREF(item);
999 if (ret < 0) {
1000 goto fail;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001001 }
1002 }
1003
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001004 if (j == 0) {
1005 Py_CLEAR(self->fut_callbacks);
1006 Py_DECREF(newlist);
1007 return PyLong_FromSsize_t(len + cleared_callback0);
1008 }
1009
Serhiy Storchakabca49392017-09-03 08:10:14 +03001010 if (j < len) {
1011 Py_SIZE(newlist) = j;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001012 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03001013 j = PyList_GET_SIZE(newlist);
1014 len = PyList_GET_SIZE(self->fut_callbacks);
1015 if (j != len) {
1016 if (PyList_SetSlice(self->fut_callbacks, 0, len, newlist) < 0) {
1017 goto fail;
1018 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001019 }
1020 Py_DECREF(newlist);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001021 return PyLong_FromSsize_t(len - j + cleared_callback0);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001022
1023fail:
1024 Py_DECREF(newlist);
1025 return NULL;
1026}
1027
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001028/*[clinic input]
1029_asyncio.Future.cancel
1030
1031Cancel the future and schedule callbacks.
1032
1033If the future is already done or cancelled, return False. Otherwise,
1034change the future's state to cancelled, schedule the callbacks and
1035return True.
1036[clinic start generated code]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001037
1038static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001039_asyncio_Future_cancel_impl(FutureObj *self)
1040/*[clinic end generated code: output=e45b932ba8bd68a1 input=515709a127995109]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001041{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001042 ENSURE_FUTURE_ALIVE(self)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001043 return future_cancel(self);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001044}
1045
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001046/*[clinic input]
1047_asyncio.Future.cancelled
1048
1049Return True if the future was cancelled.
1050[clinic start generated code]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001051
1052static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001053_asyncio_Future_cancelled_impl(FutureObj *self)
1054/*[clinic end generated code: output=145197ced586357d input=943ab8b7b7b17e45]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001055{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001056 if (future_is_alive(self) && self->fut_state == STATE_CANCELLED) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001057 Py_RETURN_TRUE;
1058 }
1059 else {
1060 Py_RETURN_FALSE;
1061 }
1062}
1063
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001064/*[clinic input]
1065_asyncio.Future.done
1066
1067Return True if the future is done.
1068
1069Done means either that a result / exception are available, or that the
1070future was cancelled.
1071[clinic start generated code]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001072
1073static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001074_asyncio_Future_done_impl(FutureObj *self)
1075/*[clinic end generated code: output=244c5ac351145096 input=28d7b23fdb65d2ac]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001076{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001077 if (!future_is_alive(self) || self->fut_state == STATE_PENDING) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001078 Py_RETURN_FALSE;
1079 }
1080 else {
1081 Py_RETURN_TRUE;
1082 }
1083}
1084
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001085/*[clinic input]
1086_asyncio.Future.get_loop
1087
1088Return the event loop the Future is bound to.
1089[clinic start generated code]*/
1090
1091static PyObject *
1092_asyncio_Future_get_loop_impl(FutureObj *self)
1093/*[clinic end generated code: output=119b6ea0c9816c3f input=cba48c2136c79d1f]*/
1094{
1095 Py_INCREF(self->fut_loop);
1096 return self->fut_loop;
1097}
1098
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001099static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001100FutureObj_get_blocking(FutureObj *fut, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001101{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001102 if (future_is_alive(fut) && fut->fut_blocking) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001103 Py_RETURN_TRUE;
1104 }
1105 else {
1106 Py_RETURN_FALSE;
1107 }
1108}
1109
1110static int
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001111FutureObj_set_blocking(FutureObj *fut, PyObject *val, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001112{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001113 if (future_ensure_alive(fut)) {
1114 return -1;
1115 }
Zackery Spytz842acaa2018-12-17 07:52:45 -07001116 if (val == NULL) {
1117 PyErr_SetString(PyExc_AttributeError, "cannot delete attribute");
1118 return -1;
1119 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001120
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001121 int is_true = PyObject_IsTrue(val);
1122 if (is_true < 0) {
1123 return -1;
1124 }
1125 fut->fut_blocking = is_true;
1126 return 0;
1127}
1128
1129static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001130FutureObj_get_log_traceback(FutureObj *fut, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001131{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001132 ENSURE_FUTURE_ALIVE(fut)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001133 if (fut->fut_log_tb) {
1134 Py_RETURN_TRUE;
1135 }
1136 else {
1137 Py_RETURN_FALSE;
1138 }
1139}
1140
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +00001141static int
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001142FutureObj_set_log_traceback(FutureObj *fut, PyObject *val, void *Py_UNUSED(ignored))
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +00001143{
Zackery Spytz842acaa2018-12-17 07:52:45 -07001144 if (val == NULL) {
1145 PyErr_SetString(PyExc_AttributeError, "cannot delete attribute");
1146 return -1;
1147 }
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +00001148 int is_true = PyObject_IsTrue(val);
1149 if (is_true < 0) {
1150 return -1;
1151 }
Yury Selivanove0aef4f2017-12-25 16:16:10 -05001152 if (is_true) {
1153 PyErr_SetString(PyExc_ValueError,
1154 "_log_traceback can only be set to False");
1155 return -1;
1156 }
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +00001157 fut->fut_log_tb = is_true;
1158 return 0;
1159}
1160
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001161static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001162FutureObj_get_loop(FutureObj *fut, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001163{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001164 if (!future_is_alive(fut)) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001165 Py_RETURN_NONE;
1166 }
1167 Py_INCREF(fut->fut_loop);
1168 return fut->fut_loop;
1169}
1170
1171static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001172FutureObj_get_callbacks(FutureObj *fut, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001173{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001174 Py_ssize_t i;
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001175
1176 ENSURE_FUTURE_ALIVE(fut)
1177
Yury Selivanovf23746a2018-01-22 19:11:18 -05001178 if (fut->fut_callback0 == NULL) {
1179 if (fut->fut_callbacks == NULL) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001180 Py_RETURN_NONE;
1181 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001182
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001183 Py_INCREF(fut->fut_callbacks);
1184 return fut->fut_callbacks;
1185 }
1186
Yury Selivanovf23746a2018-01-22 19:11:18 -05001187 Py_ssize_t len = 1;
1188 if (fut->fut_callbacks != NULL) {
1189 len += PyList_GET_SIZE(fut->fut_callbacks);
1190 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001191
Yury Selivanovf23746a2018-01-22 19:11:18 -05001192
1193 PyObject *new_list = PyList_New(len);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001194 if (new_list == NULL) {
1195 return NULL;
1196 }
1197
Yury Selivanovf23746a2018-01-22 19:11:18 -05001198 PyObject *tup0 = PyTuple_New(2);
1199 if (tup0 == NULL) {
1200 Py_DECREF(new_list);
1201 return NULL;
1202 }
1203
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001204 Py_INCREF(fut->fut_callback0);
Yury Selivanovf23746a2018-01-22 19:11:18 -05001205 PyTuple_SET_ITEM(tup0, 0, fut->fut_callback0);
1206 assert(fut->fut_context0 != NULL);
1207 Py_INCREF(fut->fut_context0);
1208 PyTuple_SET_ITEM(tup0, 1, (PyObject *)fut->fut_context0);
1209
1210 PyList_SET_ITEM(new_list, 0, tup0);
1211
1212 if (fut->fut_callbacks != NULL) {
1213 for (i = 0; i < PyList_GET_SIZE(fut->fut_callbacks); i++) {
1214 PyObject *cb = PyList_GET_ITEM(fut->fut_callbacks, i);
1215 Py_INCREF(cb);
1216 PyList_SET_ITEM(new_list, i + 1, cb);
1217 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001218 }
1219
1220 return new_list;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001221}
1222
1223static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001224FutureObj_get_result(FutureObj *fut, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001225{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001226 ENSURE_FUTURE_ALIVE(fut)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001227 if (fut->fut_result == NULL) {
1228 Py_RETURN_NONE;
1229 }
1230 Py_INCREF(fut->fut_result);
1231 return fut->fut_result;
1232}
1233
1234static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001235FutureObj_get_exception(FutureObj *fut, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001236{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001237 ENSURE_FUTURE_ALIVE(fut)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001238 if (fut->fut_exception == NULL) {
1239 Py_RETURN_NONE;
1240 }
1241 Py_INCREF(fut->fut_exception);
1242 return fut->fut_exception;
1243}
1244
1245static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001246FutureObj_get_source_traceback(FutureObj *fut, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001247{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001248 if (!future_is_alive(fut) || fut->fut_source_tb == NULL) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001249 Py_RETURN_NONE;
1250 }
1251 Py_INCREF(fut->fut_source_tb);
1252 return fut->fut_source_tb;
1253}
1254
1255static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001256FutureObj_get_state(FutureObj *fut, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001257{
1258 _Py_IDENTIFIER(PENDING);
1259 _Py_IDENTIFIER(CANCELLED);
1260 _Py_IDENTIFIER(FINISHED);
1261 PyObject *ret = NULL;
1262
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001263 ENSURE_FUTURE_ALIVE(fut)
1264
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001265 switch (fut->fut_state) {
1266 case STATE_PENDING:
1267 ret = _PyUnicode_FromId(&PyId_PENDING);
1268 break;
1269 case STATE_CANCELLED:
1270 ret = _PyUnicode_FromId(&PyId_CANCELLED);
1271 break;
1272 case STATE_FINISHED:
1273 ret = _PyUnicode_FromId(&PyId_FINISHED);
1274 break;
1275 default:
1276 assert (0);
1277 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03001278 Py_XINCREF(ret);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001279 return ret;
1280}
1281
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001282/*[clinic input]
1283_asyncio.Future._repr_info
1284[clinic start generated code]*/
1285
1286static PyObject *
1287_asyncio_Future__repr_info_impl(FutureObj *self)
1288/*[clinic end generated code: output=fa69e901bd176cfb input=f21504d8e2ae1ca2]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001289{
Victor Stinnerde4ae3d2016-12-04 22:59:09 +01001290 return PyObject_CallFunctionObjArgs(
1291 asyncio_future_repr_info_func, self, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001292}
1293
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001294static PyObject *
1295FutureObj_repr(FutureObj *fut)
1296{
1297 _Py_IDENTIFIER(_repr_info);
1298
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001299 ENSURE_FUTURE_ALIVE(fut)
1300
Serhiy Storchakabca49392017-09-03 08:10:14 +03001301 PyObject *rinfo = _PyObject_CallMethodIdObjArgs((PyObject*)fut,
1302 &PyId__repr_info,
1303 NULL);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001304 if (rinfo == NULL) {
1305 return NULL;
1306 }
1307
Serhiy Storchakabca49392017-09-03 08:10:14 +03001308 PyObject *rinfo_s = PyUnicode_Join(NULL, rinfo);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001309 Py_DECREF(rinfo);
1310 if (rinfo_s == NULL) {
1311 return NULL;
1312 }
1313
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03001314 PyObject *rstr = PyUnicode_FromFormat("<%s %U>",
1315 _PyType_Name(Py_TYPE(fut)), rinfo_s);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001316 Py_DECREF(rinfo_s);
1317 return rstr;
1318}
1319
1320static void
1321FutureObj_finalize(FutureObj *fut)
1322{
1323 _Py_IDENTIFIER(call_exception_handler);
1324 _Py_IDENTIFIER(message);
1325 _Py_IDENTIFIER(exception);
1326 _Py_IDENTIFIER(future);
1327 _Py_IDENTIFIER(source_traceback);
1328
Serhiy Storchakabca49392017-09-03 08:10:14 +03001329 PyObject *error_type, *error_value, *error_traceback;
1330 PyObject *context;
Serhiy Storchakabca49392017-09-03 08:10:14 +03001331 PyObject *message = NULL;
1332 PyObject *func;
1333
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001334 if (!fut->fut_log_tb) {
1335 return;
1336 }
1337 assert(fut->fut_exception != NULL);
Serhiy Storchakabca49392017-09-03 08:10:14 +03001338 fut->fut_log_tb = 0;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001339
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001340 /* Save the current exception, if any. */
1341 PyErr_Fetch(&error_type, &error_value, &error_traceback);
1342
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001343 context = PyDict_New();
1344 if (context == NULL) {
1345 goto finally;
1346 }
1347
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001348 message = PyUnicode_FromFormat(
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03001349 "%s exception was never retrieved", _PyType_Name(Py_TYPE(fut)));
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001350 if (message == NULL) {
1351 goto finally;
1352 }
1353
1354 if (_PyDict_SetItemId(context, &PyId_message, message) < 0 ||
1355 _PyDict_SetItemId(context, &PyId_exception, fut->fut_exception) < 0 ||
1356 _PyDict_SetItemId(context, &PyId_future, (PyObject*)fut) < 0) {
1357 goto finally;
1358 }
1359 if (fut->fut_source_tb != NULL) {
1360 if (_PyDict_SetItemId(context, &PyId_source_traceback,
1361 fut->fut_source_tb) < 0) {
1362 goto finally;
1363 }
1364 }
1365
1366 func = _PyObject_GetAttrId(fut->fut_loop, &PyId_call_exception_handler);
1367 if (func != NULL) {
Serhiy Storchakabca49392017-09-03 08:10:14 +03001368 PyObject *res = PyObject_CallFunctionObjArgs(func, context, NULL);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001369 if (res == NULL) {
1370 PyErr_WriteUnraisable(func);
1371 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03001372 else {
1373 Py_DECREF(res);
1374 }
1375 Py_DECREF(func);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001376 }
1377
1378finally:
Serhiy Storchakabca49392017-09-03 08:10:14 +03001379 Py_XDECREF(context);
1380 Py_XDECREF(message);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001381
1382 /* Restore the saved exception. */
1383 PyErr_Restore(error_type, error_value, error_traceback);
1384}
1385
1386
1387static PyAsyncMethods FutureType_as_async = {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001388 (unaryfunc)future_new_iter, /* am_await */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001389 0, /* am_aiter */
1390 0 /* am_anext */
1391};
1392
1393static PyMethodDef FutureType_methods[] = {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001394 _ASYNCIO_FUTURE_RESULT_METHODDEF
1395 _ASYNCIO_FUTURE_EXCEPTION_METHODDEF
1396 _ASYNCIO_FUTURE_SET_RESULT_METHODDEF
1397 _ASYNCIO_FUTURE_SET_EXCEPTION_METHODDEF
1398 _ASYNCIO_FUTURE_ADD_DONE_CALLBACK_METHODDEF
1399 _ASYNCIO_FUTURE_REMOVE_DONE_CALLBACK_METHODDEF
1400 _ASYNCIO_FUTURE_CANCEL_METHODDEF
1401 _ASYNCIO_FUTURE_CANCELLED_METHODDEF
1402 _ASYNCIO_FUTURE_DONE_METHODDEF
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001403 _ASYNCIO_FUTURE_GET_LOOP_METHODDEF
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001404 _ASYNCIO_FUTURE__REPR_INFO_METHODDEF
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001405 {NULL, NULL} /* Sentinel */
1406};
1407
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001408#define FUTURE_COMMON_GETSETLIST \
1409 {"_state", (getter)FutureObj_get_state, NULL, NULL}, \
1410 {"_asyncio_future_blocking", (getter)FutureObj_get_blocking, \
1411 (setter)FutureObj_set_blocking, NULL}, \
1412 {"_loop", (getter)FutureObj_get_loop, NULL, NULL}, \
1413 {"_callbacks", (getter)FutureObj_get_callbacks, NULL, NULL}, \
1414 {"_result", (getter)FutureObj_get_result, NULL, NULL}, \
1415 {"_exception", (getter)FutureObj_get_exception, NULL, NULL}, \
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +00001416 {"_log_traceback", (getter)FutureObj_get_log_traceback, \
1417 (setter)FutureObj_set_log_traceback, NULL}, \
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001418 {"_source_traceback", (getter)FutureObj_get_source_traceback, NULL, NULL},
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001419
1420static PyGetSetDef FutureType_getsetlist[] = {
1421 FUTURE_COMMON_GETSETLIST
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001422 {NULL} /* Sentinel */
1423};
1424
1425static void FutureObj_dealloc(PyObject *self);
1426
1427static PyTypeObject FutureType = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02001428 PyVarObject_HEAD_INIT(NULL, 0)
INADA Naoki9f2ce252016-10-15 15:39:19 +09001429 "_asyncio.Future",
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001430 sizeof(FutureObj), /* tp_basicsize */
1431 .tp_dealloc = FutureObj_dealloc,
1432 .tp_as_async = &FutureType_as_async,
1433 .tp_repr = (reprfunc)FutureObj_repr,
1434 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE
1435 | Py_TPFLAGS_HAVE_FINALIZE,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001436 .tp_doc = _asyncio_Future___init____doc__,
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001437 .tp_traverse = (traverseproc)FutureObj_traverse,
1438 .tp_clear = (inquiry)FutureObj_clear,
1439 .tp_weaklistoffset = offsetof(FutureObj, fut_weakreflist),
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001440 .tp_iter = (getiterfunc)future_new_iter,
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001441 .tp_methods = FutureType_methods,
1442 .tp_getset = FutureType_getsetlist,
1443 .tp_dictoffset = offsetof(FutureObj, dict),
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001444 .tp_init = (initproc)_asyncio_Future___init__,
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001445 .tp_new = PyType_GenericNew,
1446 .tp_finalize = (destructor)FutureObj_finalize,
1447};
1448
1449static void
1450FutureObj_dealloc(PyObject *self)
1451{
1452 FutureObj *fut = (FutureObj *)self;
1453
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001454 if (Future_CheckExact(fut)) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001455 /* When fut is subclass of Future, finalizer is called from
1456 * subtype_dealloc.
1457 */
1458 if (PyObject_CallFinalizerFromDealloc(self) < 0) {
1459 // resurrected.
1460 return;
1461 }
1462 }
1463
Alexander Mohrde34cbe2017-08-01 23:31:07 -07001464 PyObject_GC_UnTrack(self);
1465
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001466 if (fut->fut_weakreflist != NULL) {
1467 PyObject_ClearWeakRefs(self);
1468 }
1469
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001470 (void)FutureObj_clear(fut);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001471 Py_TYPE(fut)->tp_free(fut);
1472}
1473
1474
1475/*********************** Future Iterator **************************/
1476
1477typedef struct {
1478 PyObject_HEAD
1479 FutureObj *future;
1480} futureiterobject;
1481
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001482
1483#define FI_FREELIST_MAXLEN 255
1484static futureiterobject *fi_freelist = NULL;
1485static Py_ssize_t fi_freelist_len = 0;
1486
1487
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001488static void
1489FutureIter_dealloc(futureiterobject *it)
1490{
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001491 PyObject_GC_UnTrack(it);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001492 Py_CLEAR(it->future);
1493
1494 if (fi_freelist_len < FI_FREELIST_MAXLEN) {
1495 fi_freelist_len++;
1496 it->future = (FutureObj*) fi_freelist;
1497 fi_freelist = it;
1498 }
1499 else {
1500 PyObject_GC_Del(it);
1501 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001502}
1503
1504static PyObject *
1505FutureIter_iternext(futureiterobject *it)
1506{
1507 PyObject *res;
1508 FutureObj *fut = it->future;
1509
1510 if (fut == NULL) {
1511 return NULL;
1512 }
1513
1514 if (fut->fut_state == STATE_PENDING) {
1515 if (!fut->fut_blocking) {
1516 fut->fut_blocking = 1;
1517 Py_INCREF(fut);
1518 return (PyObject *)fut;
1519 }
Yury Selivanov0cf16f92017-12-25 10:48:15 -05001520 PyErr_SetString(PyExc_RuntimeError,
1521 "await wasn't used with future");
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001522 return NULL;
1523 }
1524
Serhiy Storchakabca49392017-09-03 08:10:14 +03001525 it->future = NULL;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001526 res = _asyncio_Future_result_impl(fut);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001527 if (res != NULL) {
Serhiy Storchaka60e49aa2016-11-06 18:47:03 +02001528 /* The result of the Future is not an exception. */
Serhiy Storchakabca49392017-09-03 08:10:14 +03001529 (void)_PyGen_SetStopIterationValue(res);
Serhiy Storchaka60e49aa2016-11-06 18:47:03 +02001530 Py_DECREF(res);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001531 }
1532
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001533 Py_DECREF(fut);
1534 return NULL;
1535}
1536
1537static PyObject *
INADA Naoki74c17532016-10-25 19:00:45 +09001538FutureIter_send(futureiterobject *self, PyObject *unused)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001539{
INADA Naoki74c17532016-10-25 19:00:45 +09001540 /* Future.__iter__ doesn't care about values that are pushed to the
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03001541 * generator, it just returns self.result().
INADA Naoki74c17532016-10-25 19:00:45 +09001542 */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001543 return FutureIter_iternext(self);
1544}
1545
1546static PyObject *
1547FutureIter_throw(futureiterobject *self, PyObject *args)
1548{
Serhiy Storchakabca49392017-09-03 08:10:14 +03001549 PyObject *type, *val = NULL, *tb = NULL;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001550 if (!PyArg_ParseTuple(args, "O|OO", &type, &val, &tb))
1551 return NULL;
1552
1553 if (val == Py_None) {
1554 val = NULL;
1555 }
1556 if (tb == Py_None) {
1557 tb = NULL;
Benjamin Peterson996fc1f2016-11-14 00:15:44 -08001558 } else if (tb != NULL && !PyTraceBack_Check(tb)) {
1559 PyErr_SetString(PyExc_TypeError, "throw() third argument must be a traceback");
1560 return NULL;
1561 }
1562
1563 Py_INCREF(type);
1564 Py_XINCREF(val);
1565 Py_XINCREF(tb);
1566
1567 if (PyExceptionClass_Check(type)) {
1568 PyErr_NormalizeException(&type, &val, &tb);
Yury Selivanovedfe8862016-12-01 11:37:47 -05001569 /* No need to call PyException_SetTraceback since we'll be calling
1570 PyErr_Restore for `type`, `val`, and `tb`. */
Benjamin Peterson996fc1f2016-11-14 00:15:44 -08001571 } else if (PyExceptionInstance_Check(type)) {
1572 if (val) {
1573 PyErr_SetString(PyExc_TypeError,
1574 "instance exception may not have a separate value");
1575 goto fail;
1576 }
1577 val = type;
1578 type = PyExceptionInstance_Class(type);
1579 Py_INCREF(type);
1580 if (tb == NULL)
1581 tb = PyException_GetTraceback(val);
1582 } else {
1583 PyErr_SetString(PyExc_TypeError,
1584 "exceptions must be classes deriving BaseException or "
1585 "instances of such a class");
1586 goto fail;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001587 }
1588
1589 Py_CLEAR(self->future);
1590
Benjamin Peterson996fc1f2016-11-14 00:15:44 -08001591 PyErr_Restore(type, val, tb);
1592
Serhiy Storchakabca49392017-09-03 08:10:14 +03001593 return NULL;
Benjamin Peterson996fc1f2016-11-14 00:15:44 -08001594
1595 fail:
1596 Py_DECREF(type);
1597 Py_XDECREF(val);
1598 Py_XDECREF(tb);
1599 return NULL;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001600}
1601
1602static PyObject *
1603FutureIter_close(futureiterobject *self, PyObject *arg)
1604{
1605 Py_CLEAR(self->future);
1606 Py_RETURN_NONE;
1607}
1608
1609static int
1610FutureIter_traverse(futureiterobject *it, visitproc visit, void *arg)
1611{
1612 Py_VISIT(it->future);
1613 return 0;
1614}
1615
1616static PyMethodDef FutureIter_methods[] = {
1617 {"send", (PyCFunction)FutureIter_send, METH_O, NULL},
1618 {"throw", (PyCFunction)FutureIter_throw, METH_VARARGS, NULL},
1619 {"close", (PyCFunction)FutureIter_close, METH_NOARGS, NULL},
1620 {NULL, NULL} /* Sentinel */
1621};
1622
1623static PyTypeObject FutureIterType = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02001624 PyVarObject_HEAD_INIT(NULL, 0)
INADA Naoki9f2ce252016-10-15 15:39:19 +09001625 "_asyncio.FutureIter",
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001626 .tp_basicsize = sizeof(futureiterobject),
1627 .tp_itemsize = 0,
1628 .tp_dealloc = (destructor)FutureIter_dealloc,
1629 .tp_getattro = PyObject_GenericGetAttr,
1630 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
1631 .tp_traverse = (traverseproc)FutureIter_traverse,
1632 .tp_iter = PyObject_SelfIter,
1633 .tp_iternext = (iternextfunc)FutureIter_iternext,
1634 .tp_methods = FutureIter_methods,
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001635};
1636
1637static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001638future_new_iter(PyObject *fut)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001639{
1640 futureiterobject *it;
1641
1642 if (!PyObject_TypeCheck(fut, &FutureType)) {
1643 PyErr_BadInternalCall();
1644 return NULL;
1645 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001646
1647 ENSURE_FUTURE_ALIVE(fut)
1648
1649 if (fi_freelist_len) {
1650 fi_freelist_len--;
1651 it = fi_freelist;
1652 fi_freelist = (futureiterobject*) it->future;
1653 it->future = NULL;
1654 _Py_NewReference((PyObject*) it);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001655 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001656 else {
1657 it = PyObject_GC_New(futureiterobject, &FutureIterType);
1658 if (it == NULL) {
1659 return NULL;
1660 }
1661 }
1662
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001663 Py_INCREF(fut);
1664 it->future = (FutureObj*)fut;
INADA Naoki1be427b2016-10-11 02:12:34 +09001665 PyObject_GC_Track(it);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001666 return (PyObject*)it;
1667}
1668
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001669
1670/*********************** Task **************************/
1671
1672
1673/*[clinic input]
1674class _asyncio.Task "TaskObj *" "&Task_Type"
1675[clinic start generated code]*/
1676/*[clinic end generated code: output=da39a3ee5e6b4b0d input=719dcef0fcc03b37]*/
1677
1678static int task_call_step_soon(TaskObj *, PyObject *);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001679static PyObject * task_wakeup(TaskObj *, PyObject *);
1680static PyObject * task_step(TaskObj *, PyObject *);
1681
1682/* ----- Task._step wrapper */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001683
INADA Naokic411a7d2016-10-18 11:48:14 +09001684static int
Serhiy Storchakabca49392017-09-03 08:10:14 +03001685TaskStepMethWrapper_clear(TaskStepMethWrapper *o)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001686{
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001687 Py_CLEAR(o->sw_task);
1688 Py_CLEAR(o->sw_arg);
1689 return 0;
1690}
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001691
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001692static void
Serhiy Storchakabca49392017-09-03 08:10:14 +03001693TaskStepMethWrapper_dealloc(TaskStepMethWrapper *o)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001694{
1695 PyObject_GC_UnTrack(o);
Serhiy Storchakabca49392017-09-03 08:10:14 +03001696 (void)TaskStepMethWrapper_clear(o);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001697 Py_TYPE(o)->tp_free(o);
1698}
1699
1700static PyObject *
Serhiy Storchakabca49392017-09-03 08:10:14 +03001701TaskStepMethWrapper_call(TaskStepMethWrapper *o,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001702 PyObject *args, PyObject *kwds)
1703{
Serhiy Storchakabca49392017-09-03 08:10:14 +03001704 if (kwds != NULL && PyDict_GET_SIZE(kwds) != 0) {
1705 PyErr_SetString(PyExc_TypeError, "function takes no keyword arguments");
1706 return NULL;
1707 }
1708 if (args != NULL && PyTuple_GET_SIZE(args) != 0) {
1709 PyErr_SetString(PyExc_TypeError, "function takes no positional arguments");
1710 return NULL;
1711 }
Yury Selivanov22feeb82018-01-24 11:31:01 -05001712 return task_step(o->sw_task, o->sw_arg);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001713}
1714
1715static int
Serhiy Storchakabca49392017-09-03 08:10:14 +03001716TaskStepMethWrapper_traverse(TaskStepMethWrapper *o,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001717 visitproc visit, void *arg)
1718{
1719 Py_VISIT(o->sw_task);
1720 Py_VISIT(o->sw_arg);
1721 return 0;
1722}
1723
1724static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001725TaskStepMethWrapper_get___self__(TaskStepMethWrapper *o, void *Py_UNUSED(ignored))
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001726{
1727 if (o->sw_task) {
1728 Py_INCREF(o->sw_task);
1729 return (PyObject*)o->sw_task;
1730 }
1731 Py_RETURN_NONE;
1732}
1733
Serhiy Storchakabca49392017-09-03 08:10:14 +03001734static PyGetSetDef TaskStepMethWrapper_getsetlist[] = {
1735 {"__self__", (getter)TaskStepMethWrapper_get___self__, NULL, NULL},
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001736 {NULL} /* Sentinel */
1737};
1738
Benjamin Peterson3c8aae92018-07-05 22:39:34 -07001739static PyTypeObject TaskStepMethWrapper_Type = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02001740 PyVarObject_HEAD_INIT(NULL, 0)
Serhiy Storchakabca49392017-09-03 08:10:14 +03001741 "TaskStepMethWrapper",
1742 .tp_basicsize = sizeof(TaskStepMethWrapper),
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001743 .tp_itemsize = 0,
Serhiy Storchakabca49392017-09-03 08:10:14 +03001744 .tp_getset = TaskStepMethWrapper_getsetlist,
1745 .tp_dealloc = (destructor)TaskStepMethWrapper_dealloc,
1746 .tp_call = (ternaryfunc)TaskStepMethWrapper_call,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001747 .tp_getattro = PyObject_GenericGetAttr,
1748 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
Serhiy Storchakabca49392017-09-03 08:10:14 +03001749 .tp_traverse = (traverseproc)TaskStepMethWrapper_traverse,
1750 .tp_clear = (inquiry)TaskStepMethWrapper_clear,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001751};
1752
1753static PyObject *
Serhiy Storchakabca49392017-09-03 08:10:14 +03001754TaskStepMethWrapper_new(TaskObj *task, PyObject *arg)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001755{
Serhiy Storchakabca49392017-09-03 08:10:14 +03001756 TaskStepMethWrapper *o;
1757 o = PyObject_GC_New(TaskStepMethWrapper, &TaskStepMethWrapper_Type);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001758 if (o == NULL) {
1759 return NULL;
1760 }
1761
1762 Py_INCREF(task);
1763 o->sw_task = task;
1764
1765 Py_XINCREF(arg);
1766 o->sw_arg = arg;
1767
1768 PyObject_GC_Track(o);
1769 return (PyObject*) o;
1770}
1771
1772/* ----- Task._wakeup wrapper */
1773
1774static PyObject *
1775TaskWakeupMethWrapper_call(TaskWakeupMethWrapper *o,
1776 PyObject *args, PyObject *kwds)
1777{
1778 PyObject *fut;
1779
Serhiy Storchakabca49392017-09-03 08:10:14 +03001780 if (kwds != NULL && PyDict_GET_SIZE(kwds) != 0) {
1781 PyErr_SetString(PyExc_TypeError, "function takes no keyword arguments");
1782 return NULL;
1783 }
1784 if (!PyArg_ParseTuple(args, "O", &fut)) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001785 return NULL;
1786 }
1787
Yury Selivanov22feeb82018-01-24 11:31:01 -05001788 return task_wakeup(o->ww_task, fut);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001789}
1790
1791static int
1792TaskWakeupMethWrapper_clear(TaskWakeupMethWrapper *o)
1793{
1794 Py_CLEAR(o->ww_task);
1795 return 0;
1796}
1797
1798static int
1799TaskWakeupMethWrapper_traverse(TaskWakeupMethWrapper *o,
1800 visitproc visit, void *arg)
1801{
1802 Py_VISIT(o->ww_task);
1803 return 0;
1804}
1805
1806static void
1807TaskWakeupMethWrapper_dealloc(TaskWakeupMethWrapper *o)
1808{
1809 PyObject_GC_UnTrack(o);
1810 (void)TaskWakeupMethWrapper_clear(o);
1811 Py_TYPE(o)->tp_free(o);
1812}
1813
Benjamin Peterson3c8aae92018-07-05 22:39:34 -07001814static PyTypeObject TaskWakeupMethWrapper_Type = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02001815 PyVarObject_HEAD_INIT(NULL, 0)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001816 "TaskWakeupMethWrapper",
1817 .tp_basicsize = sizeof(TaskWakeupMethWrapper),
1818 .tp_itemsize = 0,
1819 .tp_dealloc = (destructor)TaskWakeupMethWrapper_dealloc,
1820 .tp_call = (ternaryfunc)TaskWakeupMethWrapper_call,
1821 .tp_getattro = PyObject_GenericGetAttr,
1822 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
1823 .tp_traverse = (traverseproc)TaskWakeupMethWrapper_traverse,
1824 .tp_clear = (inquiry)TaskWakeupMethWrapper_clear,
1825};
1826
1827static PyObject *
1828TaskWakeupMethWrapper_new(TaskObj *task)
1829{
1830 TaskWakeupMethWrapper *o;
1831 o = PyObject_GC_New(TaskWakeupMethWrapper, &TaskWakeupMethWrapper_Type);
1832 if (o == NULL) {
1833 return NULL;
1834 }
1835
1836 Py_INCREF(task);
1837 o->ww_task = task;
1838
1839 PyObject_GC_Track(o);
1840 return (PyObject*) o;
1841}
1842
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001843/* ----- Task introspection helpers */
1844
1845static int
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001846register_task(PyObject *task)
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001847{
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001848 _Py_IDENTIFIER(add);
1849
1850 PyObject *res = _PyObject_CallMethodIdObjArgs(
1851 all_tasks, &PyId_add, task, NULL);
1852 if (res == NULL) {
1853 return -1;
1854 }
1855 Py_DECREF(res);
1856 return 0;
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001857}
1858
1859
1860static int
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001861unregister_task(PyObject *task)
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001862{
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001863 _Py_IDENTIFIER(discard);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001864
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001865 PyObject *res = _PyObject_CallMethodIdObjArgs(
1866 all_tasks, &PyId_discard, task, NULL);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001867 if (res == NULL) {
1868 return -1;
1869 }
1870 Py_DECREF(res);
1871 return 0;
1872}
1873
1874
1875static int
1876enter_task(PyObject *loop, PyObject *task)
1877{
1878 PyObject *item;
1879 Py_hash_t hash;
1880 hash = PyObject_Hash(loop);
1881 if (hash == -1) {
1882 return -1;
1883 }
1884 item = _PyDict_GetItem_KnownHash(current_tasks, loop, hash);
1885 if (item != NULL) {
Serhiy Storchaka66553542018-05-20 16:30:31 +03001886 Py_INCREF(item);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001887 PyErr_Format(
1888 PyExc_RuntimeError,
1889 "Cannot enter into task %R while another " \
1890 "task %R is being executed.",
1891 task, item, NULL);
Serhiy Storchaka66553542018-05-20 16:30:31 +03001892 Py_DECREF(item);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001893 return -1;
1894 }
Serhiy Storchaka66553542018-05-20 16:30:31 +03001895 if (PyErr_Occurred()) {
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001896 return -1;
1897 }
Serhiy Storchaka66553542018-05-20 16:30:31 +03001898 return _PyDict_SetItem_KnownHash(current_tasks, loop, task, hash);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001899}
1900
1901
1902static int
1903leave_task(PyObject *loop, PyObject *task)
1904/*[clinic end generated code: output=0ebf6db4b858fb41 input=51296a46313d1ad8]*/
1905{
1906 PyObject *item;
1907 Py_hash_t hash;
1908 hash = PyObject_Hash(loop);
1909 if (hash == -1) {
1910 return -1;
1911 }
1912 item = _PyDict_GetItem_KnownHash(current_tasks, loop, hash);
1913 if (item != task) {
1914 if (item == NULL) {
1915 /* Not entered, replace with None */
1916 item = Py_None;
1917 }
1918 PyErr_Format(
1919 PyExc_RuntimeError,
1920 "Leaving task %R does not match the current task %R.",
1921 task, item, NULL);
1922 return -1;
1923 }
1924 return _PyDict_DelItem_KnownHash(current_tasks, loop, hash);
1925}
1926
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001927/* ----- Task */
1928
1929/*[clinic input]
1930_asyncio.Task.__init__
1931
Serhiy Storchakabca49392017-09-03 08:10:14 +03001932 coro: object
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001933 *
Serhiy Storchakabca49392017-09-03 08:10:14 +03001934 loop: object = None
Alex Grönholmcca4eec2018-08-09 00:06:47 +03001935 name: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001936
1937A coroutine wrapped in a Future.
1938[clinic start generated code]*/
1939
1940static int
Alex Grönholmcca4eec2018-08-09 00:06:47 +03001941_asyncio_Task___init___impl(TaskObj *self, PyObject *coro, PyObject *loop,
1942 PyObject *name)
1943/*[clinic end generated code: output=88b12b83d570df50 input=352a3137fe60091d]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001944{
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001945 if (future_init((FutureObj*)self, loop)) {
INADA Naokic411a7d2016-10-18 11:48:14 +09001946 return -1;
1947 }
INADA Naokic411a7d2016-10-18 11:48:14 +09001948
Yury Selivanova9d7e552017-12-19 07:18:45 -05001949 int is_coro = is_coroutine(coro);
1950 if (is_coro == -1) {
1951 return -1;
1952 }
1953 if (is_coro == 0) {
1954 self->task_log_destroy_pending = 0;
1955 PyErr_Format(PyExc_TypeError,
1956 "a coroutine was expected, got %R",
1957 coro, NULL);
1958 return -1;
Andrew Svetlovf74ef452017-12-15 07:04:38 +02001959 }
1960
Oren Milmand019bc82018-02-13 12:28:33 +02001961 Py_XSETREF(self->task_context, PyContext_CopyCurrent());
Yury Selivanovf23746a2018-01-22 19:11:18 -05001962 if (self->task_context == NULL) {
1963 return -1;
1964 }
1965
Oren Milmand019bc82018-02-13 12:28:33 +02001966 Py_CLEAR(self->task_fut_waiter);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001967 self->task_must_cancel = 0;
1968 self->task_log_destroy_pending = 1;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001969 Py_INCREF(coro);
Oren Milmand019bc82018-02-13 12:28:33 +02001970 Py_XSETREF(self->task_coro, coro);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001971
Alex Grönholmcca4eec2018-08-09 00:06:47 +03001972 if (name == Py_None) {
1973 name = PyUnicode_FromFormat("Task-%" PRIu64, ++task_name_counter);
Alex Grönholma7548232018-08-09 23:49:49 +03001974 } else if (!PyUnicode_CheckExact(name)) {
Alex Grönholmcca4eec2018-08-09 00:06:47 +03001975 name = PyObject_Str(name);
1976 } else {
1977 Py_INCREF(name);
1978 }
1979 Py_XSETREF(self->task_name, name);
1980 if (self->task_name == NULL) {
1981 return -1;
1982 }
1983
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001984 if (task_call_step_soon(self, NULL)) {
1985 return -1;
INADA Naokic411a7d2016-10-18 11:48:14 +09001986 }
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001987 return register_task((PyObject*)self);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001988}
1989
1990static int
1991TaskObj_clear(TaskObj *task)
1992{
1993 (void)FutureObj_clear((FutureObj*) task);
Yury Selivanovf23746a2018-01-22 19:11:18 -05001994 Py_CLEAR(task->task_context);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001995 Py_CLEAR(task->task_coro);
Alex Grönholmcca4eec2018-08-09 00:06:47 +03001996 Py_CLEAR(task->task_name);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001997 Py_CLEAR(task->task_fut_waiter);
1998 return 0;
1999}
2000
2001static int
2002TaskObj_traverse(TaskObj *task, visitproc visit, void *arg)
2003{
Yury Selivanovf23746a2018-01-22 19:11:18 -05002004 Py_VISIT(task->task_context);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002005 Py_VISIT(task->task_coro);
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002006 Py_VISIT(task->task_name);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002007 Py_VISIT(task->task_fut_waiter);
2008 (void)FutureObj_traverse((FutureObj*) task, visit, arg);
2009 return 0;
2010}
2011
2012static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02002013TaskObj_get_log_destroy_pending(TaskObj *task, void *Py_UNUSED(ignored))
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002014{
2015 if (task->task_log_destroy_pending) {
2016 Py_RETURN_TRUE;
2017 }
2018 else {
2019 Py_RETURN_FALSE;
2020 }
2021}
2022
2023static int
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02002024TaskObj_set_log_destroy_pending(TaskObj *task, PyObject *val, void *Py_UNUSED(ignored))
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002025{
Zackery Spytz842acaa2018-12-17 07:52:45 -07002026 if (val == NULL) {
2027 PyErr_SetString(PyExc_AttributeError, "cannot delete attribute");
2028 return -1;
2029 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002030 int is_true = PyObject_IsTrue(val);
2031 if (is_true < 0) {
2032 return -1;
2033 }
2034 task->task_log_destroy_pending = is_true;
2035 return 0;
2036}
2037
2038static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02002039TaskObj_get_must_cancel(TaskObj *task, void *Py_UNUSED(ignored))
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002040{
2041 if (task->task_must_cancel) {
2042 Py_RETURN_TRUE;
2043 }
2044 else {
2045 Py_RETURN_FALSE;
2046 }
2047}
2048
2049static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02002050TaskObj_get_coro(TaskObj *task, void *Py_UNUSED(ignored))
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002051{
2052 if (task->task_coro) {
2053 Py_INCREF(task->task_coro);
2054 return task->task_coro;
2055 }
2056
2057 Py_RETURN_NONE;
2058}
2059
2060static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02002061TaskObj_get_fut_waiter(TaskObj *task, void *Py_UNUSED(ignored))
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002062{
2063 if (task->task_fut_waiter) {
2064 Py_INCREF(task->task_fut_waiter);
2065 return task->task_fut_waiter;
2066 }
2067
2068 Py_RETURN_NONE;
2069}
2070
2071/*[clinic input]
2072@classmethod
2073_asyncio.Task.current_task
2074
Serhiy Storchakabca49392017-09-03 08:10:14 +03002075 loop: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002076
2077Return the currently running task in an event loop or None.
2078
2079By default the current task for the current event loop is returned.
2080
2081None is returned when called not in the context of a Task.
2082[clinic start generated code]*/
2083
2084static PyObject *
2085_asyncio_Task_current_task_impl(PyTypeObject *type, PyObject *loop)
Serhiy Storchakabca49392017-09-03 08:10:14 +03002086/*[clinic end generated code: output=99fbe7332c516e03 input=cd14770c5b79c7eb]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002087{
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002088 PyObject *ret;
2089 PyObject *current_task_func;
2090
Inada Naokic5c6cda2019-03-22 20:07:32 +09002091 if (PyErr_WarnEx(PyExc_DeprecationWarning,
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002092 "Task.current_task() is deprecated, " \
2093 "use asyncio.current_task() instead",
2094 1) < 0) {
2095 return NULL;
2096 }
2097
2098 current_task_func = _PyObject_GetAttrId(asyncio_mod, &PyId_current_task);
2099 if (current_task_func == NULL) {
2100 return NULL;
2101 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002102
Yury Selivanov8d26aa92017-03-02 22:16:33 -05002103 if (loop == Py_None) {
Yury Selivanova70232f2017-12-13 14:49:42 -05002104 loop = get_event_loop();
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002105 if (loop == NULL) {
Serhiy Storchaka66553542018-05-20 16:30:31 +03002106 Py_DECREF(current_task_func);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002107 return NULL;
2108 }
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002109 ret = PyObject_CallFunctionObjArgs(current_task_func, loop, NULL);
2110 Py_DECREF(current_task_func);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002111 Py_DECREF(loop);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002112 return ret;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002113 }
2114 else {
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002115 ret = PyObject_CallFunctionObjArgs(current_task_func, loop, NULL);
2116 Py_DECREF(current_task_func);
2117 return ret;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002118 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002119}
2120
2121/*[clinic input]
2122@classmethod
2123_asyncio.Task.all_tasks
2124
Serhiy Storchakabca49392017-09-03 08:10:14 +03002125 loop: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002126
2127Return a set of all tasks for an event loop.
2128
2129By default all tasks for the current event loop are returned.
2130[clinic start generated code]*/
2131
2132static PyObject *
2133_asyncio_Task_all_tasks_impl(PyTypeObject *type, PyObject *loop)
Serhiy Storchakabca49392017-09-03 08:10:14 +03002134/*[clinic end generated code: output=11f9b20749ccca5d input=497f80bc9ce726b5]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002135{
2136 PyObject *res;
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002137 PyObject *all_tasks_func;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002138
Inada Naokic5c6cda2019-03-22 20:07:32 +09002139 if (PyErr_WarnEx(PyExc_DeprecationWarning,
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002140 "Task.all_tasks() is deprecated, " \
2141 "use asyncio.all_tasks() instead",
2142 1) < 0) {
2143 return NULL;
2144 }
2145
Yury Selivanov416c1eb2018-05-28 17:54:02 -04002146 all_tasks_func = _PyObject_GetAttrId(asyncio_mod, &PyId__all_tasks_compat);
Serhiy Storchaka66553542018-05-20 16:30:31 +03002147 if (all_tasks_func == NULL) {
2148 return NULL;
2149 }
2150
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002151 res = PyObject_CallFunctionObjArgs(all_tasks_func, loop, NULL);
2152 Py_DECREF(all_tasks_func);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002153 return res;
2154}
2155
2156/*[clinic input]
2157_asyncio.Task._repr_info
2158[clinic start generated code]*/
2159
2160static PyObject *
2161_asyncio_Task__repr_info_impl(TaskObj *self)
2162/*[clinic end generated code: output=6a490eb66d5ba34b input=3c6d051ed3ddec8b]*/
2163{
Victor Stinnerde4ae3d2016-12-04 22:59:09 +01002164 return PyObject_CallFunctionObjArgs(
2165 asyncio_task_repr_info_func, self, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002166}
2167
2168/*[clinic input]
2169_asyncio.Task.cancel
2170
2171Request that this task cancel itself.
2172
2173This arranges for a CancelledError to be thrown into the
2174wrapped coroutine on the next cycle through the event loop.
2175The coroutine then has a chance to clean up or even deny
2176the request using try/except/finally.
2177
2178Unlike Future.cancel, this does not guarantee that the
2179task will be cancelled: the exception might be caught and
2180acted upon, delaying cancellation of the task or preventing
2181cancellation completely. The task may also return a value or
2182raise a different exception.
2183
2184Immediately after this method is called, Task.cancelled() will
2185not return True (unless the task was already cancelled). A
2186task will be marked as cancelled when the wrapped coroutine
2187terminates with a CancelledError exception (even if cancel()
2188was not called).
2189[clinic start generated code]*/
2190
2191static PyObject *
2192_asyncio_Task_cancel_impl(TaskObj *self)
2193/*[clinic end generated code: output=6bfc0479da9d5757 input=13f9bf496695cb52]*/
2194{
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +00002195 self->task_log_tb = 0;
2196
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002197 if (self->task_state != STATE_PENDING) {
2198 Py_RETURN_FALSE;
2199 }
2200
2201 if (self->task_fut_waiter) {
2202 PyObject *res;
2203 int is_true;
2204
2205 res = _PyObject_CallMethodId(
2206 self->task_fut_waiter, &PyId_cancel, NULL);
2207 if (res == NULL) {
2208 return NULL;
2209 }
2210
2211 is_true = PyObject_IsTrue(res);
2212 Py_DECREF(res);
2213 if (is_true < 0) {
2214 return NULL;
2215 }
2216
2217 if (is_true) {
2218 Py_RETURN_TRUE;
2219 }
2220 }
2221
2222 self->task_must_cancel = 1;
2223 Py_RETURN_TRUE;
2224}
2225
2226/*[clinic input]
2227_asyncio.Task.get_stack
2228
2229 *
Serhiy Storchakabca49392017-09-03 08:10:14 +03002230 limit: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002231
2232Return the list of stack frames for this task's coroutine.
2233
2234If the coroutine is not done, this returns the stack where it is
2235suspended. If the coroutine has completed successfully or was
2236cancelled, this returns an empty list. If the coroutine was
2237terminated by an exception, this returns the list of traceback
2238frames.
2239
2240The frames are always ordered from oldest to newest.
2241
2242The optional limit gives the maximum number of frames to
2243return; by default all available frames are returned. Its
2244meaning differs depending on whether a stack or a traceback is
2245returned: the newest frames of a stack are returned, but the
2246oldest frames of a traceback are returned. (This matches the
2247behavior of the traceback module.)
2248
2249For reasons beyond our control, only one stack frame is
2250returned for a suspended coroutine.
2251[clinic start generated code]*/
2252
2253static PyObject *
2254_asyncio_Task_get_stack_impl(TaskObj *self, PyObject *limit)
Serhiy Storchakabca49392017-09-03 08:10:14 +03002255/*[clinic end generated code: output=c9aeeeebd1e18118 input=05b323d42b809b90]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002256{
2257 return PyObject_CallFunctionObjArgs(
2258 asyncio_task_get_stack_func, self, limit, NULL);
2259}
2260
2261/*[clinic input]
2262_asyncio.Task.print_stack
2263
2264 *
Serhiy Storchakabca49392017-09-03 08:10:14 +03002265 limit: object = None
2266 file: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002267
2268Print the stack or traceback for this task's coroutine.
2269
2270This produces output similar to that of the traceback module,
2271for the frames retrieved by get_stack(). The limit argument
2272is passed to get_stack(). The file argument is an I/O stream
2273to which the output is written; by default output is written
2274to sys.stderr.
2275[clinic start generated code]*/
2276
2277static PyObject *
2278_asyncio_Task_print_stack_impl(TaskObj *self, PyObject *limit,
2279 PyObject *file)
Serhiy Storchakabca49392017-09-03 08:10:14 +03002280/*[clinic end generated code: output=7339e10314cd3f4d input=1a0352913b7fcd92]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002281{
2282 return PyObject_CallFunctionObjArgs(
2283 asyncio_task_print_stack_func, self, limit, file, NULL);
2284}
2285
2286/*[clinic input]
Yury Selivanov0cf16f92017-12-25 10:48:15 -05002287_asyncio.Task.set_result
2288
2289 result: object
2290 /
2291[clinic start generated code]*/
2292
2293static PyObject *
2294_asyncio_Task_set_result(TaskObj *self, PyObject *result)
2295/*[clinic end generated code: output=1dcae308bfcba318 input=9d1a00c07be41bab]*/
2296{
2297 PyErr_SetString(PyExc_RuntimeError,
2298 "Task does not support set_result operation");
2299 return NULL;
2300}
2301
2302/*[clinic input]
2303_asyncio.Task.set_exception
2304
2305 exception: object
2306 /
2307[clinic start generated code]*/
2308
2309static PyObject *
2310_asyncio_Task_set_exception(TaskObj *self, PyObject *exception)
2311/*[clinic end generated code: output=bc377fc28067303d input=9a8f65c83dcf893a]*/
2312{
2313 PyErr_SetString(PyExc_RuntimeError,
Andrew Svetlovfc359322017-12-30 15:40:27 +02002314 "Task does not support set_exception operation");
Yury Selivanov0cf16f92017-12-25 10:48:15 -05002315 return NULL;
2316}
2317
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002318/*[clinic input]
2319_asyncio.Task.get_name
2320[clinic start generated code]*/
2321
2322static PyObject *
2323_asyncio_Task_get_name_impl(TaskObj *self)
2324/*[clinic end generated code: output=0ecf1570c3b37a8f input=a4a6595d12f4f0f8]*/
2325{
2326 if (self->task_name) {
2327 Py_INCREF(self->task_name);
2328 return self->task_name;
2329 }
2330
2331 Py_RETURN_NONE;
2332}
2333
2334/*[clinic input]
2335_asyncio.Task.set_name
2336
2337 value: object
2338 /
2339[clinic start generated code]*/
2340
2341static PyObject *
2342_asyncio_Task_set_name(TaskObj *self, PyObject *value)
2343/*[clinic end generated code: output=138a8d51e32057d6 input=a8359b6e65f8fd31]*/
2344{
Alex Grönholma7548232018-08-09 23:49:49 +03002345 if (!PyUnicode_CheckExact(value)) {
2346 value = PyObject_Str(value);
2347 if (value == NULL) {
2348 return NULL;
2349 }
2350 } else {
2351 Py_INCREF(value);
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002352 }
2353
Alex Grönholma7548232018-08-09 23:49:49 +03002354 Py_XSETREF(self->task_name, value);
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002355 Py_RETURN_NONE;
2356}
Yury Selivanov0cf16f92017-12-25 10:48:15 -05002357
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002358static void
2359TaskObj_finalize(TaskObj *task)
2360{
2361 _Py_IDENTIFIER(call_exception_handler);
2362 _Py_IDENTIFIER(task);
2363 _Py_IDENTIFIER(message);
2364 _Py_IDENTIFIER(source_traceback);
2365
Serhiy Storchakabca49392017-09-03 08:10:14 +03002366 PyObject *context;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002367 PyObject *message = NULL;
Serhiy Storchakabca49392017-09-03 08:10:14 +03002368 PyObject *func;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002369 PyObject *error_type, *error_value, *error_traceback;
2370
2371 if (task->task_state != STATE_PENDING || !task->task_log_destroy_pending) {
2372 goto done;
2373 }
2374
2375 /* Save the current exception, if any. */
2376 PyErr_Fetch(&error_type, &error_value, &error_traceback);
2377
2378 context = PyDict_New();
2379 if (context == NULL) {
2380 goto finally;
2381 }
2382
2383 message = PyUnicode_FromString("Task was destroyed but it is pending!");
2384 if (message == NULL) {
2385 goto finally;
2386 }
2387
2388 if (_PyDict_SetItemId(context, &PyId_message, message) < 0 ||
2389 _PyDict_SetItemId(context, &PyId_task, (PyObject*)task) < 0)
2390 {
2391 goto finally;
2392 }
2393
2394 if (task->task_source_tb != NULL) {
2395 if (_PyDict_SetItemId(context, &PyId_source_traceback,
2396 task->task_source_tb) < 0)
2397 {
2398 goto finally;
2399 }
2400 }
2401
2402 func = _PyObject_GetAttrId(task->task_loop, &PyId_call_exception_handler);
2403 if (func != NULL) {
Serhiy Storchakabca49392017-09-03 08:10:14 +03002404 PyObject *res = PyObject_CallFunctionObjArgs(func, context, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002405 if (res == NULL) {
2406 PyErr_WriteUnraisable(func);
2407 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03002408 else {
2409 Py_DECREF(res);
2410 }
2411 Py_DECREF(func);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002412 }
2413
2414finally:
Serhiy Storchakabca49392017-09-03 08:10:14 +03002415 Py_XDECREF(context);
2416 Py_XDECREF(message);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002417
2418 /* Restore the saved exception. */
2419 PyErr_Restore(error_type, error_value, error_traceback);
2420
2421done:
2422 FutureObj_finalize((FutureObj*)task);
2423}
2424
2425static void TaskObj_dealloc(PyObject *); /* Needs Task_CheckExact */
2426
2427static PyMethodDef TaskType_methods[] = {
2428 _ASYNCIO_FUTURE_RESULT_METHODDEF
2429 _ASYNCIO_FUTURE_EXCEPTION_METHODDEF
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002430 _ASYNCIO_FUTURE_ADD_DONE_CALLBACK_METHODDEF
2431 _ASYNCIO_FUTURE_REMOVE_DONE_CALLBACK_METHODDEF
2432 _ASYNCIO_FUTURE_CANCELLED_METHODDEF
2433 _ASYNCIO_FUTURE_DONE_METHODDEF
Yury Selivanov0cf16f92017-12-25 10:48:15 -05002434 _ASYNCIO_TASK_SET_RESULT_METHODDEF
2435 _ASYNCIO_TASK_SET_EXCEPTION_METHODDEF
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002436 _ASYNCIO_TASK_CURRENT_TASK_METHODDEF
2437 _ASYNCIO_TASK_ALL_TASKS_METHODDEF
2438 _ASYNCIO_TASK_CANCEL_METHODDEF
2439 _ASYNCIO_TASK_GET_STACK_METHODDEF
2440 _ASYNCIO_TASK_PRINT_STACK_METHODDEF
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002441 _ASYNCIO_TASK__REPR_INFO_METHODDEF
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002442 _ASYNCIO_TASK_GET_NAME_METHODDEF
2443 _ASYNCIO_TASK_SET_NAME_METHODDEF
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002444 {NULL, NULL} /* Sentinel */
2445};
2446
2447static PyGetSetDef TaskType_getsetlist[] = {
2448 FUTURE_COMMON_GETSETLIST
2449 {"_log_destroy_pending", (getter)TaskObj_get_log_destroy_pending,
2450 (setter)TaskObj_set_log_destroy_pending, NULL},
2451 {"_must_cancel", (getter)TaskObj_get_must_cancel, NULL, NULL},
2452 {"_coro", (getter)TaskObj_get_coro, NULL, NULL},
2453 {"_fut_waiter", (getter)TaskObj_get_fut_waiter, NULL, NULL},
2454 {NULL} /* Sentinel */
2455};
2456
2457static PyTypeObject TaskType = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02002458 PyVarObject_HEAD_INIT(NULL, 0)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002459 "_asyncio.Task",
2460 sizeof(TaskObj), /* tp_basicsize */
2461 .tp_base = &FutureType,
2462 .tp_dealloc = TaskObj_dealloc,
2463 .tp_as_async = &FutureType_as_async,
2464 .tp_repr = (reprfunc)FutureObj_repr,
2465 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE
2466 | Py_TPFLAGS_HAVE_FINALIZE,
2467 .tp_doc = _asyncio_Task___init____doc__,
2468 .tp_traverse = (traverseproc)TaskObj_traverse,
2469 .tp_clear = (inquiry)TaskObj_clear,
2470 .tp_weaklistoffset = offsetof(TaskObj, task_weakreflist),
2471 .tp_iter = (getiterfunc)future_new_iter,
2472 .tp_methods = TaskType_methods,
2473 .tp_getset = TaskType_getsetlist,
2474 .tp_dictoffset = offsetof(TaskObj, dict),
2475 .tp_init = (initproc)_asyncio_Task___init__,
2476 .tp_new = PyType_GenericNew,
2477 .tp_finalize = (destructor)TaskObj_finalize,
2478};
2479
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002480static void
2481TaskObj_dealloc(PyObject *self)
2482{
2483 TaskObj *task = (TaskObj *)self;
2484
2485 if (Task_CheckExact(self)) {
2486 /* When fut is subclass of Task, finalizer is called from
2487 * subtype_dealloc.
2488 */
2489 if (PyObject_CallFinalizerFromDealloc(self) < 0) {
2490 // resurrected.
2491 return;
2492 }
2493 }
2494
Alexander Mohrde34cbe2017-08-01 23:31:07 -07002495 PyObject_GC_UnTrack(self);
2496
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002497 if (task->task_weakreflist != NULL) {
2498 PyObject_ClearWeakRefs(self);
2499 }
2500
2501 (void)TaskObj_clear(task);
2502 Py_TYPE(task)->tp_free(task);
2503}
2504
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002505static int
2506task_call_step_soon(TaskObj *task, PyObject *arg)
2507{
Serhiy Storchakabca49392017-09-03 08:10:14 +03002508 PyObject *cb = TaskStepMethWrapper_new(task, arg);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002509 if (cb == NULL) {
2510 return -1;
2511 }
2512
Yury Selivanovf23746a2018-01-22 19:11:18 -05002513 int ret = call_soon(task->task_loop, cb, NULL, task->task_context);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002514 Py_DECREF(cb);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05002515 return ret;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002516}
2517
2518static PyObject *
2519task_set_error_soon(TaskObj *task, PyObject *et, const char *format, ...)
2520{
2521 PyObject* msg;
2522
2523 va_list vargs;
2524#ifdef HAVE_STDARG_PROTOTYPES
2525 va_start(vargs, format);
2526#else
2527 va_start(vargs);
2528#endif
2529 msg = PyUnicode_FromFormatV(format, vargs);
2530 va_end(vargs);
2531
2532 if (msg == NULL) {
2533 return NULL;
2534 }
2535
Victor Stinnerde4ae3d2016-12-04 22:59:09 +01002536 PyObject *e = PyObject_CallFunctionObjArgs(et, msg, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002537 Py_DECREF(msg);
2538 if (e == NULL) {
2539 return NULL;
2540 }
2541
2542 if (task_call_step_soon(task, e) == -1) {
2543 Py_DECREF(e);
2544 return NULL;
2545 }
2546
2547 Py_DECREF(e);
2548 Py_RETURN_NONE;
2549}
2550
2551static PyObject *
2552task_step_impl(TaskObj *task, PyObject *exc)
2553{
2554 int res;
2555 int clear_exc = 0;
2556 PyObject *result = NULL;
Serhiy Storchakabca49392017-09-03 08:10:14 +03002557 PyObject *coro;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002558 PyObject *o;
2559
2560 if (task->task_state != STATE_PENDING) {
Yury Selivanov0cf16f92017-12-25 10:48:15 -05002561 PyErr_Format(asyncio_InvalidStateError,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002562 "_step(): already done: %R %R",
2563 task,
2564 exc ? exc : Py_None);
INADA Naokic411a7d2016-10-18 11:48:14 +09002565 goto fail;
2566 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09002567
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002568 if (task->task_must_cancel) {
2569 assert(exc != Py_None);
2570
2571 if (exc) {
2572 /* Check if exc is a CancelledError */
2573 res = PyObject_IsInstance(exc, asyncio_CancelledError);
2574 if (res == -1) {
2575 /* An error occurred, abort */
2576 goto fail;
2577 }
2578 if (res == 0) {
2579 /* exc is not CancelledError; reset it to NULL */
2580 exc = NULL;
2581 }
2582 }
2583
2584 if (!exc) {
2585 /* exc was not a CancelledError */
Victor Stinnerf17c3de2016-12-06 18:46:19 +01002586 exc = _PyObject_CallNoArg(asyncio_CancelledError);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002587 if (!exc) {
2588 goto fail;
2589 }
2590 clear_exc = 1;
2591 }
2592
2593 task->task_must_cancel = 0;
2594 }
2595
2596 Py_CLEAR(task->task_fut_waiter);
2597
Serhiy Storchakabca49392017-09-03 08:10:14 +03002598 coro = task->task_coro;
2599 if (coro == NULL) {
2600 PyErr_SetString(PyExc_RuntimeError, "uninitialized Task object");
2601 return NULL;
2602 }
2603
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002604 if (exc == NULL) {
2605 if (PyGen_CheckExact(coro) || PyCoro_CheckExact(coro)) {
2606 result = _PyGen_Send((PyGenObject*)coro, Py_None);
2607 }
2608 else {
Victor Stinnerb6ed57d2016-12-09 14:24:02 +01002609 result = _PyObject_CallMethodIdObjArgs(coro, &PyId_send,
2610 Py_None, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002611 }
2612 }
2613 else {
Victor Stinnerb6ed57d2016-12-09 14:24:02 +01002614 result = _PyObject_CallMethodIdObjArgs(coro, &PyId_throw,
2615 exc, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002616 if (clear_exc) {
2617 /* We created 'exc' during this call */
Serhiy Storchakabca49392017-09-03 08:10:14 +03002618 Py_DECREF(exc);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002619 }
2620 }
2621
2622 if (result == NULL) {
2623 PyObject *et, *ev, *tb;
2624
2625 if (_PyGen_FetchStopIterationValue(&o) == 0) {
2626 /* The error is StopIteration and that means that
2627 the underlying coroutine has resolved */
INADA Naoki991adca2017-05-11 21:18:38 +09002628 if (task->task_must_cancel) {
2629 // Task is cancelled right before coro stops.
2630 Py_DECREF(o);
2631 task->task_must_cancel = 0;
2632 et = asyncio_CancelledError;
2633 Py_INCREF(et);
2634 ev = NULL;
2635 tb = NULL;
2636 goto set_exception;
2637 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002638 PyObject *res = future_set_result((FutureObj*)task, o);
2639 Py_DECREF(o);
2640 if (res == NULL) {
2641 return NULL;
2642 }
2643 Py_DECREF(res);
2644 Py_RETURN_NONE;
2645 }
2646
2647 if (PyErr_ExceptionMatches(asyncio_CancelledError)) {
2648 /* CancelledError */
2649 PyErr_Clear();
2650 return future_cancel((FutureObj*)task);
2651 }
2652
2653 /* Some other exception; pop it and call Task.set_exception() */
2654 PyErr_Fetch(&et, &ev, &tb);
INADA Naoki991adca2017-05-11 21:18:38 +09002655
2656set_exception:
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002657 assert(et);
2658 if (!ev || !PyObject_TypeCheck(ev, (PyTypeObject *) et)) {
2659 PyErr_NormalizeException(&et, &ev, &tb);
2660 }
Yury Selivanovedfe8862016-12-01 11:37:47 -05002661 if (tb != NULL) {
2662 PyException_SetTraceback(ev, tb);
2663 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002664 o = future_set_exception((FutureObj*)task, ev);
2665 if (!o) {
2666 /* An exception in Task.set_exception() */
Serhiy Storchakabca49392017-09-03 08:10:14 +03002667 Py_DECREF(et);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002668 Py_XDECREF(tb);
2669 Py_XDECREF(ev);
2670 goto fail;
2671 }
2672 assert(o == Py_None);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002673 Py_DECREF(o);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002674
2675 if (!PyErr_GivenExceptionMatches(et, PyExc_Exception)) {
2676 /* We've got a BaseException; re-raise it */
2677 PyErr_Restore(et, ev, tb);
2678 goto fail;
2679 }
2680
Serhiy Storchakabca49392017-09-03 08:10:14 +03002681 Py_DECREF(et);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002682 Py_XDECREF(tb);
2683 Py_XDECREF(ev);
2684
2685 Py_RETURN_NONE;
2686 }
2687
2688 if (result == (PyObject*)task) {
2689 /* We have a task that wants to await on itself */
2690 goto self_await;
2691 }
2692
2693 /* Check if `result` is FutureObj or TaskObj (and not a subclass) */
2694 if (Future_CheckExact(result) || Task_CheckExact(result)) {
2695 PyObject *wrapper;
2696 PyObject *res;
2697 FutureObj *fut = (FutureObj*)result;
2698
2699 /* Check if `result` future is attached to a different loop */
2700 if (fut->fut_loop != task->task_loop) {
2701 goto different_loop;
2702 }
2703
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002704 if (!fut->fut_blocking) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002705 goto yield_insteadof_yf;
2706 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002707
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002708 fut->fut_blocking = 0;
2709
2710 /* result.add_done_callback(task._wakeup) */
2711 wrapper = TaskWakeupMethWrapper_new(task);
2712 if (wrapper == NULL) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002713 goto fail;
2714 }
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002715 res = future_add_done_callback(
2716 (FutureObj*)result, wrapper, task->task_context);
2717 Py_DECREF(wrapper);
2718 if (res == NULL) {
2719 goto fail;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002720 }
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002721 Py_DECREF(res);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002722
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002723 /* task._fut_waiter = result */
2724 task->task_fut_waiter = result; /* no incref is necessary */
2725
2726 if (task->task_must_cancel) {
2727 PyObject *r;
Elvis Pranskevichus0c797a62018-10-03 10:30:31 -04002728 int is_true;
Serhiy Storchakaaddf8af2018-10-05 21:20:02 +03002729 r = _PyObject_CallMethodId(result, &PyId_cancel, NULL);
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002730 if (r == NULL) {
2731 return NULL;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002732 }
Elvis Pranskevichus0c797a62018-10-03 10:30:31 -04002733 is_true = PyObject_IsTrue(r);
2734 Py_DECREF(r);
2735 if (is_true < 0) {
2736 return NULL;
2737 }
2738 else if (is_true) {
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002739 task->task_must_cancel = 0;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002740 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002741 }
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002742
2743 Py_RETURN_NONE;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002744 }
2745
2746 /* Check if `result` is None */
2747 if (result == Py_None) {
2748 /* Bare yield relinquishes control for one event loop iteration. */
2749 if (task_call_step_soon(task, NULL)) {
2750 goto fail;
2751 }
2752 return result;
2753 }
2754
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002755 /* Check if `result` is a Future-compatible object */
2756 if (_PyObject_LookupAttrId(result, &PyId__asyncio_future_blocking, &o) < 0) {
2757 goto fail;
2758 }
2759 if (o != NULL && o != Py_None) {
2760 /* `result` is a Future-compatible object */
2761 PyObject *wrapper;
2762 PyObject *res;
2763
2764 int blocking = PyObject_IsTrue(o);
2765 Py_DECREF(o);
2766 if (blocking < 0) {
2767 goto fail;
2768 }
2769
2770 /* Check if `result` future is attached to a different loop */
2771 PyObject *oloop = get_future_loop(result);
2772 if (oloop == NULL) {
2773 goto fail;
2774 }
2775 if (oloop != task->task_loop) {
2776 Py_DECREF(oloop);
2777 goto different_loop;
2778 }
2779 Py_DECREF(oloop);
2780
2781 if (!blocking) {
2782 goto yield_insteadof_yf;
2783 }
2784
2785 /* result._asyncio_future_blocking = False */
2786 if (_PyObject_SetAttrId(
2787 result, &PyId__asyncio_future_blocking, Py_False) == -1) {
2788 goto fail;
2789 }
2790
2791 wrapper = TaskWakeupMethWrapper_new(task);
2792 if (wrapper == NULL) {
2793 goto fail;
2794 }
2795
2796 /* result.add_done_callback(task._wakeup) */
2797 PyObject *add_cb = _PyObject_GetAttrId(
2798 result, &PyId_add_done_callback);
2799 if (add_cb == NULL) {
2800 Py_DECREF(wrapper);
2801 goto fail;
2802 }
2803 PyObject *stack[2];
2804 stack[0] = wrapper;
2805 stack[1] = (PyObject *)task->task_context;
2806 res = _PyObject_FastCallKeywords(
2807 add_cb, stack, 1, context_kwname);
2808 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);
2953 if (!PyErr_GivenExceptionMatches(et, PyExc_Exception)) {
2954 /* We've got a BaseException; re-raise it */
2955 PyErr_Restore(et, ev, tb);
2956 return NULL;
2957 }
2958 if (!ev || !PyObject_TypeCheck(ev, (PyTypeObject *) et)) {
2959 PyErr_NormalizeException(&et, &ev, &tb);
2960 }
2961
Yury Selivanov22feeb82018-01-24 11:31:01 -05002962 result = task_step(task, ev);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002963
2964 Py_DECREF(et);
2965 Py_XDECREF(tb);
2966 Py_XDECREF(ev);
2967
2968 return result;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002969}
2970
2971
Yury Selivanova70232f2017-12-13 14:49:42 -05002972/*********************** Functions **************************/
2973
2974
2975/*[clinic input]
2976_asyncio._get_running_loop
2977
2978Return the running event loop or None.
2979
2980This is a low-level function intended to be used by event loops.
2981This function is thread-specific.
2982
2983[clinic start generated code]*/
2984
2985static PyObject *
2986_asyncio__get_running_loop_impl(PyObject *module)
2987/*[clinic end generated code: output=b4390af721411a0a input=0a21627e25a4bd43]*/
2988{
2989 PyObject *loop;
2990 if (get_running_loop(&loop)) {
2991 return NULL;
2992 }
2993 if (loop == NULL) {
2994 /* There's no currently running event loop */
2995 Py_RETURN_NONE;
2996 }
2997 return loop;
2998}
2999
3000/*[clinic input]
3001_asyncio._set_running_loop
3002 loop: 'O'
3003 /
3004
3005Set the running event loop.
3006
3007This is a low-level function intended to be used by event loops.
3008This function is thread-specific.
3009[clinic start generated code]*/
3010
3011static PyObject *
3012_asyncio__set_running_loop(PyObject *module, PyObject *loop)
3013/*[clinic end generated code: output=ae56bf7a28ca189a input=4c9720233d606604]*/
3014{
3015 if (set_running_loop(loop)) {
3016 return NULL;
3017 }
3018 Py_RETURN_NONE;
3019}
3020
3021/*[clinic input]
3022_asyncio.get_event_loop
3023
3024Return an asyncio event loop.
3025
3026When called from a coroutine or a callback (e.g. scheduled with
3027call_soon or similar API), this function will always return the
3028running event loop.
3029
3030If there is no running event loop set, the function will return
3031the result of `get_event_loop_policy().get_event_loop()` call.
3032[clinic start generated code]*/
3033
3034static PyObject *
3035_asyncio_get_event_loop_impl(PyObject *module)
3036/*[clinic end generated code: output=2a2d8b2f824c648b input=9364bf2916c8655d]*/
3037{
3038 return get_event_loop();
3039}
3040
3041/*[clinic input]
3042_asyncio.get_running_loop
3043
3044Return the running event loop. Raise a RuntimeError if there is none.
3045
3046This function is thread-specific.
3047[clinic start generated code]*/
3048
3049static PyObject *
3050_asyncio_get_running_loop_impl(PyObject *module)
3051/*[clinic end generated code: output=c247b5f9e529530e input=2a3bf02ba39f173d]*/
3052{
3053 PyObject *loop;
3054 if (get_running_loop(&loop)) {
3055 return NULL;
3056 }
3057 if (loop == NULL) {
3058 /* There's no currently running event loop */
3059 PyErr_SetString(
3060 PyExc_RuntimeError, "no running event loop");
3061 }
3062 return loop;
3063}
3064
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003065/*[clinic input]
3066_asyncio._register_task
3067
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003068 task: object
3069
3070Register a new task in asyncio as executed by loop.
3071
3072Returns None.
3073[clinic start generated code]*/
3074
3075static PyObject *
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003076_asyncio__register_task_impl(PyObject *module, PyObject *task)
3077/*[clinic end generated code: output=8672dadd69a7d4e2 input=21075aaea14dfbad]*/
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003078{
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003079 if (register_task(task) < 0) {
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003080 return NULL;
3081 }
3082 Py_RETURN_NONE;
3083}
3084
3085
3086/*[clinic input]
3087_asyncio._unregister_task
3088
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003089 task: object
3090
3091Unregister a task.
3092
3093Returns None.
3094[clinic start generated code]*/
3095
3096static PyObject *
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003097_asyncio__unregister_task_impl(PyObject *module, PyObject *task)
3098/*[clinic end generated code: output=6e5585706d568a46 input=28fb98c3975f7bdc]*/
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003099{
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003100 if (unregister_task(task) < 0) {
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003101 return NULL;
3102 }
3103 Py_RETURN_NONE;
3104}
3105
3106
3107/*[clinic input]
3108_asyncio._enter_task
3109
3110 loop: object
3111 task: object
3112
3113Enter into task execution or resume suspended task.
3114
3115Task belongs to loop.
3116
3117Returns None.
3118[clinic start generated code]*/
3119
3120static PyObject *
3121_asyncio__enter_task_impl(PyObject *module, PyObject *loop, PyObject *task)
3122/*[clinic end generated code: output=a22611c858035b73 input=de1b06dca70d8737]*/
3123{
3124 if (enter_task(loop, task) < 0) {
3125 return NULL;
3126 }
3127 Py_RETURN_NONE;
3128}
3129
3130
3131/*[clinic input]
3132_asyncio._leave_task
3133
3134 loop: object
3135 task: object
3136
3137Leave task execution or suspend a task.
3138
3139Task belongs to loop.
3140
3141Returns None.
3142[clinic start generated code]*/
3143
3144static PyObject *
3145_asyncio__leave_task_impl(PyObject *module, PyObject *loop, PyObject *task)
3146/*[clinic end generated code: output=0ebf6db4b858fb41 input=51296a46313d1ad8]*/
3147{
3148 if (leave_task(loop, task) < 0) {
3149 return NULL;
3150 }
3151 Py_RETURN_NONE;
3152}
3153
Yury Selivanova70232f2017-12-13 14:49:42 -05003154
Yury Selivanov9d411c12018-01-23 15:10:03 -05003155/*********************** PyRunningLoopHolder ********************/
3156
3157
3158static PyRunningLoopHolder *
3159new_running_loop_holder(PyObject *loop)
3160{
3161 PyRunningLoopHolder *rl = PyObject_New(
3162 PyRunningLoopHolder, &PyRunningLoopHolder_Type);
3163 if (rl == NULL) {
3164 return NULL;
3165 }
3166
3167#if defined(HAVE_GETPID) && !defined(MS_WINDOWS)
3168 rl->rl_pid = getpid();
3169#endif
3170
3171 Py_INCREF(loop);
3172 rl->rl_loop = loop;
3173
3174 return rl;
3175}
3176
3177
3178static void
3179PyRunningLoopHolder_tp_dealloc(PyRunningLoopHolder *rl)
3180{
3181 Py_CLEAR(rl->rl_loop);
3182 PyObject_Free(rl);
3183}
3184
3185
3186static PyTypeObject PyRunningLoopHolder_Type = {
3187 PyVarObject_HEAD_INIT(NULL, 0)
3188 "_RunningLoopHolder",
3189 sizeof(PyRunningLoopHolder),
3190 .tp_getattro = PyObject_GenericGetAttr,
3191 .tp_flags = Py_TPFLAGS_DEFAULT,
3192 .tp_dealloc = (destructor)PyRunningLoopHolder_tp_dealloc,
3193};
3194
3195
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003196/*********************** Module **************************/
3197
3198
3199static void
Zackery Spytze40ad792017-12-19 11:48:13 -07003200module_free_freelists(void)
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05003201{
3202 PyObject *next;
3203 PyObject *current;
3204
3205 next = (PyObject*) fi_freelist;
3206 while (next != NULL) {
3207 assert(fi_freelist_len > 0);
3208 fi_freelist_len--;
3209
3210 current = next;
3211 next = (PyObject*) ((futureiterobject*) current)->future;
3212 PyObject_GC_Del(current);
3213 }
3214 assert(fi_freelist_len == 0);
3215 fi_freelist = NULL;
3216}
3217
3218
3219static void
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003220module_free(void *m)
3221{
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003222 Py_CLEAR(asyncio_mod);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003223 Py_CLEAR(traceback_extract_stack);
3224 Py_CLEAR(asyncio_future_repr_info_func);
3225 Py_CLEAR(asyncio_get_event_loop_policy);
3226 Py_CLEAR(asyncio_iscoroutine_func);
3227 Py_CLEAR(asyncio_task_get_stack_func);
3228 Py_CLEAR(asyncio_task_print_stack_func);
3229 Py_CLEAR(asyncio_task_repr_info_func);
3230 Py_CLEAR(asyncio_InvalidStateError);
3231 Py_CLEAR(asyncio_CancelledError);
3232
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003233 Py_CLEAR(all_tasks);
Yury Selivanova9d7e552017-12-19 07:18:45 -05003234 Py_CLEAR(current_tasks);
3235 Py_CLEAR(iscoroutine_typecache);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05003236
Yury Selivanovf23746a2018-01-22 19:11:18 -05003237 Py_CLEAR(context_kwname);
3238
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05003239 module_free_freelists();
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003240}
3241
3242static int
3243module_init(void)
3244{
3245 PyObject *module = NULL;
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003246
3247 asyncio_mod = PyImport_ImportModule("asyncio");
3248 if (asyncio_mod == NULL) {
3249 goto fail;
3250 }
3251
3252 current_tasks = PyDict_New();
3253 if (current_tasks == NULL) {
3254 goto fail;
3255 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003256
Yury Selivanova9d7e552017-12-19 07:18:45 -05003257 iscoroutine_typecache = PySet_New(NULL);
3258 if (iscoroutine_typecache == NULL) {
3259 goto fail;
3260 }
3261
Yury Selivanovf23746a2018-01-22 19:11:18 -05003262
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03003263 context_kwname = Py_BuildValue("(s)", "context");
Yury Selivanovf23746a2018-01-22 19:11:18 -05003264 if (context_kwname == NULL) {
3265 goto fail;
3266 }
Yury Selivanovf23746a2018-01-22 19:11:18 -05003267
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003268#define WITH_MOD(NAME) \
3269 Py_CLEAR(module); \
3270 module = PyImport_ImportModule(NAME); \
3271 if (module == NULL) { \
Serhiy Storchakabca49392017-09-03 08:10:14 +03003272 goto fail; \
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003273 }
3274
3275#define GET_MOD_ATTR(VAR, NAME) \
3276 VAR = PyObject_GetAttrString(module, NAME); \
3277 if (VAR == NULL) { \
3278 goto fail; \
3279 }
3280
3281 WITH_MOD("asyncio.events")
Yury Selivanova70232f2017-12-13 14:49:42 -05003282 GET_MOD_ATTR(asyncio_get_event_loop_policy, "get_event_loop_policy")
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003283
3284 WITH_MOD("asyncio.base_futures")
3285 GET_MOD_ATTR(asyncio_future_repr_info_func, "_future_repr_info")
Andrew Svetlov0baa72f2018-09-11 10:13:04 -07003286
3287 WITH_MOD("asyncio.exceptions")
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003288 GET_MOD_ATTR(asyncio_InvalidStateError, "InvalidStateError")
3289 GET_MOD_ATTR(asyncio_CancelledError, "CancelledError")
3290
3291 WITH_MOD("asyncio.base_tasks")
3292 GET_MOD_ATTR(asyncio_task_repr_info_func, "_task_repr_info")
3293 GET_MOD_ATTR(asyncio_task_get_stack_func, "_task_get_stack")
3294 GET_MOD_ATTR(asyncio_task_print_stack_func, "_task_print_stack")
3295
Andrew Svetlovf74ef452017-12-15 07:04:38 +02003296 WITH_MOD("asyncio.coroutines")
3297 GET_MOD_ATTR(asyncio_iscoroutine_func, "iscoroutine")
3298
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003299 WITH_MOD("traceback")
3300 GET_MOD_ATTR(traceback_extract_stack, "extract_stack")
3301
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003302 PyObject *weak_set;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003303 WITH_MOD("weakref")
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003304 GET_MOD_ATTR(weak_set, "WeakSet");
3305 all_tasks = _PyObject_CallNoArg(weak_set);
3306 Py_CLEAR(weak_set);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003307 if (all_tasks == NULL) {
INADA Naokic411a7d2016-10-18 11:48:14 +09003308 goto fail;
3309 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003310
Serhiy Storchakabca49392017-09-03 08:10:14 +03003311 Py_DECREF(module);
INADA Naokic411a7d2016-10-18 11:48:14 +09003312 return 0;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003313
INADA Naokic411a7d2016-10-18 11:48:14 +09003314fail:
INADA Naokic411a7d2016-10-18 11:48:14 +09003315 Py_CLEAR(module);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003316 module_free(NULL);
INADA Naokic411a7d2016-10-18 11:48:14 +09003317 return -1;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003318
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003319#undef WITH_MOD
3320#undef GET_MOD_ATTR
3321}
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003322
INADA Naokic411a7d2016-10-18 11:48:14 +09003323PyDoc_STRVAR(module_doc, "Accelerator module for asyncio");
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003324
Yury Selivanova70232f2017-12-13 14:49:42 -05003325static PyMethodDef asyncio_methods[] = {
3326 _ASYNCIO_GET_EVENT_LOOP_METHODDEF
3327 _ASYNCIO_GET_RUNNING_LOOP_METHODDEF
3328 _ASYNCIO__GET_RUNNING_LOOP_METHODDEF
3329 _ASYNCIO__SET_RUNNING_LOOP_METHODDEF
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003330 _ASYNCIO__REGISTER_TASK_METHODDEF
3331 _ASYNCIO__UNREGISTER_TASK_METHODDEF
3332 _ASYNCIO__ENTER_TASK_METHODDEF
3333 _ASYNCIO__LEAVE_TASK_METHODDEF
Yury Selivanova70232f2017-12-13 14:49:42 -05003334 {NULL, NULL}
3335};
3336
INADA Naoki9f2ce252016-10-15 15:39:19 +09003337static struct PyModuleDef _asynciomodule = {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003338 PyModuleDef_HEAD_INIT, /* m_base */
INADA Naoki9f2ce252016-10-15 15:39:19 +09003339 "_asyncio", /* m_name */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003340 module_doc, /* m_doc */
3341 -1, /* m_size */
Yury Selivanova70232f2017-12-13 14:49:42 -05003342 asyncio_methods, /* m_methods */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003343 NULL, /* m_slots */
3344 NULL, /* m_traverse */
3345 NULL, /* m_clear */
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003346 (freefunc)module_free /* m_free */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003347};
3348
3349
3350PyMODINIT_FUNC
INADA Naoki9f2ce252016-10-15 15:39:19 +09003351PyInit__asyncio(void)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003352{
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003353 if (module_init() < 0) {
INADA Naokic411a7d2016-10-18 11:48:14 +09003354 return NULL;
3355 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003356 if (PyType_Ready(&FutureType) < 0) {
3357 return NULL;
3358 }
3359 if (PyType_Ready(&FutureIterType) < 0) {
3360 return NULL;
3361 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03003362 if (PyType_Ready(&TaskStepMethWrapper_Type) < 0) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003363 return NULL;
3364 }
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03003365 if (PyType_Ready(&TaskWakeupMethWrapper_Type) < 0) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003366 return NULL;
3367 }
3368 if (PyType_Ready(&TaskType) < 0) {
3369 return NULL;
3370 }
Yury Selivanov9d411c12018-01-23 15:10:03 -05003371 if (PyType_Ready(&PyRunningLoopHolder_Type) < 0) {
3372 return NULL;
3373 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003374
INADA Naoki9f2ce252016-10-15 15:39:19 +09003375 PyObject *m = PyModule_Create(&_asynciomodule);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003376 if (m == NULL) {
3377 return NULL;
3378 }
3379
3380 Py_INCREF(&FutureType);
3381 if (PyModule_AddObject(m, "Future", (PyObject *)&FutureType) < 0) {
3382 Py_DECREF(&FutureType);
3383 return NULL;
3384 }
3385
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003386 Py_INCREF(&TaskType);
3387 if (PyModule_AddObject(m, "Task", (PyObject *)&TaskType) < 0) {
3388 Py_DECREF(&TaskType);
3389 return NULL;
3390 }
3391
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003392 Py_INCREF(all_tasks);
3393 if (PyModule_AddObject(m, "_all_tasks", all_tasks) < 0) {
3394 Py_DECREF(all_tasks);
3395 return NULL;
3396 }
3397
3398 Py_INCREF(current_tasks);
3399 if (PyModule_AddObject(m, "_current_tasks", current_tasks) < 0) {
3400 Py_DECREF(current_tasks);
3401 return NULL;
3402 }
3403
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003404 return m;
3405}