blob: 809879ac77d3c754e17242d4e8ecfb44eb8f2df3 [file] [log] [blame]
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001#include "Python.h"
2#include "structmember.h"
3
4
Yury Selivanova0c1ba62016-10-28 12:52:37 -04005/*[clinic input]
6module _asyncio
7[clinic start generated code]*/
8/*[clinic end generated code: output=da39a3ee5e6b4b0d input=8fd17862aa989c69]*/
9
10
INADA Naoki9e4e38e2016-10-09 14:44:47 +090011/* identifiers used from some functions */
Yury Selivanova70232f2017-12-13 14:49:42 -050012_Py_IDENTIFIER(__asyncio_running_event_loop__);
Yury Selivanova0c1ba62016-10-28 12:52:37 -040013_Py_IDENTIFIER(add_done_callback);
Miss Islington (bot)ddc613f2018-05-28 17:16:43 -070014_Py_IDENTIFIER(_all_tasks_compat);
INADA Naoki9e4e38e2016-10-09 14:44:47 +090015_Py_IDENTIFIER(call_soon);
Yury Selivanova0c1ba62016-10-28 12:52:37 -040016_Py_IDENTIFIER(cancel);
Andrew Svetlov44d1a592017-12-16 21:58:38 +020017_Py_IDENTIFIER(current_task);
Yury Selivanova70232f2017-12-13 14:49:42 -050018_Py_IDENTIFIER(get_event_loop);
Yury Selivanova0c1ba62016-10-28 12:52:37 -040019_Py_IDENTIFIER(send);
20_Py_IDENTIFIER(throw);
INADA Naoki9e4e38e2016-10-09 14:44:47 +090021
22
INADA Naoki9f2ce252016-10-15 15:39:19 +090023/* State of the _asyncio module */
Andrew Svetlov44d1a592017-12-16 21:58:38 +020024static PyObject *asyncio_mod;
Yury Selivanova0c1ba62016-10-28 12:52:37 -040025static PyObject *inspect_isgenerator;
Andrew Svetlov44d1a592017-12-16 21:58:38 +020026static PyObject *traceback_extract_stack;
27static PyObject *asyncio_get_event_loop_policy;
28static PyObject *asyncio_future_repr_info_func;
29static PyObject *asyncio_iscoroutine_func;
30static PyObject *asyncio_task_get_stack_func;
31static PyObject *asyncio_task_print_stack_func;
32static PyObject *asyncio_task_repr_info_func;
33static PyObject *asyncio_InvalidStateError;
34static PyObject *asyncio_CancelledError;
Yury Selivanovf23746a2018-01-22 19:11:18 -050035static PyObject *context_kwname;
Andrew Svetlov44d1a592017-12-16 21:58:38 +020036
Yury Selivanov9d411c12018-01-23 15:10:03 -050037static PyObject *cached_running_holder;
38static volatile uint64_t cached_running_holder_tsid;
39
Andrew Svetlov44d1a592017-12-16 21:58:38 +020040
Yury Selivanovca9b36c2017-12-23 15:04:15 -050041/* WeakSet containing all alive tasks. */
42static PyObject *all_tasks;
Andrew Svetlov44d1a592017-12-16 21:58:38 +020043
44/* Dictionary containing tasks that are currently active in
45 all running event loops. {EventLoop: Task} */
Yury Selivanovca9b36c2017-12-23 15:04:15 -050046static PyObject *current_tasks;
INADA Naoki9e4e38e2016-10-09 14:44:47 +090047
Yury Selivanova9d7e552017-12-19 07:18:45 -050048/* An isinstance type cache for the 'is_coroutine()' function. */
49static PyObject *iscoroutine_typecache;
50
INADA Naoki9e4e38e2016-10-09 14:44:47 +090051
INADA Naoki9e4e38e2016-10-09 14:44:47 +090052typedef enum {
53 STATE_PENDING,
54 STATE_CANCELLED,
55 STATE_FINISHED
56} fut_state;
57
Yury Selivanova0c1ba62016-10-28 12:52:37 -040058#define FutureObj_HEAD(prefix) \
59 PyObject_HEAD \
60 PyObject *prefix##_loop; \
Yury Selivanov1b7c11f2017-12-17 20:19:47 -050061 PyObject *prefix##_callback0; \
Yury Selivanov24cb7de2018-09-27 15:33:23 -040062 PyObject *prefix##_context0; \
Yury Selivanova0c1ba62016-10-28 12:52:37 -040063 PyObject *prefix##_callbacks; \
64 PyObject *prefix##_exception; \
65 PyObject *prefix##_result; \
66 PyObject *prefix##_source_tb; \
67 fut_state prefix##_state; \
68 int prefix##_log_tb; \
69 int prefix##_blocking; \
70 PyObject *dict; \
71 PyObject *prefix##_weakreflist;
72
73typedef struct {
74 FutureObj_HEAD(fut)
75} FutureObj;
76
77typedef struct {
78 FutureObj_HEAD(task)
79 PyObject *task_fut_waiter;
80 PyObject *task_coro;
Yury Selivanov24cb7de2018-09-27 15:33:23 -040081 PyObject *task_context;
Yury Selivanova0c1ba62016-10-28 12:52:37 -040082 int task_must_cancel;
83 int task_log_destroy_pending;
84} TaskObj;
INADA Naoki9e4e38e2016-10-09 14:44:47 +090085
86typedef struct {
87 PyObject_HEAD
Yury Selivanova0c1ba62016-10-28 12:52:37 -040088 TaskObj *sw_task;
89 PyObject *sw_arg;
Serhiy Storchakabca49392017-09-03 08:10:14 +030090} TaskStepMethWrapper;
INADA Naoki9e4e38e2016-10-09 14:44:47 +090091
Yury Selivanova0c1ba62016-10-28 12:52:37 -040092typedef struct {
93 PyObject_HEAD
94 TaskObj *ww_task;
95} TaskWakeupMethWrapper;
96
Yury Selivanov9d411c12018-01-23 15:10:03 -050097typedef struct {
98 PyObject_HEAD
99 PyObject *rl_loop;
100#if defined(HAVE_GETPID) && !defined(MS_WINDOWS)
101 pid_t rl_pid;
102#endif
103} PyRunningLoopHolder;
104
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400105
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500106static PyTypeObject FutureType;
107static PyTypeObject TaskType;
Yury Selivanov9d411c12018-01-23 15:10:03 -0500108static PyTypeObject PyRunningLoopHolder_Type;
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500109
110
111#define Future_CheckExact(obj) (Py_TYPE(obj) == &FutureType)
112#define Task_CheckExact(obj) (Py_TYPE(obj) == &TaskType)
113
114#define Future_Check(obj) PyObject_TypeCheck(obj, &FutureType)
115#define Task_Check(obj) PyObject_TypeCheck(obj, &TaskType)
116
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400117#include "clinic/_asynciomodule.c.h"
118
119
120/*[clinic input]
121class _asyncio.Future "FutureObj *" "&Future_Type"
122[clinic start generated code]*/
123/*[clinic end generated code: output=da39a3ee5e6b4b0d input=00d3e4abca711e0f]*/
124
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500125
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400126/* Get FutureIter from Future */
Yury Selivanov9d411c12018-01-23 15:10:03 -0500127static PyObject * future_new_iter(PyObject *);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900128
Yury Selivanov9d411c12018-01-23 15:10:03 -0500129static PyRunningLoopHolder * new_running_loop_holder(PyObject *);
130
Yury Selivanova70232f2017-12-13 14:49:42 -0500131
132static int
Yury Selivanova9d7e552017-12-19 07:18:45 -0500133_is_coroutine(PyObject *coro)
134{
135 /* 'coro' is not a native coroutine, call asyncio.iscoroutine()
136 to check if it's another coroutine flavour.
137
138 Do this check after 'future_init()'; in case we need to raise
139 an error, __del__ needs a properly initialized object.
140 */
141 PyObject *res = PyObject_CallFunctionObjArgs(
142 asyncio_iscoroutine_func, coro, NULL);
143 if (res == NULL) {
144 return -1;
145 }
146
147 int is_res_true = PyObject_IsTrue(res);
148 Py_DECREF(res);
149 if (is_res_true <= 0) {
150 return is_res_true;
151 }
152
Andrew Svetlov0f47fa22017-12-23 22:06:46 +0200153 if (PySet_GET_SIZE(iscoroutine_typecache) < 100) {
Yury Selivanova9d7e552017-12-19 07:18:45 -0500154 /* Just in case we don't want to cache more than 100
155 positive types. That shouldn't ever happen, unless
156 someone stressing the system on purpose.
157 */
158 if (PySet_Add(iscoroutine_typecache, (PyObject*) Py_TYPE(coro))) {
159 return -1;
160 }
161 }
162
163 return 1;
164}
165
166
167static inline int
168is_coroutine(PyObject *coro)
169{
170 if (PyCoro_CheckExact(coro)) {
171 return 1;
172 }
173
174 /* Check if `type(coro)` is in the cache.
175 Caching makes is_coroutine() function almost as fast as
176 PyCoro_CheckExact() for non-native coroutine-like objects
177 (like coroutines compiled with Cython).
178
179 asyncio.iscoroutine() has its own type caching mechanism.
180 This cache allows us to avoid the cost of even calling
181 a pure-Python function in 99.9% cases.
182 */
183 int has_it = PySet_Contains(
184 iscoroutine_typecache, (PyObject*) Py_TYPE(coro));
185 if (has_it == 0) {
186 /* type(coro) is not in iscoroutine_typecache */
187 return _is_coroutine(coro);
188 }
189
Miss Islington (bot)e86db342018-02-03 17:41:43 -0800190 /* either an error has occurred or
Yury Selivanova9d7e552017-12-19 07:18:45 -0500191 type(coro) is in iscoroutine_typecache
192 */
193 return has_it;
194}
195
196
Yury Selivanovca9b36c2017-12-23 15:04:15 -0500197static PyObject *
198get_future_loop(PyObject *fut)
199{
200 /* Implementation of `asyncio.futures._get_loop` */
201
202 _Py_IDENTIFIER(get_loop);
203 _Py_IDENTIFIER(_loop);
Miss Islington (bot)52d17412018-05-20 07:34:28 -0700204 PyObject *getloop;
Yury Selivanovca9b36c2017-12-23 15:04:15 -0500205
206 if (Future_CheckExact(fut) || Task_CheckExact(fut)) {
207 PyObject *loop = ((FutureObj *)fut)->fut_loop;
208 Py_INCREF(loop);
209 return loop;
210 }
211
Miss Islington (bot)52d17412018-05-20 07:34:28 -0700212 if (_PyObject_LookupAttrId(fut, &PyId_get_loop, &getloop) < 0) {
213 return NULL;
214 }
Yury Selivanovca9b36c2017-12-23 15:04:15 -0500215 if (getloop != NULL) {
216 PyObject *res = _PyObject_CallNoArg(getloop);
217 Py_DECREF(getloop);
218 return res;
219 }
220
221 return _PyObject_GetAttrId(fut, &PyId__loop);
222}
223
224
Yury Selivanova9d7e552017-12-19 07:18:45 -0500225static int
Yury Selivanova70232f2017-12-13 14:49:42 -0500226get_running_loop(PyObject **loop)
227{
Yury Selivanov9d411c12018-01-23 15:10:03 -0500228 PyObject *rl;
Yury Selivanova70232f2017-12-13 14:49:42 -0500229
Yury Selivanov9d411c12018-01-23 15:10:03 -0500230 PyThreadState *ts = PyThreadState_Get();
231 if (ts->id == cached_running_holder_tsid && cached_running_holder != NULL) {
232 // Fast path, check the cache.
233 rl = cached_running_holder; // borrowed
234 }
235 else {
236 if (ts->dict == NULL) {
237 goto not_found;
238 }
239
240 rl = _PyDict_GetItemIdWithError(
241 ts->dict, &PyId___asyncio_running_event_loop__); // borrowed
242 if (rl == NULL) {
243 if (PyErr_Occurred()) {
244 goto error;
245 }
246 else {
247 goto not_found;
248 }
249 }
250
251 cached_running_holder = rl; // borrowed
252 cached_running_holder_tsid = ts->id;
Yury Selivanova70232f2017-12-13 14:49:42 -0500253 }
254
Yury Selivanov9d411c12018-01-23 15:10:03 -0500255 assert(Py_TYPE(rl) == &PyRunningLoopHolder_Type);
256 PyObject *running_loop = ((PyRunningLoopHolder *)rl)->rl_loop;
Yury Selivanova70232f2017-12-13 14:49:42 -0500257
258 if (running_loop == Py_None) {
259 goto not_found;
260 }
261
Yury Selivanov9d411c12018-01-23 15:10:03 -0500262#if defined(HAVE_GETPID) && !defined(MS_WINDOWS)
263 /* On Windows there is no getpid, but there is also no os.fork(),
264 so there is no need for this check.
265 */
266 if (getpid() != ((PyRunningLoopHolder *)rl)->rl_pid) {
267 goto not_found;
Yury Selivanova70232f2017-12-13 14:49:42 -0500268 }
Yury Selivanov9d411c12018-01-23 15:10:03 -0500269#endif
Yury Selivanova70232f2017-12-13 14:49:42 -0500270
Yury Selivanov9d411c12018-01-23 15:10:03 -0500271 Py_INCREF(running_loop);
272 *loop = running_loop;
273 return 0;
Yury Selivanova70232f2017-12-13 14:49:42 -0500274
275not_found:
276 *loop = NULL;
277 return 0;
278
Yury Selivanova70232f2017-12-13 14:49:42 -0500279error:
280 *loop = NULL;
281 return -1;
282}
283
284
285static int
286set_running_loop(PyObject *loop)
287{
Yury Selivanov9d411c12018-01-23 15:10:03 -0500288 cached_running_holder = NULL;
289 cached_running_holder_tsid = 0;
Yury Selivanova70232f2017-12-13 14:49:42 -0500290
Yury Selivanov9d411c12018-01-23 15:10:03 -0500291 PyObject *ts_dict = PyThreadState_GetDict(); // borrowed
Yury Selivanova70232f2017-12-13 14:49:42 -0500292 if (ts_dict == NULL) {
293 PyErr_SetString(
294 PyExc_RuntimeError, "thread-local storage is not available");
295 return -1;
296 }
297
Yury Selivanov9d411c12018-01-23 15:10:03 -0500298 PyRunningLoopHolder *rl = new_running_loop_holder(loop);
299 if (rl == NULL) {
Yury Selivanova70232f2017-12-13 14:49:42 -0500300 return -1;
301 }
302
Yury Selivanova70232f2017-12-13 14:49:42 -0500303 if (_PyDict_SetItemId(
Yury Selivanov9d411c12018-01-23 15:10:03 -0500304 ts_dict, &PyId___asyncio_running_event_loop__, (PyObject *)rl) < 0)
305 {
306 Py_DECREF(rl); // will cleanup loop & current_pid
Yury Selivanova70232f2017-12-13 14:49:42 -0500307 return -1;
308 }
Yury Selivanov9d411c12018-01-23 15:10:03 -0500309 Py_DECREF(rl);
Yury Selivanova70232f2017-12-13 14:49:42 -0500310
311 return 0;
312}
313
314
315static PyObject *
316get_event_loop(void)
317{
318 PyObject *loop;
319 PyObject *policy;
320
321 if (get_running_loop(&loop)) {
322 return NULL;
323 }
324 if (loop != NULL) {
325 return loop;
326 }
327
328 policy = _PyObject_CallNoArg(asyncio_get_event_loop_policy);
329 if (policy == NULL) {
330 return NULL;
331 }
332
333 loop = _PyObject_CallMethodId(policy, &PyId_get_event_loop, NULL);
334 Py_DECREF(policy);
335 return loop;
336}
337
338
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900339static int
Yury Selivanov24cb7de2018-09-27 15:33:23 -0400340call_soon(PyObject *loop, PyObject *func, PyObject *arg, PyObject *ctx)
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500341{
342 PyObject *handle;
Yury Selivanovf23746a2018-01-22 19:11:18 -0500343 PyObject *stack[3];
344 Py_ssize_t nargs;
345
346 if (ctx == NULL) {
347 handle = _PyObject_CallMethodIdObjArgs(
348 loop, &PyId_call_soon, func, arg, NULL);
349 }
350 else {
351 /* Use FASTCALL to pass a keyword-only argument to call_soon */
352
353 PyObject *callable = _PyObject_GetAttrId(loop, &PyId_call_soon);
354 if (callable == NULL) {
355 return -1;
356 }
357
358 /* All refs in 'stack' are borrowed. */
359 nargs = 1;
360 stack[0] = func;
361 if (arg != NULL) {
362 stack[1] = arg;
363 nargs++;
364 }
365 stack[nargs] = (PyObject *)ctx;
366
367 handle = _PyObject_FastCallKeywords(
368 callable, stack, nargs, context_kwname);
369 Py_DECREF(callable);
370 }
371
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500372 if (handle == NULL) {
373 return -1;
374 }
375 Py_DECREF(handle);
376 return 0;
377}
378
379
380static inline int
381future_is_alive(FutureObj *fut)
382{
383 return fut->fut_loop != NULL;
384}
385
386
387static inline int
388future_ensure_alive(FutureObj *fut)
389{
390 if (!future_is_alive(fut)) {
391 PyErr_SetString(PyExc_RuntimeError,
392 "Future object is not initialized.");
393 return -1;
394 }
395 return 0;
396}
397
398
399#define ENSURE_FUTURE_ALIVE(fut) \
400 do { \
401 assert(Future_Check(fut) || Task_Check(fut)); \
402 if (future_ensure_alive((FutureObj*)fut)) { \
403 return NULL; \
404 } \
405 } while(0);
406
407
408static int
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400409future_schedule_callbacks(FutureObj *fut)
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900410{
411 Py_ssize_t len;
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500412 Py_ssize_t i;
413
414 if (fut->fut_callback0 != NULL) {
415 /* There's a 1st callback */
416
417 int ret = call_soon(
Yury Selivanovf23746a2018-01-22 19:11:18 -0500418 fut->fut_loop, fut->fut_callback0,
419 (PyObject *)fut, fut->fut_context0);
420
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500421 Py_CLEAR(fut->fut_callback0);
Yury Selivanovf23746a2018-01-22 19:11:18 -0500422 Py_CLEAR(fut->fut_context0);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500423 if (ret) {
424 /* If an error occurs in pure-Python implementation,
425 all callbacks are cleared. */
426 Py_CLEAR(fut->fut_callbacks);
427 return ret;
428 }
429
430 /* we called the first callback, now try calling
431 callbacks from the 'fut_callbacks' list. */
432 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900433
434 if (fut->fut_callbacks == NULL) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500435 /* No more callbacks, return. */
436 return 0;
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900437 }
438
439 len = PyList_GET_SIZE(fut->fut_callbacks);
440 if (len == 0) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500441 /* The list of callbacks was empty; clear it and return. */
442 Py_CLEAR(fut->fut_callbacks);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900443 return 0;
444 }
445
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900446 for (i = 0; i < len; i++) {
Yury Selivanovf23746a2018-01-22 19:11:18 -0500447 PyObject *cb_tup = PyList_GET_ITEM(fut->fut_callbacks, i);
448 PyObject *cb = PyTuple_GET_ITEM(cb_tup, 0);
449 PyObject *ctx = PyTuple_GET_ITEM(cb_tup, 1);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900450
Yury Selivanov24cb7de2018-09-27 15:33:23 -0400451 if (call_soon(fut->fut_loop, cb, (PyObject *)fut, ctx)) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500452 /* If an error occurs in pure-Python implementation,
453 all callbacks are cleared. */
454 Py_CLEAR(fut->fut_callbacks);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900455 return -1;
456 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900457 }
458
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500459 Py_CLEAR(fut->fut_callbacks);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900460 return 0;
461}
462
Miss Islington (bot)ef20abe2018-02-13 03:32:18 -0800463
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900464static int
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400465future_init(FutureObj *fut, PyObject *loop)
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900466{
Serhiy Storchakabca49392017-09-03 08:10:14 +0300467 PyObject *res;
468 int is_true;
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900469 _Py_IDENTIFIER(get_debug);
470
Miss Islington (bot)ef20abe2018-02-13 03:32:18 -0800471 // Same to FutureObj_clear() but not clearing fut->dict
472 Py_CLEAR(fut->fut_loop);
473 Py_CLEAR(fut->fut_callback0);
474 Py_CLEAR(fut->fut_context0);
475 Py_CLEAR(fut->fut_callbacks);
476 Py_CLEAR(fut->fut_result);
477 Py_CLEAR(fut->fut_exception);
478 Py_CLEAR(fut->fut_source_tb);
479
480 fut->fut_state = STATE_PENDING;
481 fut->fut_log_tb = 0;
482 fut->fut_blocking = 0;
483
Serhiy Storchakabca49392017-09-03 08:10:14 +0300484 if (loop == Py_None) {
Yury Selivanova70232f2017-12-13 14:49:42 -0500485 loop = get_event_loop();
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900486 if (loop == NULL) {
487 return -1;
488 }
489 }
490 else {
491 Py_INCREF(loop);
492 }
Miss Islington (bot)ef20abe2018-02-13 03:32:18 -0800493 fut->fut_loop = loop;
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900494
Victor Stinnerf94d1ee2016-10-29 09:05:39 +0200495 res = _PyObject_CallMethodId(fut->fut_loop, &PyId_get_debug, NULL);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900496 if (res == NULL) {
497 return -1;
498 }
Serhiy Storchakabca49392017-09-03 08:10:14 +0300499 is_true = PyObject_IsTrue(res);
500 Py_DECREF(res);
501 if (is_true < 0) {
502 return -1;
503 }
Miss Islington (bot)51d0a2c2018-05-28 08:28:12 -0700504 if (is_true && !_Py_IsFinalizing()) {
505 /* Only try to capture the traceback if the interpreter is not being
506 finalized. The original motivation to add a `_Py_IsFinalizing()`
507 call was to prevent SIGSEGV when a Future is created in a __del__
508 method, which is called during the interpreter shutdown and the
509 traceback module is already unloaded.
510 */
Miss Islington (bot)ef20abe2018-02-13 03:32:18 -0800511 fut->fut_source_tb = _PyObject_CallNoArg(traceback_extract_stack);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900512 if (fut->fut_source_tb == NULL) {
513 return -1;
514 }
515 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900516
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900517 return 0;
518}
519
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900520static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400521future_set_result(FutureObj *fut, PyObject *res)
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900522{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500523 if (future_ensure_alive(fut)) {
524 return NULL;
525 }
526
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900527 if (fut->fut_state != STATE_PENDING) {
528 PyErr_SetString(asyncio_InvalidStateError, "invalid state");
529 return NULL;
530 }
531
Serhiy Storchakabca49392017-09-03 08:10:14 +0300532 assert(!fut->fut_result);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900533 Py_INCREF(res);
534 fut->fut_result = res;
535 fut->fut_state = STATE_FINISHED;
536
Yury Selivanov22feeb82018-01-24 11:31:01 -0500537 if (future_schedule_callbacks(fut) == -1) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900538 return NULL;
539 }
540 Py_RETURN_NONE;
541}
542
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900543static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400544future_set_exception(FutureObj *fut, PyObject *exc)
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900545{
546 PyObject *exc_val = NULL;
547
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900548 if (fut->fut_state != STATE_PENDING) {
549 PyErr_SetString(asyncio_InvalidStateError, "invalid state");
550 return NULL;
551 }
552
553 if (PyExceptionClass_Check(exc)) {
Victor Stinnera5ed5f02016-12-06 18:45:50 +0100554 exc_val = _PyObject_CallNoArg(exc);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900555 if (exc_val == NULL) {
556 return NULL;
557 }
Serhiy Storchakabca49392017-09-03 08:10:14 +0300558 if (fut->fut_state != STATE_PENDING) {
559 Py_DECREF(exc_val);
560 PyErr_SetString(asyncio_InvalidStateError, "invalid state");
561 return NULL;
562 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900563 }
564 else {
565 exc_val = exc;
566 Py_INCREF(exc_val);
567 }
568 if (!PyExceptionInstance_Check(exc_val)) {
569 Py_DECREF(exc_val);
570 PyErr_SetString(PyExc_TypeError, "invalid exception object");
571 return NULL;
572 }
573 if ((PyObject*)Py_TYPE(exc_val) == PyExc_StopIteration) {
574 Py_DECREF(exc_val);
575 PyErr_SetString(PyExc_TypeError,
576 "StopIteration interacts badly with generators "
577 "and cannot be raised into a Future");
578 return NULL;
579 }
580
Serhiy Storchakabca49392017-09-03 08:10:14 +0300581 assert(!fut->fut_exception);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900582 fut->fut_exception = exc_val;
583 fut->fut_state = STATE_FINISHED;
584
Yury Selivanov22feeb82018-01-24 11:31:01 -0500585 if (future_schedule_callbacks(fut) == -1) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900586 return NULL;
587 }
588
589 fut->fut_log_tb = 1;
590 Py_RETURN_NONE;
591}
592
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400593static int
594future_get_result(FutureObj *fut, PyObject **result)
595{
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400596 if (fut->fut_state == STATE_CANCELLED) {
Serhiy Storchakabca49392017-09-03 08:10:14 +0300597 PyErr_SetNone(asyncio_CancelledError);
598 return -1;
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400599 }
600
601 if (fut->fut_state != STATE_FINISHED) {
Serhiy Storchakabca49392017-09-03 08:10:14 +0300602 PyErr_SetString(asyncio_InvalidStateError, "Result is not set.");
603 return -1;
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400604 }
605
606 fut->fut_log_tb = 0;
607 if (fut->fut_exception != NULL) {
608 Py_INCREF(fut->fut_exception);
609 *result = fut->fut_exception;
610 return 1;
611 }
612
613 Py_INCREF(fut->fut_result);
614 *result = fut->fut_result;
615 return 0;
616}
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900617
618static PyObject *
Yury Selivanov24cb7de2018-09-27 15:33:23 -0400619future_add_done_callback(FutureObj *fut, PyObject *arg, PyObject *ctx)
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900620{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500621 if (!future_is_alive(fut)) {
622 PyErr_SetString(PyExc_RuntimeError, "uninitialized Future object");
623 return NULL;
624 }
625
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900626 if (fut->fut_state != STATE_PENDING) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500627 /* The future is done/cancelled, so schedule the callback
628 right away. */
Yury Selivanovf23746a2018-01-22 19:11:18 -0500629 if (call_soon(fut->fut_loop, arg, (PyObject*) fut, ctx)) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900630 return NULL;
631 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900632 }
633 else {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500634 /* The future is pending, add a callback.
635
636 Callbacks in the future object are stored as follows:
637
638 callback0 -- a pointer to the first callback
639 callbacks -- a list of 2nd, 3rd, ... callbacks
640
641 Invariants:
642
643 * callbacks != NULL:
644 There are some callbacks in in the list. Just
645 add the new callback to it.
646
647 * callbacks == NULL and callback0 == NULL:
648 This is the first callback. Set it to callback0.
649
650 * callbacks == NULL and callback0 != NULL:
651 This is a second callback. Initialize callbacks
652 with a new list and add the new callback to it.
653 */
654
Yury Selivanovf23746a2018-01-22 19:11:18 -0500655 if (fut->fut_callbacks == NULL && fut->fut_callback0 == NULL) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500656 Py_INCREF(arg);
657 fut->fut_callback0 = arg;
Yury Selivanovf23746a2018-01-22 19:11:18 -0500658 Py_INCREF(ctx);
659 fut->fut_context0 = ctx;
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500660 }
661 else {
Yury Selivanovf23746a2018-01-22 19:11:18 -0500662 PyObject *tup = PyTuple_New(2);
663 if (tup == NULL) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500664 return NULL;
665 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500666 Py_INCREF(arg);
Yury Selivanovf23746a2018-01-22 19:11:18 -0500667 PyTuple_SET_ITEM(tup, 0, arg);
668 Py_INCREF(ctx);
669 PyTuple_SET_ITEM(tup, 1, (PyObject *)ctx);
670
671 if (fut->fut_callbacks != NULL) {
672 int err = PyList_Append(fut->fut_callbacks, tup);
673 if (err) {
674 Py_DECREF(tup);
675 return NULL;
676 }
677 Py_DECREF(tup);
678 }
679 else {
680 fut->fut_callbacks = PyList_New(1);
681 if (fut->fut_callbacks == NULL) {
682 return NULL;
683 }
684
685 PyList_SET_ITEM(fut->fut_callbacks, 0, tup); /* borrow */
686 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900687 }
688 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500689
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900690 Py_RETURN_NONE;
691}
692
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400693static PyObject *
694future_cancel(FutureObj *fut)
695{
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +0000696 fut->fut_log_tb = 0;
697
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400698 if (fut->fut_state != STATE_PENDING) {
699 Py_RETURN_FALSE;
700 }
701 fut->fut_state = STATE_CANCELLED;
702
Yury Selivanov22feeb82018-01-24 11:31:01 -0500703 if (future_schedule_callbacks(fut) == -1) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400704 return NULL;
705 }
706
707 Py_RETURN_TRUE;
708}
709
710/*[clinic input]
711_asyncio.Future.__init__
712
713 *
Serhiy Storchakabca49392017-09-03 08:10:14 +0300714 loop: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400715
716This class is *almost* compatible with concurrent.futures.Future.
717
718 Differences:
719
720 - result() and exception() do not take a timeout argument and
721 raise an exception when the future isn't done yet.
722
723 - Callbacks registered with add_done_callback() are always called
724 via the event loop's call_soon_threadsafe().
725
726 - This class is not compatible with the wait() and as_completed()
727 methods in the concurrent.futures package.
728[clinic start generated code]*/
729
730static int
731_asyncio_Future___init___impl(FutureObj *self, PyObject *loop)
Serhiy Storchakabca49392017-09-03 08:10:14 +0300732/*[clinic end generated code: output=9ed75799eaccb5d6 input=89af317082bc0bf8]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400733
734{
735 return future_init(self, loop);
736}
737
738static int
739FutureObj_clear(FutureObj *fut)
740{
741 Py_CLEAR(fut->fut_loop);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500742 Py_CLEAR(fut->fut_callback0);
Yury Selivanovf23746a2018-01-22 19:11:18 -0500743 Py_CLEAR(fut->fut_context0);
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400744 Py_CLEAR(fut->fut_callbacks);
745 Py_CLEAR(fut->fut_result);
746 Py_CLEAR(fut->fut_exception);
747 Py_CLEAR(fut->fut_source_tb);
748 Py_CLEAR(fut->dict);
749 return 0;
750}
751
752static int
753FutureObj_traverse(FutureObj *fut, visitproc visit, void *arg)
754{
755 Py_VISIT(fut->fut_loop);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500756 Py_VISIT(fut->fut_callback0);
Yury Selivanovf23746a2018-01-22 19:11:18 -0500757 Py_VISIT(fut->fut_context0);
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400758 Py_VISIT(fut->fut_callbacks);
759 Py_VISIT(fut->fut_result);
760 Py_VISIT(fut->fut_exception);
761 Py_VISIT(fut->fut_source_tb);
762 Py_VISIT(fut->dict);
763 return 0;
764}
765
766/*[clinic input]
767_asyncio.Future.result
768
769Return the result this future represents.
770
771If the future has been cancelled, raises CancelledError. If the
772future's result isn't yet available, raises InvalidStateError. If
773the future is done and has an exception set, this exception is raised.
774[clinic start generated code]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900775
776static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400777_asyncio_Future_result_impl(FutureObj *self)
778/*[clinic end generated code: output=f35f940936a4b1e5 input=49ecf9cf5ec50dc5]*/
779{
780 PyObject *result;
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500781
782 if (!future_is_alive(self)) {
783 PyErr_SetString(asyncio_InvalidStateError,
784 "Future object is not initialized.");
785 return NULL;
786 }
787
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400788 int res = future_get_result(self, &result);
789
790 if (res == -1) {
791 return NULL;
792 }
793
794 if (res == 0) {
795 return result;
796 }
797
798 assert(res == 1);
799
800 PyErr_SetObject(PyExceptionInstance_Class(result), result);
801 Py_DECREF(result);
802 return NULL;
803}
804
805/*[clinic input]
806_asyncio.Future.exception
807
808Return the exception that was set on this future.
809
810The exception (or None if no exception was set) is returned only if
811the future is done. If the future has been cancelled, raises
812CancelledError. If the future isn't done yet, raises
813InvalidStateError.
814[clinic start generated code]*/
815
816static PyObject *
817_asyncio_Future_exception_impl(FutureObj *self)
818/*[clinic end generated code: output=88b20d4f855e0710 input=733547a70c841c68]*/
819{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500820 if (!future_is_alive(self)) {
821 PyErr_SetString(asyncio_InvalidStateError,
822 "Future object is not initialized.");
823 return NULL;
824 }
825
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400826 if (self->fut_state == STATE_CANCELLED) {
Serhiy Storchakabca49392017-09-03 08:10:14 +0300827 PyErr_SetNone(asyncio_CancelledError);
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400828 return NULL;
829 }
830
831 if (self->fut_state != STATE_FINISHED) {
Serhiy Storchakabca49392017-09-03 08:10:14 +0300832 PyErr_SetString(asyncio_InvalidStateError, "Exception is not set.");
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400833 return NULL;
834 }
835
836 if (self->fut_exception != NULL) {
837 self->fut_log_tb = 0;
838 Py_INCREF(self->fut_exception);
839 return self->fut_exception;
840 }
841
842 Py_RETURN_NONE;
843}
844
845/*[clinic input]
846_asyncio.Future.set_result
847
Yury Selivanov0cf16f92017-12-25 10:48:15 -0500848 result: object
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400849 /
850
851Mark the future done and set its result.
852
853If the future is already done when this method is called, raises
854InvalidStateError.
855[clinic start generated code]*/
856
857static PyObject *
Yury Selivanov0cf16f92017-12-25 10:48:15 -0500858_asyncio_Future_set_result(FutureObj *self, PyObject *result)
859/*[clinic end generated code: output=1ec2e6bcccd6f2ce input=8b75172c2a7b05f1]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400860{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500861 ENSURE_FUTURE_ALIVE(self)
Yury Selivanov0cf16f92017-12-25 10:48:15 -0500862 return future_set_result(self, result);
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400863}
864
865/*[clinic input]
866_asyncio.Future.set_exception
867
Serhiy Storchakabca49392017-09-03 08:10:14 +0300868 exception: object
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400869 /
870
871Mark the future done and set an exception.
872
873If the future is already done when this method is called, raises
874InvalidStateError.
875[clinic start generated code]*/
876
877static PyObject *
878_asyncio_Future_set_exception(FutureObj *self, PyObject *exception)
Serhiy Storchakabca49392017-09-03 08:10:14 +0300879/*[clinic end generated code: output=f1c1b0cd321be360 input=e45b7d7aa71cc66d]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400880{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500881 ENSURE_FUTURE_ALIVE(self)
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400882 return future_set_exception(self, exception);
883}
884
885/*[clinic input]
886_asyncio.Future.add_done_callback
887
Serhiy Storchakabca49392017-09-03 08:10:14 +0300888 fn: object
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400889 /
Yury Selivanovf23746a2018-01-22 19:11:18 -0500890 *
891 context: object = NULL
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400892
893Add a callback to be run when the future becomes done.
894
895The callback is called with a single argument - the future object. If
896the future is already done when this is called, the callback is
897scheduled with call_soon.
898[clinic start generated code]*/
899
900static PyObject *
Yury Selivanovf23746a2018-01-22 19:11:18 -0500901_asyncio_Future_add_done_callback_impl(FutureObj *self, PyObject *fn,
902 PyObject *context)
903/*[clinic end generated code: output=7ce635bbc9554c1e input=15ab0693a96e9533]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400904{
Yury Selivanovf23746a2018-01-22 19:11:18 -0500905 if (context == NULL) {
Yury Selivanov24cb7de2018-09-27 15:33:23 -0400906 context = PyContext_CopyCurrent();
Yury Selivanovf23746a2018-01-22 19:11:18 -0500907 if (context == NULL) {
908 return NULL;
909 }
Yury Selivanov24cb7de2018-09-27 15:33:23 -0400910 PyObject *res = future_add_done_callback(self, fn, context);
Yury Selivanovf23746a2018-01-22 19:11:18 -0500911 Py_DECREF(context);
912 return res;
913 }
Yury Selivanov24cb7de2018-09-27 15:33:23 -0400914 return future_add_done_callback(self, fn, context);
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400915}
916
917/*[clinic input]
918_asyncio.Future.remove_done_callback
919
Serhiy Storchakabca49392017-09-03 08:10:14 +0300920 fn: object
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400921 /
922
923Remove all instances of a callback from the "call when done" list.
924
925Returns the number of callbacks removed.
926[clinic start generated code]*/
927
928static PyObject *
929_asyncio_Future_remove_done_callback(FutureObj *self, PyObject *fn)
Serhiy Storchakabca49392017-09-03 08:10:14 +0300930/*[clinic end generated code: output=5ab1fb52b24ef31f input=0a43280a149d505b]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900931{
932 PyObject *newlist;
933 Py_ssize_t len, i, j=0;
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500934 Py_ssize_t cleared_callback0 = 0;
935
936 ENSURE_FUTURE_ALIVE(self)
937
938 if (self->fut_callback0 != NULL) {
939 int cmp = PyObject_RichCompareBool(fn, self->fut_callback0, Py_EQ);
940 if (cmp == -1) {
941 return NULL;
942 }
943 if (cmp == 1) {
944 /* callback0 == fn */
945 Py_CLEAR(self->fut_callback0);
Yury Selivanovf23746a2018-01-22 19:11:18 -0500946 Py_CLEAR(self->fut_context0);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500947 cleared_callback0 = 1;
948 }
949 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900950
Serhiy Storchakabca49392017-09-03 08:10:14 +0300951 if (self->fut_callbacks == NULL) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500952 return PyLong_FromSsize_t(cleared_callback0);
Serhiy Storchakabca49392017-09-03 08:10:14 +0300953 }
954
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400955 len = PyList_GET_SIZE(self->fut_callbacks);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900956 if (len == 0) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500957 Py_CLEAR(self->fut_callbacks);
958 return PyLong_FromSsize_t(cleared_callback0);
959 }
960
961 if (len == 1) {
Yury Selivanovf23746a2018-01-22 19:11:18 -0500962 PyObject *cb_tup = PyList_GET_ITEM(self->fut_callbacks, 0);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500963 int cmp = PyObject_RichCompareBool(
Yury Selivanovf23746a2018-01-22 19:11:18 -0500964 fn, PyTuple_GET_ITEM(cb_tup, 0), Py_EQ);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500965 if (cmp == -1) {
966 return NULL;
967 }
968 if (cmp == 1) {
969 /* callbacks[0] == fn */
970 Py_CLEAR(self->fut_callbacks);
971 return PyLong_FromSsize_t(1 + cleared_callback0);
972 }
973 /* callbacks[0] != fn and len(callbacks) == 1 */
974 return PyLong_FromSsize_t(cleared_callback0);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900975 }
976
977 newlist = PyList_New(len);
978 if (newlist == NULL) {
979 return NULL;
980 }
981
Yury Selivanov84af9032017-03-02 23:46:56 -0500982 for (i = 0; i < PyList_GET_SIZE(self->fut_callbacks); i++) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900983 int ret;
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400984 PyObject *item = PyList_GET_ITEM(self->fut_callbacks, i);
Serhiy Storchakabca49392017-09-03 08:10:14 +0300985 Py_INCREF(item);
Yury Selivanovf23746a2018-01-22 19:11:18 -0500986 ret = PyObject_RichCompareBool(fn, PyTuple_GET_ITEM(item, 0), Py_EQ);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900987 if (ret == 0) {
Yury Selivanov833a3b02017-07-05 13:32:03 -0400988 if (j < len) {
Yury Selivanov833a3b02017-07-05 13:32:03 -0400989 PyList_SET_ITEM(newlist, j, item);
990 j++;
Serhiy Storchakabca49392017-09-03 08:10:14 +0300991 continue;
Yury Selivanov833a3b02017-07-05 13:32:03 -0400992 }
Serhiy Storchakabca49392017-09-03 08:10:14 +0300993 ret = PyList_Append(newlist, item);
994 }
995 Py_DECREF(item);
996 if (ret < 0) {
997 goto fail;
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900998 }
999 }
1000
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001001 if (j == 0) {
1002 Py_CLEAR(self->fut_callbacks);
1003 Py_DECREF(newlist);
1004 return PyLong_FromSsize_t(len + cleared_callback0);
1005 }
1006
Serhiy Storchakabca49392017-09-03 08:10:14 +03001007 if (j < len) {
1008 Py_SIZE(newlist) = j;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001009 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03001010 j = PyList_GET_SIZE(newlist);
1011 len = PyList_GET_SIZE(self->fut_callbacks);
1012 if (j != len) {
1013 if (PyList_SetSlice(self->fut_callbacks, 0, len, newlist) < 0) {
1014 goto fail;
1015 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001016 }
1017 Py_DECREF(newlist);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001018 return PyLong_FromSsize_t(len - j + cleared_callback0);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001019
1020fail:
1021 Py_DECREF(newlist);
1022 return NULL;
1023}
1024
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001025/*[clinic input]
1026_asyncio.Future.cancel
1027
1028Cancel the future and schedule callbacks.
1029
1030If the future is already done or cancelled, return False. Otherwise,
1031change the future's state to cancelled, schedule the callbacks and
1032return True.
1033[clinic start generated code]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001034
1035static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001036_asyncio_Future_cancel_impl(FutureObj *self)
1037/*[clinic end generated code: output=e45b932ba8bd68a1 input=515709a127995109]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001038{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001039 ENSURE_FUTURE_ALIVE(self)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001040 return future_cancel(self);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001041}
1042
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001043/*[clinic input]
1044_asyncio.Future.cancelled
1045
1046Return True if the future was cancelled.
1047[clinic start generated code]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001048
1049static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001050_asyncio_Future_cancelled_impl(FutureObj *self)
1051/*[clinic end generated code: output=145197ced586357d input=943ab8b7b7b17e45]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001052{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001053 if (future_is_alive(self) && self->fut_state == STATE_CANCELLED) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001054 Py_RETURN_TRUE;
1055 }
1056 else {
1057 Py_RETURN_FALSE;
1058 }
1059}
1060
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001061/*[clinic input]
1062_asyncio.Future.done
1063
1064Return True if the future is done.
1065
1066Done means either that a result / exception are available, or that the
1067future was cancelled.
1068[clinic start generated code]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001069
1070static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001071_asyncio_Future_done_impl(FutureObj *self)
1072/*[clinic end generated code: output=244c5ac351145096 input=28d7b23fdb65d2ac]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001073{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001074 if (!future_is_alive(self) || self->fut_state == STATE_PENDING) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001075 Py_RETURN_FALSE;
1076 }
1077 else {
1078 Py_RETURN_TRUE;
1079 }
1080}
1081
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001082/*[clinic input]
1083_asyncio.Future.get_loop
1084
1085Return the event loop the Future is bound to.
1086[clinic start generated code]*/
1087
1088static PyObject *
1089_asyncio_Future_get_loop_impl(FutureObj *self)
1090/*[clinic end generated code: output=119b6ea0c9816c3f input=cba48c2136c79d1f]*/
1091{
1092 Py_INCREF(self->fut_loop);
1093 return self->fut_loop;
1094}
1095
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001096static PyObject *
1097FutureObj_get_blocking(FutureObj *fut)
1098{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001099 if (future_is_alive(fut) && fut->fut_blocking) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001100 Py_RETURN_TRUE;
1101 }
1102 else {
1103 Py_RETURN_FALSE;
1104 }
1105}
1106
1107static int
1108FutureObj_set_blocking(FutureObj *fut, PyObject *val)
1109{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001110 if (future_ensure_alive(fut)) {
1111 return -1;
1112 }
1113
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001114 int is_true = PyObject_IsTrue(val);
1115 if (is_true < 0) {
1116 return -1;
1117 }
1118 fut->fut_blocking = is_true;
1119 return 0;
1120}
1121
1122static PyObject *
1123FutureObj_get_log_traceback(FutureObj *fut)
1124{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001125 ENSURE_FUTURE_ALIVE(fut)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001126 if (fut->fut_log_tb) {
1127 Py_RETURN_TRUE;
1128 }
1129 else {
1130 Py_RETURN_FALSE;
1131 }
1132}
1133
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +00001134static int
1135FutureObj_set_log_traceback(FutureObj *fut, PyObject *val)
1136{
1137 int is_true = PyObject_IsTrue(val);
1138 if (is_true < 0) {
1139 return -1;
1140 }
Yury Selivanove0aef4f2017-12-25 16:16:10 -05001141 if (is_true) {
1142 PyErr_SetString(PyExc_ValueError,
1143 "_log_traceback can only be set to False");
1144 return -1;
1145 }
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +00001146 fut->fut_log_tb = is_true;
1147 return 0;
1148}
1149
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001150static PyObject *
1151FutureObj_get_loop(FutureObj *fut)
1152{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001153 if (!future_is_alive(fut)) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001154 Py_RETURN_NONE;
1155 }
1156 Py_INCREF(fut->fut_loop);
1157 return fut->fut_loop;
1158}
1159
1160static PyObject *
1161FutureObj_get_callbacks(FutureObj *fut)
1162{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001163 Py_ssize_t i;
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001164
1165 ENSURE_FUTURE_ALIVE(fut)
1166
Yury Selivanovf23746a2018-01-22 19:11:18 -05001167 if (fut->fut_callback0 == NULL) {
1168 if (fut->fut_callbacks == NULL) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001169 Py_RETURN_NONE;
1170 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001171
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001172 Py_INCREF(fut->fut_callbacks);
1173 return fut->fut_callbacks;
1174 }
1175
Yury Selivanovf23746a2018-01-22 19:11:18 -05001176 Py_ssize_t len = 1;
1177 if (fut->fut_callbacks != NULL) {
1178 len += PyList_GET_SIZE(fut->fut_callbacks);
1179 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001180
Yury Selivanovf23746a2018-01-22 19:11:18 -05001181
1182 PyObject *new_list = PyList_New(len);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001183 if (new_list == NULL) {
1184 return NULL;
1185 }
1186
Yury Selivanovf23746a2018-01-22 19:11:18 -05001187 PyObject *tup0 = PyTuple_New(2);
1188 if (tup0 == NULL) {
1189 Py_DECREF(new_list);
1190 return NULL;
1191 }
1192
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001193 Py_INCREF(fut->fut_callback0);
Yury Selivanovf23746a2018-01-22 19:11:18 -05001194 PyTuple_SET_ITEM(tup0, 0, fut->fut_callback0);
1195 assert(fut->fut_context0 != NULL);
1196 Py_INCREF(fut->fut_context0);
1197 PyTuple_SET_ITEM(tup0, 1, (PyObject *)fut->fut_context0);
1198
1199 PyList_SET_ITEM(new_list, 0, tup0);
1200
1201 if (fut->fut_callbacks != NULL) {
1202 for (i = 0; i < PyList_GET_SIZE(fut->fut_callbacks); i++) {
1203 PyObject *cb = PyList_GET_ITEM(fut->fut_callbacks, i);
1204 Py_INCREF(cb);
1205 PyList_SET_ITEM(new_list, i + 1, cb);
1206 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001207 }
1208
1209 return new_list;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001210}
1211
1212static PyObject *
1213FutureObj_get_result(FutureObj *fut)
1214{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001215 ENSURE_FUTURE_ALIVE(fut)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001216 if (fut->fut_result == NULL) {
1217 Py_RETURN_NONE;
1218 }
1219 Py_INCREF(fut->fut_result);
1220 return fut->fut_result;
1221}
1222
1223static PyObject *
1224FutureObj_get_exception(FutureObj *fut)
1225{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001226 ENSURE_FUTURE_ALIVE(fut)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001227 if (fut->fut_exception == NULL) {
1228 Py_RETURN_NONE;
1229 }
1230 Py_INCREF(fut->fut_exception);
1231 return fut->fut_exception;
1232}
1233
1234static PyObject *
1235FutureObj_get_source_traceback(FutureObj *fut)
1236{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001237 if (!future_is_alive(fut) || fut->fut_source_tb == NULL) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001238 Py_RETURN_NONE;
1239 }
1240 Py_INCREF(fut->fut_source_tb);
1241 return fut->fut_source_tb;
1242}
1243
1244static PyObject *
1245FutureObj_get_state(FutureObj *fut)
1246{
1247 _Py_IDENTIFIER(PENDING);
1248 _Py_IDENTIFIER(CANCELLED);
1249 _Py_IDENTIFIER(FINISHED);
1250 PyObject *ret = NULL;
1251
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001252 ENSURE_FUTURE_ALIVE(fut)
1253
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001254 switch (fut->fut_state) {
1255 case STATE_PENDING:
1256 ret = _PyUnicode_FromId(&PyId_PENDING);
1257 break;
1258 case STATE_CANCELLED:
1259 ret = _PyUnicode_FromId(&PyId_CANCELLED);
1260 break;
1261 case STATE_FINISHED:
1262 ret = _PyUnicode_FromId(&PyId_FINISHED);
1263 break;
1264 default:
1265 assert (0);
1266 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03001267 Py_XINCREF(ret);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001268 return ret;
1269}
1270
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001271/*[clinic input]
1272_asyncio.Future._repr_info
1273[clinic start generated code]*/
1274
1275static PyObject *
1276_asyncio_Future__repr_info_impl(FutureObj *self)
1277/*[clinic end generated code: output=fa69e901bd176cfb input=f21504d8e2ae1ca2]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001278{
Victor Stinnerde4ae3d2016-12-04 22:59:09 +01001279 return PyObject_CallFunctionObjArgs(
1280 asyncio_future_repr_info_func, self, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001281}
1282
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001283static PyObject *
1284FutureObj_repr(FutureObj *fut)
1285{
1286 _Py_IDENTIFIER(_repr_info);
1287
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001288 ENSURE_FUTURE_ALIVE(fut)
1289
Serhiy Storchakabca49392017-09-03 08:10:14 +03001290 PyObject *rinfo = _PyObject_CallMethodIdObjArgs((PyObject*)fut,
1291 &PyId__repr_info,
1292 NULL);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001293 if (rinfo == NULL) {
1294 return NULL;
1295 }
1296
Serhiy Storchakabca49392017-09-03 08:10:14 +03001297 PyObject *rinfo_s = PyUnicode_Join(NULL, rinfo);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001298 Py_DECREF(rinfo);
1299 if (rinfo_s == NULL) {
1300 return NULL;
1301 }
1302
1303 PyObject *rstr = NULL;
1304 PyObject *type_name = PyObject_GetAttrString((PyObject*)Py_TYPE(fut),
1305 "__name__");
1306 if (type_name != NULL) {
Serhiy Storchakabca49392017-09-03 08:10:14 +03001307 rstr = PyUnicode_FromFormat("<%S %U>", type_name, rinfo_s);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001308 Py_DECREF(type_name);
1309 }
1310 Py_DECREF(rinfo_s);
1311 return rstr;
1312}
1313
1314static void
1315FutureObj_finalize(FutureObj *fut)
1316{
1317 _Py_IDENTIFIER(call_exception_handler);
1318 _Py_IDENTIFIER(message);
1319 _Py_IDENTIFIER(exception);
1320 _Py_IDENTIFIER(future);
1321 _Py_IDENTIFIER(source_traceback);
1322
Serhiy Storchakabca49392017-09-03 08:10:14 +03001323 PyObject *error_type, *error_value, *error_traceback;
1324 PyObject *context;
1325 PyObject *type_name;
1326 PyObject *message = NULL;
1327 PyObject *func;
1328
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001329 if (!fut->fut_log_tb) {
1330 return;
1331 }
1332 assert(fut->fut_exception != NULL);
Serhiy Storchakabca49392017-09-03 08:10:14 +03001333 fut->fut_log_tb = 0;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001334
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001335 /* Save the current exception, if any. */
1336 PyErr_Fetch(&error_type, &error_value, &error_traceback);
1337
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001338 context = PyDict_New();
1339 if (context == NULL) {
1340 goto finally;
1341 }
1342
1343 type_name = PyObject_GetAttrString((PyObject*)Py_TYPE(fut), "__name__");
1344 if (type_name == NULL) {
1345 goto finally;
1346 }
1347
1348 message = PyUnicode_FromFormat(
1349 "%S exception was never retrieved", type_name);
Serhiy Storchakabca49392017-09-03 08:10:14 +03001350 Py_DECREF(type_name);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001351 if (message == NULL) {
1352 goto finally;
1353 }
1354
1355 if (_PyDict_SetItemId(context, &PyId_message, message) < 0 ||
1356 _PyDict_SetItemId(context, &PyId_exception, fut->fut_exception) < 0 ||
1357 _PyDict_SetItemId(context, &PyId_future, (PyObject*)fut) < 0) {
1358 goto finally;
1359 }
1360 if (fut->fut_source_tb != NULL) {
1361 if (_PyDict_SetItemId(context, &PyId_source_traceback,
1362 fut->fut_source_tb) < 0) {
1363 goto finally;
1364 }
1365 }
1366
1367 func = _PyObject_GetAttrId(fut->fut_loop, &PyId_call_exception_handler);
1368 if (func != NULL) {
Serhiy Storchakabca49392017-09-03 08:10:14 +03001369 PyObject *res = PyObject_CallFunctionObjArgs(func, context, NULL);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001370 if (res == NULL) {
1371 PyErr_WriteUnraisable(func);
1372 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03001373 else {
1374 Py_DECREF(res);
1375 }
1376 Py_DECREF(func);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001377 }
1378
1379finally:
Serhiy Storchakabca49392017-09-03 08:10:14 +03001380 Py_XDECREF(context);
1381 Py_XDECREF(message);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001382
1383 /* Restore the saved exception. */
1384 PyErr_Restore(error_type, error_value, error_traceback);
1385}
1386
1387
1388static PyAsyncMethods FutureType_as_async = {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001389 (unaryfunc)future_new_iter, /* am_await */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001390 0, /* am_aiter */
1391 0 /* am_anext */
1392};
1393
1394static PyMethodDef FutureType_methods[] = {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001395 _ASYNCIO_FUTURE_RESULT_METHODDEF
1396 _ASYNCIO_FUTURE_EXCEPTION_METHODDEF
1397 _ASYNCIO_FUTURE_SET_RESULT_METHODDEF
1398 _ASYNCIO_FUTURE_SET_EXCEPTION_METHODDEF
1399 _ASYNCIO_FUTURE_ADD_DONE_CALLBACK_METHODDEF
1400 _ASYNCIO_FUTURE_REMOVE_DONE_CALLBACK_METHODDEF
1401 _ASYNCIO_FUTURE_CANCEL_METHODDEF
1402 _ASYNCIO_FUTURE_CANCELLED_METHODDEF
1403 _ASYNCIO_FUTURE_DONE_METHODDEF
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001404 _ASYNCIO_FUTURE_GET_LOOP_METHODDEF
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001405 _ASYNCIO_FUTURE__REPR_INFO_METHODDEF
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001406 {NULL, NULL} /* Sentinel */
1407};
1408
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001409#define FUTURE_COMMON_GETSETLIST \
1410 {"_state", (getter)FutureObj_get_state, NULL, NULL}, \
1411 {"_asyncio_future_blocking", (getter)FutureObj_get_blocking, \
1412 (setter)FutureObj_set_blocking, NULL}, \
1413 {"_loop", (getter)FutureObj_get_loop, NULL, NULL}, \
1414 {"_callbacks", (getter)FutureObj_get_callbacks, NULL, NULL}, \
1415 {"_result", (getter)FutureObj_get_result, NULL, NULL}, \
1416 {"_exception", (getter)FutureObj_get_exception, NULL, NULL}, \
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +00001417 {"_log_traceback", (getter)FutureObj_get_log_traceback, \
1418 (setter)FutureObj_set_log_traceback, NULL}, \
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001419 {"_source_traceback", (getter)FutureObj_get_source_traceback, NULL, NULL},
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001420
1421static PyGetSetDef FutureType_getsetlist[] = {
1422 FUTURE_COMMON_GETSETLIST
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001423 {NULL} /* Sentinel */
1424};
1425
1426static void FutureObj_dealloc(PyObject *self);
1427
1428static PyTypeObject FutureType = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02001429 PyVarObject_HEAD_INIT(NULL, 0)
INADA Naoki9f2ce252016-10-15 15:39:19 +09001430 "_asyncio.Future",
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001431 sizeof(FutureObj), /* tp_basicsize */
1432 .tp_dealloc = FutureObj_dealloc,
1433 .tp_as_async = &FutureType_as_async,
1434 .tp_repr = (reprfunc)FutureObj_repr,
1435 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE
1436 | Py_TPFLAGS_HAVE_FINALIZE,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001437 .tp_doc = _asyncio_Future___init____doc__,
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001438 .tp_traverse = (traverseproc)FutureObj_traverse,
1439 .tp_clear = (inquiry)FutureObj_clear,
1440 .tp_weaklistoffset = offsetof(FutureObj, fut_weakreflist),
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001441 .tp_iter = (getiterfunc)future_new_iter,
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001442 .tp_methods = FutureType_methods,
1443 .tp_getset = FutureType_getsetlist,
1444 .tp_dictoffset = offsetof(FutureObj, dict),
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001445 .tp_init = (initproc)_asyncio_Future___init__,
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001446 .tp_new = PyType_GenericNew,
1447 .tp_finalize = (destructor)FutureObj_finalize,
1448};
1449
1450static void
1451FutureObj_dealloc(PyObject *self)
1452{
1453 FutureObj *fut = (FutureObj *)self;
1454
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001455 if (Future_CheckExact(fut)) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001456 /* When fut is subclass of Future, finalizer is called from
1457 * subtype_dealloc.
1458 */
1459 if (PyObject_CallFinalizerFromDealloc(self) < 0) {
1460 // resurrected.
1461 return;
1462 }
1463 }
1464
Alexander Mohrde34cbe2017-08-01 23:31:07 -07001465 PyObject_GC_UnTrack(self);
1466
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001467 if (fut->fut_weakreflist != NULL) {
1468 PyObject_ClearWeakRefs(self);
1469 }
1470
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001471 (void)FutureObj_clear(fut);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001472 Py_TYPE(fut)->tp_free(fut);
1473}
1474
1475
1476/*********************** Future Iterator **************************/
1477
1478typedef struct {
1479 PyObject_HEAD
1480 FutureObj *future;
1481} futureiterobject;
1482
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001483
1484#define FI_FREELIST_MAXLEN 255
1485static futureiterobject *fi_freelist = NULL;
1486static Py_ssize_t fi_freelist_len = 0;
1487
1488
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001489static void
1490FutureIter_dealloc(futureiterobject *it)
1491{
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001492 PyObject_GC_UnTrack(it);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001493 Py_CLEAR(it->future);
1494
1495 if (fi_freelist_len < FI_FREELIST_MAXLEN) {
1496 fi_freelist_len++;
1497 it->future = (FutureObj*) fi_freelist;
1498 fi_freelist = it;
1499 }
1500 else {
1501 PyObject_GC_Del(it);
1502 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001503}
1504
1505static PyObject *
1506FutureIter_iternext(futureiterobject *it)
1507{
1508 PyObject *res;
1509 FutureObj *fut = it->future;
1510
1511 if (fut == NULL) {
1512 return NULL;
1513 }
1514
1515 if (fut->fut_state == STATE_PENDING) {
1516 if (!fut->fut_blocking) {
1517 fut->fut_blocking = 1;
1518 Py_INCREF(fut);
1519 return (PyObject *)fut;
1520 }
Yury Selivanov0cf16f92017-12-25 10:48:15 -05001521 PyErr_SetString(PyExc_RuntimeError,
1522 "await wasn't used with future");
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001523 return NULL;
1524 }
1525
Serhiy Storchakabca49392017-09-03 08:10:14 +03001526 it->future = NULL;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001527 res = _asyncio_Future_result_impl(fut);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001528 if (res != NULL) {
Serhiy Storchaka60e49aa2016-11-06 18:47:03 +02001529 /* The result of the Future is not an exception. */
Serhiy Storchakabca49392017-09-03 08:10:14 +03001530 (void)_PyGen_SetStopIterationValue(res);
Serhiy Storchaka60e49aa2016-11-06 18:47:03 +02001531 Py_DECREF(res);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001532 }
1533
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001534 Py_DECREF(fut);
1535 return NULL;
1536}
1537
1538static PyObject *
INADA Naoki74c17532016-10-25 19:00:45 +09001539FutureIter_send(futureiterobject *self, PyObject *unused)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001540{
INADA Naoki74c17532016-10-25 19:00:45 +09001541 /* Future.__iter__ doesn't care about values that are pushed to the
1542 * generator, it just returns "self.result().
1543 */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001544 return FutureIter_iternext(self);
1545}
1546
1547static PyObject *
1548FutureIter_throw(futureiterobject *self, PyObject *args)
1549{
Serhiy Storchakabca49392017-09-03 08:10:14 +03001550 PyObject *type, *val = NULL, *tb = NULL;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001551 if (!PyArg_ParseTuple(args, "O|OO", &type, &val, &tb))
1552 return NULL;
1553
1554 if (val == Py_None) {
1555 val = NULL;
1556 }
1557 if (tb == Py_None) {
1558 tb = NULL;
Benjamin Peterson996fc1f2016-11-14 00:15:44 -08001559 } else if (tb != NULL && !PyTraceBack_Check(tb)) {
1560 PyErr_SetString(PyExc_TypeError, "throw() third argument must be a traceback");
1561 return NULL;
1562 }
1563
1564 Py_INCREF(type);
1565 Py_XINCREF(val);
1566 Py_XINCREF(tb);
1567
1568 if (PyExceptionClass_Check(type)) {
1569 PyErr_NormalizeException(&type, &val, &tb);
Yury Selivanovedfe8862016-12-01 11:37:47 -05001570 /* No need to call PyException_SetTraceback since we'll be calling
1571 PyErr_Restore for `type`, `val`, and `tb`. */
Benjamin Peterson996fc1f2016-11-14 00:15:44 -08001572 } else if (PyExceptionInstance_Check(type)) {
1573 if (val) {
1574 PyErr_SetString(PyExc_TypeError,
1575 "instance exception may not have a separate value");
1576 goto fail;
1577 }
1578 val = type;
1579 type = PyExceptionInstance_Class(type);
1580 Py_INCREF(type);
1581 if (tb == NULL)
1582 tb = PyException_GetTraceback(val);
1583 } else {
1584 PyErr_SetString(PyExc_TypeError,
1585 "exceptions must be classes deriving BaseException or "
1586 "instances of such a class");
1587 goto fail;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001588 }
1589
1590 Py_CLEAR(self->future);
1591
Benjamin Peterson996fc1f2016-11-14 00:15:44 -08001592 PyErr_Restore(type, val, tb);
1593
Serhiy Storchakabca49392017-09-03 08:10:14 +03001594 return NULL;
Benjamin Peterson996fc1f2016-11-14 00:15:44 -08001595
1596 fail:
1597 Py_DECREF(type);
1598 Py_XDECREF(val);
1599 Py_XDECREF(tb);
1600 return NULL;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001601}
1602
1603static PyObject *
1604FutureIter_close(futureiterobject *self, PyObject *arg)
1605{
1606 Py_CLEAR(self->future);
1607 Py_RETURN_NONE;
1608}
1609
1610static int
1611FutureIter_traverse(futureiterobject *it, visitproc visit, void *arg)
1612{
1613 Py_VISIT(it->future);
1614 return 0;
1615}
1616
1617static PyMethodDef FutureIter_methods[] = {
1618 {"send", (PyCFunction)FutureIter_send, METH_O, NULL},
1619 {"throw", (PyCFunction)FutureIter_throw, METH_VARARGS, NULL},
1620 {"close", (PyCFunction)FutureIter_close, METH_NOARGS, NULL},
1621 {NULL, NULL} /* Sentinel */
1622};
1623
1624static PyTypeObject FutureIterType = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02001625 PyVarObject_HEAD_INIT(NULL, 0)
INADA Naoki9f2ce252016-10-15 15:39:19 +09001626 "_asyncio.FutureIter",
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001627 .tp_basicsize = sizeof(futureiterobject),
1628 .tp_itemsize = 0,
1629 .tp_dealloc = (destructor)FutureIter_dealloc,
1630 .tp_getattro = PyObject_GenericGetAttr,
1631 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
1632 .tp_traverse = (traverseproc)FutureIter_traverse,
1633 .tp_iter = PyObject_SelfIter,
1634 .tp_iternext = (iternextfunc)FutureIter_iternext,
1635 .tp_methods = FutureIter_methods,
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001636};
1637
1638static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001639future_new_iter(PyObject *fut)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001640{
1641 futureiterobject *it;
1642
1643 if (!PyObject_TypeCheck(fut, &FutureType)) {
1644 PyErr_BadInternalCall();
1645 return NULL;
1646 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001647
1648 ENSURE_FUTURE_ALIVE(fut)
1649
1650 if (fi_freelist_len) {
1651 fi_freelist_len--;
1652 it = fi_freelist;
1653 fi_freelist = (futureiterobject*) it->future;
1654 it->future = NULL;
1655 _Py_NewReference((PyObject*) it);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001656 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001657 else {
1658 it = PyObject_GC_New(futureiterobject, &FutureIterType);
1659 if (it == NULL) {
1660 return NULL;
1661 }
1662 }
1663
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001664 Py_INCREF(fut);
1665 it->future = (FutureObj*)fut;
INADA Naoki1be427b2016-10-11 02:12:34 +09001666 PyObject_GC_Track(it);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001667 return (PyObject*)it;
1668}
1669
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001670
1671/*********************** Task **************************/
1672
1673
1674/*[clinic input]
1675class _asyncio.Task "TaskObj *" "&Task_Type"
1676[clinic start generated code]*/
1677/*[clinic end generated code: output=da39a3ee5e6b4b0d input=719dcef0fcc03b37]*/
1678
1679static int task_call_step_soon(TaskObj *, PyObject *);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001680static PyObject * task_wakeup(TaskObj *, PyObject *);
1681static PyObject * task_step(TaskObj *, PyObject *);
1682
1683/* ----- Task._step wrapper */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001684
INADA Naokic411a7d2016-10-18 11:48:14 +09001685static int
Serhiy Storchakabca49392017-09-03 08:10:14 +03001686TaskStepMethWrapper_clear(TaskStepMethWrapper *o)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001687{
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001688 Py_CLEAR(o->sw_task);
1689 Py_CLEAR(o->sw_arg);
1690 return 0;
1691}
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001692
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001693static void
Serhiy Storchakabca49392017-09-03 08:10:14 +03001694TaskStepMethWrapper_dealloc(TaskStepMethWrapper *o)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001695{
1696 PyObject_GC_UnTrack(o);
Serhiy Storchakabca49392017-09-03 08:10:14 +03001697 (void)TaskStepMethWrapper_clear(o);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001698 Py_TYPE(o)->tp_free(o);
1699}
1700
1701static PyObject *
Serhiy Storchakabca49392017-09-03 08:10:14 +03001702TaskStepMethWrapper_call(TaskStepMethWrapper *o,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001703 PyObject *args, PyObject *kwds)
1704{
Serhiy Storchakabca49392017-09-03 08:10:14 +03001705 if (kwds != NULL && PyDict_GET_SIZE(kwds) != 0) {
1706 PyErr_SetString(PyExc_TypeError, "function takes no keyword arguments");
1707 return NULL;
1708 }
1709 if (args != NULL && PyTuple_GET_SIZE(args) != 0) {
1710 PyErr_SetString(PyExc_TypeError, "function takes no positional arguments");
1711 return NULL;
1712 }
Yury Selivanov22feeb82018-01-24 11:31:01 -05001713 return task_step(o->sw_task, o->sw_arg);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001714}
1715
1716static int
Serhiy Storchakabca49392017-09-03 08:10:14 +03001717TaskStepMethWrapper_traverse(TaskStepMethWrapper *o,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001718 visitproc visit, void *arg)
1719{
1720 Py_VISIT(o->sw_task);
1721 Py_VISIT(o->sw_arg);
1722 return 0;
1723}
1724
1725static PyObject *
Serhiy Storchakabca49392017-09-03 08:10:14 +03001726TaskStepMethWrapper_get___self__(TaskStepMethWrapper *o)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001727{
1728 if (o->sw_task) {
1729 Py_INCREF(o->sw_task);
1730 return (PyObject*)o->sw_task;
1731 }
1732 Py_RETURN_NONE;
1733}
1734
Serhiy Storchakabca49392017-09-03 08:10:14 +03001735static PyGetSetDef TaskStepMethWrapper_getsetlist[] = {
1736 {"__self__", (getter)TaskStepMethWrapper_get___self__, NULL, NULL},
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001737 {NULL} /* Sentinel */
1738};
1739
Miss Islington (bot)60214dd2018-07-05 22:58:27 -07001740static PyTypeObject TaskStepMethWrapper_Type = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02001741 PyVarObject_HEAD_INIT(NULL, 0)
Serhiy Storchakabca49392017-09-03 08:10:14 +03001742 "TaskStepMethWrapper",
1743 .tp_basicsize = sizeof(TaskStepMethWrapper),
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001744 .tp_itemsize = 0,
Serhiy Storchakabca49392017-09-03 08:10:14 +03001745 .tp_getset = TaskStepMethWrapper_getsetlist,
1746 .tp_dealloc = (destructor)TaskStepMethWrapper_dealloc,
1747 .tp_call = (ternaryfunc)TaskStepMethWrapper_call,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001748 .tp_getattro = PyObject_GenericGetAttr,
1749 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
Serhiy Storchakabca49392017-09-03 08:10:14 +03001750 .tp_traverse = (traverseproc)TaskStepMethWrapper_traverse,
1751 .tp_clear = (inquiry)TaskStepMethWrapper_clear,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001752};
1753
1754static PyObject *
Serhiy Storchakabca49392017-09-03 08:10:14 +03001755TaskStepMethWrapper_new(TaskObj *task, PyObject *arg)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001756{
Serhiy Storchakabca49392017-09-03 08:10:14 +03001757 TaskStepMethWrapper *o;
1758 o = PyObject_GC_New(TaskStepMethWrapper, &TaskStepMethWrapper_Type);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001759 if (o == NULL) {
1760 return NULL;
1761 }
1762
1763 Py_INCREF(task);
1764 o->sw_task = task;
1765
1766 Py_XINCREF(arg);
1767 o->sw_arg = arg;
1768
1769 PyObject_GC_Track(o);
1770 return (PyObject*) o;
1771}
1772
1773/* ----- Task._wakeup wrapper */
1774
1775static PyObject *
1776TaskWakeupMethWrapper_call(TaskWakeupMethWrapper *o,
1777 PyObject *args, PyObject *kwds)
1778{
1779 PyObject *fut;
1780
Serhiy Storchakabca49392017-09-03 08:10:14 +03001781 if (kwds != NULL && PyDict_GET_SIZE(kwds) != 0) {
1782 PyErr_SetString(PyExc_TypeError, "function takes no keyword arguments");
1783 return NULL;
1784 }
1785 if (!PyArg_ParseTuple(args, "O", &fut)) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001786 return NULL;
1787 }
1788
Yury Selivanov22feeb82018-01-24 11:31:01 -05001789 return task_wakeup(o->ww_task, fut);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001790}
1791
1792static int
1793TaskWakeupMethWrapper_clear(TaskWakeupMethWrapper *o)
1794{
1795 Py_CLEAR(o->ww_task);
1796 return 0;
1797}
1798
1799static int
1800TaskWakeupMethWrapper_traverse(TaskWakeupMethWrapper *o,
1801 visitproc visit, void *arg)
1802{
1803 Py_VISIT(o->ww_task);
1804 return 0;
1805}
1806
1807static void
1808TaskWakeupMethWrapper_dealloc(TaskWakeupMethWrapper *o)
1809{
1810 PyObject_GC_UnTrack(o);
1811 (void)TaskWakeupMethWrapper_clear(o);
1812 Py_TYPE(o)->tp_free(o);
1813}
1814
Miss Islington (bot)60214dd2018-07-05 22:58:27 -07001815static PyTypeObject TaskWakeupMethWrapper_Type = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02001816 PyVarObject_HEAD_INIT(NULL, 0)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001817 "TaskWakeupMethWrapper",
1818 .tp_basicsize = sizeof(TaskWakeupMethWrapper),
1819 .tp_itemsize = 0,
1820 .tp_dealloc = (destructor)TaskWakeupMethWrapper_dealloc,
1821 .tp_call = (ternaryfunc)TaskWakeupMethWrapper_call,
1822 .tp_getattro = PyObject_GenericGetAttr,
1823 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
1824 .tp_traverse = (traverseproc)TaskWakeupMethWrapper_traverse,
1825 .tp_clear = (inquiry)TaskWakeupMethWrapper_clear,
1826};
1827
1828static PyObject *
1829TaskWakeupMethWrapper_new(TaskObj *task)
1830{
1831 TaskWakeupMethWrapper *o;
1832 o = PyObject_GC_New(TaskWakeupMethWrapper, &TaskWakeupMethWrapper_Type);
1833 if (o == NULL) {
1834 return NULL;
1835 }
1836
1837 Py_INCREF(task);
1838 o->ww_task = task;
1839
1840 PyObject_GC_Track(o);
1841 return (PyObject*) o;
1842}
1843
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001844/* ----- Task introspection helpers */
1845
1846static int
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001847register_task(PyObject *task)
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001848{
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001849 _Py_IDENTIFIER(add);
1850
1851 PyObject *res = _PyObject_CallMethodIdObjArgs(
1852 all_tasks, &PyId_add, task, NULL);
1853 if (res == NULL) {
1854 return -1;
1855 }
1856 Py_DECREF(res);
1857 return 0;
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001858}
1859
1860
1861static int
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001862unregister_task(PyObject *task)
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001863{
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001864 _Py_IDENTIFIER(discard);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001865
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001866 PyObject *res = _PyObject_CallMethodIdObjArgs(
1867 all_tasks, &PyId_discard, task, NULL);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001868 if (res == NULL) {
1869 return -1;
1870 }
1871 Py_DECREF(res);
1872 return 0;
1873}
1874
1875
1876static int
1877enter_task(PyObject *loop, PyObject *task)
1878{
1879 PyObject *item;
1880 Py_hash_t hash;
1881 hash = PyObject_Hash(loop);
1882 if (hash == -1) {
1883 return -1;
1884 }
1885 item = _PyDict_GetItem_KnownHash(current_tasks, loop, hash);
1886 if (item != NULL) {
Miss Islington (bot)52d17412018-05-20 07:34:28 -07001887 Py_INCREF(item);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001888 PyErr_Format(
1889 PyExc_RuntimeError,
1890 "Cannot enter into task %R while another " \
1891 "task %R is being executed.",
1892 task, item, NULL);
Miss Islington (bot)52d17412018-05-20 07:34:28 -07001893 Py_DECREF(item);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001894 return -1;
1895 }
Miss Islington (bot)52d17412018-05-20 07:34:28 -07001896 if (PyErr_Occurred()) {
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001897 return -1;
1898 }
Miss Islington (bot)52d17412018-05-20 07:34:28 -07001899 return _PyDict_SetItem_KnownHash(current_tasks, loop, task, hash);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001900}
1901
1902
1903static int
1904leave_task(PyObject *loop, PyObject *task)
1905/*[clinic end generated code: output=0ebf6db4b858fb41 input=51296a46313d1ad8]*/
1906{
1907 PyObject *item;
1908 Py_hash_t hash;
1909 hash = PyObject_Hash(loop);
1910 if (hash == -1) {
1911 return -1;
1912 }
1913 item = _PyDict_GetItem_KnownHash(current_tasks, loop, hash);
1914 if (item != task) {
1915 if (item == NULL) {
1916 /* Not entered, replace with None */
1917 item = Py_None;
1918 }
1919 PyErr_Format(
1920 PyExc_RuntimeError,
1921 "Leaving task %R does not match the current task %R.",
1922 task, item, NULL);
1923 return -1;
1924 }
1925 return _PyDict_DelItem_KnownHash(current_tasks, loop, hash);
1926}
1927
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001928/* ----- Task */
1929
1930/*[clinic input]
1931_asyncio.Task.__init__
1932
Serhiy Storchakabca49392017-09-03 08:10:14 +03001933 coro: object
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001934 *
Serhiy Storchakabca49392017-09-03 08:10:14 +03001935 loop: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001936
1937A coroutine wrapped in a Future.
1938[clinic start generated code]*/
1939
1940static int
1941_asyncio_Task___init___impl(TaskObj *self, PyObject *coro, PyObject *loop)
Serhiy Storchakabca49392017-09-03 08:10:14 +03001942/*[clinic end generated code: output=9f24774c2287fc2f input=8d132974b049593e]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001943{
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001944 if (future_init((FutureObj*)self, loop)) {
INADA Naokic411a7d2016-10-18 11:48:14 +09001945 return -1;
1946 }
INADA Naokic411a7d2016-10-18 11:48:14 +09001947
Yury Selivanova9d7e552017-12-19 07:18:45 -05001948 int is_coro = is_coroutine(coro);
1949 if (is_coro == -1) {
1950 return -1;
1951 }
1952 if (is_coro == 0) {
1953 self->task_log_destroy_pending = 0;
1954 PyErr_Format(PyExc_TypeError,
1955 "a coroutine was expected, got %R",
1956 coro, NULL);
1957 return -1;
Andrew Svetlovf74ef452017-12-15 07:04:38 +02001958 }
1959
Miss Islington (bot)ef20abe2018-02-13 03:32:18 -08001960 Py_XSETREF(self->task_context, PyContext_CopyCurrent());
Yury Selivanovf23746a2018-01-22 19:11:18 -05001961 if (self->task_context == NULL) {
1962 return -1;
1963 }
1964
Miss Islington (bot)ef20abe2018-02-13 03:32:18 -08001965 Py_CLEAR(self->task_fut_waiter);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001966 self->task_must_cancel = 0;
1967 self->task_log_destroy_pending = 1;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001968 Py_INCREF(coro);
Miss Islington (bot)ef20abe2018-02-13 03:32:18 -08001969 Py_XSETREF(self->task_coro, coro);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001970
1971 if (task_call_step_soon(self, NULL)) {
1972 return -1;
INADA Naokic411a7d2016-10-18 11:48:14 +09001973 }
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001974 return register_task((PyObject*)self);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001975}
1976
1977static int
1978TaskObj_clear(TaskObj *task)
1979{
1980 (void)FutureObj_clear((FutureObj*) task);
Yury Selivanovf23746a2018-01-22 19:11:18 -05001981 Py_CLEAR(task->task_context);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001982 Py_CLEAR(task->task_coro);
1983 Py_CLEAR(task->task_fut_waiter);
1984 return 0;
1985}
1986
1987static int
1988TaskObj_traverse(TaskObj *task, visitproc visit, void *arg)
1989{
Yury Selivanovf23746a2018-01-22 19:11:18 -05001990 Py_VISIT(task->task_context);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001991 Py_VISIT(task->task_coro);
1992 Py_VISIT(task->task_fut_waiter);
1993 (void)FutureObj_traverse((FutureObj*) task, visit, arg);
1994 return 0;
1995}
1996
1997static PyObject *
1998TaskObj_get_log_destroy_pending(TaskObj *task)
1999{
2000 if (task->task_log_destroy_pending) {
2001 Py_RETURN_TRUE;
2002 }
2003 else {
2004 Py_RETURN_FALSE;
2005 }
2006}
2007
2008static int
2009TaskObj_set_log_destroy_pending(TaskObj *task, PyObject *val)
2010{
2011 int is_true = PyObject_IsTrue(val);
2012 if (is_true < 0) {
2013 return -1;
2014 }
2015 task->task_log_destroy_pending = is_true;
2016 return 0;
2017}
2018
2019static PyObject *
2020TaskObj_get_must_cancel(TaskObj *task)
2021{
2022 if (task->task_must_cancel) {
2023 Py_RETURN_TRUE;
2024 }
2025 else {
2026 Py_RETURN_FALSE;
2027 }
2028}
2029
2030static PyObject *
2031TaskObj_get_coro(TaskObj *task)
2032{
2033 if (task->task_coro) {
2034 Py_INCREF(task->task_coro);
2035 return task->task_coro;
2036 }
2037
2038 Py_RETURN_NONE;
2039}
2040
2041static PyObject *
2042TaskObj_get_fut_waiter(TaskObj *task)
2043{
2044 if (task->task_fut_waiter) {
2045 Py_INCREF(task->task_fut_waiter);
2046 return task->task_fut_waiter;
2047 }
2048
2049 Py_RETURN_NONE;
2050}
2051
2052/*[clinic input]
2053@classmethod
2054_asyncio.Task.current_task
2055
Serhiy Storchakabca49392017-09-03 08:10:14 +03002056 loop: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002057
2058Return the currently running task in an event loop or None.
2059
2060By default the current task for the current event loop is returned.
2061
2062None is returned when called not in the context of a Task.
2063[clinic start generated code]*/
2064
2065static PyObject *
2066_asyncio_Task_current_task_impl(PyTypeObject *type, PyObject *loop)
Serhiy Storchakabca49392017-09-03 08:10:14 +03002067/*[clinic end generated code: output=99fbe7332c516e03 input=cd14770c5b79c7eb]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002068{
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002069 PyObject *ret;
2070 PyObject *current_task_func;
2071
2072 if (PyErr_WarnEx(PyExc_PendingDeprecationWarning,
2073 "Task.current_task() is deprecated, " \
2074 "use asyncio.current_task() instead",
2075 1) < 0) {
2076 return NULL;
2077 }
2078
2079 current_task_func = _PyObject_GetAttrId(asyncio_mod, &PyId_current_task);
2080 if (current_task_func == NULL) {
2081 return NULL;
2082 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002083
Yury Selivanov8d26aa92017-03-02 22:16:33 -05002084 if (loop == Py_None) {
Yury Selivanova70232f2017-12-13 14:49:42 -05002085 loop = get_event_loop();
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002086 if (loop == NULL) {
Miss Islington (bot)52d17412018-05-20 07:34:28 -07002087 Py_DECREF(current_task_func);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002088 return NULL;
2089 }
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002090 ret = PyObject_CallFunctionObjArgs(current_task_func, loop, NULL);
2091 Py_DECREF(current_task_func);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002092 Py_DECREF(loop);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002093 return ret;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002094 }
2095 else {
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002096 ret = PyObject_CallFunctionObjArgs(current_task_func, loop, NULL);
2097 Py_DECREF(current_task_func);
2098 return ret;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002099 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002100}
2101
2102/*[clinic input]
2103@classmethod
2104_asyncio.Task.all_tasks
2105
Serhiy Storchakabca49392017-09-03 08:10:14 +03002106 loop: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002107
2108Return a set of all tasks for an event loop.
2109
2110By default all tasks for the current event loop are returned.
2111[clinic start generated code]*/
2112
2113static PyObject *
2114_asyncio_Task_all_tasks_impl(PyTypeObject *type, PyObject *loop)
Serhiy Storchakabca49392017-09-03 08:10:14 +03002115/*[clinic end generated code: output=11f9b20749ccca5d input=497f80bc9ce726b5]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002116{
2117 PyObject *res;
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002118 PyObject *all_tasks_func;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002119
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002120 if (PyErr_WarnEx(PyExc_PendingDeprecationWarning,
2121 "Task.all_tasks() is deprecated, " \
2122 "use asyncio.all_tasks() instead",
2123 1) < 0) {
2124 return NULL;
2125 }
2126
Miss Islington (bot)ddc613f2018-05-28 17:16:43 -07002127 all_tasks_func = _PyObject_GetAttrId(asyncio_mod, &PyId__all_tasks_compat);
Miss Islington (bot)52d17412018-05-20 07:34:28 -07002128 if (all_tasks_func == NULL) {
2129 return NULL;
2130 }
2131
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002132 res = PyObject_CallFunctionObjArgs(all_tasks_func, loop, NULL);
2133 Py_DECREF(all_tasks_func);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002134 return res;
2135}
2136
2137/*[clinic input]
2138_asyncio.Task._repr_info
2139[clinic start generated code]*/
2140
2141static PyObject *
2142_asyncio_Task__repr_info_impl(TaskObj *self)
2143/*[clinic end generated code: output=6a490eb66d5ba34b input=3c6d051ed3ddec8b]*/
2144{
Victor Stinnerde4ae3d2016-12-04 22:59:09 +01002145 return PyObject_CallFunctionObjArgs(
2146 asyncio_task_repr_info_func, self, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002147}
2148
2149/*[clinic input]
2150_asyncio.Task.cancel
2151
2152Request that this task cancel itself.
2153
2154This arranges for a CancelledError to be thrown into the
2155wrapped coroutine on the next cycle through the event loop.
2156The coroutine then has a chance to clean up or even deny
2157the request using try/except/finally.
2158
2159Unlike Future.cancel, this does not guarantee that the
2160task will be cancelled: the exception might be caught and
2161acted upon, delaying cancellation of the task or preventing
2162cancellation completely. The task may also return a value or
2163raise a different exception.
2164
2165Immediately after this method is called, Task.cancelled() will
2166not return True (unless the task was already cancelled). A
2167task will be marked as cancelled when the wrapped coroutine
2168terminates with a CancelledError exception (even if cancel()
2169was not called).
2170[clinic start generated code]*/
2171
2172static PyObject *
2173_asyncio_Task_cancel_impl(TaskObj *self)
2174/*[clinic end generated code: output=6bfc0479da9d5757 input=13f9bf496695cb52]*/
2175{
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +00002176 self->task_log_tb = 0;
2177
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002178 if (self->task_state != STATE_PENDING) {
2179 Py_RETURN_FALSE;
2180 }
2181
2182 if (self->task_fut_waiter) {
2183 PyObject *res;
2184 int is_true;
2185
2186 res = _PyObject_CallMethodId(
2187 self->task_fut_waiter, &PyId_cancel, NULL);
2188 if (res == NULL) {
2189 return NULL;
2190 }
2191
2192 is_true = PyObject_IsTrue(res);
2193 Py_DECREF(res);
2194 if (is_true < 0) {
2195 return NULL;
2196 }
2197
2198 if (is_true) {
2199 Py_RETURN_TRUE;
2200 }
2201 }
2202
2203 self->task_must_cancel = 1;
2204 Py_RETURN_TRUE;
2205}
2206
2207/*[clinic input]
2208_asyncio.Task.get_stack
2209
2210 *
Serhiy Storchakabca49392017-09-03 08:10:14 +03002211 limit: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002212
2213Return the list of stack frames for this task's coroutine.
2214
2215If the coroutine is not done, this returns the stack where it is
2216suspended. If the coroutine has completed successfully or was
2217cancelled, this returns an empty list. If the coroutine was
2218terminated by an exception, this returns the list of traceback
2219frames.
2220
2221The frames are always ordered from oldest to newest.
2222
2223The optional limit gives the maximum number of frames to
2224return; by default all available frames are returned. Its
2225meaning differs depending on whether a stack or a traceback is
2226returned: the newest frames of a stack are returned, but the
2227oldest frames of a traceback are returned. (This matches the
2228behavior of the traceback module.)
2229
2230For reasons beyond our control, only one stack frame is
2231returned for a suspended coroutine.
2232[clinic start generated code]*/
2233
2234static PyObject *
2235_asyncio_Task_get_stack_impl(TaskObj *self, PyObject *limit)
Serhiy Storchakabca49392017-09-03 08:10:14 +03002236/*[clinic end generated code: output=c9aeeeebd1e18118 input=05b323d42b809b90]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002237{
2238 return PyObject_CallFunctionObjArgs(
2239 asyncio_task_get_stack_func, self, limit, NULL);
2240}
2241
2242/*[clinic input]
2243_asyncio.Task.print_stack
2244
2245 *
Serhiy Storchakabca49392017-09-03 08:10:14 +03002246 limit: object = None
2247 file: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002248
2249Print the stack or traceback for this task's coroutine.
2250
2251This produces output similar to that of the traceback module,
2252for the frames retrieved by get_stack(). The limit argument
2253is passed to get_stack(). The file argument is an I/O stream
2254to which the output is written; by default output is written
2255to sys.stderr.
2256[clinic start generated code]*/
2257
2258static PyObject *
2259_asyncio_Task_print_stack_impl(TaskObj *self, PyObject *limit,
2260 PyObject *file)
Serhiy Storchakabca49392017-09-03 08:10:14 +03002261/*[clinic end generated code: output=7339e10314cd3f4d input=1a0352913b7fcd92]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002262{
2263 return PyObject_CallFunctionObjArgs(
2264 asyncio_task_print_stack_func, self, limit, file, NULL);
2265}
2266
2267/*[clinic input]
Yury Selivanov0cf16f92017-12-25 10:48:15 -05002268_asyncio.Task.set_result
2269
2270 result: object
2271 /
2272[clinic start generated code]*/
2273
2274static PyObject *
2275_asyncio_Task_set_result(TaskObj *self, PyObject *result)
2276/*[clinic end generated code: output=1dcae308bfcba318 input=9d1a00c07be41bab]*/
2277{
2278 PyErr_SetString(PyExc_RuntimeError,
2279 "Task does not support set_result operation");
2280 return NULL;
2281}
2282
2283/*[clinic input]
2284_asyncio.Task.set_exception
2285
2286 exception: object
2287 /
2288[clinic start generated code]*/
2289
2290static PyObject *
2291_asyncio_Task_set_exception(TaskObj *self, PyObject *exception)
2292/*[clinic end generated code: output=bc377fc28067303d input=9a8f65c83dcf893a]*/
2293{
2294 PyErr_SetString(PyExc_RuntimeError,
Andrew Svetlovfc359322017-12-30 15:40:27 +02002295 "Task does not support set_exception operation");
Yury Selivanov0cf16f92017-12-25 10:48:15 -05002296 return NULL;
2297}
2298
2299
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002300static void
2301TaskObj_finalize(TaskObj *task)
2302{
2303 _Py_IDENTIFIER(call_exception_handler);
2304 _Py_IDENTIFIER(task);
2305 _Py_IDENTIFIER(message);
2306 _Py_IDENTIFIER(source_traceback);
2307
Serhiy Storchakabca49392017-09-03 08:10:14 +03002308 PyObject *context;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002309 PyObject *message = NULL;
Serhiy Storchakabca49392017-09-03 08:10:14 +03002310 PyObject *func;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002311 PyObject *error_type, *error_value, *error_traceback;
2312
2313 if (task->task_state != STATE_PENDING || !task->task_log_destroy_pending) {
2314 goto done;
2315 }
2316
2317 /* Save the current exception, if any. */
2318 PyErr_Fetch(&error_type, &error_value, &error_traceback);
2319
2320 context = PyDict_New();
2321 if (context == NULL) {
2322 goto finally;
2323 }
2324
2325 message = PyUnicode_FromString("Task was destroyed but it is pending!");
2326 if (message == NULL) {
2327 goto finally;
2328 }
2329
2330 if (_PyDict_SetItemId(context, &PyId_message, message) < 0 ||
2331 _PyDict_SetItemId(context, &PyId_task, (PyObject*)task) < 0)
2332 {
2333 goto finally;
2334 }
2335
2336 if (task->task_source_tb != NULL) {
2337 if (_PyDict_SetItemId(context, &PyId_source_traceback,
2338 task->task_source_tb) < 0)
2339 {
2340 goto finally;
2341 }
2342 }
2343
2344 func = _PyObject_GetAttrId(task->task_loop, &PyId_call_exception_handler);
2345 if (func != NULL) {
Serhiy Storchakabca49392017-09-03 08:10:14 +03002346 PyObject *res = PyObject_CallFunctionObjArgs(func, context, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002347 if (res == NULL) {
2348 PyErr_WriteUnraisable(func);
2349 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03002350 else {
2351 Py_DECREF(res);
2352 }
2353 Py_DECREF(func);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002354 }
2355
2356finally:
Serhiy Storchakabca49392017-09-03 08:10:14 +03002357 Py_XDECREF(context);
2358 Py_XDECREF(message);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002359
2360 /* Restore the saved exception. */
2361 PyErr_Restore(error_type, error_value, error_traceback);
2362
2363done:
2364 FutureObj_finalize((FutureObj*)task);
2365}
2366
2367static void TaskObj_dealloc(PyObject *); /* Needs Task_CheckExact */
2368
2369static PyMethodDef TaskType_methods[] = {
2370 _ASYNCIO_FUTURE_RESULT_METHODDEF
2371 _ASYNCIO_FUTURE_EXCEPTION_METHODDEF
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002372 _ASYNCIO_FUTURE_ADD_DONE_CALLBACK_METHODDEF
2373 _ASYNCIO_FUTURE_REMOVE_DONE_CALLBACK_METHODDEF
2374 _ASYNCIO_FUTURE_CANCELLED_METHODDEF
2375 _ASYNCIO_FUTURE_DONE_METHODDEF
Yury Selivanov0cf16f92017-12-25 10:48:15 -05002376 _ASYNCIO_TASK_SET_RESULT_METHODDEF
2377 _ASYNCIO_TASK_SET_EXCEPTION_METHODDEF
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002378 _ASYNCIO_TASK_CURRENT_TASK_METHODDEF
2379 _ASYNCIO_TASK_ALL_TASKS_METHODDEF
2380 _ASYNCIO_TASK_CANCEL_METHODDEF
2381 _ASYNCIO_TASK_GET_STACK_METHODDEF
2382 _ASYNCIO_TASK_PRINT_STACK_METHODDEF
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002383 _ASYNCIO_TASK__REPR_INFO_METHODDEF
2384 {NULL, NULL} /* Sentinel */
2385};
2386
2387static PyGetSetDef TaskType_getsetlist[] = {
2388 FUTURE_COMMON_GETSETLIST
2389 {"_log_destroy_pending", (getter)TaskObj_get_log_destroy_pending,
2390 (setter)TaskObj_set_log_destroy_pending, NULL},
2391 {"_must_cancel", (getter)TaskObj_get_must_cancel, NULL, NULL},
2392 {"_coro", (getter)TaskObj_get_coro, NULL, NULL},
2393 {"_fut_waiter", (getter)TaskObj_get_fut_waiter, NULL, NULL},
2394 {NULL} /* Sentinel */
2395};
2396
2397static PyTypeObject TaskType = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02002398 PyVarObject_HEAD_INIT(NULL, 0)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002399 "_asyncio.Task",
2400 sizeof(TaskObj), /* tp_basicsize */
2401 .tp_base = &FutureType,
2402 .tp_dealloc = TaskObj_dealloc,
2403 .tp_as_async = &FutureType_as_async,
2404 .tp_repr = (reprfunc)FutureObj_repr,
2405 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE
2406 | Py_TPFLAGS_HAVE_FINALIZE,
2407 .tp_doc = _asyncio_Task___init____doc__,
2408 .tp_traverse = (traverseproc)TaskObj_traverse,
2409 .tp_clear = (inquiry)TaskObj_clear,
2410 .tp_weaklistoffset = offsetof(TaskObj, task_weakreflist),
2411 .tp_iter = (getiterfunc)future_new_iter,
2412 .tp_methods = TaskType_methods,
2413 .tp_getset = TaskType_getsetlist,
2414 .tp_dictoffset = offsetof(TaskObj, dict),
2415 .tp_init = (initproc)_asyncio_Task___init__,
2416 .tp_new = PyType_GenericNew,
2417 .tp_finalize = (destructor)TaskObj_finalize,
2418};
2419
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002420static void
2421TaskObj_dealloc(PyObject *self)
2422{
2423 TaskObj *task = (TaskObj *)self;
2424
2425 if (Task_CheckExact(self)) {
2426 /* When fut is subclass of Task, finalizer is called from
2427 * subtype_dealloc.
2428 */
2429 if (PyObject_CallFinalizerFromDealloc(self) < 0) {
2430 // resurrected.
2431 return;
2432 }
2433 }
2434
Alexander Mohrde34cbe2017-08-01 23:31:07 -07002435 PyObject_GC_UnTrack(self);
2436
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002437 if (task->task_weakreflist != NULL) {
2438 PyObject_ClearWeakRefs(self);
2439 }
2440
2441 (void)TaskObj_clear(task);
2442 Py_TYPE(task)->tp_free(task);
2443}
2444
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002445static int
2446task_call_step_soon(TaskObj *task, PyObject *arg)
2447{
Serhiy Storchakabca49392017-09-03 08:10:14 +03002448 PyObject *cb = TaskStepMethWrapper_new(task, arg);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002449 if (cb == NULL) {
2450 return -1;
2451 }
2452
Yury Selivanovf23746a2018-01-22 19:11:18 -05002453 int ret = call_soon(task->task_loop, cb, NULL, task->task_context);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002454 Py_DECREF(cb);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05002455 return ret;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002456}
2457
2458static PyObject *
2459task_set_error_soon(TaskObj *task, PyObject *et, const char *format, ...)
2460{
2461 PyObject* msg;
2462
2463 va_list vargs;
2464#ifdef HAVE_STDARG_PROTOTYPES
2465 va_start(vargs, format);
2466#else
2467 va_start(vargs);
2468#endif
2469 msg = PyUnicode_FromFormatV(format, vargs);
2470 va_end(vargs);
2471
2472 if (msg == NULL) {
2473 return NULL;
2474 }
2475
Victor Stinnerde4ae3d2016-12-04 22:59:09 +01002476 PyObject *e = PyObject_CallFunctionObjArgs(et, msg, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002477 Py_DECREF(msg);
2478 if (e == NULL) {
2479 return NULL;
2480 }
2481
2482 if (task_call_step_soon(task, e) == -1) {
2483 Py_DECREF(e);
2484 return NULL;
2485 }
2486
2487 Py_DECREF(e);
2488 Py_RETURN_NONE;
2489}
2490
2491static PyObject *
2492task_step_impl(TaskObj *task, PyObject *exc)
2493{
2494 int res;
2495 int clear_exc = 0;
2496 PyObject *result = NULL;
Serhiy Storchakabca49392017-09-03 08:10:14 +03002497 PyObject *coro;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002498 PyObject *o;
2499
2500 if (task->task_state != STATE_PENDING) {
Yury Selivanov0cf16f92017-12-25 10:48:15 -05002501 PyErr_Format(asyncio_InvalidStateError,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002502 "_step(): already done: %R %R",
2503 task,
2504 exc ? exc : Py_None);
INADA Naokic411a7d2016-10-18 11:48:14 +09002505 goto fail;
2506 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09002507
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002508 if (task->task_must_cancel) {
2509 assert(exc != Py_None);
2510
2511 if (exc) {
2512 /* Check if exc is a CancelledError */
2513 res = PyObject_IsInstance(exc, asyncio_CancelledError);
2514 if (res == -1) {
2515 /* An error occurred, abort */
2516 goto fail;
2517 }
2518 if (res == 0) {
2519 /* exc is not CancelledError; reset it to NULL */
2520 exc = NULL;
2521 }
2522 }
2523
2524 if (!exc) {
2525 /* exc was not a CancelledError */
Victor Stinnerf17c3de2016-12-06 18:46:19 +01002526 exc = _PyObject_CallNoArg(asyncio_CancelledError);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002527 if (!exc) {
2528 goto fail;
2529 }
2530 clear_exc = 1;
2531 }
2532
2533 task->task_must_cancel = 0;
2534 }
2535
2536 Py_CLEAR(task->task_fut_waiter);
2537
Serhiy Storchakabca49392017-09-03 08:10:14 +03002538 coro = task->task_coro;
2539 if (coro == NULL) {
2540 PyErr_SetString(PyExc_RuntimeError, "uninitialized Task object");
2541 return NULL;
2542 }
2543
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002544 if (exc == NULL) {
2545 if (PyGen_CheckExact(coro) || PyCoro_CheckExact(coro)) {
2546 result = _PyGen_Send((PyGenObject*)coro, Py_None);
2547 }
2548 else {
Victor Stinnerb6ed57d2016-12-09 14:24:02 +01002549 result = _PyObject_CallMethodIdObjArgs(coro, &PyId_send,
2550 Py_None, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002551 }
2552 }
2553 else {
Victor Stinnerb6ed57d2016-12-09 14:24:02 +01002554 result = _PyObject_CallMethodIdObjArgs(coro, &PyId_throw,
2555 exc, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002556 if (clear_exc) {
2557 /* We created 'exc' during this call */
Serhiy Storchakabca49392017-09-03 08:10:14 +03002558 Py_DECREF(exc);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002559 }
2560 }
2561
2562 if (result == NULL) {
2563 PyObject *et, *ev, *tb;
2564
2565 if (_PyGen_FetchStopIterationValue(&o) == 0) {
2566 /* The error is StopIteration and that means that
2567 the underlying coroutine has resolved */
INADA Naoki991adca2017-05-11 21:18:38 +09002568 if (task->task_must_cancel) {
2569 // Task is cancelled right before coro stops.
2570 Py_DECREF(o);
2571 task->task_must_cancel = 0;
2572 et = asyncio_CancelledError;
2573 Py_INCREF(et);
2574 ev = NULL;
2575 tb = NULL;
2576 goto set_exception;
2577 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002578 PyObject *res = future_set_result((FutureObj*)task, o);
2579 Py_DECREF(o);
2580 if (res == NULL) {
2581 return NULL;
2582 }
2583 Py_DECREF(res);
2584 Py_RETURN_NONE;
2585 }
2586
2587 if (PyErr_ExceptionMatches(asyncio_CancelledError)) {
2588 /* CancelledError */
2589 PyErr_Clear();
2590 return future_cancel((FutureObj*)task);
2591 }
2592
2593 /* Some other exception; pop it and call Task.set_exception() */
2594 PyErr_Fetch(&et, &ev, &tb);
INADA Naoki991adca2017-05-11 21:18:38 +09002595
2596set_exception:
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002597 assert(et);
2598 if (!ev || !PyObject_TypeCheck(ev, (PyTypeObject *) et)) {
2599 PyErr_NormalizeException(&et, &ev, &tb);
2600 }
Yury Selivanovedfe8862016-12-01 11:37:47 -05002601 if (tb != NULL) {
2602 PyException_SetTraceback(ev, tb);
2603 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002604 o = future_set_exception((FutureObj*)task, ev);
2605 if (!o) {
2606 /* An exception in Task.set_exception() */
Serhiy Storchakabca49392017-09-03 08:10:14 +03002607 Py_DECREF(et);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002608 Py_XDECREF(tb);
2609 Py_XDECREF(ev);
2610 goto fail;
2611 }
2612 assert(o == Py_None);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002613 Py_DECREF(o);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002614
2615 if (!PyErr_GivenExceptionMatches(et, PyExc_Exception)) {
2616 /* We've got a BaseException; re-raise it */
2617 PyErr_Restore(et, ev, tb);
2618 goto fail;
2619 }
2620
Serhiy Storchakabca49392017-09-03 08:10:14 +03002621 Py_DECREF(et);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002622 Py_XDECREF(tb);
2623 Py_XDECREF(ev);
2624
2625 Py_RETURN_NONE;
2626 }
2627
2628 if (result == (PyObject*)task) {
2629 /* We have a task that wants to await on itself */
2630 goto self_await;
2631 }
2632
2633 /* Check if `result` is FutureObj or TaskObj (and not a subclass) */
2634 if (Future_CheckExact(result) || Task_CheckExact(result)) {
2635 PyObject *wrapper;
2636 PyObject *res;
2637 FutureObj *fut = (FutureObj*)result;
2638
2639 /* Check if `result` future is attached to a different loop */
2640 if (fut->fut_loop != task->task_loop) {
2641 goto different_loop;
2642 }
2643
2644 if (fut->fut_blocking) {
2645 fut->fut_blocking = 0;
2646
2647 /* result.add_done_callback(task._wakeup) */
2648 wrapper = TaskWakeupMethWrapper_new(task);
2649 if (wrapper == NULL) {
2650 goto fail;
2651 }
Yury Selivanovf23746a2018-01-22 19:11:18 -05002652 res = future_add_done_callback(
2653 (FutureObj*)result, wrapper, task->task_context);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002654 Py_DECREF(wrapper);
2655 if (res == NULL) {
2656 goto fail;
2657 }
2658 Py_DECREF(res);
2659
2660 /* task._fut_waiter = result */
2661 task->task_fut_waiter = result; /* no incref is necessary */
2662
2663 if (task->task_must_cancel) {
2664 PyObject *r;
Elvis Pranskevichusa67bd53d2018-10-03 11:49:00 -04002665 int is_true;
Serhiy Storchakad9212202018-10-05 21:58:15 +03002666 r = _PyObject_CallMethodId(result, &PyId_cancel, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002667 if (r == NULL) {
2668 return NULL;
2669 }
Elvis Pranskevichusa67bd53d2018-10-03 11:49:00 -04002670 is_true = PyObject_IsTrue(r);
2671 Py_DECREF(r);
2672 if (is_true < 0) {
2673 return NULL;
2674 }
2675 else if (is_true) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002676 task->task_must_cancel = 0;
2677 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002678 }
2679
2680 Py_RETURN_NONE;
2681 }
2682 else {
2683 goto yield_insteadof_yf;
2684 }
2685 }
2686
2687 /* Check if `result` is a Future-compatible object */
2688 o = PyObject_GetAttrString(result, "_asyncio_future_blocking");
2689 if (o == NULL) {
2690 if (PyErr_ExceptionMatches(PyExc_AttributeError)) {
2691 PyErr_Clear();
2692 }
2693 else {
2694 goto fail;
2695 }
2696 }
2697 else {
2698 if (o == Py_None) {
Serhiy Storchakabca49392017-09-03 08:10:14 +03002699 Py_DECREF(o);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002700 }
2701 else {
2702 /* `result` is a Future-compatible object */
2703 PyObject *wrapper;
2704 PyObject *res;
2705
2706 int blocking = PyObject_IsTrue(o);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002707 Py_DECREF(o);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002708 if (blocking < 0) {
2709 goto fail;
2710 }
2711
2712 /* Check if `result` future is attached to a different loop */
Yury Selivanovca9b36c2017-12-23 15:04:15 -05002713 PyObject *oloop = get_future_loop(result);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002714 if (oloop == NULL) {
2715 goto fail;
2716 }
2717 if (oloop != task->task_loop) {
2718 Py_DECREF(oloop);
2719 goto different_loop;
2720 }
2721 else {
2722 Py_DECREF(oloop);
2723 }
2724
2725 if (blocking) {
2726 /* result._asyncio_future_blocking = False */
2727 if (PyObject_SetAttrString(
2728 result, "_asyncio_future_blocking", Py_False) == -1) {
2729 goto fail;
2730 }
2731
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002732 wrapper = TaskWakeupMethWrapper_new(task);
2733 if (wrapper == NULL) {
2734 goto fail;
2735 }
Yury Selivanovf23746a2018-01-22 19:11:18 -05002736
2737 /* result.add_done_callback(task._wakeup) */
2738 PyObject *add_cb = _PyObject_GetAttrId(
2739 result, &PyId_add_done_callback);
2740 if (add_cb == NULL) {
Miss Islington (bot)52d17412018-05-20 07:34:28 -07002741 Py_DECREF(wrapper);
Yury Selivanovf23746a2018-01-22 19:11:18 -05002742 goto fail;
2743 }
2744 PyObject *stack[2];
2745 stack[0] = wrapper;
2746 stack[1] = (PyObject *)task->task_context;
2747 res = _PyObject_FastCallKeywords(
2748 add_cb, stack, 1, context_kwname);
2749 Py_DECREF(add_cb);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002750 Py_DECREF(wrapper);
2751 if (res == NULL) {
2752 goto fail;
2753 }
2754 Py_DECREF(res);
2755
2756 /* task._fut_waiter = result */
2757 task->task_fut_waiter = result; /* no incref is necessary */
2758
2759 if (task->task_must_cancel) {
2760 PyObject *r;
2761 int is_true;
2762 r = _PyObject_CallMethodId(result, &PyId_cancel, NULL);
2763 if (r == NULL) {
2764 return NULL;
2765 }
2766 is_true = PyObject_IsTrue(r);
2767 Py_DECREF(r);
2768 if (is_true < 0) {
2769 return NULL;
2770 }
2771 else if (is_true) {
2772 task->task_must_cancel = 0;
2773 }
2774 }
2775
2776 Py_RETURN_NONE;
2777 }
2778 else {
2779 goto yield_insteadof_yf;
2780 }
2781 }
2782 }
2783
2784 /* Check if `result` is None */
2785 if (result == Py_None) {
2786 /* Bare yield relinquishes control for one event loop iteration. */
2787 if (task_call_step_soon(task, NULL)) {
2788 goto fail;
2789 }
2790 return result;
2791 }
2792
2793 /* Check if `result` is a generator */
Victor Stinnerde4ae3d2016-12-04 22:59:09 +01002794 o = PyObject_CallFunctionObjArgs(inspect_isgenerator, result, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002795 if (o == NULL) {
2796 /* An exception in inspect.isgenerator */
2797 goto fail;
2798 }
2799 res = PyObject_IsTrue(o);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002800 Py_DECREF(o);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002801 if (res == -1) {
2802 /* An exception while checking if 'val' is True */
2803 goto fail;
2804 }
2805 if (res == 1) {
2806 /* `result` is a generator */
Miss Islington (bot)52d17412018-05-20 07:34:28 -07002807 o = task_set_error_soon(
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002808 task, PyExc_RuntimeError,
2809 "yield was used instead of yield from for "
Miss Islington (bot)52d17412018-05-20 07:34:28 -07002810 "generator in task %R with %R", task, result);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002811 Py_DECREF(result);
Miss Islington (bot)52d17412018-05-20 07:34:28 -07002812 return o;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002813 }
2814
2815 /* The `result` is none of the above */
Miss Islington (bot)52d17412018-05-20 07:34:28 -07002816 o = task_set_error_soon(
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002817 task, PyExc_RuntimeError, "Task got bad yield: %R", result);
Miss Islington (bot)52d17412018-05-20 07:34:28 -07002818 Py_DECREF(result);
2819 return o;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002820
2821self_await:
2822 o = task_set_error_soon(
2823 task, PyExc_RuntimeError,
2824 "Task cannot await on itself: %R", task);
2825 Py_DECREF(result);
2826 return o;
2827
2828yield_insteadof_yf:
2829 o = task_set_error_soon(
2830 task, PyExc_RuntimeError,
2831 "yield was used instead of yield from "
2832 "in task %R with %R",
2833 task, result);
2834 Py_DECREF(result);
2835 return o;
2836
2837different_loop:
2838 o = task_set_error_soon(
2839 task, PyExc_RuntimeError,
2840 "Task %R got Future %R attached to a different loop",
2841 task, result);
2842 Py_DECREF(result);
2843 return o;
2844
2845fail:
2846 Py_XDECREF(result);
2847 return NULL;
2848}
2849
2850static PyObject *
2851task_step(TaskObj *task, PyObject *exc)
2852{
2853 PyObject *res;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002854
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002855 if (enter_task(task->task_loop, (PyObject*)task) < 0) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002856 return NULL;
2857 }
2858
2859 res = task_step_impl(task, exc);
2860
2861 if (res == NULL) {
2862 PyObject *et, *ev, *tb;
2863 PyErr_Fetch(&et, &ev, &tb);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002864 leave_task(task->task_loop, (PyObject*)task);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002865 _PyErr_ChainExceptions(et, ev, tb);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002866 return NULL;
2867 }
2868 else {
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002869 if(leave_task(task->task_loop, (PyObject*)task) < 0) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002870 Py_DECREF(res);
2871 return NULL;
2872 }
2873 else {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002874 return res;
2875 }
2876 }
2877}
2878
2879static PyObject *
2880task_wakeup(TaskObj *task, PyObject *o)
2881{
Serhiy Storchakabca49392017-09-03 08:10:14 +03002882 PyObject *et, *ev, *tb;
2883 PyObject *result;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002884 assert(o);
2885
2886 if (Future_CheckExact(o) || Task_CheckExact(o)) {
2887 PyObject *fut_result = NULL;
2888 int res = future_get_result((FutureObj*)o, &fut_result);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002889
2890 switch(res) {
2891 case -1:
2892 assert(fut_result == NULL);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002893 break; /* exception raised */
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002894 case 0:
2895 Py_DECREF(fut_result);
Yury Selivanov22feeb82018-01-24 11:31:01 -05002896 return task_step(task, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002897 default:
2898 assert(res == 1);
Yury Selivanov22feeb82018-01-24 11:31:01 -05002899 result = task_step(task, fut_result);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002900 Py_DECREF(fut_result);
2901 return result;
2902 }
2903 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002904 else {
Serhiy Storchakabca49392017-09-03 08:10:14 +03002905 PyObject *fut_result = PyObject_CallMethod(o, "result", NULL);
2906 if (fut_result != NULL) {
2907 Py_DECREF(fut_result);
Yury Selivanov22feeb82018-01-24 11:31:01 -05002908 return task_step(task, NULL);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002909 }
2910 /* exception raised */
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002911 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03002912
2913 PyErr_Fetch(&et, &ev, &tb);
2914 if (!PyErr_GivenExceptionMatches(et, PyExc_Exception)) {
2915 /* We've got a BaseException; re-raise it */
2916 PyErr_Restore(et, ev, tb);
2917 return NULL;
2918 }
2919 if (!ev || !PyObject_TypeCheck(ev, (PyTypeObject *) et)) {
2920 PyErr_NormalizeException(&et, &ev, &tb);
2921 }
2922
Yury Selivanov22feeb82018-01-24 11:31:01 -05002923 result = task_step(task, ev);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002924
2925 Py_DECREF(et);
2926 Py_XDECREF(tb);
2927 Py_XDECREF(ev);
2928
2929 return result;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002930}
2931
2932
Yury Selivanova70232f2017-12-13 14:49:42 -05002933/*********************** Functions **************************/
2934
2935
2936/*[clinic input]
2937_asyncio._get_running_loop
2938
2939Return the running event loop or None.
2940
2941This is a low-level function intended to be used by event loops.
2942This function is thread-specific.
2943
2944[clinic start generated code]*/
2945
2946static PyObject *
2947_asyncio__get_running_loop_impl(PyObject *module)
2948/*[clinic end generated code: output=b4390af721411a0a input=0a21627e25a4bd43]*/
2949{
2950 PyObject *loop;
2951 if (get_running_loop(&loop)) {
2952 return NULL;
2953 }
2954 if (loop == NULL) {
2955 /* There's no currently running event loop */
2956 Py_RETURN_NONE;
2957 }
2958 return loop;
2959}
2960
2961/*[clinic input]
2962_asyncio._set_running_loop
2963 loop: 'O'
2964 /
2965
2966Set the running event loop.
2967
2968This is a low-level function intended to be used by event loops.
2969This function is thread-specific.
2970[clinic start generated code]*/
2971
2972static PyObject *
2973_asyncio__set_running_loop(PyObject *module, PyObject *loop)
2974/*[clinic end generated code: output=ae56bf7a28ca189a input=4c9720233d606604]*/
2975{
2976 if (set_running_loop(loop)) {
2977 return NULL;
2978 }
2979 Py_RETURN_NONE;
2980}
2981
2982/*[clinic input]
2983_asyncio.get_event_loop
2984
2985Return an asyncio event loop.
2986
2987When called from a coroutine or a callback (e.g. scheduled with
2988call_soon or similar API), this function will always return the
2989running event loop.
2990
2991If there is no running event loop set, the function will return
2992the result of `get_event_loop_policy().get_event_loop()` call.
2993[clinic start generated code]*/
2994
2995static PyObject *
2996_asyncio_get_event_loop_impl(PyObject *module)
2997/*[clinic end generated code: output=2a2d8b2f824c648b input=9364bf2916c8655d]*/
2998{
2999 return get_event_loop();
3000}
3001
3002/*[clinic input]
3003_asyncio.get_running_loop
3004
3005Return the running event loop. Raise a RuntimeError if there is none.
3006
3007This function is thread-specific.
3008[clinic start generated code]*/
3009
3010static PyObject *
3011_asyncio_get_running_loop_impl(PyObject *module)
3012/*[clinic end generated code: output=c247b5f9e529530e input=2a3bf02ba39f173d]*/
3013{
3014 PyObject *loop;
3015 if (get_running_loop(&loop)) {
3016 return NULL;
3017 }
3018 if (loop == NULL) {
3019 /* There's no currently running event loop */
3020 PyErr_SetString(
3021 PyExc_RuntimeError, "no running event loop");
3022 }
3023 return loop;
3024}
3025
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003026/*[clinic input]
3027_asyncio._register_task
3028
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003029 task: object
3030
3031Register a new task in asyncio as executed by loop.
3032
3033Returns None.
3034[clinic start generated code]*/
3035
3036static PyObject *
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003037_asyncio__register_task_impl(PyObject *module, PyObject *task)
3038/*[clinic end generated code: output=8672dadd69a7d4e2 input=21075aaea14dfbad]*/
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003039{
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003040 if (register_task(task) < 0) {
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003041 return NULL;
3042 }
3043 Py_RETURN_NONE;
3044}
3045
3046
3047/*[clinic input]
3048_asyncio._unregister_task
3049
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003050 task: object
3051
3052Unregister a task.
3053
3054Returns None.
3055[clinic start generated code]*/
3056
3057static PyObject *
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003058_asyncio__unregister_task_impl(PyObject *module, PyObject *task)
3059/*[clinic end generated code: output=6e5585706d568a46 input=28fb98c3975f7bdc]*/
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003060{
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003061 if (unregister_task(task) < 0) {
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003062 return NULL;
3063 }
3064 Py_RETURN_NONE;
3065}
3066
3067
3068/*[clinic input]
3069_asyncio._enter_task
3070
3071 loop: object
3072 task: object
3073
3074Enter into task execution or resume suspended task.
3075
3076Task belongs to loop.
3077
3078Returns None.
3079[clinic start generated code]*/
3080
3081static PyObject *
3082_asyncio__enter_task_impl(PyObject *module, PyObject *loop, PyObject *task)
3083/*[clinic end generated code: output=a22611c858035b73 input=de1b06dca70d8737]*/
3084{
3085 if (enter_task(loop, task) < 0) {
3086 return NULL;
3087 }
3088 Py_RETURN_NONE;
3089}
3090
3091
3092/*[clinic input]
3093_asyncio._leave_task
3094
3095 loop: object
3096 task: object
3097
3098Leave task execution or suspend a task.
3099
3100Task belongs to loop.
3101
3102Returns None.
3103[clinic start generated code]*/
3104
3105static PyObject *
3106_asyncio__leave_task_impl(PyObject *module, PyObject *loop, PyObject *task)
3107/*[clinic end generated code: output=0ebf6db4b858fb41 input=51296a46313d1ad8]*/
3108{
3109 if (leave_task(loop, task) < 0) {
3110 return NULL;
3111 }
3112 Py_RETURN_NONE;
3113}
3114
Yury Selivanova70232f2017-12-13 14:49:42 -05003115
Yury Selivanov9d411c12018-01-23 15:10:03 -05003116/*********************** PyRunningLoopHolder ********************/
3117
3118
3119static PyRunningLoopHolder *
3120new_running_loop_holder(PyObject *loop)
3121{
3122 PyRunningLoopHolder *rl = PyObject_New(
3123 PyRunningLoopHolder, &PyRunningLoopHolder_Type);
3124 if (rl == NULL) {
3125 return NULL;
3126 }
3127
3128#if defined(HAVE_GETPID) && !defined(MS_WINDOWS)
3129 rl->rl_pid = getpid();
3130#endif
3131
3132 Py_INCREF(loop);
3133 rl->rl_loop = loop;
3134
3135 return rl;
3136}
3137
3138
3139static void
3140PyRunningLoopHolder_tp_dealloc(PyRunningLoopHolder *rl)
3141{
3142 Py_CLEAR(rl->rl_loop);
3143 PyObject_Free(rl);
3144}
3145
3146
3147static PyTypeObject PyRunningLoopHolder_Type = {
3148 PyVarObject_HEAD_INIT(NULL, 0)
3149 "_RunningLoopHolder",
3150 sizeof(PyRunningLoopHolder),
3151 .tp_getattro = PyObject_GenericGetAttr,
3152 .tp_flags = Py_TPFLAGS_DEFAULT,
3153 .tp_dealloc = (destructor)PyRunningLoopHolder_tp_dealloc,
3154};
3155
3156
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003157/*********************** Module **************************/
3158
3159
3160static void
Zackery Spytze40ad792017-12-19 11:48:13 -07003161module_free_freelists(void)
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05003162{
3163 PyObject *next;
3164 PyObject *current;
3165
3166 next = (PyObject*) fi_freelist;
3167 while (next != NULL) {
3168 assert(fi_freelist_len > 0);
3169 fi_freelist_len--;
3170
3171 current = next;
3172 next = (PyObject*) ((futureiterobject*) current)->future;
3173 PyObject_GC_Del(current);
3174 }
3175 assert(fi_freelist_len == 0);
3176 fi_freelist = NULL;
3177}
3178
3179
3180static void
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003181module_free(void *m)
3182{
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003183 Py_CLEAR(asyncio_mod);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003184 Py_CLEAR(inspect_isgenerator);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003185 Py_CLEAR(traceback_extract_stack);
3186 Py_CLEAR(asyncio_future_repr_info_func);
3187 Py_CLEAR(asyncio_get_event_loop_policy);
3188 Py_CLEAR(asyncio_iscoroutine_func);
3189 Py_CLEAR(asyncio_task_get_stack_func);
3190 Py_CLEAR(asyncio_task_print_stack_func);
3191 Py_CLEAR(asyncio_task_repr_info_func);
3192 Py_CLEAR(asyncio_InvalidStateError);
3193 Py_CLEAR(asyncio_CancelledError);
3194
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003195 Py_CLEAR(all_tasks);
Yury Selivanova9d7e552017-12-19 07:18:45 -05003196 Py_CLEAR(current_tasks);
3197 Py_CLEAR(iscoroutine_typecache);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05003198
Yury Selivanovf23746a2018-01-22 19:11:18 -05003199 Py_CLEAR(context_kwname);
3200
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05003201 module_free_freelists();
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003202}
3203
3204static int
3205module_init(void)
3206{
3207 PyObject *module = NULL;
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003208
3209 asyncio_mod = PyImport_ImportModule("asyncio");
3210 if (asyncio_mod == NULL) {
3211 goto fail;
3212 }
3213
3214 current_tasks = PyDict_New();
3215 if (current_tasks == NULL) {
3216 goto fail;
3217 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003218
Yury Selivanova9d7e552017-12-19 07:18:45 -05003219 iscoroutine_typecache = PySet_New(NULL);
3220 if (iscoroutine_typecache == NULL) {
3221 goto fail;
3222 }
3223
Yury Selivanovf23746a2018-01-22 19:11:18 -05003224
3225 context_kwname = PyTuple_New(1);
3226 if (context_kwname == NULL) {
3227 goto fail;
3228 }
3229 PyObject *context_str = PyUnicode_FromString("context");
3230 if (context_str == NULL) {
3231 goto fail;
3232 }
3233 PyTuple_SET_ITEM(context_kwname, 0, context_str);
3234
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003235#define WITH_MOD(NAME) \
3236 Py_CLEAR(module); \
3237 module = PyImport_ImportModule(NAME); \
3238 if (module == NULL) { \
Serhiy Storchakabca49392017-09-03 08:10:14 +03003239 goto fail; \
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003240 }
3241
3242#define GET_MOD_ATTR(VAR, NAME) \
3243 VAR = PyObject_GetAttrString(module, NAME); \
3244 if (VAR == NULL) { \
3245 goto fail; \
3246 }
3247
3248 WITH_MOD("asyncio.events")
Yury Selivanova70232f2017-12-13 14:49:42 -05003249 GET_MOD_ATTR(asyncio_get_event_loop_policy, "get_event_loop_policy")
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003250
3251 WITH_MOD("asyncio.base_futures")
3252 GET_MOD_ATTR(asyncio_future_repr_info_func, "_future_repr_info")
3253 GET_MOD_ATTR(asyncio_InvalidStateError, "InvalidStateError")
3254 GET_MOD_ATTR(asyncio_CancelledError, "CancelledError")
3255
3256 WITH_MOD("asyncio.base_tasks")
3257 GET_MOD_ATTR(asyncio_task_repr_info_func, "_task_repr_info")
3258 GET_MOD_ATTR(asyncio_task_get_stack_func, "_task_get_stack")
3259 GET_MOD_ATTR(asyncio_task_print_stack_func, "_task_print_stack")
3260
Andrew Svetlovf74ef452017-12-15 07:04:38 +02003261 WITH_MOD("asyncio.coroutines")
3262 GET_MOD_ATTR(asyncio_iscoroutine_func, "iscoroutine")
3263
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003264 WITH_MOD("inspect")
3265 GET_MOD_ATTR(inspect_isgenerator, "isgenerator")
3266
3267 WITH_MOD("traceback")
3268 GET_MOD_ATTR(traceback_extract_stack, "extract_stack")
3269
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003270 PyObject *weak_set;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003271 WITH_MOD("weakref")
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003272 GET_MOD_ATTR(weak_set, "WeakSet");
3273 all_tasks = _PyObject_CallNoArg(weak_set);
3274 Py_CLEAR(weak_set);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003275 if (all_tasks == NULL) {
INADA Naokic411a7d2016-10-18 11:48:14 +09003276 goto fail;
3277 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003278
Serhiy Storchakabca49392017-09-03 08:10:14 +03003279 Py_DECREF(module);
INADA Naokic411a7d2016-10-18 11:48:14 +09003280 return 0;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003281
INADA Naokic411a7d2016-10-18 11:48:14 +09003282fail:
INADA Naokic411a7d2016-10-18 11:48:14 +09003283 Py_CLEAR(module);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003284 module_free(NULL);
INADA Naokic411a7d2016-10-18 11:48:14 +09003285 return -1;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003286
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003287#undef WITH_MOD
3288#undef GET_MOD_ATTR
3289}
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003290
INADA Naokic411a7d2016-10-18 11:48:14 +09003291PyDoc_STRVAR(module_doc, "Accelerator module for asyncio");
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003292
Yury Selivanova70232f2017-12-13 14:49:42 -05003293static PyMethodDef asyncio_methods[] = {
3294 _ASYNCIO_GET_EVENT_LOOP_METHODDEF
3295 _ASYNCIO_GET_RUNNING_LOOP_METHODDEF
3296 _ASYNCIO__GET_RUNNING_LOOP_METHODDEF
3297 _ASYNCIO__SET_RUNNING_LOOP_METHODDEF
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003298 _ASYNCIO__REGISTER_TASK_METHODDEF
3299 _ASYNCIO__UNREGISTER_TASK_METHODDEF
3300 _ASYNCIO__ENTER_TASK_METHODDEF
3301 _ASYNCIO__LEAVE_TASK_METHODDEF
Yury Selivanova70232f2017-12-13 14:49:42 -05003302 {NULL, NULL}
3303};
3304
INADA Naoki9f2ce252016-10-15 15:39:19 +09003305static struct PyModuleDef _asynciomodule = {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003306 PyModuleDef_HEAD_INIT, /* m_base */
INADA Naoki9f2ce252016-10-15 15:39:19 +09003307 "_asyncio", /* m_name */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003308 module_doc, /* m_doc */
3309 -1, /* m_size */
Yury Selivanova70232f2017-12-13 14:49:42 -05003310 asyncio_methods, /* m_methods */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003311 NULL, /* m_slots */
3312 NULL, /* m_traverse */
3313 NULL, /* m_clear */
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003314 (freefunc)module_free /* m_free */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003315};
3316
3317
3318PyMODINIT_FUNC
INADA Naoki9f2ce252016-10-15 15:39:19 +09003319PyInit__asyncio(void)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003320{
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003321 if (module_init() < 0) {
INADA Naokic411a7d2016-10-18 11:48:14 +09003322 return NULL;
3323 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003324 if (PyType_Ready(&FutureType) < 0) {
3325 return NULL;
3326 }
3327 if (PyType_Ready(&FutureIterType) < 0) {
3328 return NULL;
3329 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03003330 if (PyType_Ready(&TaskStepMethWrapper_Type) < 0) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003331 return NULL;
3332 }
3333 if(PyType_Ready(&TaskWakeupMethWrapper_Type) < 0) {
3334 return NULL;
3335 }
3336 if (PyType_Ready(&TaskType) < 0) {
3337 return NULL;
3338 }
Yury Selivanov9d411c12018-01-23 15:10:03 -05003339 if (PyType_Ready(&PyRunningLoopHolder_Type) < 0) {
3340 return NULL;
3341 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003342
INADA Naoki9f2ce252016-10-15 15:39:19 +09003343 PyObject *m = PyModule_Create(&_asynciomodule);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003344 if (m == NULL) {
3345 return NULL;
3346 }
3347
3348 Py_INCREF(&FutureType);
3349 if (PyModule_AddObject(m, "Future", (PyObject *)&FutureType) < 0) {
3350 Py_DECREF(&FutureType);
3351 return NULL;
3352 }
3353
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003354 Py_INCREF(&TaskType);
3355 if (PyModule_AddObject(m, "Task", (PyObject *)&TaskType) < 0) {
3356 Py_DECREF(&TaskType);
3357 return NULL;
3358 }
3359
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003360 Py_INCREF(all_tasks);
3361 if (PyModule_AddObject(m, "_all_tasks", all_tasks) < 0) {
3362 Py_DECREF(all_tasks);
3363 return NULL;
3364 }
3365
3366 Py_INCREF(current_tasks);
3367 if (PyModule_AddObject(m, "_current_tasks", current_tasks) < 0) {
3368 Py_DECREF(current_tasks);
3369 return NULL;
3370 }
3371
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003372 return m;
3373}