blob: 35264f5815c3bce2ca37d184134f2e249a1ca433 [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 *
Miss Islington (bot)5ceb7012018-11-27 09:58:07 -08001097FutureObj_get_blocking(FutureObj *fut, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001098{
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
Miss Islington (bot)5ceb7012018-11-27 09:58:07 -08001108FutureObj_set_blocking(FutureObj *fut, PyObject *val, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001109{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001110 if (future_ensure_alive(fut)) {
1111 return -1;
1112 }
Miss Islington (bot)cb272842018-12-17 07:10:20 -08001113 if (val == NULL) {
1114 PyErr_SetString(PyExc_AttributeError, "cannot delete attribute");
1115 return -1;
1116 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001117
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001118 int is_true = PyObject_IsTrue(val);
1119 if (is_true < 0) {
1120 return -1;
1121 }
1122 fut->fut_blocking = is_true;
1123 return 0;
1124}
1125
1126static PyObject *
Miss Islington (bot)5ceb7012018-11-27 09:58:07 -08001127FutureObj_get_log_traceback(FutureObj *fut, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001128{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001129 ENSURE_FUTURE_ALIVE(fut)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001130 if (fut->fut_log_tb) {
1131 Py_RETURN_TRUE;
1132 }
1133 else {
1134 Py_RETURN_FALSE;
1135 }
1136}
1137
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +00001138static int
Miss Islington (bot)5ceb7012018-11-27 09:58:07 -08001139FutureObj_set_log_traceback(FutureObj *fut, PyObject *val, void *Py_UNUSED(ignored))
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +00001140{
Miss Islington (bot)cb272842018-12-17 07:10:20 -08001141 if (val == NULL) {
1142 PyErr_SetString(PyExc_AttributeError, "cannot delete attribute");
1143 return -1;
1144 }
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +00001145 int is_true = PyObject_IsTrue(val);
1146 if (is_true < 0) {
1147 return -1;
1148 }
Yury Selivanove0aef4f2017-12-25 16:16:10 -05001149 if (is_true) {
1150 PyErr_SetString(PyExc_ValueError,
1151 "_log_traceback can only be set to False");
1152 return -1;
1153 }
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +00001154 fut->fut_log_tb = is_true;
1155 return 0;
1156}
1157
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001158static PyObject *
Miss Islington (bot)5ceb7012018-11-27 09:58:07 -08001159FutureObj_get_loop(FutureObj *fut, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001160{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001161 if (!future_is_alive(fut)) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001162 Py_RETURN_NONE;
1163 }
1164 Py_INCREF(fut->fut_loop);
1165 return fut->fut_loop;
1166}
1167
1168static PyObject *
Miss Islington (bot)5ceb7012018-11-27 09:58:07 -08001169FutureObj_get_callbacks(FutureObj *fut, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001170{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001171 Py_ssize_t i;
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001172
1173 ENSURE_FUTURE_ALIVE(fut)
1174
Yury Selivanovf23746a2018-01-22 19:11:18 -05001175 if (fut->fut_callback0 == NULL) {
1176 if (fut->fut_callbacks == NULL) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001177 Py_RETURN_NONE;
1178 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001179
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001180 Py_INCREF(fut->fut_callbacks);
1181 return fut->fut_callbacks;
1182 }
1183
Yury Selivanovf23746a2018-01-22 19:11:18 -05001184 Py_ssize_t len = 1;
1185 if (fut->fut_callbacks != NULL) {
1186 len += PyList_GET_SIZE(fut->fut_callbacks);
1187 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001188
Yury Selivanovf23746a2018-01-22 19:11:18 -05001189
1190 PyObject *new_list = PyList_New(len);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001191 if (new_list == NULL) {
1192 return NULL;
1193 }
1194
Yury Selivanovf23746a2018-01-22 19:11:18 -05001195 PyObject *tup0 = PyTuple_New(2);
1196 if (tup0 == NULL) {
1197 Py_DECREF(new_list);
1198 return NULL;
1199 }
1200
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001201 Py_INCREF(fut->fut_callback0);
Yury Selivanovf23746a2018-01-22 19:11:18 -05001202 PyTuple_SET_ITEM(tup0, 0, fut->fut_callback0);
1203 assert(fut->fut_context0 != NULL);
1204 Py_INCREF(fut->fut_context0);
1205 PyTuple_SET_ITEM(tup0, 1, (PyObject *)fut->fut_context0);
1206
1207 PyList_SET_ITEM(new_list, 0, tup0);
1208
1209 if (fut->fut_callbacks != NULL) {
1210 for (i = 0; i < PyList_GET_SIZE(fut->fut_callbacks); i++) {
1211 PyObject *cb = PyList_GET_ITEM(fut->fut_callbacks, i);
1212 Py_INCREF(cb);
1213 PyList_SET_ITEM(new_list, i + 1, cb);
1214 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001215 }
1216
1217 return new_list;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001218}
1219
1220static PyObject *
Miss Islington (bot)5ceb7012018-11-27 09:58:07 -08001221FutureObj_get_result(FutureObj *fut, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001222{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001223 ENSURE_FUTURE_ALIVE(fut)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001224 if (fut->fut_result == NULL) {
1225 Py_RETURN_NONE;
1226 }
1227 Py_INCREF(fut->fut_result);
1228 return fut->fut_result;
1229}
1230
1231static PyObject *
Miss Islington (bot)5ceb7012018-11-27 09:58:07 -08001232FutureObj_get_exception(FutureObj *fut, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001233{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001234 ENSURE_FUTURE_ALIVE(fut)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001235 if (fut->fut_exception == NULL) {
1236 Py_RETURN_NONE;
1237 }
1238 Py_INCREF(fut->fut_exception);
1239 return fut->fut_exception;
1240}
1241
1242static PyObject *
Miss Islington (bot)5ceb7012018-11-27 09:58:07 -08001243FutureObj_get_source_traceback(FutureObj *fut, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001244{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001245 if (!future_is_alive(fut) || fut->fut_source_tb == NULL) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001246 Py_RETURN_NONE;
1247 }
1248 Py_INCREF(fut->fut_source_tb);
1249 return fut->fut_source_tb;
1250}
1251
1252static PyObject *
Miss Islington (bot)5ceb7012018-11-27 09:58:07 -08001253FutureObj_get_state(FutureObj *fut, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001254{
1255 _Py_IDENTIFIER(PENDING);
1256 _Py_IDENTIFIER(CANCELLED);
1257 _Py_IDENTIFIER(FINISHED);
1258 PyObject *ret = NULL;
1259
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001260 ENSURE_FUTURE_ALIVE(fut)
1261
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001262 switch (fut->fut_state) {
1263 case STATE_PENDING:
1264 ret = _PyUnicode_FromId(&PyId_PENDING);
1265 break;
1266 case STATE_CANCELLED:
1267 ret = _PyUnicode_FromId(&PyId_CANCELLED);
1268 break;
1269 case STATE_FINISHED:
1270 ret = _PyUnicode_FromId(&PyId_FINISHED);
1271 break;
1272 default:
1273 assert (0);
1274 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03001275 Py_XINCREF(ret);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001276 return ret;
1277}
1278
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001279/*[clinic input]
1280_asyncio.Future._repr_info
1281[clinic start generated code]*/
1282
1283static PyObject *
1284_asyncio_Future__repr_info_impl(FutureObj *self)
1285/*[clinic end generated code: output=fa69e901bd176cfb input=f21504d8e2ae1ca2]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001286{
Victor Stinnerde4ae3d2016-12-04 22:59:09 +01001287 return PyObject_CallFunctionObjArgs(
1288 asyncio_future_repr_info_func, self, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001289}
1290
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001291static PyObject *
1292FutureObj_repr(FutureObj *fut)
1293{
1294 _Py_IDENTIFIER(_repr_info);
1295
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001296 ENSURE_FUTURE_ALIVE(fut)
1297
Serhiy Storchakabca49392017-09-03 08:10:14 +03001298 PyObject *rinfo = _PyObject_CallMethodIdObjArgs((PyObject*)fut,
1299 &PyId__repr_info,
1300 NULL);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001301 if (rinfo == NULL) {
1302 return NULL;
1303 }
1304
Serhiy Storchakabca49392017-09-03 08:10:14 +03001305 PyObject *rinfo_s = PyUnicode_Join(NULL, rinfo);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001306 Py_DECREF(rinfo);
1307 if (rinfo_s == NULL) {
1308 return NULL;
1309 }
1310
1311 PyObject *rstr = NULL;
1312 PyObject *type_name = PyObject_GetAttrString((PyObject*)Py_TYPE(fut),
1313 "__name__");
1314 if (type_name != NULL) {
Serhiy Storchakabca49392017-09-03 08:10:14 +03001315 rstr = PyUnicode_FromFormat("<%S %U>", type_name, rinfo_s);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001316 Py_DECREF(type_name);
1317 }
1318 Py_DECREF(rinfo_s);
1319 return rstr;
1320}
1321
1322static void
1323FutureObj_finalize(FutureObj *fut)
1324{
1325 _Py_IDENTIFIER(call_exception_handler);
1326 _Py_IDENTIFIER(message);
1327 _Py_IDENTIFIER(exception);
1328 _Py_IDENTIFIER(future);
1329 _Py_IDENTIFIER(source_traceback);
1330
Serhiy Storchakabca49392017-09-03 08:10:14 +03001331 PyObject *error_type, *error_value, *error_traceback;
1332 PyObject *context;
1333 PyObject *type_name;
1334 PyObject *message = NULL;
1335 PyObject *func;
1336
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001337 if (!fut->fut_log_tb) {
1338 return;
1339 }
1340 assert(fut->fut_exception != NULL);
Serhiy Storchakabca49392017-09-03 08:10:14 +03001341 fut->fut_log_tb = 0;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001342
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001343 /* Save the current exception, if any. */
1344 PyErr_Fetch(&error_type, &error_value, &error_traceback);
1345
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001346 context = PyDict_New();
1347 if (context == NULL) {
1348 goto finally;
1349 }
1350
1351 type_name = PyObject_GetAttrString((PyObject*)Py_TYPE(fut), "__name__");
1352 if (type_name == NULL) {
1353 goto finally;
1354 }
1355
1356 message = PyUnicode_FromFormat(
1357 "%S exception was never retrieved", type_name);
Serhiy Storchakabca49392017-09-03 08:10:14 +03001358 Py_DECREF(type_name);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001359 if (message == NULL) {
1360 goto finally;
1361 }
1362
1363 if (_PyDict_SetItemId(context, &PyId_message, message) < 0 ||
1364 _PyDict_SetItemId(context, &PyId_exception, fut->fut_exception) < 0 ||
1365 _PyDict_SetItemId(context, &PyId_future, (PyObject*)fut) < 0) {
1366 goto finally;
1367 }
1368 if (fut->fut_source_tb != NULL) {
1369 if (_PyDict_SetItemId(context, &PyId_source_traceback,
1370 fut->fut_source_tb) < 0) {
1371 goto finally;
1372 }
1373 }
1374
1375 func = _PyObject_GetAttrId(fut->fut_loop, &PyId_call_exception_handler);
1376 if (func != NULL) {
Serhiy Storchakabca49392017-09-03 08:10:14 +03001377 PyObject *res = PyObject_CallFunctionObjArgs(func, context, NULL);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001378 if (res == NULL) {
1379 PyErr_WriteUnraisable(func);
1380 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03001381 else {
1382 Py_DECREF(res);
1383 }
1384 Py_DECREF(func);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001385 }
1386
1387finally:
Serhiy Storchakabca49392017-09-03 08:10:14 +03001388 Py_XDECREF(context);
1389 Py_XDECREF(message);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001390
1391 /* Restore the saved exception. */
1392 PyErr_Restore(error_type, error_value, error_traceback);
1393}
1394
1395
1396static PyAsyncMethods FutureType_as_async = {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001397 (unaryfunc)future_new_iter, /* am_await */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001398 0, /* am_aiter */
1399 0 /* am_anext */
1400};
1401
1402static PyMethodDef FutureType_methods[] = {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001403 _ASYNCIO_FUTURE_RESULT_METHODDEF
1404 _ASYNCIO_FUTURE_EXCEPTION_METHODDEF
1405 _ASYNCIO_FUTURE_SET_RESULT_METHODDEF
1406 _ASYNCIO_FUTURE_SET_EXCEPTION_METHODDEF
1407 _ASYNCIO_FUTURE_ADD_DONE_CALLBACK_METHODDEF
1408 _ASYNCIO_FUTURE_REMOVE_DONE_CALLBACK_METHODDEF
1409 _ASYNCIO_FUTURE_CANCEL_METHODDEF
1410 _ASYNCIO_FUTURE_CANCELLED_METHODDEF
1411 _ASYNCIO_FUTURE_DONE_METHODDEF
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001412 _ASYNCIO_FUTURE_GET_LOOP_METHODDEF
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001413 _ASYNCIO_FUTURE__REPR_INFO_METHODDEF
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001414 {NULL, NULL} /* Sentinel */
1415};
1416
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001417#define FUTURE_COMMON_GETSETLIST \
1418 {"_state", (getter)FutureObj_get_state, NULL, NULL}, \
1419 {"_asyncio_future_blocking", (getter)FutureObj_get_blocking, \
1420 (setter)FutureObj_set_blocking, NULL}, \
1421 {"_loop", (getter)FutureObj_get_loop, NULL, NULL}, \
1422 {"_callbacks", (getter)FutureObj_get_callbacks, NULL, NULL}, \
1423 {"_result", (getter)FutureObj_get_result, NULL, NULL}, \
1424 {"_exception", (getter)FutureObj_get_exception, NULL, NULL}, \
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +00001425 {"_log_traceback", (getter)FutureObj_get_log_traceback, \
1426 (setter)FutureObj_set_log_traceback, NULL}, \
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001427 {"_source_traceback", (getter)FutureObj_get_source_traceback, NULL, NULL},
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001428
1429static PyGetSetDef FutureType_getsetlist[] = {
1430 FUTURE_COMMON_GETSETLIST
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001431 {NULL} /* Sentinel */
1432};
1433
1434static void FutureObj_dealloc(PyObject *self);
1435
1436static PyTypeObject FutureType = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02001437 PyVarObject_HEAD_INIT(NULL, 0)
INADA Naoki9f2ce252016-10-15 15:39:19 +09001438 "_asyncio.Future",
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001439 sizeof(FutureObj), /* tp_basicsize */
1440 .tp_dealloc = FutureObj_dealloc,
1441 .tp_as_async = &FutureType_as_async,
1442 .tp_repr = (reprfunc)FutureObj_repr,
1443 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE
1444 | Py_TPFLAGS_HAVE_FINALIZE,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001445 .tp_doc = _asyncio_Future___init____doc__,
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001446 .tp_traverse = (traverseproc)FutureObj_traverse,
1447 .tp_clear = (inquiry)FutureObj_clear,
1448 .tp_weaklistoffset = offsetof(FutureObj, fut_weakreflist),
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001449 .tp_iter = (getiterfunc)future_new_iter,
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001450 .tp_methods = FutureType_methods,
1451 .tp_getset = FutureType_getsetlist,
1452 .tp_dictoffset = offsetof(FutureObj, dict),
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001453 .tp_init = (initproc)_asyncio_Future___init__,
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001454 .tp_new = PyType_GenericNew,
1455 .tp_finalize = (destructor)FutureObj_finalize,
1456};
1457
1458static void
1459FutureObj_dealloc(PyObject *self)
1460{
1461 FutureObj *fut = (FutureObj *)self;
1462
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001463 if (Future_CheckExact(fut)) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001464 /* When fut is subclass of Future, finalizer is called from
1465 * subtype_dealloc.
1466 */
1467 if (PyObject_CallFinalizerFromDealloc(self) < 0) {
1468 // resurrected.
1469 return;
1470 }
1471 }
1472
Alexander Mohrde34cbe2017-08-01 23:31:07 -07001473 PyObject_GC_UnTrack(self);
1474
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001475 if (fut->fut_weakreflist != NULL) {
1476 PyObject_ClearWeakRefs(self);
1477 }
1478
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001479 (void)FutureObj_clear(fut);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001480 Py_TYPE(fut)->tp_free(fut);
1481}
1482
1483
1484/*********************** Future Iterator **************************/
1485
1486typedef struct {
1487 PyObject_HEAD
1488 FutureObj *future;
1489} futureiterobject;
1490
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001491
1492#define FI_FREELIST_MAXLEN 255
1493static futureiterobject *fi_freelist = NULL;
1494static Py_ssize_t fi_freelist_len = 0;
1495
1496
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001497static void
1498FutureIter_dealloc(futureiterobject *it)
1499{
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001500 PyObject_GC_UnTrack(it);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001501 Py_CLEAR(it->future);
1502
1503 if (fi_freelist_len < FI_FREELIST_MAXLEN) {
1504 fi_freelist_len++;
1505 it->future = (FutureObj*) fi_freelist;
1506 fi_freelist = it;
1507 }
1508 else {
1509 PyObject_GC_Del(it);
1510 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001511}
1512
1513static PyObject *
1514FutureIter_iternext(futureiterobject *it)
1515{
1516 PyObject *res;
1517 FutureObj *fut = it->future;
1518
1519 if (fut == NULL) {
1520 return NULL;
1521 }
1522
1523 if (fut->fut_state == STATE_PENDING) {
1524 if (!fut->fut_blocking) {
1525 fut->fut_blocking = 1;
1526 Py_INCREF(fut);
1527 return (PyObject *)fut;
1528 }
Yury Selivanov0cf16f92017-12-25 10:48:15 -05001529 PyErr_SetString(PyExc_RuntimeError,
1530 "await wasn't used with future");
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001531 return NULL;
1532 }
1533
Serhiy Storchakabca49392017-09-03 08:10:14 +03001534 it->future = NULL;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001535 res = _asyncio_Future_result_impl(fut);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001536 if (res != NULL) {
Serhiy Storchaka60e49aa2016-11-06 18:47:03 +02001537 /* The result of the Future is not an exception. */
Serhiy Storchakabca49392017-09-03 08:10:14 +03001538 (void)_PyGen_SetStopIterationValue(res);
Serhiy Storchaka60e49aa2016-11-06 18:47:03 +02001539 Py_DECREF(res);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001540 }
1541
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001542 Py_DECREF(fut);
1543 return NULL;
1544}
1545
1546static PyObject *
INADA Naoki74c17532016-10-25 19:00:45 +09001547FutureIter_send(futureiterobject *self, PyObject *unused)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001548{
INADA Naoki74c17532016-10-25 19:00:45 +09001549 /* Future.__iter__ doesn't care about values that are pushed to the
1550 * generator, it just returns "self.result().
1551 */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001552 return FutureIter_iternext(self);
1553}
1554
1555static PyObject *
1556FutureIter_throw(futureiterobject *self, PyObject *args)
1557{
Serhiy Storchakabca49392017-09-03 08:10:14 +03001558 PyObject *type, *val = NULL, *tb = NULL;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001559 if (!PyArg_ParseTuple(args, "O|OO", &type, &val, &tb))
1560 return NULL;
1561
1562 if (val == Py_None) {
1563 val = NULL;
1564 }
1565 if (tb == Py_None) {
1566 tb = NULL;
Benjamin Peterson996fc1f2016-11-14 00:15:44 -08001567 } else if (tb != NULL && !PyTraceBack_Check(tb)) {
1568 PyErr_SetString(PyExc_TypeError, "throw() third argument must be a traceback");
1569 return NULL;
1570 }
1571
1572 Py_INCREF(type);
1573 Py_XINCREF(val);
1574 Py_XINCREF(tb);
1575
1576 if (PyExceptionClass_Check(type)) {
1577 PyErr_NormalizeException(&type, &val, &tb);
Yury Selivanovedfe8862016-12-01 11:37:47 -05001578 /* No need to call PyException_SetTraceback since we'll be calling
1579 PyErr_Restore for `type`, `val`, and `tb`. */
Benjamin Peterson996fc1f2016-11-14 00:15:44 -08001580 } else if (PyExceptionInstance_Check(type)) {
1581 if (val) {
1582 PyErr_SetString(PyExc_TypeError,
1583 "instance exception may not have a separate value");
1584 goto fail;
1585 }
1586 val = type;
1587 type = PyExceptionInstance_Class(type);
1588 Py_INCREF(type);
1589 if (tb == NULL)
1590 tb = PyException_GetTraceback(val);
1591 } else {
1592 PyErr_SetString(PyExc_TypeError,
1593 "exceptions must be classes deriving BaseException or "
1594 "instances of such a class");
1595 goto fail;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001596 }
1597
1598 Py_CLEAR(self->future);
1599
Benjamin Peterson996fc1f2016-11-14 00:15:44 -08001600 PyErr_Restore(type, val, tb);
1601
Serhiy Storchakabca49392017-09-03 08:10:14 +03001602 return NULL;
Benjamin Peterson996fc1f2016-11-14 00:15:44 -08001603
1604 fail:
1605 Py_DECREF(type);
1606 Py_XDECREF(val);
1607 Py_XDECREF(tb);
1608 return NULL;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001609}
1610
1611static PyObject *
1612FutureIter_close(futureiterobject *self, PyObject *arg)
1613{
1614 Py_CLEAR(self->future);
1615 Py_RETURN_NONE;
1616}
1617
1618static int
1619FutureIter_traverse(futureiterobject *it, visitproc visit, void *arg)
1620{
1621 Py_VISIT(it->future);
1622 return 0;
1623}
1624
1625static PyMethodDef FutureIter_methods[] = {
1626 {"send", (PyCFunction)FutureIter_send, METH_O, NULL},
1627 {"throw", (PyCFunction)FutureIter_throw, METH_VARARGS, NULL},
1628 {"close", (PyCFunction)FutureIter_close, METH_NOARGS, NULL},
1629 {NULL, NULL} /* Sentinel */
1630};
1631
1632static PyTypeObject FutureIterType = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02001633 PyVarObject_HEAD_INIT(NULL, 0)
INADA Naoki9f2ce252016-10-15 15:39:19 +09001634 "_asyncio.FutureIter",
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001635 .tp_basicsize = sizeof(futureiterobject),
1636 .tp_itemsize = 0,
1637 .tp_dealloc = (destructor)FutureIter_dealloc,
1638 .tp_getattro = PyObject_GenericGetAttr,
1639 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
1640 .tp_traverse = (traverseproc)FutureIter_traverse,
1641 .tp_iter = PyObject_SelfIter,
1642 .tp_iternext = (iternextfunc)FutureIter_iternext,
1643 .tp_methods = FutureIter_methods,
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001644};
1645
1646static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001647future_new_iter(PyObject *fut)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001648{
1649 futureiterobject *it;
1650
1651 if (!PyObject_TypeCheck(fut, &FutureType)) {
1652 PyErr_BadInternalCall();
1653 return NULL;
1654 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001655
1656 ENSURE_FUTURE_ALIVE(fut)
1657
1658 if (fi_freelist_len) {
1659 fi_freelist_len--;
1660 it = fi_freelist;
1661 fi_freelist = (futureiterobject*) it->future;
1662 it->future = NULL;
1663 _Py_NewReference((PyObject*) it);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001664 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001665 else {
1666 it = PyObject_GC_New(futureiterobject, &FutureIterType);
1667 if (it == NULL) {
1668 return NULL;
1669 }
1670 }
1671
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001672 Py_INCREF(fut);
1673 it->future = (FutureObj*)fut;
INADA Naoki1be427b2016-10-11 02:12:34 +09001674 PyObject_GC_Track(it);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001675 return (PyObject*)it;
1676}
1677
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001678
1679/*********************** Task **************************/
1680
1681
1682/*[clinic input]
1683class _asyncio.Task "TaskObj *" "&Task_Type"
1684[clinic start generated code]*/
1685/*[clinic end generated code: output=da39a3ee5e6b4b0d input=719dcef0fcc03b37]*/
1686
1687static int task_call_step_soon(TaskObj *, PyObject *);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001688static PyObject * task_wakeup(TaskObj *, PyObject *);
1689static PyObject * task_step(TaskObj *, PyObject *);
1690
1691/* ----- Task._step wrapper */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001692
INADA Naokic411a7d2016-10-18 11:48:14 +09001693static int
Serhiy Storchakabca49392017-09-03 08:10:14 +03001694TaskStepMethWrapper_clear(TaskStepMethWrapper *o)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001695{
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001696 Py_CLEAR(o->sw_task);
1697 Py_CLEAR(o->sw_arg);
1698 return 0;
1699}
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001700
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001701static void
Serhiy Storchakabca49392017-09-03 08:10:14 +03001702TaskStepMethWrapper_dealloc(TaskStepMethWrapper *o)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001703{
1704 PyObject_GC_UnTrack(o);
Serhiy Storchakabca49392017-09-03 08:10:14 +03001705 (void)TaskStepMethWrapper_clear(o);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001706 Py_TYPE(o)->tp_free(o);
1707}
1708
1709static PyObject *
Serhiy Storchakabca49392017-09-03 08:10:14 +03001710TaskStepMethWrapper_call(TaskStepMethWrapper *o,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001711 PyObject *args, PyObject *kwds)
1712{
Serhiy Storchakabca49392017-09-03 08:10:14 +03001713 if (kwds != NULL && PyDict_GET_SIZE(kwds) != 0) {
1714 PyErr_SetString(PyExc_TypeError, "function takes no keyword arguments");
1715 return NULL;
1716 }
1717 if (args != NULL && PyTuple_GET_SIZE(args) != 0) {
1718 PyErr_SetString(PyExc_TypeError, "function takes no positional arguments");
1719 return NULL;
1720 }
Yury Selivanov22feeb82018-01-24 11:31:01 -05001721 return task_step(o->sw_task, o->sw_arg);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001722}
1723
1724static int
Serhiy Storchakabca49392017-09-03 08:10:14 +03001725TaskStepMethWrapper_traverse(TaskStepMethWrapper *o,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001726 visitproc visit, void *arg)
1727{
1728 Py_VISIT(o->sw_task);
1729 Py_VISIT(o->sw_arg);
1730 return 0;
1731}
1732
1733static PyObject *
Miss Islington (bot)5ceb7012018-11-27 09:58:07 -08001734TaskStepMethWrapper_get___self__(TaskStepMethWrapper *o, void *Py_UNUSED(ignored))
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001735{
1736 if (o->sw_task) {
1737 Py_INCREF(o->sw_task);
1738 return (PyObject*)o->sw_task;
1739 }
1740 Py_RETURN_NONE;
1741}
1742
Serhiy Storchakabca49392017-09-03 08:10:14 +03001743static PyGetSetDef TaskStepMethWrapper_getsetlist[] = {
1744 {"__self__", (getter)TaskStepMethWrapper_get___self__, NULL, NULL},
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001745 {NULL} /* Sentinel */
1746};
1747
Miss Islington (bot)60214dd2018-07-05 22:58:27 -07001748static PyTypeObject TaskStepMethWrapper_Type = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02001749 PyVarObject_HEAD_INIT(NULL, 0)
Serhiy Storchakabca49392017-09-03 08:10:14 +03001750 "TaskStepMethWrapper",
1751 .tp_basicsize = sizeof(TaskStepMethWrapper),
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001752 .tp_itemsize = 0,
Serhiy Storchakabca49392017-09-03 08:10:14 +03001753 .tp_getset = TaskStepMethWrapper_getsetlist,
1754 .tp_dealloc = (destructor)TaskStepMethWrapper_dealloc,
1755 .tp_call = (ternaryfunc)TaskStepMethWrapper_call,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001756 .tp_getattro = PyObject_GenericGetAttr,
1757 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
Serhiy Storchakabca49392017-09-03 08:10:14 +03001758 .tp_traverse = (traverseproc)TaskStepMethWrapper_traverse,
1759 .tp_clear = (inquiry)TaskStepMethWrapper_clear,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001760};
1761
1762static PyObject *
Serhiy Storchakabca49392017-09-03 08:10:14 +03001763TaskStepMethWrapper_new(TaskObj *task, PyObject *arg)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001764{
Serhiy Storchakabca49392017-09-03 08:10:14 +03001765 TaskStepMethWrapper *o;
1766 o = PyObject_GC_New(TaskStepMethWrapper, &TaskStepMethWrapper_Type);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001767 if (o == NULL) {
1768 return NULL;
1769 }
1770
1771 Py_INCREF(task);
1772 o->sw_task = task;
1773
1774 Py_XINCREF(arg);
1775 o->sw_arg = arg;
1776
1777 PyObject_GC_Track(o);
1778 return (PyObject*) o;
1779}
1780
1781/* ----- Task._wakeup wrapper */
1782
1783static PyObject *
1784TaskWakeupMethWrapper_call(TaskWakeupMethWrapper *o,
1785 PyObject *args, PyObject *kwds)
1786{
1787 PyObject *fut;
1788
Serhiy Storchakabca49392017-09-03 08:10:14 +03001789 if (kwds != NULL && PyDict_GET_SIZE(kwds) != 0) {
1790 PyErr_SetString(PyExc_TypeError, "function takes no keyword arguments");
1791 return NULL;
1792 }
1793 if (!PyArg_ParseTuple(args, "O", &fut)) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001794 return NULL;
1795 }
1796
Yury Selivanov22feeb82018-01-24 11:31:01 -05001797 return task_wakeup(o->ww_task, fut);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001798}
1799
1800static int
1801TaskWakeupMethWrapper_clear(TaskWakeupMethWrapper *o)
1802{
1803 Py_CLEAR(o->ww_task);
1804 return 0;
1805}
1806
1807static int
1808TaskWakeupMethWrapper_traverse(TaskWakeupMethWrapper *o,
1809 visitproc visit, void *arg)
1810{
1811 Py_VISIT(o->ww_task);
1812 return 0;
1813}
1814
1815static void
1816TaskWakeupMethWrapper_dealloc(TaskWakeupMethWrapper *o)
1817{
1818 PyObject_GC_UnTrack(o);
1819 (void)TaskWakeupMethWrapper_clear(o);
1820 Py_TYPE(o)->tp_free(o);
1821}
1822
Miss Islington (bot)60214dd2018-07-05 22:58:27 -07001823static PyTypeObject TaskWakeupMethWrapper_Type = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02001824 PyVarObject_HEAD_INIT(NULL, 0)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001825 "TaskWakeupMethWrapper",
1826 .tp_basicsize = sizeof(TaskWakeupMethWrapper),
1827 .tp_itemsize = 0,
1828 .tp_dealloc = (destructor)TaskWakeupMethWrapper_dealloc,
1829 .tp_call = (ternaryfunc)TaskWakeupMethWrapper_call,
1830 .tp_getattro = PyObject_GenericGetAttr,
1831 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
1832 .tp_traverse = (traverseproc)TaskWakeupMethWrapper_traverse,
1833 .tp_clear = (inquiry)TaskWakeupMethWrapper_clear,
1834};
1835
1836static PyObject *
1837TaskWakeupMethWrapper_new(TaskObj *task)
1838{
1839 TaskWakeupMethWrapper *o;
1840 o = PyObject_GC_New(TaskWakeupMethWrapper, &TaskWakeupMethWrapper_Type);
1841 if (o == NULL) {
1842 return NULL;
1843 }
1844
1845 Py_INCREF(task);
1846 o->ww_task = task;
1847
1848 PyObject_GC_Track(o);
1849 return (PyObject*) o;
1850}
1851
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001852/* ----- Task introspection helpers */
1853
1854static int
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001855register_task(PyObject *task)
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001856{
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001857 _Py_IDENTIFIER(add);
1858
1859 PyObject *res = _PyObject_CallMethodIdObjArgs(
1860 all_tasks, &PyId_add, task, NULL);
1861 if (res == NULL) {
1862 return -1;
1863 }
1864 Py_DECREF(res);
1865 return 0;
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001866}
1867
1868
1869static int
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001870unregister_task(PyObject *task)
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001871{
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001872 _Py_IDENTIFIER(discard);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001873
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001874 PyObject *res = _PyObject_CallMethodIdObjArgs(
1875 all_tasks, &PyId_discard, task, NULL);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001876 if (res == NULL) {
1877 return -1;
1878 }
1879 Py_DECREF(res);
1880 return 0;
1881}
1882
1883
1884static int
1885enter_task(PyObject *loop, PyObject *task)
1886{
1887 PyObject *item;
1888 Py_hash_t hash;
1889 hash = PyObject_Hash(loop);
1890 if (hash == -1) {
1891 return -1;
1892 }
1893 item = _PyDict_GetItem_KnownHash(current_tasks, loop, hash);
1894 if (item != NULL) {
Miss Islington (bot)52d17412018-05-20 07:34:28 -07001895 Py_INCREF(item);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001896 PyErr_Format(
1897 PyExc_RuntimeError,
1898 "Cannot enter into task %R while another " \
1899 "task %R is being executed.",
1900 task, item, NULL);
Miss Islington (bot)52d17412018-05-20 07:34:28 -07001901 Py_DECREF(item);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001902 return -1;
1903 }
Miss Islington (bot)52d17412018-05-20 07:34:28 -07001904 if (PyErr_Occurred()) {
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001905 return -1;
1906 }
Miss Islington (bot)52d17412018-05-20 07:34:28 -07001907 return _PyDict_SetItem_KnownHash(current_tasks, loop, task, hash);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001908}
1909
1910
1911static int
1912leave_task(PyObject *loop, PyObject *task)
1913/*[clinic end generated code: output=0ebf6db4b858fb41 input=51296a46313d1ad8]*/
1914{
1915 PyObject *item;
1916 Py_hash_t hash;
1917 hash = PyObject_Hash(loop);
1918 if (hash == -1) {
1919 return -1;
1920 }
1921 item = _PyDict_GetItem_KnownHash(current_tasks, loop, hash);
1922 if (item != task) {
1923 if (item == NULL) {
1924 /* Not entered, replace with None */
1925 item = Py_None;
1926 }
1927 PyErr_Format(
1928 PyExc_RuntimeError,
1929 "Leaving task %R does not match the current task %R.",
1930 task, item, NULL);
1931 return -1;
1932 }
1933 return _PyDict_DelItem_KnownHash(current_tasks, loop, hash);
1934}
1935
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001936/* ----- Task */
1937
1938/*[clinic input]
1939_asyncio.Task.__init__
1940
Serhiy Storchakabca49392017-09-03 08:10:14 +03001941 coro: object
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001942 *
Serhiy Storchakabca49392017-09-03 08:10:14 +03001943 loop: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001944
1945A coroutine wrapped in a Future.
1946[clinic start generated code]*/
1947
1948static int
1949_asyncio_Task___init___impl(TaskObj *self, PyObject *coro, PyObject *loop)
Serhiy Storchakabca49392017-09-03 08:10:14 +03001950/*[clinic end generated code: output=9f24774c2287fc2f input=8d132974b049593e]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001951{
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001952 if (future_init((FutureObj*)self, loop)) {
INADA Naokic411a7d2016-10-18 11:48:14 +09001953 return -1;
1954 }
INADA Naokic411a7d2016-10-18 11:48:14 +09001955
Yury Selivanova9d7e552017-12-19 07:18:45 -05001956 int is_coro = is_coroutine(coro);
1957 if (is_coro == -1) {
1958 return -1;
1959 }
1960 if (is_coro == 0) {
1961 self->task_log_destroy_pending = 0;
1962 PyErr_Format(PyExc_TypeError,
1963 "a coroutine was expected, got %R",
1964 coro, NULL);
1965 return -1;
Andrew Svetlovf74ef452017-12-15 07:04:38 +02001966 }
1967
Miss Islington (bot)ef20abe2018-02-13 03:32:18 -08001968 Py_XSETREF(self->task_context, PyContext_CopyCurrent());
Yury Selivanovf23746a2018-01-22 19:11:18 -05001969 if (self->task_context == NULL) {
1970 return -1;
1971 }
1972
Miss Islington (bot)ef20abe2018-02-13 03:32:18 -08001973 Py_CLEAR(self->task_fut_waiter);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001974 self->task_must_cancel = 0;
1975 self->task_log_destroy_pending = 1;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001976 Py_INCREF(coro);
Miss Islington (bot)ef20abe2018-02-13 03:32:18 -08001977 Py_XSETREF(self->task_coro, coro);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001978
1979 if (task_call_step_soon(self, NULL)) {
1980 return -1;
INADA Naokic411a7d2016-10-18 11:48:14 +09001981 }
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001982 return register_task((PyObject*)self);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001983}
1984
1985static int
1986TaskObj_clear(TaskObj *task)
1987{
1988 (void)FutureObj_clear((FutureObj*) task);
Yury Selivanovf23746a2018-01-22 19:11:18 -05001989 Py_CLEAR(task->task_context);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001990 Py_CLEAR(task->task_coro);
1991 Py_CLEAR(task->task_fut_waiter);
1992 return 0;
1993}
1994
1995static int
1996TaskObj_traverse(TaskObj *task, visitproc visit, void *arg)
1997{
Yury Selivanovf23746a2018-01-22 19:11:18 -05001998 Py_VISIT(task->task_context);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001999 Py_VISIT(task->task_coro);
2000 Py_VISIT(task->task_fut_waiter);
2001 (void)FutureObj_traverse((FutureObj*) task, visit, arg);
2002 return 0;
2003}
2004
2005static PyObject *
Miss Islington (bot)5ceb7012018-11-27 09:58:07 -08002006TaskObj_get_log_destroy_pending(TaskObj *task, void *Py_UNUSED(ignored))
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002007{
2008 if (task->task_log_destroy_pending) {
2009 Py_RETURN_TRUE;
2010 }
2011 else {
2012 Py_RETURN_FALSE;
2013 }
2014}
2015
2016static int
Miss Islington (bot)5ceb7012018-11-27 09:58:07 -08002017TaskObj_set_log_destroy_pending(TaskObj *task, PyObject *val, void *Py_UNUSED(ignored))
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002018{
Miss Islington (bot)cb272842018-12-17 07:10:20 -08002019 if (val == NULL) {
2020 PyErr_SetString(PyExc_AttributeError, "cannot delete attribute");
2021 return -1;
2022 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002023 int is_true = PyObject_IsTrue(val);
2024 if (is_true < 0) {
2025 return -1;
2026 }
2027 task->task_log_destroy_pending = is_true;
2028 return 0;
2029}
2030
2031static PyObject *
Miss Islington (bot)5ceb7012018-11-27 09:58:07 -08002032TaskObj_get_must_cancel(TaskObj *task, void *Py_UNUSED(ignored))
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002033{
2034 if (task->task_must_cancel) {
2035 Py_RETURN_TRUE;
2036 }
2037 else {
2038 Py_RETURN_FALSE;
2039 }
2040}
2041
2042static PyObject *
Miss Islington (bot)5ceb7012018-11-27 09:58:07 -08002043TaskObj_get_coro(TaskObj *task, void *Py_UNUSED(ignored))
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002044{
2045 if (task->task_coro) {
2046 Py_INCREF(task->task_coro);
2047 return task->task_coro;
2048 }
2049
2050 Py_RETURN_NONE;
2051}
2052
2053static PyObject *
Miss Islington (bot)5ceb7012018-11-27 09:58:07 -08002054TaskObj_get_fut_waiter(TaskObj *task, void *Py_UNUSED(ignored))
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002055{
2056 if (task->task_fut_waiter) {
2057 Py_INCREF(task->task_fut_waiter);
2058 return task->task_fut_waiter;
2059 }
2060
2061 Py_RETURN_NONE;
2062}
2063
2064/*[clinic input]
2065@classmethod
2066_asyncio.Task.current_task
2067
Serhiy Storchakabca49392017-09-03 08:10:14 +03002068 loop: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002069
2070Return the currently running task in an event loop or None.
2071
2072By default the current task for the current event loop is returned.
2073
2074None is returned when called not in the context of a Task.
2075[clinic start generated code]*/
2076
2077static PyObject *
2078_asyncio_Task_current_task_impl(PyTypeObject *type, PyObject *loop)
Serhiy Storchakabca49392017-09-03 08:10:14 +03002079/*[clinic end generated code: output=99fbe7332c516e03 input=cd14770c5b79c7eb]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002080{
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002081 PyObject *ret;
2082 PyObject *current_task_func;
2083
2084 if (PyErr_WarnEx(PyExc_PendingDeprecationWarning,
2085 "Task.current_task() is deprecated, " \
2086 "use asyncio.current_task() instead",
2087 1) < 0) {
2088 return NULL;
2089 }
2090
2091 current_task_func = _PyObject_GetAttrId(asyncio_mod, &PyId_current_task);
2092 if (current_task_func == NULL) {
2093 return NULL;
2094 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002095
Yury Selivanov8d26aa92017-03-02 22:16:33 -05002096 if (loop == Py_None) {
Yury Selivanova70232f2017-12-13 14:49:42 -05002097 loop = get_event_loop();
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002098 if (loop == NULL) {
Miss Islington (bot)52d17412018-05-20 07:34:28 -07002099 Py_DECREF(current_task_func);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002100 return NULL;
2101 }
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002102 ret = PyObject_CallFunctionObjArgs(current_task_func, loop, NULL);
2103 Py_DECREF(current_task_func);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002104 Py_DECREF(loop);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002105 return ret;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002106 }
2107 else {
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002108 ret = PyObject_CallFunctionObjArgs(current_task_func, loop, NULL);
2109 Py_DECREF(current_task_func);
2110 return ret;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002111 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002112}
2113
2114/*[clinic input]
2115@classmethod
2116_asyncio.Task.all_tasks
2117
Serhiy Storchakabca49392017-09-03 08:10:14 +03002118 loop: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002119
2120Return a set of all tasks for an event loop.
2121
2122By default all tasks for the current event loop are returned.
2123[clinic start generated code]*/
2124
2125static PyObject *
2126_asyncio_Task_all_tasks_impl(PyTypeObject *type, PyObject *loop)
Serhiy Storchakabca49392017-09-03 08:10:14 +03002127/*[clinic end generated code: output=11f9b20749ccca5d input=497f80bc9ce726b5]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002128{
2129 PyObject *res;
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002130 PyObject *all_tasks_func;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002131
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002132 if (PyErr_WarnEx(PyExc_PendingDeprecationWarning,
2133 "Task.all_tasks() is deprecated, " \
2134 "use asyncio.all_tasks() instead",
2135 1) < 0) {
2136 return NULL;
2137 }
2138
Miss Islington (bot)ddc613f2018-05-28 17:16:43 -07002139 all_tasks_func = _PyObject_GetAttrId(asyncio_mod, &PyId__all_tasks_compat);
Miss Islington (bot)52d17412018-05-20 07:34:28 -07002140 if (all_tasks_func == NULL) {
2141 return NULL;
2142 }
2143
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002144 res = PyObject_CallFunctionObjArgs(all_tasks_func, loop, NULL);
2145 Py_DECREF(all_tasks_func);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002146 return res;
2147}
2148
2149/*[clinic input]
2150_asyncio.Task._repr_info
2151[clinic start generated code]*/
2152
2153static PyObject *
2154_asyncio_Task__repr_info_impl(TaskObj *self)
2155/*[clinic end generated code: output=6a490eb66d5ba34b input=3c6d051ed3ddec8b]*/
2156{
Victor Stinnerde4ae3d2016-12-04 22:59:09 +01002157 return PyObject_CallFunctionObjArgs(
2158 asyncio_task_repr_info_func, self, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002159}
2160
2161/*[clinic input]
2162_asyncio.Task.cancel
2163
2164Request that this task cancel itself.
2165
2166This arranges for a CancelledError to be thrown into the
2167wrapped coroutine on the next cycle through the event loop.
2168The coroutine then has a chance to clean up or even deny
2169the request using try/except/finally.
2170
2171Unlike Future.cancel, this does not guarantee that the
2172task will be cancelled: the exception might be caught and
2173acted upon, delaying cancellation of the task or preventing
2174cancellation completely. The task may also return a value or
2175raise a different exception.
2176
2177Immediately after this method is called, Task.cancelled() will
2178not return True (unless the task was already cancelled). A
2179task will be marked as cancelled when the wrapped coroutine
2180terminates with a CancelledError exception (even if cancel()
2181was not called).
2182[clinic start generated code]*/
2183
2184static PyObject *
2185_asyncio_Task_cancel_impl(TaskObj *self)
2186/*[clinic end generated code: output=6bfc0479da9d5757 input=13f9bf496695cb52]*/
2187{
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +00002188 self->task_log_tb = 0;
2189
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002190 if (self->task_state != STATE_PENDING) {
2191 Py_RETURN_FALSE;
2192 }
2193
2194 if (self->task_fut_waiter) {
2195 PyObject *res;
2196 int is_true;
2197
2198 res = _PyObject_CallMethodId(
2199 self->task_fut_waiter, &PyId_cancel, NULL);
2200 if (res == NULL) {
2201 return NULL;
2202 }
2203
2204 is_true = PyObject_IsTrue(res);
2205 Py_DECREF(res);
2206 if (is_true < 0) {
2207 return NULL;
2208 }
2209
2210 if (is_true) {
2211 Py_RETURN_TRUE;
2212 }
2213 }
2214
2215 self->task_must_cancel = 1;
2216 Py_RETURN_TRUE;
2217}
2218
2219/*[clinic input]
2220_asyncio.Task.get_stack
2221
2222 *
Serhiy Storchakabca49392017-09-03 08:10:14 +03002223 limit: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002224
2225Return the list of stack frames for this task's coroutine.
2226
2227If the coroutine is not done, this returns the stack where it is
2228suspended. If the coroutine has completed successfully or was
2229cancelled, this returns an empty list. If the coroutine was
2230terminated by an exception, this returns the list of traceback
2231frames.
2232
2233The frames are always ordered from oldest to newest.
2234
2235The optional limit gives the maximum number of frames to
2236return; by default all available frames are returned. Its
2237meaning differs depending on whether a stack or a traceback is
2238returned: the newest frames of a stack are returned, but the
2239oldest frames of a traceback are returned. (This matches the
2240behavior of the traceback module.)
2241
2242For reasons beyond our control, only one stack frame is
2243returned for a suspended coroutine.
2244[clinic start generated code]*/
2245
2246static PyObject *
2247_asyncio_Task_get_stack_impl(TaskObj *self, PyObject *limit)
Serhiy Storchakabca49392017-09-03 08:10:14 +03002248/*[clinic end generated code: output=c9aeeeebd1e18118 input=05b323d42b809b90]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002249{
2250 return PyObject_CallFunctionObjArgs(
2251 asyncio_task_get_stack_func, self, limit, NULL);
2252}
2253
2254/*[clinic input]
2255_asyncio.Task.print_stack
2256
2257 *
Serhiy Storchakabca49392017-09-03 08:10:14 +03002258 limit: object = None
2259 file: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002260
2261Print the stack or traceback for this task's coroutine.
2262
2263This produces output similar to that of the traceback module,
2264for the frames retrieved by get_stack(). The limit argument
2265is passed to get_stack(). The file argument is an I/O stream
2266to which the output is written; by default output is written
2267to sys.stderr.
2268[clinic start generated code]*/
2269
2270static PyObject *
2271_asyncio_Task_print_stack_impl(TaskObj *self, PyObject *limit,
2272 PyObject *file)
Serhiy Storchakabca49392017-09-03 08:10:14 +03002273/*[clinic end generated code: output=7339e10314cd3f4d input=1a0352913b7fcd92]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002274{
2275 return PyObject_CallFunctionObjArgs(
2276 asyncio_task_print_stack_func, self, limit, file, NULL);
2277}
2278
2279/*[clinic input]
Yury Selivanov0cf16f92017-12-25 10:48:15 -05002280_asyncio.Task.set_result
2281
2282 result: object
2283 /
2284[clinic start generated code]*/
2285
2286static PyObject *
2287_asyncio_Task_set_result(TaskObj *self, PyObject *result)
2288/*[clinic end generated code: output=1dcae308bfcba318 input=9d1a00c07be41bab]*/
2289{
2290 PyErr_SetString(PyExc_RuntimeError,
2291 "Task does not support set_result operation");
2292 return NULL;
2293}
2294
2295/*[clinic input]
2296_asyncio.Task.set_exception
2297
2298 exception: object
2299 /
2300[clinic start generated code]*/
2301
2302static PyObject *
2303_asyncio_Task_set_exception(TaskObj *self, PyObject *exception)
2304/*[clinic end generated code: output=bc377fc28067303d input=9a8f65c83dcf893a]*/
2305{
2306 PyErr_SetString(PyExc_RuntimeError,
Andrew Svetlovfc359322017-12-30 15:40:27 +02002307 "Task does not support set_exception operation");
Yury Selivanov0cf16f92017-12-25 10:48:15 -05002308 return NULL;
2309}
2310
2311
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002312static void
2313TaskObj_finalize(TaskObj *task)
2314{
2315 _Py_IDENTIFIER(call_exception_handler);
2316 _Py_IDENTIFIER(task);
2317 _Py_IDENTIFIER(message);
2318 _Py_IDENTIFIER(source_traceback);
2319
Serhiy Storchakabca49392017-09-03 08:10:14 +03002320 PyObject *context;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002321 PyObject *message = NULL;
Serhiy Storchakabca49392017-09-03 08:10:14 +03002322 PyObject *func;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002323 PyObject *error_type, *error_value, *error_traceback;
2324
2325 if (task->task_state != STATE_PENDING || !task->task_log_destroy_pending) {
2326 goto done;
2327 }
2328
2329 /* Save the current exception, if any. */
2330 PyErr_Fetch(&error_type, &error_value, &error_traceback);
2331
2332 context = PyDict_New();
2333 if (context == NULL) {
2334 goto finally;
2335 }
2336
2337 message = PyUnicode_FromString("Task was destroyed but it is pending!");
2338 if (message == NULL) {
2339 goto finally;
2340 }
2341
2342 if (_PyDict_SetItemId(context, &PyId_message, message) < 0 ||
2343 _PyDict_SetItemId(context, &PyId_task, (PyObject*)task) < 0)
2344 {
2345 goto finally;
2346 }
2347
2348 if (task->task_source_tb != NULL) {
2349 if (_PyDict_SetItemId(context, &PyId_source_traceback,
2350 task->task_source_tb) < 0)
2351 {
2352 goto finally;
2353 }
2354 }
2355
2356 func = _PyObject_GetAttrId(task->task_loop, &PyId_call_exception_handler);
2357 if (func != NULL) {
Serhiy Storchakabca49392017-09-03 08:10:14 +03002358 PyObject *res = PyObject_CallFunctionObjArgs(func, context, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002359 if (res == NULL) {
2360 PyErr_WriteUnraisable(func);
2361 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03002362 else {
2363 Py_DECREF(res);
2364 }
2365 Py_DECREF(func);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002366 }
2367
2368finally:
Serhiy Storchakabca49392017-09-03 08:10:14 +03002369 Py_XDECREF(context);
2370 Py_XDECREF(message);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002371
2372 /* Restore the saved exception. */
2373 PyErr_Restore(error_type, error_value, error_traceback);
2374
2375done:
2376 FutureObj_finalize((FutureObj*)task);
2377}
2378
2379static void TaskObj_dealloc(PyObject *); /* Needs Task_CheckExact */
2380
2381static PyMethodDef TaskType_methods[] = {
2382 _ASYNCIO_FUTURE_RESULT_METHODDEF
2383 _ASYNCIO_FUTURE_EXCEPTION_METHODDEF
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002384 _ASYNCIO_FUTURE_ADD_DONE_CALLBACK_METHODDEF
2385 _ASYNCIO_FUTURE_REMOVE_DONE_CALLBACK_METHODDEF
2386 _ASYNCIO_FUTURE_CANCELLED_METHODDEF
2387 _ASYNCIO_FUTURE_DONE_METHODDEF
Yury Selivanov0cf16f92017-12-25 10:48:15 -05002388 _ASYNCIO_TASK_SET_RESULT_METHODDEF
2389 _ASYNCIO_TASK_SET_EXCEPTION_METHODDEF
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002390 _ASYNCIO_TASK_CURRENT_TASK_METHODDEF
2391 _ASYNCIO_TASK_ALL_TASKS_METHODDEF
2392 _ASYNCIO_TASK_CANCEL_METHODDEF
2393 _ASYNCIO_TASK_GET_STACK_METHODDEF
2394 _ASYNCIO_TASK_PRINT_STACK_METHODDEF
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002395 _ASYNCIO_TASK__REPR_INFO_METHODDEF
2396 {NULL, NULL} /* Sentinel */
2397};
2398
2399static PyGetSetDef TaskType_getsetlist[] = {
2400 FUTURE_COMMON_GETSETLIST
2401 {"_log_destroy_pending", (getter)TaskObj_get_log_destroy_pending,
2402 (setter)TaskObj_set_log_destroy_pending, NULL},
2403 {"_must_cancel", (getter)TaskObj_get_must_cancel, NULL, NULL},
2404 {"_coro", (getter)TaskObj_get_coro, NULL, NULL},
2405 {"_fut_waiter", (getter)TaskObj_get_fut_waiter, NULL, NULL},
2406 {NULL} /* Sentinel */
2407};
2408
2409static PyTypeObject TaskType = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02002410 PyVarObject_HEAD_INIT(NULL, 0)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002411 "_asyncio.Task",
2412 sizeof(TaskObj), /* tp_basicsize */
2413 .tp_base = &FutureType,
2414 .tp_dealloc = TaskObj_dealloc,
2415 .tp_as_async = &FutureType_as_async,
2416 .tp_repr = (reprfunc)FutureObj_repr,
2417 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE
2418 | Py_TPFLAGS_HAVE_FINALIZE,
2419 .tp_doc = _asyncio_Task___init____doc__,
2420 .tp_traverse = (traverseproc)TaskObj_traverse,
2421 .tp_clear = (inquiry)TaskObj_clear,
2422 .tp_weaklistoffset = offsetof(TaskObj, task_weakreflist),
2423 .tp_iter = (getiterfunc)future_new_iter,
2424 .tp_methods = TaskType_methods,
2425 .tp_getset = TaskType_getsetlist,
2426 .tp_dictoffset = offsetof(TaskObj, dict),
2427 .tp_init = (initproc)_asyncio_Task___init__,
2428 .tp_new = PyType_GenericNew,
2429 .tp_finalize = (destructor)TaskObj_finalize,
2430};
2431
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002432static void
2433TaskObj_dealloc(PyObject *self)
2434{
2435 TaskObj *task = (TaskObj *)self;
2436
2437 if (Task_CheckExact(self)) {
2438 /* When fut is subclass of Task, finalizer is called from
2439 * subtype_dealloc.
2440 */
2441 if (PyObject_CallFinalizerFromDealloc(self) < 0) {
2442 // resurrected.
2443 return;
2444 }
2445 }
2446
Alexander Mohrde34cbe2017-08-01 23:31:07 -07002447 PyObject_GC_UnTrack(self);
2448
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002449 if (task->task_weakreflist != NULL) {
2450 PyObject_ClearWeakRefs(self);
2451 }
2452
2453 (void)TaskObj_clear(task);
2454 Py_TYPE(task)->tp_free(task);
2455}
2456
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002457static int
2458task_call_step_soon(TaskObj *task, PyObject *arg)
2459{
Serhiy Storchakabca49392017-09-03 08:10:14 +03002460 PyObject *cb = TaskStepMethWrapper_new(task, arg);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002461 if (cb == NULL) {
2462 return -1;
2463 }
2464
Yury Selivanovf23746a2018-01-22 19:11:18 -05002465 int ret = call_soon(task->task_loop, cb, NULL, task->task_context);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002466 Py_DECREF(cb);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05002467 return ret;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002468}
2469
2470static PyObject *
2471task_set_error_soon(TaskObj *task, PyObject *et, const char *format, ...)
2472{
2473 PyObject* msg;
2474
2475 va_list vargs;
2476#ifdef HAVE_STDARG_PROTOTYPES
2477 va_start(vargs, format);
2478#else
2479 va_start(vargs);
2480#endif
2481 msg = PyUnicode_FromFormatV(format, vargs);
2482 va_end(vargs);
2483
2484 if (msg == NULL) {
2485 return NULL;
2486 }
2487
Victor Stinnerde4ae3d2016-12-04 22:59:09 +01002488 PyObject *e = PyObject_CallFunctionObjArgs(et, msg, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002489 Py_DECREF(msg);
2490 if (e == NULL) {
2491 return NULL;
2492 }
2493
2494 if (task_call_step_soon(task, e) == -1) {
2495 Py_DECREF(e);
2496 return NULL;
2497 }
2498
2499 Py_DECREF(e);
2500 Py_RETURN_NONE;
2501}
2502
2503static PyObject *
2504task_step_impl(TaskObj *task, PyObject *exc)
2505{
2506 int res;
2507 int clear_exc = 0;
2508 PyObject *result = NULL;
Serhiy Storchakabca49392017-09-03 08:10:14 +03002509 PyObject *coro;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002510 PyObject *o;
2511
2512 if (task->task_state != STATE_PENDING) {
Yury Selivanov0cf16f92017-12-25 10:48:15 -05002513 PyErr_Format(asyncio_InvalidStateError,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002514 "_step(): already done: %R %R",
2515 task,
2516 exc ? exc : Py_None);
INADA Naokic411a7d2016-10-18 11:48:14 +09002517 goto fail;
2518 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09002519
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002520 if (task->task_must_cancel) {
2521 assert(exc != Py_None);
2522
2523 if (exc) {
2524 /* Check if exc is a CancelledError */
2525 res = PyObject_IsInstance(exc, asyncio_CancelledError);
2526 if (res == -1) {
2527 /* An error occurred, abort */
2528 goto fail;
2529 }
2530 if (res == 0) {
2531 /* exc is not CancelledError; reset it to NULL */
2532 exc = NULL;
2533 }
2534 }
2535
2536 if (!exc) {
2537 /* exc was not a CancelledError */
Victor Stinnerf17c3de2016-12-06 18:46:19 +01002538 exc = _PyObject_CallNoArg(asyncio_CancelledError);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002539 if (!exc) {
2540 goto fail;
2541 }
2542 clear_exc = 1;
2543 }
2544
2545 task->task_must_cancel = 0;
2546 }
2547
2548 Py_CLEAR(task->task_fut_waiter);
2549
Serhiy Storchakabca49392017-09-03 08:10:14 +03002550 coro = task->task_coro;
2551 if (coro == NULL) {
2552 PyErr_SetString(PyExc_RuntimeError, "uninitialized Task object");
2553 return NULL;
2554 }
2555
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002556 if (exc == NULL) {
2557 if (PyGen_CheckExact(coro) || PyCoro_CheckExact(coro)) {
2558 result = _PyGen_Send((PyGenObject*)coro, Py_None);
2559 }
2560 else {
Victor Stinnerb6ed57d2016-12-09 14:24:02 +01002561 result = _PyObject_CallMethodIdObjArgs(coro, &PyId_send,
2562 Py_None, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002563 }
2564 }
2565 else {
Victor Stinnerb6ed57d2016-12-09 14:24:02 +01002566 result = _PyObject_CallMethodIdObjArgs(coro, &PyId_throw,
2567 exc, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002568 if (clear_exc) {
2569 /* We created 'exc' during this call */
Serhiy Storchakabca49392017-09-03 08:10:14 +03002570 Py_DECREF(exc);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002571 }
2572 }
2573
2574 if (result == NULL) {
2575 PyObject *et, *ev, *tb;
2576
2577 if (_PyGen_FetchStopIterationValue(&o) == 0) {
2578 /* The error is StopIteration and that means that
2579 the underlying coroutine has resolved */
INADA Naoki991adca2017-05-11 21:18:38 +09002580 if (task->task_must_cancel) {
2581 // Task is cancelled right before coro stops.
2582 Py_DECREF(o);
2583 task->task_must_cancel = 0;
2584 et = asyncio_CancelledError;
2585 Py_INCREF(et);
2586 ev = NULL;
2587 tb = NULL;
2588 goto set_exception;
2589 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002590 PyObject *res = future_set_result((FutureObj*)task, o);
2591 Py_DECREF(o);
2592 if (res == NULL) {
2593 return NULL;
2594 }
2595 Py_DECREF(res);
2596 Py_RETURN_NONE;
2597 }
2598
2599 if (PyErr_ExceptionMatches(asyncio_CancelledError)) {
2600 /* CancelledError */
2601 PyErr_Clear();
2602 return future_cancel((FutureObj*)task);
2603 }
2604
2605 /* Some other exception; pop it and call Task.set_exception() */
2606 PyErr_Fetch(&et, &ev, &tb);
INADA Naoki991adca2017-05-11 21:18:38 +09002607
2608set_exception:
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002609 assert(et);
2610 if (!ev || !PyObject_TypeCheck(ev, (PyTypeObject *) et)) {
2611 PyErr_NormalizeException(&et, &ev, &tb);
2612 }
Yury Selivanovedfe8862016-12-01 11:37:47 -05002613 if (tb != NULL) {
2614 PyException_SetTraceback(ev, tb);
2615 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002616 o = future_set_exception((FutureObj*)task, ev);
2617 if (!o) {
2618 /* An exception in Task.set_exception() */
Serhiy Storchakabca49392017-09-03 08:10:14 +03002619 Py_DECREF(et);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002620 Py_XDECREF(tb);
2621 Py_XDECREF(ev);
2622 goto fail;
2623 }
2624 assert(o == Py_None);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002625 Py_DECREF(o);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002626
2627 if (!PyErr_GivenExceptionMatches(et, PyExc_Exception)) {
2628 /* We've got a BaseException; re-raise it */
2629 PyErr_Restore(et, ev, tb);
2630 goto fail;
2631 }
2632
Serhiy Storchakabca49392017-09-03 08:10:14 +03002633 Py_DECREF(et);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002634 Py_XDECREF(tb);
2635 Py_XDECREF(ev);
2636
2637 Py_RETURN_NONE;
2638 }
2639
2640 if (result == (PyObject*)task) {
2641 /* We have a task that wants to await on itself */
2642 goto self_await;
2643 }
2644
2645 /* Check if `result` is FutureObj or TaskObj (and not a subclass) */
2646 if (Future_CheckExact(result) || Task_CheckExact(result)) {
2647 PyObject *wrapper;
2648 PyObject *res;
2649 FutureObj *fut = (FutureObj*)result;
2650
2651 /* Check if `result` future is attached to a different loop */
2652 if (fut->fut_loop != task->task_loop) {
2653 goto different_loop;
2654 }
2655
2656 if (fut->fut_blocking) {
2657 fut->fut_blocking = 0;
2658
2659 /* result.add_done_callback(task._wakeup) */
2660 wrapper = TaskWakeupMethWrapper_new(task);
2661 if (wrapper == NULL) {
2662 goto fail;
2663 }
Yury Selivanovf23746a2018-01-22 19:11:18 -05002664 res = future_add_done_callback(
2665 (FutureObj*)result, wrapper, task->task_context);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002666 Py_DECREF(wrapper);
2667 if (res == NULL) {
2668 goto fail;
2669 }
2670 Py_DECREF(res);
2671
2672 /* task._fut_waiter = result */
2673 task->task_fut_waiter = result; /* no incref is necessary */
2674
2675 if (task->task_must_cancel) {
2676 PyObject *r;
Elvis Pranskevichusa67bd53d2018-10-03 11:49:00 -04002677 int is_true;
Serhiy Storchakad9212202018-10-05 21:58:15 +03002678 r = _PyObject_CallMethodId(result, &PyId_cancel, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002679 if (r == NULL) {
2680 return NULL;
2681 }
Elvis Pranskevichusa67bd53d2018-10-03 11:49:00 -04002682 is_true = PyObject_IsTrue(r);
2683 Py_DECREF(r);
2684 if (is_true < 0) {
2685 return NULL;
2686 }
2687 else if (is_true) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002688 task->task_must_cancel = 0;
2689 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002690 }
2691
2692 Py_RETURN_NONE;
2693 }
2694 else {
2695 goto yield_insteadof_yf;
2696 }
2697 }
2698
2699 /* Check if `result` is a Future-compatible object */
2700 o = PyObject_GetAttrString(result, "_asyncio_future_blocking");
2701 if (o == NULL) {
2702 if (PyErr_ExceptionMatches(PyExc_AttributeError)) {
2703 PyErr_Clear();
2704 }
2705 else {
2706 goto fail;
2707 }
2708 }
2709 else {
2710 if (o == Py_None) {
Serhiy Storchakabca49392017-09-03 08:10:14 +03002711 Py_DECREF(o);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002712 }
2713 else {
2714 /* `result` is a Future-compatible object */
2715 PyObject *wrapper;
2716 PyObject *res;
2717
2718 int blocking = PyObject_IsTrue(o);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002719 Py_DECREF(o);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002720 if (blocking < 0) {
2721 goto fail;
2722 }
2723
2724 /* Check if `result` future is attached to a different loop */
Yury Selivanovca9b36c2017-12-23 15:04:15 -05002725 PyObject *oloop = get_future_loop(result);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002726 if (oloop == NULL) {
2727 goto fail;
2728 }
2729 if (oloop != task->task_loop) {
2730 Py_DECREF(oloop);
2731 goto different_loop;
2732 }
2733 else {
2734 Py_DECREF(oloop);
2735 }
2736
2737 if (blocking) {
2738 /* result._asyncio_future_blocking = False */
2739 if (PyObject_SetAttrString(
2740 result, "_asyncio_future_blocking", Py_False) == -1) {
2741 goto fail;
2742 }
2743
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002744 wrapper = TaskWakeupMethWrapper_new(task);
2745 if (wrapper == NULL) {
2746 goto fail;
2747 }
Yury Selivanovf23746a2018-01-22 19:11:18 -05002748
2749 /* result.add_done_callback(task._wakeup) */
2750 PyObject *add_cb = _PyObject_GetAttrId(
2751 result, &PyId_add_done_callback);
2752 if (add_cb == NULL) {
Miss Islington (bot)52d17412018-05-20 07:34:28 -07002753 Py_DECREF(wrapper);
Yury Selivanovf23746a2018-01-22 19:11:18 -05002754 goto fail;
2755 }
2756 PyObject *stack[2];
2757 stack[0] = wrapper;
2758 stack[1] = (PyObject *)task->task_context;
2759 res = _PyObject_FastCallKeywords(
2760 add_cb, stack, 1, context_kwname);
2761 Py_DECREF(add_cb);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002762 Py_DECREF(wrapper);
2763 if (res == NULL) {
2764 goto fail;
2765 }
2766 Py_DECREF(res);
2767
2768 /* task._fut_waiter = result */
2769 task->task_fut_waiter = result; /* no incref is necessary */
2770
2771 if (task->task_must_cancel) {
2772 PyObject *r;
2773 int is_true;
2774 r = _PyObject_CallMethodId(result, &PyId_cancel, NULL);
2775 if (r == NULL) {
2776 return NULL;
2777 }
2778 is_true = PyObject_IsTrue(r);
2779 Py_DECREF(r);
2780 if (is_true < 0) {
2781 return NULL;
2782 }
2783 else if (is_true) {
2784 task->task_must_cancel = 0;
2785 }
2786 }
2787
2788 Py_RETURN_NONE;
2789 }
2790 else {
2791 goto yield_insteadof_yf;
2792 }
2793 }
2794 }
2795
2796 /* Check if `result` is None */
2797 if (result == Py_None) {
2798 /* Bare yield relinquishes control for one event loop iteration. */
2799 if (task_call_step_soon(task, NULL)) {
2800 goto fail;
2801 }
2802 return result;
2803 }
2804
2805 /* Check if `result` is a generator */
Victor Stinnerde4ae3d2016-12-04 22:59:09 +01002806 o = PyObject_CallFunctionObjArgs(inspect_isgenerator, result, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002807 if (o == NULL) {
2808 /* An exception in inspect.isgenerator */
2809 goto fail;
2810 }
2811 res = PyObject_IsTrue(o);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002812 Py_DECREF(o);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002813 if (res == -1) {
2814 /* An exception while checking if 'val' is True */
2815 goto fail;
2816 }
2817 if (res == 1) {
2818 /* `result` is a generator */
Miss Islington (bot)52d17412018-05-20 07:34:28 -07002819 o = task_set_error_soon(
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002820 task, PyExc_RuntimeError,
2821 "yield was used instead of yield from for "
Miss Islington (bot)52d17412018-05-20 07:34:28 -07002822 "generator in task %R with %R", task, result);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002823 Py_DECREF(result);
Miss Islington (bot)52d17412018-05-20 07:34:28 -07002824 return o;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002825 }
2826
2827 /* The `result` is none of the above */
Miss Islington (bot)52d17412018-05-20 07:34:28 -07002828 o = task_set_error_soon(
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002829 task, PyExc_RuntimeError, "Task got bad yield: %R", result);
Miss Islington (bot)52d17412018-05-20 07:34:28 -07002830 Py_DECREF(result);
2831 return o;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002832
2833self_await:
2834 o = task_set_error_soon(
2835 task, PyExc_RuntimeError,
2836 "Task cannot await on itself: %R", task);
2837 Py_DECREF(result);
2838 return o;
2839
2840yield_insteadof_yf:
2841 o = task_set_error_soon(
2842 task, PyExc_RuntimeError,
2843 "yield was used instead of yield from "
2844 "in task %R with %R",
2845 task, result);
2846 Py_DECREF(result);
2847 return o;
2848
2849different_loop:
2850 o = task_set_error_soon(
2851 task, PyExc_RuntimeError,
2852 "Task %R got Future %R attached to a different loop",
2853 task, result);
2854 Py_DECREF(result);
2855 return o;
2856
2857fail:
2858 Py_XDECREF(result);
2859 return NULL;
2860}
2861
2862static PyObject *
2863task_step(TaskObj *task, PyObject *exc)
2864{
2865 PyObject *res;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002866
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002867 if (enter_task(task->task_loop, (PyObject*)task) < 0) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002868 return NULL;
2869 }
2870
2871 res = task_step_impl(task, exc);
2872
2873 if (res == NULL) {
2874 PyObject *et, *ev, *tb;
2875 PyErr_Fetch(&et, &ev, &tb);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002876 leave_task(task->task_loop, (PyObject*)task);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002877 _PyErr_ChainExceptions(et, ev, tb);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002878 return NULL;
2879 }
2880 else {
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002881 if(leave_task(task->task_loop, (PyObject*)task) < 0) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002882 Py_DECREF(res);
2883 return NULL;
2884 }
2885 else {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002886 return res;
2887 }
2888 }
2889}
2890
2891static PyObject *
2892task_wakeup(TaskObj *task, PyObject *o)
2893{
Serhiy Storchakabca49392017-09-03 08:10:14 +03002894 PyObject *et, *ev, *tb;
2895 PyObject *result;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002896 assert(o);
2897
2898 if (Future_CheckExact(o) || Task_CheckExact(o)) {
2899 PyObject *fut_result = NULL;
2900 int res = future_get_result((FutureObj*)o, &fut_result);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002901
2902 switch(res) {
2903 case -1:
2904 assert(fut_result == NULL);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002905 break; /* exception raised */
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002906 case 0:
2907 Py_DECREF(fut_result);
Yury Selivanov22feeb82018-01-24 11:31:01 -05002908 return task_step(task, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002909 default:
2910 assert(res == 1);
Yury Selivanov22feeb82018-01-24 11:31:01 -05002911 result = task_step(task, fut_result);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002912 Py_DECREF(fut_result);
2913 return result;
2914 }
2915 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002916 else {
Serhiy Storchakabca49392017-09-03 08:10:14 +03002917 PyObject *fut_result = PyObject_CallMethod(o, "result", NULL);
2918 if (fut_result != NULL) {
2919 Py_DECREF(fut_result);
Yury Selivanov22feeb82018-01-24 11:31:01 -05002920 return task_step(task, NULL);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002921 }
2922 /* exception raised */
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002923 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03002924
2925 PyErr_Fetch(&et, &ev, &tb);
2926 if (!PyErr_GivenExceptionMatches(et, PyExc_Exception)) {
2927 /* We've got a BaseException; re-raise it */
2928 PyErr_Restore(et, ev, tb);
2929 return NULL;
2930 }
2931 if (!ev || !PyObject_TypeCheck(ev, (PyTypeObject *) et)) {
2932 PyErr_NormalizeException(&et, &ev, &tb);
2933 }
2934
Yury Selivanov22feeb82018-01-24 11:31:01 -05002935 result = task_step(task, ev);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002936
2937 Py_DECREF(et);
2938 Py_XDECREF(tb);
2939 Py_XDECREF(ev);
2940
2941 return result;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002942}
2943
2944
Yury Selivanova70232f2017-12-13 14:49:42 -05002945/*********************** Functions **************************/
2946
2947
2948/*[clinic input]
2949_asyncio._get_running_loop
2950
2951Return the running event loop or None.
2952
2953This is a low-level function intended to be used by event loops.
2954This function is thread-specific.
2955
2956[clinic start generated code]*/
2957
2958static PyObject *
2959_asyncio__get_running_loop_impl(PyObject *module)
2960/*[clinic end generated code: output=b4390af721411a0a input=0a21627e25a4bd43]*/
2961{
2962 PyObject *loop;
2963 if (get_running_loop(&loop)) {
2964 return NULL;
2965 }
2966 if (loop == NULL) {
2967 /* There's no currently running event loop */
2968 Py_RETURN_NONE;
2969 }
2970 return loop;
2971}
2972
2973/*[clinic input]
2974_asyncio._set_running_loop
2975 loop: 'O'
2976 /
2977
2978Set the running event loop.
2979
2980This is a low-level function intended to be used by event loops.
2981This function is thread-specific.
2982[clinic start generated code]*/
2983
2984static PyObject *
2985_asyncio__set_running_loop(PyObject *module, PyObject *loop)
2986/*[clinic end generated code: output=ae56bf7a28ca189a input=4c9720233d606604]*/
2987{
2988 if (set_running_loop(loop)) {
2989 return NULL;
2990 }
2991 Py_RETURN_NONE;
2992}
2993
2994/*[clinic input]
2995_asyncio.get_event_loop
2996
2997Return an asyncio event loop.
2998
2999When called from a coroutine or a callback (e.g. scheduled with
3000call_soon or similar API), this function will always return the
3001running event loop.
3002
3003If there is no running event loop set, the function will return
3004the result of `get_event_loop_policy().get_event_loop()` call.
3005[clinic start generated code]*/
3006
3007static PyObject *
3008_asyncio_get_event_loop_impl(PyObject *module)
3009/*[clinic end generated code: output=2a2d8b2f824c648b input=9364bf2916c8655d]*/
3010{
3011 return get_event_loop();
3012}
3013
3014/*[clinic input]
3015_asyncio.get_running_loop
3016
3017Return the running event loop. Raise a RuntimeError if there is none.
3018
3019This function is thread-specific.
3020[clinic start generated code]*/
3021
3022static PyObject *
3023_asyncio_get_running_loop_impl(PyObject *module)
3024/*[clinic end generated code: output=c247b5f9e529530e input=2a3bf02ba39f173d]*/
3025{
3026 PyObject *loop;
3027 if (get_running_loop(&loop)) {
3028 return NULL;
3029 }
3030 if (loop == NULL) {
3031 /* There's no currently running event loop */
3032 PyErr_SetString(
3033 PyExc_RuntimeError, "no running event loop");
3034 }
3035 return loop;
3036}
3037
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003038/*[clinic input]
3039_asyncio._register_task
3040
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003041 task: object
3042
3043Register a new task in asyncio as executed by loop.
3044
3045Returns None.
3046[clinic start generated code]*/
3047
3048static PyObject *
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003049_asyncio__register_task_impl(PyObject *module, PyObject *task)
3050/*[clinic end generated code: output=8672dadd69a7d4e2 input=21075aaea14dfbad]*/
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003051{
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003052 if (register_task(task) < 0) {
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003053 return NULL;
3054 }
3055 Py_RETURN_NONE;
3056}
3057
3058
3059/*[clinic input]
3060_asyncio._unregister_task
3061
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003062 task: object
3063
3064Unregister a task.
3065
3066Returns None.
3067[clinic start generated code]*/
3068
3069static PyObject *
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003070_asyncio__unregister_task_impl(PyObject *module, PyObject *task)
3071/*[clinic end generated code: output=6e5585706d568a46 input=28fb98c3975f7bdc]*/
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003072{
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003073 if (unregister_task(task) < 0) {
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003074 return NULL;
3075 }
3076 Py_RETURN_NONE;
3077}
3078
3079
3080/*[clinic input]
3081_asyncio._enter_task
3082
3083 loop: object
3084 task: object
3085
3086Enter into task execution or resume suspended task.
3087
3088Task belongs to loop.
3089
3090Returns None.
3091[clinic start generated code]*/
3092
3093static PyObject *
3094_asyncio__enter_task_impl(PyObject *module, PyObject *loop, PyObject *task)
3095/*[clinic end generated code: output=a22611c858035b73 input=de1b06dca70d8737]*/
3096{
3097 if (enter_task(loop, task) < 0) {
3098 return NULL;
3099 }
3100 Py_RETURN_NONE;
3101}
3102
3103
3104/*[clinic input]
3105_asyncio._leave_task
3106
3107 loop: object
3108 task: object
3109
3110Leave task execution or suspend a task.
3111
3112Task belongs to loop.
3113
3114Returns None.
3115[clinic start generated code]*/
3116
3117static PyObject *
3118_asyncio__leave_task_impl(PyObject *module, PyObject *loop, PyObject *task)
3119/*[clinic end generated code: output=0ebf6db4b858fb41 input=51296a46313d1ad8]*/
3120{
3121 if (leave_task(loop, task) < 0) {
3122 return NULL;
3123 }
3124 Py_RETURN_NONE;
3125}
3126
Yury Selivanova70232f2017-12-13 14:49:42 -05003127
Yury Selivanov9d411c12018-01-23 15:10:03 -05003128/*********************** PyRunningLoopHolder ********************/
3129
3130
3131static PyRunningLoopHolder *
3132new_running_loop_holder(PyObject *loop)
3133{
3134 PyRunningLoopHolder *rl = PyObject_New(
3135 PyRunningLoopHolder, &PyRunningLoopHolder_Type);
3136 if (rl == NULL) {
3137 return NULL;
3138 }
3139
3140#if defined(HAVE_GETPID) && !defined(MS_WINDOWS)
3141 rl->rl_pid = getpid();
3142#endif
3143
3144 Py_INCREF(loop);
3145 rl->rl_loop = loop;
3146
3147 return rl;
3148}
3149
3150
3151static void
3152PyRunningLoopHolder_tp_dealloc(PyRunningLoopHolder *rl)
3153{
3154 Py_CLEAR(rl->rl_loop);
3155 PyObject_Free(rl);
3156}
3157
3158
3159static PyTypeObject PyRunningLoopHolder_Type = {
3160 PyVarObject_HEAD_INIT(NULL, 0)
3161 "_RunningLoopHolder",
3162 sizeof(PyRunningLoopHolder),
3163 .tp_getattro = PyObject_GenericGetAttr,
3164 .tp_flags = Py_TPFLAGS_DEFAULT,
3165 .tp_dealloc = (destructor)PyRunningLoopHolder_tp_dealloc,
3166};
3167
3168
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003169/*********************** Module **************************/
3170
3171
3172static void
Zackery Spytze40ad792017-12-19 11:48:13 -07003173module_free_freelists(void)
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05003174{
3175 PyObject *next;
3176 PyObject *current;
3177
3178 next = (PyObject*) fi_freelist;
3179 while (next != NULL) {
3180 assert(fi_freelist_len > 0);
3181 fi_freelist_len--;
3182
3183 current = next;
3184 next = (PyObject*) ((futureiterobject*) current)->future;
3185 PyObject_GC_Del(current);
3186 }
3187 assert(fi_freelist_len == 0);
3188 fi_freelist = NULL;
3189}
3190
3191
3192static void
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003193module_free(void *m)
3194{
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003195 Py_CLEAR(asyncio_mod);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003196 Py_CLEAR(inspect_isgenerator);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003197 Py_CLEAR(traceback_extract_stack);
3198 Py_CLEAR(asyncio_future_repr_info_func);
3199 Py_CLEAR(asyncio_get_event_loop_policy);
3200 Py_CLEAR(asyncio_iscoroutine_func);
3201 Py_CLEAR(asyncio_task_get_stack_func);
3202 Py_CLEAR(asyncio_task_print_stack_func);
3203 Py_CLEAR(asyncio_task_repr_info_func);
3204 Py_CLEAR(asyncio_InvalidStateError);
3205 Py_CLEAR(asyncio_CancelledError);
3206
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003207 Py_CLEAR(all_tasks);
Yury Selivanova9d7e552017-12-19 07:18:45 -05003208 Py_CLEAR(current_tasks);
3209 Py_CLEAR(iscoroutine_typecache);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05003210
Yury Selivanovf23746a2018-01-22 19:11:18 -05003211 Py_CLEAR(context_kwname);
3212
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05003213 module_free_freelists();
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003214}
3215
3216static int
3217module_init(void)
3218{
3219 PyObject *module = NULL;
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003220
3221 asyncio_mod = PyImport_ImportModule("asyncio");
3222 if (asyncio_mod == NULL) {
3223 goto fail;
3224 }
3225
3226 current_tasks = PyDict_New();
3227 if (current_tasks == NULL) {
3228 goto fail;
3229 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003230
Yury Selivanova9d7e552017-12-19 07:18:45 -05003231 iscoroutine_typecache = PySet_New(NULL);
3232 if (iscoroutine_typecache == NULL) {
3233 goto fail;
3234 }
3235
Yury Selivanovf23746a2018-01-22 19:11:18 -05003236
3237 context_kwname = PyTuple_New(1);
3238 if (context_kwname == NULL) {
3239 goto fail;
3240 }
3241 PyObject *context_str = PyUnicode_FromString("context");
3242 if (context_str == NULL) {
3243 goto fail;
3244 }
3245 PyTuple_SET_ITEM(context_kwname, 0, context_str);
3246
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003247#define WITH_MOD(NAME) \
3248 Py_CLEAR(module); \
3249 module = PyImport_ImportModule(NAME); \
3250 if (module == NULL) { \
Serhiy Storchakabca49392017-09-03 08:10:14 +03003251 goto fail; \
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003252 }
3253
3254#define GET_MOD_ATTR(VAR, NAME) \
3255 VAR = PyObject_GetAttrString(module, NAME); \
3256 if (VAR == NULL) { \
3257 goto fail; \
3258 }
3259
3260 WITH_MOD("asyncio.events")
Yury Selivanova70232f2017-12-13 14:49:42 -05003261 GET_MOD_ATTR(asyncio_get_event_loop_policy, "get_event_loop_policy")
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003262
3263 WITH_MOD("asyncio.base_futures")
3264 GET_MOD_ATTR(asyncio_future_repr_info_func, "_future_repr_info")
3265 GET_MOD_ATTR(asyncio_InvalidStateError, "InvalidStateError")
3266 GET_MOD_ATTR(asyncio_CancelledError, "CancelledError")
3267
3268 WITH_MOD("asyncio.base_tasks")
3269 GET_MOD_ATTR(asyncio_task_repr_info_func, "_task_repr_info")
3270 GET_MOD_ATTR(asyncio_task_get_stack_func, "_task_get_stack")
3271 GET_MOD_ATTR(asyncio_task_print_stack_func, "_task_print_stack")
3272
Andrew Svetlovf74ef452017-12-15 07:04:38 +02003273 WITH_MOD("asyncio.coroutines")
3274 GET_MOD_ATTR(asyncio_iscoroutine_func, "iscoroutine")
3275
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003276 WITH_MOD("inspect")
3277 GET_MOD_ATTR(inspect_isgenerator, "isgenerator")
3278
3279 WITH_MOD("traceback")
3280 GET_MOD_ATTR(traceback_extract_stack, "extract_stack")
3281
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003282 PyObject *weak_set;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003283 WITH_MOD("weakref")
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003284 GET_MOD_ATTR(weak_set, "WeakSet");
3285 all_tasks = _PyObject_CallNoArg(weak_set);
3286 Py_CLEAR(weak_set);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003287 if (all_tasks == NULL) {
INADA Naokic411a7d2016-10-18 11:48:14 +09003288 goto fail;
3289 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003290
Serhiy Storchakabca49392017-09-03 08:10:14 +03003291 Py_DECREF(module);
INADA Naokic411a7d2016-10-18 11:48:14 +09003292 return 0;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003293
INADA Naokic411a7d2016-10-18 11:48:14 +09003294fail:
INADA Naokic411a7d2016-10-18 11:48:14 +09003295 Py_CLEAR(module);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003296 module_free(NULL);
INADA Naokic411a7d2016-10-18 11:48:14 +09003297 return -1;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003298
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003299#undef WITH_MOD
3300#undef GET_MOD_ATTR
3301}
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003302
INADA Naokic411a7d2016-10-18 11:48:14 +09003303PyDoc_STRVAR(module_doc, "Accelerator module for asyncio");
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003304
Yury Selivanova70232f2017-12-13 14:49:42 -05003305static PyMethodDef asyncio_methods[] = {
3306 _ASYNCIO_GET_EVENT_LOOP_METHODDEF
3307 _ASYNCIO_GET_RUNNING_LOOP_METHODDEF
3308 _ASYNCIO__GET_RUNNING_LOOP_METHODDEF
3309 _ASYNCIO__SET_RUNNING_LOOP_METHODDEF
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003310 _ASYNCIO__REGISTER_TASK_METHODDEF
3311 _ASYNCIO__UNREGISTER_TASK_METHODDEF
3312 _ASYNCIO__ENTER_TASK_METHODDEF
3313 _ASYNCIO__LEAVE_TASK_METHODDEF
Yury Selivanova70232f2017-12-13 14:49:42 -05003314 {NULL, NULL}
3315};
3316
INADA Naoki9f2ce252016-10-15 15:39:19 +09003317static struct PyModuleDef _asynciomodule = {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003318 PyModuleDef_HEAD_INIT, /* m_base */
INADA Naoki9f2ce252016-10-15 15:39:19 +09003319 "_asyncio", /* m_name */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003320 module_doc, /* m_doc */
3321 -1, /* m_size */
Yury Selivanova70232f2017-12-13 14:49:42 -05003322 asyncio_methods, /* m_methods */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003323 NULL, /* m_slots */
3324 NULL, /* m_traverse */
3325 NULL, /* m_clear */
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003326 (freefunc)module_free /* m_free */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003327};
3328
3329
3330PyMODINIT_FUNC
INADA Naoki9f2ce252016-10-15 15:39:19 +09003331PyInit__asyncio(void)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003332{
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003333 if (module_init() < 0) {
INADA Naokic411a7d2016-10-18 11:48:14 +09003334 return NULL;
3335 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003336 if (PyType_Ready(&FutureType) < 0) {
3337 return NULL;
3338 }
3339 if (PyType_Ready(&FutureIterType) < 0) {
3340 return NULL;
3341 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03003342 if (PyType_Ready(&TaskStepMethWrapper_Type) < 0) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003343 return NULL;
3344 }
3345 if(PyType_Ready(&TaskWakeupMethWrapper_Type) < 0) {
3346 return NULL;
3347 }
3348 if (PyType_Ready(&TaskType) < 0) {
3349 return NULL;
3350 }
Yury Selivanov9d411c12018-01-23 15:10:03 -05003351 if (PyType_Ready(&PyRunningLoopHolder_Type) < 0) {
3352 return NULL;
3353 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003354
INADA Naoki9f2ce252016-10-15 15:39:19 +09003355 PyObject *m = PyModule_Create(&_asynciomodule);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003356 if (m == NULL) {
3357 return NULL;
3358 }
3359
3360 Py_INCREF(&FutureType);
3361 if (PyModule_AddObject(m, "Future", (PyObject *)&FutureType) < 0) {
3362 Py_DECREF(&FutureType);
3363 return NULL;
3364 }
3365
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003366 Py_INCREF(&TaskType);
3367 if (PyModule_AddObject(m, "Task", (PyObject *)&TaskType) < 0) {
3368 Py_DECREF(&TaskType);
3369 return NULL;
3370 }
3371
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003372 Py_INCREF(all_tasks);
3373 if (PyModule_AddObject(m, "_all_tasks", all_tasks) < 0) {
3374 Py_DECREF(all_tasks);
3375 return NULL;
3376 }
3377
3378 Py_INCREF(current_tasks);
3379 if (PyModule_AddObject(m, "_current_tasks", current_tasks) < 0) {
3380 Py_DECREF(current_tasks);
3381 return NULL;
3382 }
3383
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003384 return m;
3385}