blob: 6d7249a580097e755f569aab137408cb106c8601 [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);
Andrew Svetlov44d1a592017-12-16 21:58:38 +020014_Py_IDENTIFIER(all_tasks);
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 Selivanovf23746a2018-01-22 19:11:18 -050062 PyContext *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 Selivanovf23746a2018-01-22 19:11:18 -050081 PyContext *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
Leo Ariasc3d95082018-02-03 18:36:10 -0600190 /* 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);
Serhiy Storchaka66553542018-05-20 16:30:31 +0300204 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
Serhiy Storchaka66553542018-05-20 16:30:31 +0300212 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 Selivanovf23746a2018-01-22 19:11:18 -0500340call_soon(PyObject *loop, PyObject *func, PyObject *arg, PyContext *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 Selivanovf23746a2018-01-22 19:11:18 -0500451 if (call_soon(fut->fut_loop, cb, (PyObject *)fut, (PyContext *)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
Oren Milmand019bc82018-02-13 12:28:33 +0200463
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
Oren Milmand019bc82018-02-13 12:28:33 +0200471 // 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 }
Oren Milmand019bc82018-02-13 12:28:33 +0200493 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 }
504 if (is_true) {
Oren Milmand019bc82018-02-13 12:28:33 +0200505 fut->fut_source_tb = _PyObject_CallNoArg(traceback_extract_stack);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900506 if (fut->fut_source_tb == NULL) {
507 return -1;
508 }
509 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900510
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900511 return 0;
512}
513
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900514static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400515future_set_result(FutureObj *fut, PyObject *res)
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900516{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500517 if (future_ensure_alive(fut)) {
518 return NULL;
519 }
520
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900521 if (fut->fut_state != STATE_PENDING) {
522 PyErr_SetString(asyncio_InvalidStateError, "invalid state");
523 return NULL;
524 }
525
Serhiy Storchakabca49392017-09-03 08:10:14 +0300526 assert(!fut->fut_result);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900527 Py_INCREF(res);
528 fut->fut_result = res;
529 fut->fut_state = STATE_FINISHED;
530
Yury Selivanov22feeb82018-01-24 11:31:01 -0500531 if (future_schedule_callbacks(fut) == -1) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900532 return NULL;
533 }
534 Py_RETURN_NONE;
535}
536
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900537static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400538future_set_exception(FutureObj *fut, PyObject *exc)
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900539{
540 PyObject *exc_val = NULL;
541
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900542 if (fut->fut_state != STATE_PENDING) {
543 PyErr_SetString(asyncio_InvalidStateError, "invalid state");
544 return NULL;
545 }
546
547 if (PyExceptionClass_Check(exc)) {
Victor Stinnera5ed5f02016-12-06 18:45:50 +0100548 exc_val = _PyObject_CallNoArg(exc);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900549 if (exc_val == NULL) {
550 return NULL;
551 }
Serhiy Storchakabca49392017-09-03 08:10:14 +0300552 if (fut->fut_state != STATE_PENDING) {
553 Py_DECREF(exc_val);
554 PyErr_SetString(asyncio_InvalidStateError, "invalid state");
555 return NULL;
556 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900557 }
558 else {
559 exc_val = exc;
560 Py_INCREF(exc_val);
561 }
562 if (!PyExceptionInstance_Check(exc_val)) {
563 Py_DECREF(exc_val);
564 PyErr_SetString(PyExc_TypeError, "invalid exception object");
565 return NULL;
566 }
567 if ((PyObject*)Py_TYPE(exc_val) == PyExc_StopIteration) {
568 Py_DECREF(exc_val);
569 PyErr_SetString(PyExc_TypeError,
570 "StopIteration interacts badly with generators "
571 "and cannot be raised into a Future");
572 return NULL;
573 }
574
Serhiy Storchakabca49392017-09-03 08:10:14 +0300575 assert(!fut->fut_exception);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900576 fut->fut_exception = exc_val;
577 fut->fut_state = STATE_FINISHED;
578
Yury Selivanov22feeb82018-01-24 11:31:01 -0500579 if (future_schedule_callbacks(fut) == -1) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900580 return NULL;
581 }
582
583 fut->fut_log_tb = 1;
584 Py_RETURN_NONE;
585}
586
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400587static int
588future_get_result(FutureObj *fut, PyObject **result)
589{
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400590 if (fut->fut_state == STATE_CANCELLED) {
Serhiy Storchakabca49392017-09-03 08:10:14 +0300591 PyErr_SetNone(asyncio_CancelledError);
592 return -1;
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400593 }
594
595 if (fut->fut_state != STATE_FINISHED) {
Serhiy Storchakabca49392017-09-03 08:10:14 +0300596 PyErr_SetString(asyncio_InvalidStateError, "Result is not set.");
597 return -1;
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400598 }
599
600 fut->fut_log_tb = 0;
601 if (fut->fut_exception != NULL) {
602 Py_INCREF(fut->fut_exception);
603 *result = fut->fut_exception;
604 return 1;
605 }
606
607 Py_INCREF(fut->fut_result);
608 *result = fut->fut_result;
609 return 0;
610}
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900611
612static PyObject *
Yury Selivanovf23746a2018-01-22 19:11:18 -0500613future_add_done_callback(FutureObj *fut, PyObject *arg, PyContext *ctx)
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900614{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500615 if (!future_is_alive(fut)) {
616 PyErr_SetString(PyExc_RuntimeError, "uninitialized Future object");
617 return NULL;
618 }
619
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900620 if (fut->fut_state != STATE_PENDING) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500621 /* The future is done/cancelled, so schedule the callback
622 right away. */
Yury Selivanovf23746a2018-01-22 19:11:18 -0500623 if (call_soon(fut->fut_loop, arg, (PyObject*) fut, ctx)) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900624 return NULL;
625 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900626 }
627 else {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500628 /* The future is pending, add a callback.
629
630 Callbacks in the future object are stored as follows:
631
632 callback0 -- a pointer to the first callback
633 callbacks -- a list of 2nd, 3rd, ... callbacks
634
635 Invariants:
636
637 * callbacks != NULL:
638 There are some callbacks in in the list. Just
639 add the new callback to it.
640
641 * callbacks == NULL and callback0 == NULL:
642 This is the first callback. Set it to callback0.
643
644 * callbacks == NULL and callback0 != NULL:
645 This is a second callback. Initialize callbacks
646 with a new list and add the new callback to it.
647 */
648
Yury Selivanovf23746a2018-01-22 19:11:18 -0500649 if (fut->fut_callbacks == NULL && fut->fut_callback0 == NULL) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500650 Py_INCREF(arg);
651 fut->fut_callback0 = arg;
Yury Selivanovf23746a2018-01-22 19:11:18 -0500652 Py_INCREF(ctx);
653 fut->fut_context0 = ctx;
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500654 }
655 else {
Yury Selivanovf23746a2018-01-22 19:11:18 -0500656 PyObject *tup = PyTuple_New(2);
657 if (tup == NULL) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500658 return NULL;
659 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500660 Py_INCREF(arg);
Yury Selivanovf23746a2018-01-22 19:11:18 -0500661 PyTuple_SET_ITEM(tup, 0, arg);
662 Py_INCREF(ctx);
663 PyTuple_SET_ITEM(tup, 1, (PyObject *)ctx);
664
665 if (fut->fut_callbacks != NULL) {
666 int err = PyList_Append(fut->fut_callbacks, tup);
667 if (err) {
668 Py_DECREF(tup);
669 return NULL;
670 }
671 Py_DECREF(tup);
672 }
673 else {
674 fut->fut_callbacks = PyList_New(1);
675 if (fut->fut_callbacks == NULL) {
676 return NULL;
677 }
678
679 PyList_SET_ITEM(fut->fut_callbacks, 0, tup); /* borrow */
680 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900681 }
682 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500683
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900684 Py_RETURN_NONE;
685}
686
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400687static PyObject *
688future_cancel(FutureObj *fut)
689{
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +0000690 fut->fut_log_tb = 0;
691
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400692 if (fut->fut_state != STATE_PENDING) {
693 Py_RETURN_FALSE;
694 }
695 fut->fut_state = STATE_CANCELLED;
696
Yury Selivanov22feeb82018-01-24 11:31:01 -0500697 if (future_schedule_callbacks(fut) == -1) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400698 return NULL;
699 }
700
701 Py_RETURN_TRUE;
702}
703
704/*[clinic input]
705_asyncio.Future.__init__
706
707 *
Serhiy Storchakabca49392017-09-03 08:10:14 +0300708 loop: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400709
710This class is *almost* compatible with concurrent.futures.Future.
711
712 Differences:
713
714 - result() and exception() do not take a timeout argument and
715 raise an exception when the future isn't done yet.
716
717 - Callbacks registered with add_done_callback() are always called
718 via the event loop's call_soon_threadsafe().
719
720 - This class is not compatible with the wait() and as_completed()
721 methods in the concurrent.futures package.
722[clinic start generated code]*/
723
724static int
725_asyncio_Future___init___impl(FutureObj *self, PyObject *loop)
Serhiy Storchakabca49392017-09-03 08:10:14 +0300726/*[clinic end generated code: output=9ed75799eaccb5d6 input=89af317082bc0bf8]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400727
728{
729 return future_init(self, loop);
730}
731
732static int
733FutureObj_clear(FutureObj *fut)
734{
735 Py_CLEAR(fut->fut_loop);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500736 Py_CLEAR(fut->fut_callback0);
Yury Selivanovf23746a2018-01-22 19:11:18 -0500737 Py_CLEAR(fut->fut_context0);
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400738 Py_CLEAR(fut->fut_callbacks);
739 Py_CLEAR(fut->fut_result);
740 Py_CLEAR(fut->fut_exception);
741 Py_CLEAR(fut->fut_source_tb);
742 Py_CLEAR(fut->dict);
743 return 0;
744}
745
746static int
747FutureObj_traverse(FutureObj *fut, visitproc visit, void *arg)
748{
749 Py_VISIT(fut->fut_loop);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500750 Py_VISIT(fut->fut_callback0);
Yury Selivanovf23746a2018-01-22 19:11:18 -0500751 Py_VISIT(fut->fut_context0);
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400752 Py_VISIT(fut->fut_callbacks);
753 Py_VISIT(fut->fut_result);
754 Py_VISIT(fut->fut_exception);
755 Py_VISIT(fut->fut_source_tb);
756 Py_VISIT(fut->dict);
757 return 0;
758}
759
760/*[clinic input]
761_asyncio.Future.result
762
763Return the result this future represents.
764
765If the future has been cancelled, raises CancelledError. If the
766future's result isn't yet available, raises InvalidStateError. If
767the future is done and has an exception set, this exception is raised.
768[clinic start generated code]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900769
770static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400771_asyncio_Future_result_impl(FutureObj *self)
772/*[clinic end generated code: output=f35f940936a4b1e5 input=49ecf9cf5ec50dc5]*/
773{
774 PyObject *result;
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500775
776 if (!future_is_alive(self)) {
777 PyErr_SetString(asyncio_InvalidStateError,
778 "Future object is not initialized.");
779 return NULL;
780 }
781
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400782 int res = future_get_result(self, &result);
783
784 if (res == -1) {
785 return NULL;
786 }
787
788 if (res == 0) {
789 return result;
790 }
791
792 assert(res == 1);
793
794 PyErr_SetObject(PyExceptionInstance_Class(result), result);
795 Py_DECREF(result);
796 return NULL;
797}
798
799/*[clinic input]
800_asyncio.Future.exception
801
802Return the exception that was set on this future.
803
804The exception (or None if no exception was set) is returned only if
805the future is done. If the future has been cancelled, raises
806CancelledError. If the future isn't done yet, raises
807InvalidStateError.
808[clinic start generated code]*/
809
810static PyObject *
811_asyncio_Future_exception_impl(FutureObj *self)
812/*[clinic end generated code: output=88b20d4f855e0710 input=733547a70c841c68]*/
813{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500814 if (!future_is_alive(self)) {
815 PyErr_SetString(asyncio_InvalidStateError,
816 "Future object is not initialized.");
817 return NULL;
818 }
819
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400820 if (self->fut_state == STATE_CANCELLED) {
Serhiy Storchakabca49392017-09-03 08:10:14 +0300821 PyErr_SetNone(asyncio_CancelledError);
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400822 return NULL;
823 }
824
825 if (self->fut_state != STATE_FINISHED) {
Serhiy Storchakabca49392017-09-03 08:10:14 +0300826 PyErr_SetString(asyncio_InvalidStateError, "Exception is not set.");
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400827 return NULL;
828 }
829
830 if (self->fut_exception != NULL) {
831 self->fut_log_tb = 0;
832 Py_INCREF(self->fut_exception);
833 return self->fut_exception;
834 }
835
836 Py_RETURN_NONE;
837}
838
839/*[clinic input]
840_asyncio.Future.set_result
841
Yury Selivanov0cf16f92017-12-25 10:48:15 -0500842 result: object
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400843 /
844
845Mark the future done and set its result.
846
847If the future is already done when this method is called, raises
848InvalidStateError.
849[clinic start generated code]*/
850
851static PyObject *
Yury Selivanov0cf16f92017-12-25 10:48:15 -0500852_asyncio_Future_set_result(FutureObj *self, PyObject *result)
853/*[clinic end generated code: output=1ec2e6bcccd6f2ce input=8b75172c2a7b05f1]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400854{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500855 ENSURE_FUTURE_ALIVE(self)
Yury Selivanov0cf16f92017-12-25 10:48:15 -0500856 return future_set_result(self, result);
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400857}
858
859/*[clinic input]
860_asyncio.Future.set_exception
861
Serhiy Storchakabca49392017-09-03 08:10:14 +0300862 exception: object
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400863 /
864
865Mark the future done and set an exception.
866
867If the future is already done when this method is called, raises
868InvalidStateError.
869[clinic start generated code]*/
870
871static PyObject *
872_asyncio_Future_set_exception(FutureObj *self, PyObject *exception)
Serhiy Storchakabca49392017-09-03 08:10:14 +0300873/*[clinic end generated code: output=f1c1b0cd321be360 input=e45b7d7aa71cc66d]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400874{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500875 ENSURE_FUTURE_ALIVE(self)
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400876 return future_set_exception(self, exception);
877}
878
879/*[clinic input]
880_asyncio.Future.add_done_callback
881
Serhiy Storchakabca49392017-09-03 08:10:14 +0300882 fn: object
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400883 /
Yury Selivanovf23746a2018-01-22 19:11:18 -0500884 *
885 context: object = NULL
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400886
887Add a callback to be run when the future becomes done.
888
889The callback is called with a single argument - the future object. If
890the future is already done when this is called, the callback is
891scheduled with call_soon.
892[clinic start generated code]*/
893
894static PyObject *
Yury Selivanovf23746a2018-01-22 19:11:18 -0500895_asyncio_Future_add_done_callback_impl(FutureObj *self, PyObject *fn,
896 PyObject *context)
897/*[clinic end generated code: output=7ce635bbc9554c1e input=15ab0693a96e9533]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400898{
Yury Selivanovf23746a2018-01-22 19:11:18 -0500899 if (context == NULL) {
900 context = (PyObject *)PyContext_CopyCurrent();
901 if (context == NULL) {
902 return NULL;
903 }
904 PyObject *res = future_add_done_callback(
905 self, fn, (PyContext *)context);
906 Py_DECREF(context);
907 return res;
908 }
909 return future_add_done_callback(self, fn, (PyContext *)context);
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400910}
911
912/*[clinic input]
913_asyncio.Future.remove_done_callback
914
Serhiy Storchakabca49392017-09-03 08:10:14 +0300915 fn: object
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400916 /
917
918Remove all instances of a callback from the "call when done" list.
919
920Returns the number of callbacks removed.
921[clinic start generated code]*/
922
923static PyObject *
924_asyncio_Future_remove_done_callback(FutureObj *self, PyObject *fn)
Serhiy Storchakabca49392017-09-03 08:10:14 +0300925/*[clinic end generated code: output=5ab1fb52b24ef31f input=0a43280a149d505b]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900926{
927 PyObject *newlist;
928 Py_ssize_t len, i, j=0;
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500929 Py_ssize_t cleared_callback0 = 0;
930
931 ENSURE_FUTURE_ALIVE(self)
932
933 if (self->fut_callback0 != NULL) {
934 int cmp = PyObject_RichCompareBool(fn, self->fut_callback0, Py_EQ);
935 if (cmp == -1) {
936 return NULL;
937 }
938 if (cmp == 1) {
939 /* callback0 == fn */
940 Py_CLEAR(self->fut_callback0);
Yury Selivanovf23746a2018-01-22 19:11:18 -0500941 Py_CLEAR(self->fut_context0);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500942 cleared_callback0 = 1;
943 }
944 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900945
Serhiy Storchakabca49392017-09-03 08:10:14 +0300946 if (self->fut_callbacks == NULL) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500947 return PyLong_FromSsize_t(cleared_callback0);
Serhiy Storchakabca49392017-09-03 08:10:14 +0300948 }
949
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400950 len = PyList_GET_SIZE(self->fut_callbacks);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900951 if (len == 0) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500952 Py_CLEAR(self->fut_callbacks);
953 return PyLong_FromSsize_t(cleared_callback0);
954 }
955
956 if (len == 1) {
Yury Selivanovf23746a2018-01-22 19:11:18 -0500957 PyObject *cb_tup = PyList_GET_ITEM(self->fut_callbacks, 0);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500958 int cmp = PyObject_RichCompareBool(
Yury Selivanovf23746a2018-01-22 19:11:18 -0500959 fn, PyTuple_GET_ITEM(cb_tup, 0), Py_EQ);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500960 if (cmp == -1) {
961 return NULL;
962 }
963 if (cmp == 1) {
964 /* callbacks[0] == fn */
965 Py_CLEAR(self->fut_callbacks);
966 return PyLong_FromSsize_t(1 + cleared_callback0);
967 }
968 /* callbacks[0] != fn and len(callbacks) == 1 */
969 return PyLong_FromSsize_t(cleared_callback0);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900970 }
971
972 newlist = PyList_New(len);
973 if (newlist == NULL) {
974 return NULL;
975 }
976
Yury Selivanov84af9032017-03-02 23:46:56 -0500977 for (i = 0; i < PyList_GET_SIZE(self->fut_callbacks); i++) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900978 int ret;
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400979 PyObject *item = PyList_GET_ITEM(self->fut_callbacks, i);
Serhiy Storchakabca49392017-09-03 08:10:14 +0300980 Py_INCREF(item);
Yury Selivanovf23746a2018-01-22 19:11:18 -0500981 ret = PyObject_RichCompareBool(fn, PyTuple_GET_ITEM(item, 0), Py_EQ);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900982 if (ret == 0) {
Yury Selivanov833a3b02017-07-05 13:32:03 -0400983 if (j < len) {
Yury Selivanov833a3b02017-07-05 13:32:03 -0400984 PyList_SET_ITEM(newlist, j, item);
985 j++;
Serhiy Storchakabca49392017-09-03 08:10:14 +0300986 continue;
Yury Selivanov833a3b02017-07-05 13:32:03 -0400987 }
Serhiy Storchakabca49392017-09-03 08:10:14 +0300988 ret = PyList_Append(newlist, item);
989 }
990 Py_DECREF(item);
991 if (ret < 0) {
992 goto fail;
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900993 }
994 }
995
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500996 if (j == 0) {
997 Py_CLEAR(self->fut_callbacks);
998 Py_DECREF(newlist);
999 return PyLong_FromSsize_t(len + cleared_callback0);
1000 }
1001
Serhiy Storchakabca49392017-09-03 08:10:14 +03001002 if (j < len) {
1003 Py_SIZE(newlist) = j;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001004 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03001005 j = PyList_GET_SIZE(newlist);
1006 len = PyList_GET_SIZE(self->fut_callbacks);
1007 if (j != len) {
1008 if (PyList_SetSlice(self->fut_callbacks, 0, len, newlist) < 0) {
1009 goto fail;
1010 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001011 }
1012 Py_DECREF(newlist);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001013 return PyLong_FromSsize_t(len - j + cleared_callback0);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001014
1015fail:
1016 Py_DECREF(newlist);
1017 return NULL;
1018}
1019
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001020/*[clinic input]
1021_asyncio.Future.cancel
1022
1023Cancel the future and schedule callbacks.
1024
1025If the future is already done or cancelled, return False. Otherwise,
1026change the future's state to cancelled, schedule the callbacks and
1027return True.
1028[clinic start generated code]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001029
1030static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001031_asyncio_Future_cancel_impl(FutureObj *self)
1032/*[clinic end generated code: output=e45b932ba8bd68a1 input=515709a127995109]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001033{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001034 ENSURE_FUTURE_ALIVE(self)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001035 return future_cancel(self);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001036}
1037
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001038/*[clinic input]
1039_asyncio.Future.cancelled
1040
1041Return True if the future was cancelled.
1042[clinic start generated code]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001043
1044static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001045_asyncio_Future_cancelled_impl(FutureObj *self)
1046/*[clinic end generated code: output=145197ced586357d input=943ab8b7b7b17e45]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001047{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001048 if (future_is_alive(self) && self->fut_state == STATE_CANCELLED) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001049 Py_RETURN_TRUE;
1050 }
1051 else {
1052 Py_RETURN_FALSE;
1053 }
1054}
1055
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001056/*[clinic input]
1057_asyncio.Future.done
1058
1059Return True if the future is done.
1060
1061Done means either that a result / exception are available, or that the
1062future was cancelled.
1063[clinic start generated code]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001064
1065static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001066_asyncio_Future_done_impl(FutureObj *self)
1067/*[clinic end generated code: output=244c5ac351145096 input=28d7b23fdb65d2ac]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001068{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001069 if (!future_is_alive(self) || self->fut_state == STATE_PENDING) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001070 Py_RETURN_FALSE;
1071 }
1072 else {
1073 Py_RETURN_TRUE;
1074 }
1075}
1076
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001077/*[clinic input]
1078_asyncio.Future.get_loop
1079
1080Return the event loop the Future is bound to.
1081[clinic start generated code]*/
1082
1083static PyObject *
1084_asyncio_Future_get_loop_impl(FutureObj *self)
1085/*[clinic end generated code: output=119b6ea0c9816c3f input=cba48c2136c79d1f]*/
1086{
1087 Py_INCREF(self->fut_loop);
1088 return self->fut_loop;
1089}
1090
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001091static PyObject *
1092FutureObj_get_blocking(FutureObj *fut)
1093{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001094 if (future_is_alive(fut) && fut->fut_blocking) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001095 Py_RETURN_TRUE;
1096 }
1097 else {
1098 Py_RETURN_FALSE;
1099 }
1100}
1101
1102static int
1103FutureObj_set_blocking(FutureObj *fut, PyObject *val)
1104{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001105 if (future_ensure_alive(fut)) {
1106 return -1;
1107 }
1108
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001109 int is_true = PyObject_IsTrue(val);
1110 if (is_true < 0) {
1111 return -1;
1112 }
1113 fut->fut_blocking = is_true;
1114 return 0;
1115}
1116
1117static PyObject *
1118FutureObj_get_log_traceback(FutureObj *fut)
1119{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001120 ENSURE_FUTURE_ALIVE(fut)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001121 if (fut->fut_log_tb) {
1122 Py_RETURN_TRUE;
1123 }
1124 else {
1125 Py_RETURN_FALSE;
1126 }
1127}
1128
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +00001129static int
1130FutureObj_set_log_traceback(FutureObj *fut, PyObject *val)
1131{
1132 int is_true = PyObject_IsTrue(val);
1133 if (is_true < 0) {
1134 return -1;
1135 }
Yury Selivanove0aef4f2017-12-25 16:16:10 -05001136 if (is_true) {
1137 PyErr_SetString(PyExc_ValueError,
1138 "_log_traceback can only be set to False");
1139 return -1;
1140 }
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +00001141 fut->fut_log_tb = is_true;
1142 return 0;
1143}
1144
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001145static PyObject *
1146FutureObj_get_loop(FutureObj *fut)
1147{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001148 if (!future_is_alive(fut)) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001149 Py_RETURN_NONE;
1150 }
1151 Py_INCREF(fut->fut_loop);
1152 return fut->fut_loop;
1153}
1154
1155static PyObject *
1156FutureObj_get_callbacks(FutureObj *fut)
1157{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001158 Py_ssize_t i;
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001159
1160 ENSURE_FUTURE_ALIVE(fut)
1161
Yury Selivanovf23746a2018-01-22 19:11:18 -05001162 if (fut->fut_callback0 == NULL) {
1163 if (fut->fut_callbacks == NULL) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001164 Py_RETURN_NONE;
1165 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001166
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001167 Py_INCREF(fut->fut_callbacks);
1168 return fut->fut_callbacks;
1169 }
1170
Yury Selivanovf23746a2018-01-22 19:11:18 -05001171 Py_ssize_t len = 1;
1172 if (fut->fut_callbacks != NULL) {
1173 len += PyList_GET_SIZE(fut->fut_callbacks);
1174 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001175
Yury Selivanovf23746a2018-01-22 19:11:18 -05001176
1177 PyObject *new_list = PyList_New(len);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001178 if (new_list == NULL) {
1179 return NULL;
1180 }
1181
Yury Selivanovf23746a2018-01-22 19:11:18 -05001182 PyObject *tup0 = PyTuple_New(2);
1183 if (tup0 == NULL) {
1184 Py_DECREF(new_list);
1185 return NULL;
1186 }
1187
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001188 Py_INCREF(fut->fut_callback0);
Yury Selivanovf23746a2018-01-22 19:11:18 -05001189 PyTuple_SET_ITEM(tup0, 0, fut->fut_callback0);
1190 assert(fut->fut_context0 != NULL);
1191 Py_INCREF(fut->fut_context0);
1192 PyTuple_SET_ITEM(tup0, 1, (PyObject *)fut->fut_context0);
1193
1194 PyList_SET_ITEM(new_list, 0, tup0);
1195
1196 if (fut->fut_callbacks != NULL) {
1197 for (i = 0; i < PyList_GET_SIZE(fut->fut_callbacks); i++) {
1198 PyObject *cb = PyList_GET_ITEM(fut->fut_callbacks, i);
1199 Py_INCREF(cb);
1200 PyList_SET_ITEM(new_list, i + 1, cb);
1201 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001202 }
1203
1204 return new_list;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001205}
1206
1207static PyObject *
1208FutureObj_get_result(FutureObj *fut)
1209{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001210 ENSURE_FUTURE_ALIVE(fut)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001211 if (fut->fut_result == NULL) {
1212 Py_RETURN_NONE;
1213 }
1214 Py_INCREF(fut->fut_result);
1215 return fut->fut_result;
1216}
1217
1218static PyObject *
1219FutureObj_get_exception(FutureObj *fut)
1220{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001221 ENSURE_FUTURE_ALIVE(fut)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001222 if (fut->fut_exception == NULL) {
1223 Py_RETURN_NONE;
1224 }
1225 Py_INCREF(fut->fut_exception);
1226 return fut->fut_exception;
1227}
1228
1229static PyObject *
1230FutureObj_get_source_traceback(FutureObj *fut)
1231{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001232 if (!future_is_alive(fut) || fut->fut_source_tb == NULL) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001233 Py_RETURN_NONE;
1234 }
1235 Py_INCREF(fut->fut_source_tb);
1236 return fut->fut_source_tb;
1237}
1238
1239static PyObject *
1240FutureObj_get_state(FutureObj *fut)
1241{
1242 _Py_IDENTIFIER(PENDING);
1243 _Py_IDENTIFIER(CANCELLED);
1244 _Py_IDENTIFIER(FINISHED);
1245 PyObject *ret = NULL;
1246
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001247 ENSURE_FUTURE_ALIVE(fut)
1248
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001249 switch (fut->fut_state) {
1250 case STATE_PENDING:
1251 ret = _PyUnicode_FromId(&PyId_PENDING);
1252 break;
1253 case STATE_CANCELLED:
1254 ret = _PyUnicode_FromId(&PyId_CANCELLED);
1255 break;
1256 case STATE_FINISHED:
1257 ret = _PyUnicode_FromId(&PyId_FINISHED);
1258 break;
1259 default:
1260 assert (0);
1261 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03001262 Py_XINCREF(ret);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001263 return ret;
1264}
1265
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001266/*[clinic input]
1267_asyncio.Future._repr_info
1268[clinic start generated code]*/
1269
1270static PyObject *
1271_asyncio_Future__repr_info_impl(FutureObj *self)
1272/*[clinic end generated code: output=fa69e901bd176cfb input=f21504d8e2ae1ca2]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001273{
Victor Stinnerde4ae3d2016-12-04 22:59:09 +01001274 return PyObject_CallFunctionObjArgs(
1275 asyncio_future_repr_info_func, self, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001276}
1277
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001278static PyObject *
1279FutureObj_repr(FutureObj *fut)
1280{
1281 _Py_IDENTIFIER(_repr_info);
1282
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001283 ENSURE_FUTURE_ALIVE(fut)
1284
Serhiy Storchakabca49392017-09-03 08:10:14 +03001285 PyObject *rinfo = _PyObject_CallMethodIdObjArgs((PyObject*)fut,
1286 &PyId__repr_info,
1287 NULL);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001288 if (rinfo == NULL) {
1289 return NULL;
1290 }
1291
Serhiy Storchakabca49392017-09-03 08:10:14 +03001292 PyObject *rinfo_s = PyUnicode_Join(NULL, rinfo);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001293 Py_DECREF(rinfo);
1294 if (rinfo_s == NULL) {
1295 return NULL;
1296 }
1297
1298 PyObject *rstr = NULL;
1299 PyObject *type_name = PyObject_GetAttrString((PyObject*)Py_TYPE(fut),
1300 "__name__");
1301 if (type_name != NULL) {
Serhiy Storchakabca49392017-09-03 08:10:14 +03001302 rstr = PyUnicode_FromFormat("<%S %U>", type_name, rinfo_s);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001303 Py_DECREF(type_name);
1304 }
1305 Py_DECREF(rinfo_s);
1306 return rstr;
1307}
1308
1309static void
1310FutureObj_finalize(FutureObj *fut)
1311{
1312 _Py_IDENTIFIER(call_exception_handler);
1313 _Py_IDENTIFIER(message);
1314 _Py_IDENTIFIER(exception);
1315 _Py_IDENTIFIER(future);
1316 _Py_IDENTIFIER(source_traceback);
1317
Serhiy Storchakabca49392017-09-03 08:10:14 +03001318 PyObject *error_type, *error_value, *error_traceback;
1319 PyObject *context;
1320 PyObject *type_name;
1321 PyObject *message = NULL;
1322 PyObject *func;
1323
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001324 if (!fut->fut_log_tb) {
1325 return;
1326 }
1327 assert(fut->fut_exception != NULL);
Serhiy Storchakabca49392017-09-03 08:10:14 +03001328 fut->fut_log_tb = 0;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001329
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001330 /* Save the current exception, if any. */
1331 PyErr_Fetch(&error_type, &error_value, &error_traceback);
1332
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001333 context = PyDict_New();
1334 if (context == NULL) {
1335 goto finally;
1336 }
1337
1338 type_name = PyObject_GetAttrString((PyObject*)Py_TYPE(fut), "__name__");
1339 if (type_name == NULL) {
1340 goto finally;
1341 }
1342
1343 message = PyUnicode_FromFormat(
1344 "%S exception was never retrieved", type_name);
Serhiy Storchakabca49392017-09-03 08:10:14 +03001345 Py_DECREF(type_name);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001346 if (message == NULL) {
1347 goto finally;
1348 }
1349
1350 if (_PyDict_SetItemId(context, &PyId_message, message) < 0 ||
1351 _PyDict_SetItemId(context, &PyId_exception, fut->fut_exception) < 0 ||
1352 _PyDict_SetItemId(context, &PyId_future, (PyObject*)fut) < 0) {
1353 goto finally;
1354 }
1355 if (fut->fut_source_tb != NULL) {
1356 if (_PyDict_SetItemId(context, &PyId_source_traceback,
1357 fut->fut_source_tb) < 0) {
1358 goto finally;
1359 }
1360 }
1361
1362 func = _PyObject_GetAttrId(fut->fut_loop, &PyId_call_exception_handler);
1363 if (func != NULL) {
Serhiy Storchakabca49392017-09-03 08:10:14 +03001364 PyObject *res = PyObject_CallFunctionObjArgs(func, context, NULL);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001365 if (res == NULL) {
1366 PyErr_WriteUnraisable(func);
1367 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03001368 else {
1369 Py_DECREF(res);
1370 }
1371 Py_DECREF(func);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001372 }
1373
1374finally:
Serhiy Storchakabca49392017-09-03 08:10:14 +03001375 Py_XDECREF(context);
1376 Py_XDECREF(message);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001377
1378 /* Restore the saved exception. */
1379 PyErr_Restore(error_type, error_value, error_traceback);
1380}
1381
1382
1383static PyAsyncMethods FutureType_as_async = {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001384 (unaryfunc)future_new_iter, /* am_await */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001385 0, /* am_aiter */
1386 0 /* am_anext */
1387};
1388
1389static PyMethodDef FutureType_methods[] = {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001390 _ASYNCIO_FUTURE_RESULT_METHODDEF
1391 _ASYNCIO_FUTURE_EXCEPTION_METHODDEF
1392 _ASYNCIO_FUTURE_SET_RESULT_METHODDEF
1393 _ASYNCIO_FUTURE_SET_EXCEPTION_METHODDEF
1394 _ASYNCIO_FUTURE_ADD_DONE_CALLBACK_METHODDEF
1395 _ASYNCIO_FUTURE_REMOVE_DONE_CALLBACK_METHODDEF
1396 _ASYNCIO_FUTURE_CANCEL_METHODDEF
1397 _ASYNCIO_FUTURE_CANCELLED_METHODDEF
1398 _ASYNCIO_FUTURE_DONE_METHODDEF
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001399 _ASYNCIO_FUTURE_GET_LOOP_METHODDEF
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001400 _ASYNCIO_FUTURE__REPR_INFO_METHODDEF
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001401 {NULL, NULL} /* Sentinel */
1402};
1403
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001404#define FUTURE_COMMON_GETSETLIST \
1405 {"_state", (getter)FutureObj_get_state, NULL, NULL}, \
1406 {"_asyncio_future_blocking", (getter)FutureObj_get_blocking, \
1407 (setter)FutureObj_set_blocking, NULL}, \
1408 {"_loop", (getter)FutureObj_get_loop, NULL, NULL}, \
1409 {"_callbacks", (getter)FutureObj_get_callbacks, NULL, NULL}, \
1410 {"_result", (getter)FutureObj_get_result, NULL, NULL}, \
1411 {"_exception", (getter)FutureObj_get_exception, NULL, NULL}, \
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +00001412 {"_log_traceback", (getter)FutureObj_get_log_traceback, \
1413 (setter)FutureObj_set_log_traceback, NULL}, \
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001414 {"_source_traceback", (getter)FutureObj_get_source_traceback, NULL, NULL},
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001415
1416static PyGetSetDef FutureType_getsetlist[] = {
1417 FUTURE_COMMON_GETSETLIST
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001418 {NULL} /* Sentinel */
1419};
1420
1421static void FutureObj_dealloc(PyObject *self);
1422
1423static PyTypeObject FutureType = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02001424 PyVarObject_HEAD_INIT(NULL, 0)
INADA Naoki9f2ce252016-10-15 15:39:19 +09001425 "_asyncio.Future",
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001426 sizeof(FutureObj), /* tp_basicsize */
1427 .tp_dealloc = FutureObj_dealloc,
1428 .tp_as_async = &FutureType_as_async,
1429 .tp_repr = (reprfunc)FutureObj_repr,
1430 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE
1431 | Py_TPFLAGS_HAVE_FINALIZE,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001432 .tp_doc = _asyncio_Future___init____doc__,
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001433 .tp_traverse = (traverseproc)FutureObj_traverse,
1434 .tp_clear = (inquiry)FutureObj_clear,
1435 .tp_weaklistoffset = offsetof(FutureObj, fut_weakreflist),
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001436 .tp_iter = (getiterfunc)future_new_iter,
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001437 .tp_methods = FutureType_methods,
1438 .tp_getset = FutureType_getsetlist,
1439 .tp_dictoffset = offsetof(FutureObj, dict),
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001440 .tp_init = (initproc)_asyncio_Future___init__,
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001441 .tp_new = PyType_GenericNew,
1442 .tp_finalize = (destructor)FutureObj_finalize,
1443};
1444
1445static void
1446FutureObj_dealloc(PyObject *self)
1447{
1448 FutureObj *fut = (FutureObj *)self;
1449
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001450 if (Future_CheckExact(fut)) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001451 /* When fut is subclass of Future, finalizer is called from
1452 * subtype_dealloc.
1453 */
1454 if (PyObject_CallFinalizerFromDealloc(self) < 0) {
1455 // resurrected.
1456 return;
1457 }
1458 }
1459
Alexander Mohrde34cbe2017-08-01 23:31:07 -07001460 PyObject_GC_UnTrack(self);
1461
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001462 if (fut->fut_weakreflist != NULL) {
1463 PyObject_ClearWeakRefs(self);
1464 }
1465
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001466 (void)FutureObj_clear(fut);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001467 Py_TYPE(fut)->tp_free(fut);
1468}
1469
1470
1471/*********************** Future Iterator **************************/
1472
1473typedef struct {
1474 PyObject_HEAD
1475 FutureObj *future;
1476} futureiterobject;
1477
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001478
1479#define FI_FREELIST_MAXLEN 255
1480static futureiterobject *fi_freelist = NULL;
1481static Py_ssize_t fi_freelist_len = 0;
1482
1483
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001484static void
1485FutureIter_dealloc(futureiterobject *it)
1486{
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001487 PyObject_GC_UnTrack(it);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001488 Py_CLEAR(it->future);
1489
1490 if (fi_freelist_len < FI_FREELIST_MAXLEN) {
1491 fi_freelist_len++;
1492 it->future = (FutureObj*) fi_freelist;
1493 fi_freelist = it;
1494 }
1495 else {
1496 PyObject_GC_Del(it);
1497 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001498}
1499
1500static PyObject *
1501FutureIter_iternext(futureiterobject *it)
1502{
1503 PyObject *res;
1504 FutureObj *fut = it->future;
1505
1506 if (fut == NULL) {
1507 return NULL;
1508 }
1509
1510 if (fut->fut_state == STATE_PENDING) {
1511 if (!fut->fut_blocking) {
1512 fut->fut_blocking = 1;
1513 Py_INCREF(fut);
1514 return (PyObject *)fut;
1515 }
Yury Selivanov0cf16f92017-12-25 10:48:15 -05001516 PyErr_SetString(PyExc_RuntimeError,
1517 "await wasn't used with future");
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001518 return NULL;
1519 }
1520
Serhiy Storchakabca49392017-09-03 08:10:14 +03001521 it->future = NULL;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001522 res = _asyncio_Future_result_impl(fut);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001523 if (res != NULL) {
Serhiy Storchaka60e49aa2016-11-06 18:47:03 +02001524 /* The result of the Future is not an exception. */
Serhiy Storchakabca49392017-09-03 08:10:14 +03001525 (void)_PyGen_SetStopIterationValue(res);
Serhiy Storchaka60e49aa2016-11-06 18:47:03 +02001526 Py_DECREF(res);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001527 }
1528
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001529 Py_DECREF(fut);
1530 return NULL;
1531}
1532
1533static PyObject *
INADA Naoki74c17532016-10-25 19:00:45 +09001534FutureIter_send(futureiterobject *self, PyObject *unused)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001535{
INADA Naoki74c17532016-10-25 19:00:45 +09001536 /* Future.__iter__ doesn't care about values that are pushed to the
1537 * generator, it just returns "self.result().
1538 */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001539 return FutureIter_iternext(self);
1540}
1541
1542static PyObject *
1543FutureIter_throw(futureiterobject *self, PyObject *args)
1544{
Serhiy Storchakabca49392017-09-03 08:10:14 +03001545 PyObject *type, *val = NULL, *tb = NULL;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001546 if (!PyArg_ParseTuple(args, "O|OO", &type, &val, &tb))
1547 return NULL;
1548
1549 if (val == Py_None) {
1550 val = NULL;
1551 }
1552 if (tb == Py_None) {
1553 tb = NULL;
Benjamin Peterson996fc1f2016-11-14 00:15:44 -08001554 } else if (tb != NULL && !PyTraceBack_Check(tb)) {
1555 PyErr_SetString(PyExc_TypeError, "throw() third argument must be a traceback");
1556 return NULL;
1557 }
1558
1559 Py_INCREF(type);
1560 Py_XINCREF(val);
1561 Py_XINCREF(tb);
1562
1563 if (PyExceptionClass_Check(type)) {
1564 PyErr_NormalizeException(&type, &val, &tb);
Yury Selivanovedfe8862016-12-01 11:37:47 -05001565 /* No need to call PyException_SetTraceback since we'll be calling
1566 PyErr_Restore for `type`, `val`, and `tb`. */
Benjamin Peterson996fc1f2016-11-14 00:15:44 -08001567 } else if (PyExceptionInstance_Check(type)) {
1568 if (val) {
1569 PyErr_SetString(PyExc_TypeError,
1570 "instance exception may not have a separate value");
1571 goto fail;
1572 }
1573 val = type;
1574 type = PyExceptionInstance_Class(type);
1575 Py_INCREF(type);
1576 if (tb == NULL)
1577 tb = PyException_GetTraceback(val);
1578 } else {
1579 PyErr_SetString(PyExc_TypeError,
1580 "exceptions must be classes deriving BaseException or "
1581 "instances of such a class");
1582 goto fail;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001583 }
1584
1585 Py_CLEAR(self->future);
1586
Benjamin Peterson996fc1f2016-11-14 00:15:44 -08001587 PyErr_Restore(type, val, tb);
1588
Serhiy Storchakabca49392017-09-03 08:10:14 +03001589 return NULL;
Benjamin Peterson996fc1f2016-11-14 00:15:44 -08001590
1591 fail:
1592 Py_DECREF(type);
1593 Py_XDECREF(val);
1594 Py_XDECREF(tb);
1595 return NULL;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001596}
1597
1598static PyObject *
1599FutureIter_close(futureiterobject *self, PyObject *arg)
1600{
1601 Py_CLEAR(self->future);
1602 Py_RETURN_NONE;
1603}
1604
1605static int
1606FutureIter_traverse(futureiterobject *it, visitproc visit, void *arg)
1607{
1608 Py_VISIT(it->future);
1609 return 0;
1610}
1611
1612static PyMethodDef FutureIter_methods[] = {
1613 {"send", (PyCFunction)FutureIter_send, METH_O, NULL},
1614 {"throw", (PyCFunction)FutureIter_throw, METH_VARARGS, NULL},
1615 {"close", (PyCFunction)FutureIter_close, METH_NOARGS, NULL},
1616 {NULL, NULL} /* Sentinel */
1617};
1618
1619static PyTypeObject FutureIterType = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02001620 PyVarObject_HEAD_INIT(NULL, 0)
INADA Naoki9f2ce252016-10-15 15:39:19 +09001621 "_asyncio.FutureIter",
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001622 .tp_basicsize = sizeof(futureiterobject),
1623 .tp_itemsize = 0,
1624 .tp_dealloc = (destructor)FutureIter_dealloc,
1625 .tp_getattro = PyObject_GenericGetAttr,
1626 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
1627 .tp_traverse = (traverseproc)FutureIter_traverse,
1628 .tp_iter = PyObject_SelfIter,
1629 .tp_iternext = (iternextfunc)FutureIter_iternext,
1630 .tp_methods = FutureIter_methods,
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001631};
1632
1633static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001634future_new_iter(PyObject *fut)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001635{
1636 futureiterobject *it;
1637
1638 if (!PyObject_TypeCheck(fut, &FutureType)) {
1639 PyErr_BadInternalCall();
1640 return NULL;
1641 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001642
1643 ENSURE_FUTURE_ALIVE(fut)
1644
1645 if (fi_freelist_len) {
1646 fi_freelist_len--;
1647 it = fi_freelist;
1648 fi_freelist = (futureiterobject*) it->future;
1649 it->future = NULL;
1650 _Py_NewReference((PyObject*) it);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001651 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001652 else {
1653 it = PyObject_GC_New(futureiterobject, &FutureIterType);
1654 if (it == NULL) {
1655 return NULL;
1656 }
1657 }
1658
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001659 Py_INCREF(fut);
1660 it->future = (FutureObj*)fut;
INADA Naoki1be427b2016-10-11 02:12:34 +09001661 PyObject_GC_Track(it);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001662 return (PyObject*)it;
1663}
1664
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001665
1666/*********************** Task **************************/
1667
1668
1669/*[clinic input]
1670class _asyncio.Task "TaskObj *" "&Task_Type"
1671[clinic start generated code]*/
1672/*[clinic end generated code: output=da39a3ee5e6b4b0d input=719dcef0fcc03b37]*/
1673
1674static int task_call_step_soon(TaskObj *, PyObject *);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001675static PyObject * task_wakeup(TaskObj *, PyObject *);
1676static PyObject * task_step(TaskObj *, PyObject *);
1677
1678/* ----- Task._step wrapper */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001679
INADA Naokic411a7d2016-10-18 11:48:14 +09001680static int
Serhiy Storchakabca49392017-09-03 08:10:14 +03001681TaskStepMethWrapper_clear(TaskStepMethWrapper *o)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001682{
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001683 Py_CLEAR(o->sw_task);
1684 Py_CLEAR(o->sw_arg);
1685 return 0;
1686}
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001687
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001688static void
Serhiy Storchakabca49392017-09-03 08:10:14 +03001689TaskStepMethWrapper_dealloc(TaskStepMethWrapper *o)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001690{
1691 PyObject_GC_UnTrack(o);
Serhiy Storchakabca49392017-09-03 08:10:14 +03001692 (void)TaskStepMethWrapper_clear(o);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001693 Py_TYPE(o)->tp_free(o);
1694}
1695
1696static PyObject *
Serhiy Storchakabca49392017-09-03 08:10:14 +03001697TaskStepMethWrapper_call(TaskStepMethWrapper *o,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001698 PyObject *args, PyObject *kwds)
1699{
Serhiy Storchakabca49392017-09-03 08:10:14 +03001700 if (kwds != NULL && PyDict_GET_SIZE(kwds) != 0) {
1701 PyErr_SetString(PyExc_TypeError, "function takes no keyword arguments");
1702 return NULL;
1703 }
1704 if (args != NULL && PyTuple_GET_SIZE(args) != 0) {
1705 PyErr_SetString(PyExc_TypeError, "function takes no positional arguments");
1706 return NULL;
1707 }
Yury Selivanov22feeb82018-01-24 11:31:01 -05001708 return task_step(o->sw_task, o->sw_arg);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001709}
1710
1711static int
Serhiy Storchakabca49392017-09-03 08:10:14 +03001712TaskStepMethWrapper_traverse(TaskStepMethWrapper *o,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001713 visitproc visit, void *arg)
1714{
1715 Py_VISIT(o->sw_task);
1716 Py_VISIT(o->sw_arg);
1717 return 0;
1718}
1719
1720static PyObject *
Serhiy Storchakabca49392017-09-03 08:10:14 +03001721TaskStepMethWrapper_get___self__(TaskStepMethWrapper *o)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001722{
1723 if (o->sw_task) {
1724 Py_INCREF(o->sw_task);
1725 return (PyObject*)o->sw_task;
1726 }
1727 Py_RETURN_NONE;
1728}
1729
Serhiy Storchakabca49392017-09-03 08:10:14 +03001730static PyGetSetDef TaskStepMethWrapper_getsetlist[] = {
1731 {"__self__", (getter)TaskStepMethWrapper_get___self__, NULL, NULL},
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001732 {NULL} /* Sentinel */
1733};
1734
Serhiy Storchakabca49392017-09-03 08:10:14 +03001735PyTypeObject TaskStepMethWrapper_Type = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02001736 PyVarObject_HEAD_INIT(NULL, 0)
Serhiy Storchakabca49392017-09-03 08:10:14 +03001737 "TaskStepMethWrapper",
1738 .tp_basicsize = sizeof(TaskStepMethWrapper),
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001739 .tp_itemsize = 0,
Serhiy Storchakabca49392017-09-03 08:10:14 +03001740 .tp_getset = TaskStepMethWrapper_getsetlist,
1741 .tp_dealloc = (destructor)TaskStepMethWrapper_dealloc,
1742 .tp_call = (ternaryfunc)TaskStepMethWrapper_call,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001743 .tp_getattro = PyObject_GenericGetAttr,
1744 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
Serhiy Storchakabca49392017-09-03 08:10:14 +03001745 .tp_traverse = (traverseproc)TaskStepMethWrapper_traverse,
1746 .tp_clear = (inquiry)TaskStepMethWrapper_clear,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001747};
1748
1749static PyObject *
Serhiy Storchakabca49392017-09-03 08:10:14 +03001750TaskStepMethWrapper_new(TaskObj *task, PyObject *arg)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001751{
Serhiy Storchakabca49392017-09-03 08:10:14 +03001752 TaskStepMethWrapper *o;
1753 o = PyObject_GC_New(TaskStepMethWrapper, &TaskStepMethWrapper_Type);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001754 if (o == NULL) {
1755 return NULL;
1756 }
1757
1758 Py_INCREF(task);
1759 o->sw_task = task;
1760
1761 Py_XINCREF(arg);
1762 o->sw_arg = arg;
1763
1764 PyObject_GC_Track(o);
1765 return (PyObject*) o;
1766}
1767
1768/* ----- Task._wakeup wrapper */
1769
1770static PyObject *
1771TaskWakeupMethWrapper_call(TaskWakeupMethWrapper *o,
1772 PyObject *args, PyObject *kwds)
1773{
1774 PyObject *fut;
1775
Serhiy Storchakabca49392017-09-03 08:10:14 +03001776 if (kwds != NULL && PyDict_GET_SIZE(kwds) != 0) {
1777 PyErr_SetString(PyExc_TypeError, "function takes no keyword arguments");
1778 return NULL;
1779 }
1780 if (!PyArg_ParseTuple(args, "O", &fut)) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001781 return NULL;
1782 }
1783
Yury Selivanov22feeb82018-01-24 11:31:01 -05001784 return task_wakeup(o->ww_task, fut);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001785}
1786
1787static int
1788TaskWakeupMethWrapper_clear(TaskWakeupMethWrapper *o)
1789{
1790 Py_CLEAR(o->ww_task);
1791 return 0;
1792}
1793
1794static int
1795TaskWakeupMethWrapper_traverse(TaskWakeupMethWrapper *o,
1796 visitproc visit, void *arg)
1797{
1798 Py_VISIT(o->ww_task);
1799 return 0;
1800}
1801
1802static void
1803TaskWakeupMethWrapper_dealloc(TaskWakeupMethWrapper *o)
1804{
1805 PyObject_GC_UnTrack(o);
1806 (void)TaskWakeupMethWrapper_clear(o);
1807 Py_TYPE(o)->tp_free(o);
1808}
1809
1810PyTypeObject TaskWakeupMethWrapper_Type = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02001811 PyVarObject_HEAD_INIT(NULL, 0)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001812 "TaskWakeupMethWrapper",
1813 .tp_basicsize = sizeof(TaskWakeupMethWrapper),
1814 .tp_itemsize = 0,
1815 .tp_dealloc = (destructor)TaskWakeupMethWrapper_dealloc,
1816 .tp_call = (ternaryfunc)TaskWakeupMethWrapper_call,
1817 .tp_getattro = PyObject_GenericGetAttr,
1818 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
1819 .tp_traverse = (traverseproc)TaskWakeupMethWrapper_traverse,
1820 .tp_clear = (inquiry)TaskWakeupMethWrapper_clear,
1821};
1822
1823static PyObject *
1824TaskWakeupMethWrapper_new(TaskObj *task)
1825{
1826 TaskWakeupMethWrapper *o;
1827 o = PyObject_GC_New(TaskWakeupMethWrapper, &TaskWakeupMethWrapper_Type);
1828 if (o == NULL) {
1829 return NULL;
1830 }
1831
1832 Py_INCREF(task);
1833 o->ww_task = task;
1834
1835 PyObject_GC_Track(o);
1836 return (PyObject*) o;
1837}
1838
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001839/* ----- Task introspection helpers */
1840
1841static int
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001842register_task(PyObject *task)
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001843{
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001844 _Py_IDENTIFIER(add);
1845
1846 PyObject *res = _PyObject_CallMethodIdObjArgs(
1847 all_tasks, &PyId_add, task, NULL);
1848 if (res == NULL) {
1849 return -1;
1850 }
1851 Py_DECREF(res);
1852 return 0;
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001853}
1854
1855
1856static int
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001857unregister_task(PyObject *task)
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001858{
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001859 _Py_IDENTIFIER(discard);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001860
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001861 PyObject *res = _PyObject_CallMethodIdObjArgs(
1862 all_tasks, &PyId_discard, task, NULL);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001863 if (res == NULL) {
1864 return -1;
1865 }
1866 Py_DECREF(res);
1867 return 0;
1868}
1869
1870
1871static int
1872enter_task(PyObject *loop, PyObject *task)
1873{
1874 PyObject *item;
1875 Py_hash_t hash;
1876 hash = PyObject_Hash(loop);
1877 if (hash == -1) {
1878 return -1;
1879 }
1880 item = _PyDict_GetItem_KnownHash(current_tasks, loop, hash);
1881 if (item != NULL) {
Serhiy Storchaka66553542018-05-20 16:30:31 +03001882 Py_INCREF(item);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001883 PyErr_Format(
1884 PyExc_RuntimeError,
1885 "Cannot enter into task %R while another " \
1886 "task %R is being executed.",
1887 task, item, NULL);
Serhiy Storchaka66553542018-05-20 16:30:31 +03001888 Py_DECREF(item);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001889 return -1;
1890 }
Serhiy Storchaka66553542018-05-20 16:30:31 +03001891 if (PyErr_Occurred()) {
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001892 return -1;
1893 }
Serhiy Storchaka66553542018-05-20 16:30:31 +03001894 return _PyDict_SetItem_KnownHash(current_tasks, loop, task, hash);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001895}
1896
1897
1898static int
1899leave_task(PyObject *loop, PyObject *task)
1900/*[clinic end generated code: output=0ebf6db4b858fb41 input=51296a46313d1ad8]*/
1901{
1902 PyObject *item;
1903 Py_hash_t hash;
1904 hash = PyObject_Hash(loop);
1905 if (hash == -1) {
1906 return -1;
1907 }
1908 item = _PyDict_GetItem_KnownHash(current_tasks, loop, hash);
1909 if (item != task) {
1910 if (item == NULL) {
1911 /* Not entered, replace with None */
1912 item = Py_None;
1913 }
1914 PyErr_Format(
1915 PyExc_RuntimeError,
1916 "Leaving task %R does not match the current task %R.",
1917 task, item, NULL);
1918 return -1;
1919 }
1920 return _PyDict_DelItem_KnownHash(current_tasks, loop, hash);
1921}
1922
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001923/* ----- Task */
1924
1925/*[clinic input]
1926_asyncio.Task.__init__
1927
Serhiy Storchakabca49392017-09-03 08:10:14 +03001928 coro: object
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001929 *
Serhiy Storchakabca49392017-09-03 08:10:14 +03001930 loop: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001931
1932A coroutine wrapped in a Future.
1933[clinic start generated code]*/
1934
1935static int
1936_asyncio_Task___init___impl(TaskObj *self, PyObject *coro, PyObject *loop)
Serhiy Storchakabca49392017-09-03 08:10:14 +03001937/*[clinic end generated code: output=9f24774c2287fc2f input=8d132974b049593e]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001938{
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001939 if (future_init((FutureObj*)self, loop)) {
INADA Naokic411a7d2016-10-18 11:48:14 +09001940 return -1;
1941 }
INADA Naokic411a7d2016-10-18 11:48:14 +09001942
Yury Selivanova9d7e552017-12-19 07:18:45 -05001943 int is_coro = is_coroutine(coro);
1944 if (is_coro == -1) {
1945 return -1;
1946 }
1947 if (is_coro == 0) {
1948 self->task_log_destroy_pending = 0;
1949 PyErr_Format(PyExc_TypeError,
1950 "a coroutine was expected, got %R",
1951 coro, NULL);
1952 return -1;
Andrew Svetlovf74ef452017-12-15 07:04:38 +02001953 }
1954
Oren Milmand019bc82018-02-13 12:28:33 +02001955 Py_XSETREF(self->task_context, PyContext_CopyCurrent());
Yury Selivanovf23746a2018-01-22 19:11:18 -05001956 if (self->task_context == NULL) {
1957 return -1;
1958 }
1959
Oren Milmand019bc82018-02-13 12:28:33 +02001960 Py_CLEAR(self->task_fut_waiter);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001961 self->task_must_cancel = 0;
1962 self->task_log_destroy_pending = 1;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001963 Py_INCREF(coro);
Oren Milmand019bc82018-02-13 12:28:33 +02001964 Py_XSETREF(self->task_coro, coro);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001965
1966 if (task_call_step_soon(self, NULL)) {
1967 return -1;
INADA Naokic411a7d2016-10-18 11:48:14 +09001968 }
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001969 return register_task((PyObject*)self);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001970}
1971
1972static int
1973TaskObj_clear(TaskObj *task)
1974{
1975 (void)FutureObj_clear((FutureObj*) task);
Yury Selivanovf23746a2018-01-22 19:11:18 -05001976 Py_CLEAR(task->task_context);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001977 Py_CLEAR(task->task_coro);
1978 Py_CLEAR(task->task_fut_waiter);
1979 return 0;
1980}
1981
1982static int
1983TaskObj_traverse(TaskObj *task, visitproc visit, void *arg)
1984{
Yury Selivanovf23746a2018-01-22 19:11:18 -05001985 Py_VISIT(task->task_context);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001986 Py_VISIT(task->task_coro);
1987 Py_VISIT(task->task_fut_waiter);
1988 (void)FutureObj_traverse((FutureObj*) task, visit, arg);
1989 return 0;
1990}
1991
1992static PyObject *
1993TaskObj_get_log_destroy_pending(TaskObj *task)
1994{
1995 if (task->task_log_destroy_pending) {
1996 Py_RETURN_TRUE;
1997 }
1998 else {
1999 Py_RETURN_FALSE;
2000 }
2001}
2002
2003static int
2004TaskObj_set_log_destroy_pending(TaskObj *task, PyObject *val)
2005{
2006 int is_true = PyObject_IsTrue(val);
2007 if (is_true < 0) {
2008 return -1;
2009 }
2010 task->task_log_destroy_pending = is_true;
2011 return 0;
2012}
2013
2014static PyObject *
2015TaskObj_get_must_cancel(TaskObj *task)
2016{
2017 if (task->task_must_cancel) {
2018 Py_RETURN_TRUE;
2019 }
2020 else {
2021 Py_RETURN_FALSE;
2022 }
2023}
2024
2025static PyObject *
2026TaskObj_get_coro(TaskObj *task)
2027{
2028 if (task->task_coro) {
2029 Py_INCREF(task->task_coro);
2030 return task->task_coro;
2031 }
2032
2033 Py_RETURN_NONE;
2034}
2035
2036static PyObject *
2037TaskObj_get_fut_waiter(TaskObj *task)
2038{
2039 if (task->task_fut_waiter) {
2040 Py_INCREF(task->task_fut_waiter);
2041 return task->task_fut_waiter;
2042 }
2043
2044 Py_RETURN_NONE;
2045}
2046
2047/*[clinic input]
2048@classmethod
2049_asyncio.Task.current_task
2050
Serhiy Storchakabca49392017-09-03 08:10:14 +03002051 loop: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002052
2053Return the currently running task in an event loop or None.
2054
2055By default the current task for the current event loop is returned.
2056
2057None is returned when called not in the context of a Task.
2058[clinic start generated code]*/
2059
2060static PyObject *
2061_asyncio_Task_current_task_impl(PyTypeObject *type, PyObject *loop)
Serhiy Storchakabca49392017-09-03 08:10:14 +03002062/*[clinic end generated code: output=99fbe7332c516e03 input=cd14770c5b79c7eb]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002063{
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002064 PyObject *ret;
2065 PyObject *current_task_func;
2066
2067 if (PyErr_WarnEx(PyExc_PendingDeprecationWarning,
2068 "Task.current_task() is deprecated, " \
2069 "use asyncio.current_task() instead",
2070 1) < 0) {
2071 return NULL;
2072 }
2073
2074 current_task_func = _PyObject_GetAttrId(asyncio_mod, &PyId_current_task);
2075 if (current_task_func == NULL) {
2076 return NULL;
2077 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002078
Yury Selivanov8d26aa92017-03-02 22:16:33 -05002079 if (loop == Py_None) {
Yury Selivanova70232f2017-12-13 14:49:42 -05002080 loop = get_event_loop();
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002081 if (loop == NULL) {
Serhiy Storchaka66553542018-05-20 16:30:31 +03002082 Py_DECREF(current_task_func);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002083 return NULL;
2084 }
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002085 ret = PyObject_CallFunctionObjArgs(current_task_func, loop, NULL);
2086 Py_DECREF(current_task_func);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002087 Py_DECREF(loop);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002088 return ret;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002089 }
2090 else {
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002091 ret = PyObject_CallFunctionObjArgs(current_task_func, loop, NULL);
2092 Py_DECREF(current_task_func);
2093 return ret;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002094 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002095}
2096
2097/*[clinic input]
2098@classmethod
2099_asyncio.Task.all_tasks
2100
Serhiy Storchakabca49392017-09-03 08:10:14 +03002101 loop: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002102
2103Return a set of all tasks for an event loop.
2104
2105By default all tasks for the current event loop are returned.
2106[clinic start generated code]*/
2107
2108static PyObject *
2109_asyncio_Task_all_tasks_impl(PyTypeObject *type, PyObject *loop)
Serhiy Storchakabca49392017-09-03 08:10:14 +03002110/*[clinic end generated code: output=11f9b20749ccca5d input=497f80bc9ce726b5]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002111{
2112 PyObject *res;
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002113 PyObject *all_tasks_func;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002114
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002115 if (PyErr_WarnEx(PyExc_PendingDeprecationWarning,
2116 "Task.all_tasks() is deprecated, " \
2117 "use asyncio.all_tasks() instead",
2118 1) < 0) {
2119 return NULL;
2120 }
2121
Serhiy Storchaka66553542018-05-20 16:30:31 +03002122 all_tasks_func = _PyObject_GetAttrId(asyncio_mod, &PyId_all_tasks);
2123 if (all_tasks_func == NULL) {
2124 return NULL;
2125 }
2126
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002127 res = PyObject_CallFunctionObjArgs(all_tasks_func, loop, NULL);
2128 Py_DECREF(all_tasks_func);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002129 return res;
2130}
2131
2132/*[clinic input]
2133_asyncio.Task._repr_info
2134[clinic start generated code]*/
2135
2136static PyObject *
2137_asyncio_Task__repr_info_impl(TaskObj *self)
2138/*[clinic end generated code: output=6a490eb66d5ba34b input=3c6d051ed3ddec8b]*/
2139{
Victor Stinnerde4ae3d2016-12-04 22:59:09 +01002140 return PyObject_CallFunctionObjArgs(
2141 asyncio_task_repr_info_func, self, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002142}
2143
2144/*[clinic input]
2145_asyncio.Task.cancel
2146
2147Request that this task cancel itself.
2148
2149This arranges for a CancelledError to be thrown into the
2150wrapped coroutine on the next cycle through the event loop.
2151The coroutine then has a chance to clean up or even deny
2152the request using try/except/finally.
2153
2154Unlike Future.cancel, this does not guarantee that the
2155task will be cancelled: the exception might be caught and
2156acted upon, delaying cancellation of the task or preventing
2157cancellation completely. The task may also return a value or
2158raise a different exception.
2159
2160Immediately after this method is called, Task.cancelled() will
2161not return True (unless the task was already cancelled). A
2162task will be marked as cancelled when the wrapped coroutine
2163terminates with a CancelledError exception (even if cancel()
2164was not called).
2165[clinic start generated code]*/
2166
2167static PyObject *
2168_asyncio_Task_cancel_impl(TaskObj *self)
2169/*[clinic end generated code: output=6bfc0479da9d5757 input=13f9bf496695cb52]*/
2170{
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +00002171 self->task_log_tb = 0;
2172
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002173 if (self->task_state != STATE_PENDING) {
2174 Py_RETURN_FALSE;
2175 }
2176
2177 if (self->task_fut_waiter) {
2178 PyObject *res;
2179 int is_true;
2180
2181 res = _PyObject_CallMethodId(
2182 self->task_fut_waiter, &PyId_cancel, NULL);
2183 if (res == NULL) {
2184 return NULL;
2185 }
2186
2187 is_true = PyObject_IsTrue(res);
2188 Py_DECREF(res);
2189 if (is_true < 0) {
2190 return NULL;
2191 }
2192
2193 if (is_true) {
2194 Py_RETURN_TRUE;
2195 }
2196 }
2197
2198 self->task_must_cancel = 1;
2199 Py_RETURN_TRUE;
2200}
2201
2202/*[clinic input]
2203_asyncio.Task.get_stack
2204
2205 *
Serhiy Storchakabca49392017-09-03 08:10:14 +03002206 limit: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002207
2208Return the list of stack frames for this task's coroutine.
2209
2210If the coroutine is not done, this returns the stack where it is
2211suspended. If the coroutine has completed successfully or was
2212cancelled, this returns an empty list. If the coroutine was
2213terminated by an exception, this returns the list of traceback
2214frames.
2215
2216The frames are always ordered from oldest to newest.
2217
2218The optional limit gives the maximum number of frames to
2219return; by default all available frames are returned. Its
2220meaning differs depending on whether a stack or a traceback is
2221returned: the newest frames of a stack are returned, but the
2222oldest frames of a traceback are returned. (This matches the
2223behavior of the traceback module.)
2224
2225For reasons beyond our control, only one stack frame is
2226returned for a suspended coroutine.
2227[clinic start generated code]*/
2228
2229static PyObject *
2230_asyncio_Task_get_stack_impl(TaskObj *self, PyObject *limit)
Serhiy Storchakabca49392017-09-03 08:10:14 +03002231/*[clinic end generated code: output=c9aeeeebd1e18118 input=05b323d42b809b90]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002232{
2233 return PyObject_CallFunctionObjArgs(
2234 asyncio_task_get_stack_func, self, limit, NULL);
2235}
2236
2237/*[clinic input]
2238_asyncio.Task.print_stack
2239
2240 *
Serhiy Storchakabca49392017-09-03 08:10:14 +03002241 limit: object = None
2242 file: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002243
2244Print the stack or traceback for this task's coroutine.
2245
2246This produces output similar to that of the traceback module,
2247for the frames retrieved by get_stack(). The limit argument
2248is passed to get_stack(). The file argument is an I/O stream
2249to which the output is written; by default output is written
2250to sys.stderr.
2251[clinic start generated code]*/
2252
2253static PyObject *
2254_asyncio_Task_print_stack_impl(TaskObj *self, PyObject *limit,
2255 PyObject *file)
Serhiy Storchakabca49392017-09-03 08:10:14 +03002256/*[clinic end generated code: output=7339e10314cd3f4d input=1a0352913b7fcd92]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002257{
2258 return PyObject_CallFunctionObjArgs(
2259 asyncio_task_print_stack_func, self, limit, file, NULL);
2260}
2261
2262/*[clinic input]
Yury Selivanov0cf16f92017-12-25 10:48:15 -05002263_asyncio.Task.set_result
2264
2265 result: object
2266 /
2267[clinic start generated code]*/
2268
2269static PyObject *
2270_asyncio_Task_set_result(TaskObj *self, PyObject *result)
2271/*[clinic end generated code: output=1dcae308bfcba318 input=9d1a00c07be41bab]*/
2272{
2273 PyErr_SetString(PyExc_RuntimeError,
2274 "Task does not support set_result operation");
2275 return NULL;
2276}
2277
2278/*[clinic input]
2279_asyncio.Task.set_exception
2280
2281 exception: object
2282 /
2283[clinic start generated code]*/
2284
2285static PyObject *
2286_asyncio_Task_set_exception(TaskObj *self, PyObject *exception)
2287/*[clinic end generated code: output=bc377fc28067303d input=9a8f65c83dcf893a]*/
2288{
2289 PyErr_SetString(PyExc_RuntimeError,
Andrew Svetlovfc359322017-12-30 15:40:27 +02002290 "Task does not support set_exception operation");
Yury Selivanov0cf16f92017-12-25 10:48:15 -05002291 return NULL;
2292}
2293
2294
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002295static void
2296TaskObj_finalize(TaskObj *task)
2297{
2298 _Py_IDENTIFIER(call_exception_handler);
2299 _Py_IDENTIFIER(task);
2300 _Py_IDENTIFIER(message);
2301 _Py_IDENTIFIER(source_traceback);
2302
Serhiy Storchakabca49392017-09-03 08:10:14 +03002303 PyObject *context;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002304 PyObject *message = NULL;
Serhiy Storchakabca49392017-09-03 08:10:14 +03002305 PyObject *func;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002306 PyObject *error_type, *error_value, *error_traceback;
2307
2308 if (task->task_state != STATE_PENDING || !task->task_log_destroy_pending) {
2309 goto done;
2310 }
2311
2312 /* Save the current exception, if any. */
2313 PyErr_Fetch(&error_type, &error_value, &error_traceback);
2314
2315 context = PyDict_New();
2316 if (context == NULL) {
2317 goto finally;
2318 }
2319
2320 message = PyUnicode_FromString("Task was destroyed but it is pending!");
2321 if (message == NULL) {
2322 goto finally;
2323 }
2324
2325 if (_PyDict_SetItemId(context, &PyId_message, message) < 0 ||
2326 _PyDict_SetItemId(context, &PyId_task, (PyObject*)task) < 0)
2327 {
2328 goto finally;
2329 }
2330
2331 if (task->task_source_tb != NULL) {
2332 if (_PyDict_SetItemId(context, &PyId_source_traceback,
2333 task->task_source_tb) < 0)
2334 {
2335 goto finally;
2336 }
2337 }
2338
2339 func = _PyObject_GetAttrId(task->task_loop, &PyId_call_exception_handler);
2340 if (func != NULL) {
Serhiy Storchakabca49392017-09-03 08:10:14 +03002341 PyObject *res = PyObject_CallFunctionObjArgs(func, context, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002342 if (res == NULL) {
2343 PyErr_WriteUnraisable(func);
2344 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03002345 else {
2346 Py_DECREF(res);
2347 }
2348 Py_DECREF(func);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002349 }
2350
2351finally:
Serhiy Storchakabca49392017-09-03 08:10:14 +03002352 Py_XDECREF(context);
2353 Py_XDECREF(message);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002354
2355 /* Restore the saved exception. */
2356 PyErr_Restore(error_type, error_value, error_traceback);
2357
2358done:
2359 FutureObj_finalize((FutureObj*)task);
2360}
2361
2362static void TaskObj_dealloc(PyObject *); /* Needs Task_CheckExact */
2363
2364static PyMethodDef TaskType_methods[] = {
2365 _ASYNCIO_FUTURE_RESULT_METHODDEF
2366 _ASYNCIO_FUTURE_EXCEPTION_METHODDEF
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002367 _ASYNCIO_FUTURE_ADD_DONE_CALLBACK_METHODDEF
2368 _ASYNCIO_FUTURE_REMOVE_DONE_CALLBACK_METHODDEF
2369 _ASYNCIO_FUTURE_CANCELLED_METHODDEF
2370 _ASYNCIO_FUTURE_DONE_METHODDEF
Yury Selivanov0cf16f92017-12-25 10:48:15 -05002371 _ASYNCIO_TASK_SET_RESULT_METHODDEF
2372 _ASYNCIO_TASK_SET_EXCEPTION_METHODDEF
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002373 _ASYNCIO_TASK_CURRENT_TASK_METHODDEF
2374 _ASYNCIO_TASK_ALL_TASKS_METHODDEF
2375 _ASYNCIO_TASK_CANCEL_METHODDEF
2376 _ASYNCIO_TASK_GET_STACK_METHODDEF
2377 _ASYNCIO_TASK_PRINT_STACK_METHODDEF
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002378 _ASYNCIO_TASK__REPR_INFO_METHODDEF
2379 {NULL, NULL} /* Sentinel */
2380};
2381
2382static PyGetSetDef TaskType_getsetlist[] = {
2383 FUTURE_COMMON_GETSETLIST
2384 {"_log_destroy_pending", (getter)TaskObj_get_log_destroy_pending,
2385 (setter)TaskObj_set_log_destroy_pending, NULL},
2386 {"_must_cancel", (getter)TaskObj_get_must_cancel, NULL, NULL},
2387 {"_coro", (getter)TaskObj_get_coro, NULL, NULL},
2388 {"_fut_waiter", (getter)TaskObj_get_fut_waiter, NULL, NULL},
2389 {NULL} /* Sentinel */
2390};
2391
2392static PyTypeObject TaskType = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02002393 PyVarObject_HEAD_INIT(NULL, 0)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002394 "_asyncio.Task",
2395 sizeof(TaskObj), /* tp_basicsize */
2396 .tp_base = &FutureType,
2397 .tp_dealloc = TaskObj_dealloc,
2398 .tp_as_async = &FutureType_as_async,
2399 .tp_repr = (reprfunc)FutureObj_repr,
2400 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE
2401 | Py_TPFLAGS_HAVE_FINALIZE,
2402 .tp_doc = _asyncio_Task___init____doc__,
2403 .tp_traverse = (traverseproc)TaskObj_traverse,
2404 .tp_clear = (inquiry)TaskObj_clear,
2405 .tp_weaklistoffset = offsetof(TaskObj, task_weakreflist),
2406 .tp_iter = (getiterfunc)future_new_iter,
2407 .tp_methods = TaskType_methods,
2408 .tp_getset = TaskType_getsetlist,
2409 .tp_dictoffset = offsetof(TaskObj, dict),
2410 .tp_init = (initproc)_asyncio_Task___init__,
2411 .tp_new = PyType_GenericNew,
2412 .tp_finalize = (destructor)TaskObj_finalize,
2413};
2414
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002415static void
2416TaskObj_dealloc(PyObject *self)
2417{
2418 TaskObj *task = (TaskObj *)self;
2419
2420 if (Task_CheckExact(self)) {
2421 /* When fut is subclass of Task, finalizer is called from
2422 * subtype_dealloc.
2423 */
2424 if (PyObject_CallFinalizerFromDealloc(self) < 0) {
2425 // resurrected.
2426 return;
2427 }
2428 }
2429
Alexander Mohrde34cbe2017-08-01 23:31:07 -07002430 PyObject_GC_UnTrack(self);
2431
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002432 if (task->task_weakreflist != NULL) {
2433 PyObject_ClearWeakRefs(self);
2434 }
2435
2436 (void)TaskObj_clear(task);
2437 Py_TYPE(task)->tp_free(task);
2438}
2439
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002440static int
2441task_call_step_soon(TaskObj *task, PyObject *arg)
2442{
Serhiy Storchakabca49392017-09-03 08:10:14 +03002443 PyObject *cb = TaskStepMethWrapper_new(task, arg);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002444 if (cb == NULL) {
2445 return -1;
2446 }
2447
Yury Selivanovf23746a2018-01-22 19:11:18 -05002448 int ret = call_soon(task->task_loop, cb, NULL, task->task_context);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002449 Py_DECREF(cb);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05002450 return ret;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002451}
2452
2453static PyObject *
2454task_set_error_soon(TaskObj *task, PyObject *et, const char *format, ...)
2455{
2456 PyObject* msg;
2457
2458 va_list vargs;
2459#ifdef HAVE_STDARG_PROTOTYPES
2460 va_start(vargs, format);
2461#else
2462 va_start(vargs);
2463#endif
2464 msg = PyUnicode_FromFormatV(format, vargs);
2465 va_end(vargs);
2466
2467 if (msg == NULL) {
2468 return NULL;
2469 }
2470
Victor Stinnerde4ae3d2016-12-04 22:59:09 +01002471 PyObject *e = PyObject_CallFunctionObjArgs(et, msg, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002472 Py_DECREF(msg);
2473 if (e == NULL) {
2474 return NULL;
2475 }
2476
2477 if (task_call_step_soon(task, e) == -1) {
2478 Py_DECREF(e);
2479 return NULL;
2480 }
2481
2482 Py_DECREF(e);
2483 Py_RETURN_NONE;
2484}
2485
2486static PyObject *
2487task_step_impl(TaskObj *task, PyObject *exc)
2488{
2489 int res;
2490 int clear_exc = 0;
2491 PyObject *result = NULL;
Serhiy Storchakabca49392017-09-03 08:10:14 +03002492 PyObject *coro;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002493 PyObject *o;
2494
2495 if (task->task_state != STATE_PENDING) {
Yury Selivanov0cf16f92017-12-25 10:48:15 -05002496 PyErr_Format(asyncio_InvalidStateError,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002497 "_step(): already done: %R %R",
2498 task,
2499 exc ? exc : Py_None);
INADA Naokic411a7d2016-10-18 11:48:14 +09002500 goto fail;
2501 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09002502
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002503 if (task->task_must_cancel) {
2504 assert(exc != Py_None);
2505
2506 if (exc) {
2507 /* Check if exc is a CancelledError */
2508 res = PyObject_IsInstance(exc, asyncio_CancelledError);
2509 if (res == -1) {
2510 /* An error occurred, abort */
2511 goto fail;
2512 }
2513 if (res == 0) {
2514 /* exc is not CancelledError; reset it to NULL */
2515 exc = NULL;
2516 }
2517 }
2518
2519 if (!exc) {
2520 /* exc was not a CancelledError */
Victor Stinnerf17c3de2016-12-06 18:46:19 +01002521 exc = _PyObject_CallNoArg(asyncio_CancelledError);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002522 if (!exc) {
2523 goto fail;
2524 }
2525 clear_exc = 1;
2526 }
2527
2528 task->task_must_cancel = 0;
2529 }
2530
2531 Py_CLEAR(task->task_fut_waiter);
2532
Serhiy Storchakabca49392017-09-03 08:10:14 +03002533 coro = task->task_coro;
2534 if (coro == NULL) {
2535 PyErr_SetString(PyExc_RuntimeError, "uninitialized Task object");
2536 return NULL;
2537 }
2538
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002539 if (exc == NULL) {
2540 if (PyGen_CheckExact(coro) || PyCoro_CheckExact(coro)) {
2541 result = _PyGen_Send((PyGenObject*)coro, Py_None);
2542 }
2543 else {
Victor Stinnerb6ed57d2016-12-09 14:24:02 +01002544 result = _PyObject_CallMethodIdObjArgs(coro, &PyId_send,
2545 Py_None, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002546 }
2547 }
2548 else {
Victor Stinnerb6ed57d2016-12-09 14:24:02 +01002549 result = _PyObject_CallMethodIdObjArgs(coro, &PyId_throw,
2550 exc, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002551 if (clear_exc) {
2552 /* We created 'exc' during this call */
Serhiy Storchakabca49392017-09-03 08:10:14 +03002553 Py_DECREF(exc);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002554 }
2555 }
2556
2557 if (result == NULL) {
2558 PyObject *et, *ev, *tb;
2559
2560 if (_PyGen_FetchStopIterationValue(&o) == 0) {
2561 /* The error is StopIteration and that means that
2562 the underlying coroutine has resolved */
INADA Naoki991adca2017-05-11 21:18:38 +09002563 if (task->task_must_cancel) {
2564 // Task is cancelled right before coro stops.
2565 Py_DECREF(o);
2566 task->task_must_cancel = 0;
2567 et = asyncio_CancelledError;
2568 Py_INCREF(et);
2569 ev = NULL;
2570 tb = NULL;
2571 goto set_exception;
2572 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002573 PyObject *res = future_set_result((FutureObj*)task, o);
2574 Py_DECREF(o);
2575 if (res == NULL) {
2576 return NULL;
2577 }
2578 Py_DECREF(res);
2579 Py_RETURN_NONE;
2580 }
2581
2582 if (PyErr_ExceptionMatches(asyncio_CancelledError)) {
2583 /* CancelledError */
2584 PyErr_Clear();
2585 return future_cancel((FutureObj*)task);
2586 }
2587
2588 /* Some other exception; pop it and call Task.set_exception() */
2589 PyErr_Fetch(&et, &ev, &tb);
INADA Naoki991adca2017-05-11 21:18:38 +09002590
2591set_exception:
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002592 assert(et);
2593 if (!ev || !PyObject_TypeCheck(ev, (PyTypeObject *) et)) {
2594 PyErr_NormalizeException(&et, &ev, &tb);
2595 }
Yury Selivanovedfe8862016-12-01 11:37:47 -05002596 if (tb != NULL) {
2597 PyException_SetTraceback(ev, tb);
2598 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002599 o = future_set_exception((FutureObj*)task, ev);
2600 if (!o) {
2601 /* An exception in Task.set_exception() */
Serhiy Storchakabca49392017-09-03 08:10:14 +03002602 Py_DECREF(et);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002603 Py_XDECREF(tb);
2604 Py_XDECREF(ev);
2605 goto fail;
2606 }
2607 assert(o == Py_None);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002608 Py_DECREF(o);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002609
2610 if (!PyErr_GivenExceptionMatches(et, PyExc_Exception)) {
2611 /* We've got a BaseException; re-raise it */
2612 PyErr_Restore(et, ev, tb);
2613 goto fail;
2614 }
2615
Serhiy Storchakabca49392017-09-03 08:10:14 +03002616 Py_DECREF(et);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002617 Py_XDECREF(tb);
2618 Py_XDECREF(ev);
2619
2620 Py_RETURN_NONE;
2621 }
2622
2623 if (result == (PyObject*)task) {
2624 /* We have a task that wants to await on itself */
2625 goto self_await;
2626 }
2627
2628 /* Check if `result` is FutureObj or TaskObj (and not a subclass) */
2629 if (Future_CheckExact(result) || Task_CheckExact(result)) {
2630 PyObject *wrapper;
2631 PyObject *res;
2632 FutureObj *fut = (FutureObj*)result;
2633
2634 /* Check if `result` future is attached to a different loop */
2635 if (fut->fut_loop != task->task_loop) {
2636 goto different_loop;
2637 }
2638
2639 if (fut->fut_blocking) {
2640 fut->fut_blocking = 0;
2641
2642 /* result.add_done_callback(task._wakeup) */
2643 wrapper = TaskWakeupMethWrapper_new(task);
2644 if (wrapper == NULL) {
2645 goto fail;
2646 }
Yury Selivanovf23746a2018-01-22 19:11:18 -05002647 res = future_add_done_callback(
2648 (FutureObj*)result, wrapper, task->task_context);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002649 Py_DECREF(wrapper);
2650 if (res == NULL) {
2651 goto fail;
2652 }
2653 Py_DECREF(res);
2654
2655 /* task._fut_waiter = result */
2656 task->task_fut_waiter = result; /* no incref is necessary */
2657
2658 if (task->task_must_cancel) {
2659 PyObject *r;
2660 r = future_cancel(fut);
2661 if (r == NULL) {
2662 return NULL;
2663 }
2664 if (r == Py_True) {
2665 task->task_must_cancel = 0;
2666 }
2667 Py_DECREF(r);
2668 }
2669
2670 Py_RETURN_NONE;
2671 }
2672 else {
2673 goto yield_insteadof_yf;
2674 }
2675 }
2676
2677 /* Check if `result` is a Future-compatible object */
2678 o = PyObject_GetAttrString(result, "_asyncio_future_blocking");
2679 if (o == NULL) {
2680 if (PyErr_ExceptionMatches(PyExc_AttributeError)) {
2681 PyErr_Clear();
2682 }
2683 else {
2684 goto fail;
2685 }
2686 }
2687 else {
2688 if (o == Py_None) {
Serhiy Storchakabca49392017-09-03 08:10:14 +03002689 Py_DECREF(o);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002690 }
2691 else {
2692 /* `result` is a Future-compatible object */
2693 PyObject *wrapper;
2694 PyObject *res;
2695
2696 int blocking = PyObject_IsTrue(o);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002697 Py_DECREF(o);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002698 if (blocking < 0) {
2699 goto fail;
2700 }
2701
2702 /* Check if `result` future is attached to a different loop */
Yury Selivanovca9b36c2017-12-23 15:04:15 -05002703 PyObject *oloop = get_future_loop(result);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002704 if (oloop == NULL) {
2705 goto fail;
2706 }
2707 if (oloop != task->task_loop) {
2708 Py_DECREF(oloop);
2709 goto different_loop;
2710 }
2711 else {
2712 Py_DECREF(oloop);
2713 }
2714
2715 if (blocking) {
2716 /* result._asyncio_future_blocking = False */
2717 if (PyObject_SetAttrString(
2718 result, "_asyncio_future_blocking", Py_False) == -1) {
2719 goto fail;
2720 }
2721
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002722 wrapper = TaskWakeupMethWrapper_new(task);
2723 if (wrapper == NULL) {
2724 goto fail;
2725 }
Yury Selivanovf23746a2018-01-22 19:11:18 -05002726
2727 /* result.add_done_callback(task._wakeup) */
2728 PyObject *add_cb = _PyObject_GetAttrId(
2729 result, &PyId_add_done_callback);
2730 if (add_cb == NULL) {
Serhiy Storchaka66553542018-05-20 16:30:31 +03002731 Py_DECREF(wrapper);
Yury Selivanovf23746a2018-01-22 19:11:18 -05002732 goto fail;
2733 }
2734 PyObject *stack[2];
2735 stack[0] = wrapper;
2736 stack[1] = (PyObject *)task->task_context;
2737 res = _PyObject_FastCallKeywords(
2738 add_cb, stack, 1, context_kwname);
2739 Py_DECREF(add_cb);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002740 Py_DECREF(wrapper);
2741 if (res == NULL) {
2742 goto fail;
2743 }
2744 Py_DECREF(res);
2745
2746 /* task._fut_waiter = result */
2747 task->task_fut_waiter = result; /* no incref is necessary */
2748
2749 if (task->task_must_cancel) {
2750 PyObject *r;
2751 int is_true;
2752 r = _PyObject_CallMethodId(result, &PyId_cancel, NULL);
2753 if (r == NULL) {
2754 return NULL;
2755 }
2756 is_true = PyObject_IsTrue(r);
2757 Py_DECREF(r);
2758 if (is_true < 0) {
2759 return NULL;
2760 }
2761 else if (is_true) {
2762 task->task_must_cancel = 0;
2763 }
2764 }
2765
2766 Py_RETURN_NONE;
2767 }
2768 else {
2769 goto yield_insteadof_yf;
2770 }
2771 }
2772 }
2773
2774 /* Check if `result` is None */
2775 if (result == Py_None) {
2776 /* Bare yield relinquishes control for one event loop iteration. */
2777 if (task_call_step_soon(task, NULL)) {
2778 goto fail;
2779 }
2780 return result;
2781 }
2782
2783 /* Check if `result` is a generator */
Victor Stinnerde4ae3d2016-12-04 22:59:09 +01002784 o = PyObject_CallFunctionObjArgs(inspect_isgenerator, result, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002785 if (o == NULL) {
2786 /* An exception in inspect.isgenerator */
2787 goto fail;
2788 }
2789 res = PyObject_IsTrue(o);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002790 Py_DECREF(o);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002791 if (res == -1) {
2792 /* An exception while checking if 'val' is True */
2793 goto fail;
2794 }
2795 if (res == 1) {
2796 /* `result` is a generator */
Serhiy Storchaka66553542018-05-20 16:30:31 +03002797 o = task_set_error_soon(
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002798 task, PyExc_RuntimeError,
2799 "yield was used instead of yield from for "
Serhiy Storchaka66553542018-05-20 16:30:31 +03002800 "generator in task %R with %R", task, result);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002801 Py_DECREF(result);
Serhiy Storchaka66553542018-05-20 16:30:31 +03002802 return o;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002803 }
2804
2805 /* The `result` is none of the above */
Serhiy Storchaka66553542018-05-20 16:30:31 +03002806 o = task_set_error_soon(
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002807 task, PyExc_RuntimeError, "Task got bad yield: %R", result);
Serhiy Storchaka66553542018-05-20 16:30:31 +03002808 Py_DECREF(result);
2809 return o;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002810
2811self_await:
2812 o = task_set_error_soon(
2813 task, PyExc_RuntimeError,
2814 "Task cannot await on itself: %R", task);
2815 Py_DECREF(result);
2816 return o;
2817
2818yield_insteadof_yf:
2819 o = task_set_error_soon(
2820 task, PyExc_RuntimeError,
2821 "yield was used instead of yield from "
2822 "in task %R with %R",
2823 task, result);
2824 Py_DECREF(result);
2825 return o;
2826
2827different_loop:
2828 o = task_set_error_soon(
2829 task, PyExc_RuntimeError,
2830 "Task %R got Future %R attached to a different loop",
2831 task, result);
2832 Py_DECREF(result);
2833 return o;
2834
2835fail:
2836 Py_XDECREF(result);
2837 return NULL;
2838}
2839
2840static PyObject *
2841task_step(TaskObj *task, PyObject *exc)
2842{
2843 PyObject *res;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002844
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002845 if (enter_task(task->task_loop, (PyObject*)task) < 0) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002846 return NULL;
2847 }
2848
2849 res = task_step_impl(task, exc);
2850
2851 if (res == NULL) {
2852 PyObject *et, *ev, *tb;
2853 PyErr_Fetch(&et, &ev, &tb);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002854 leave_task(task->task_loop, (PyObject*)task);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002855 _PyErr_ChainExceptions(et, ev, tb);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002856 return NULL;
2857 }
2858 else {
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002859 if(leave_task(task->task_loop, (PyObject*)task) < 0) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002860 Py_DECREF(res);
2861 return NULL;
2862 }
2863 else {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002864 return res;
2865 }
2866 }
2867}
2868
2869static PyObject *
2870task_wakeup(TaskObj *task, PyObject *o)
2871{
Serhiy Storchakabca49392017-09-03 08:10:14 +03002872 PyObject *et, *ev, *tb;
2873 PyObject *result;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002874 assert(o);
2875
2876 if (Future_CheckExact(o) || Task_CheckExact(o)) {
2877 PyObject *fut_result = NULL;
2878 int res = future_get_result((FutureObj*)o, &fut_result);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002879
2880 switch(res) {
2881 case -1:
2882 assert(fut_result == NULL);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002883 break; /* exception raised */
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002884 case 0:
2885 Py_DECREF(fut_result);
Yury Selivanov22feeb82018-01-24 11:31:01 -05002886 return task_step(task, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002887 default:
2888 assert(res == 1);
Yury Selivanov22feeb82018-01-24 11:31:01 -05002889 result = task_step(task, fut_result);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002890 Py_DECREF(fut_result);
2891 return result;
2892 }
2893 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002894 else {
Serhiy Storchakabca49392017-09-03 08:10:14 +03002895 PyObject *fut_result = PyObject_CallMethod(o, "result", NULL);
2896 if (fut_result != NULL) {
2897 Py_DECREF(fut_result);
Yury Selivanov22feeb82018-01-24 11:31:01 -05002898 return task_step(task, NULL);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002899 }
2900 /* exception raised */
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002901 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03002902
2903 PyErr_Fetch(&et, &ev, &tb);
2904 if (!PyErr_GivenExceptionMatches(et, PyExc_Exception)) {
2905 /* We've got a BaseException; re-raise it */
2906 PyErr_Restore(et, ev, tb);
2907 return NULL;
2908 }
2909 if (!ev || !PyObject_TypeCheck(ev, (PyTypeObject *) et)) {
2910 PyErr_NormalizeException(&et, &ev, &tb);
2911 }
2912
Yury Selivanov22feeb82018-01-24 11:31:01 -05002913 result = task_step(task, ev);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002914
2915 Py_DECREF(et);
2916 Py_XDECREF(tb);
2917 Py_XDECREF(ev);
2918
2919 return result;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002920}
2921
2922
Yury Selivanova70232f2017-12-13 14:49:42 -05002923/*********************** Functions **************************/
2924
2925
2926/*[clinic input]
2927_asyncio._get_running_loop
2928
2929Return the running event loop or None.
2930
2931This is a low-level function intended to be used by event loops.
2932This function is thread-specific.
2933
2934[clinic start generated code]*/
2935
2936static PyObject *
2937_asyncio__get_running_loop_impl(PyObject *module)
2938/*[clinic end generated code: output=b4390af721411a0a input=0a21627e25a4bd43]*/
2939{
2940 PyObject *loop;
2941 if (get_running_loop(&loop)) {
2942 return NULL;
2943 }
2944 if (loop == NULL) {
2945 /* There's no currently running event loop */
2946 Py_RETURN_NONE;
2947 }
2948 return loop;
2949}
2950
2951/*[clinic input]
2952_asyncio._set_running_loop
2953 loop: 'O'
2954 /
2955
2956Set the running event loop.
2957
2958This is a low-level function intended to be used by event loops.
2959This function is thread-specific.
2960[clinic start generated code]*/
2961
2962static PyObject *
2963_asyncio__set_running_loop(PyObject *module, PyObject *loop)
2964/*[clinic end generated code: output=ae56bf7a28ca189a input=4c9720233d606604]*/
2965{
2966 if (set_running_loop(loop)) {
2967 return NULL;
2968 }
2969 Py_RETURN_NONE;
2970}
2971
2972/*[clinic input]
2973_asyncio.get_event_loop
2974
2975Return an asyncio event loop.
2976
2977When called from a coroutine or a callback (e.g. scheduled with
2978call_soon or similar API), this function will always return the
2979running event loop.
2980
2981If there is no running event loop set, the function will return
2982the result of `get_event_loop_policy().get_event_loop()` call.
2983[clinic start generated code]*/
2984
2985static PyObject *
2986_asyncio_get_event_loop_impl(PyObject *module)
2987/*[clinic end generated code: output=2a2d8b2f824c648b input=9364bf2916c8655d]*/
2988{
2989 return get_event_loop();
2990}
2991
2992/*[clinic input]
2993_asyncio.get_running_loop
2994
2995Return the running event loop. Raise a RuntimeError if there is none.
2996
2997This function is thread-specific.
2998[clinic start generated code]*/
2999
3000static PyObject *
3001_asyncio_get_running_loop_impl(PyObject *module)
3002/*[clinic end generated code: output=c247b5f9e529530e input=2a3bf02ba39f173d]*/
3003{
3004 PyObject *loop;
3005 if (get_running_loop(&loop)) {
3006 return NULL;
3007 }
3008 if (loop == NULL) {
3009 /* There's no currently running event loop */
3010 PyErr_SetString(
3011 PyExc_RuntimeError, "no running event loop");
3012 }
3013 return loop;
3014}
3015
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003016/*[clinic input]
3017_asyncio._register_task
3018
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003019 task: object
3020
3021Register a new task in asyncio as executed by loop.
3022
3023Returns None.
3024[clinic start generated code]*/
3025
3026static PyObject *
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003027_asyncio__register_task_impl(PyObject *module, PyObject *task)
3028/*[clinic end generated code: output=8672dadd69a7d4e2 input=21075aaea14dfbad]*/
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003029{
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003030 if (register_task(task) < 0) {
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003031 return NULL;
3032 }
3033 Py_RETURN_NONE;
3034}
3035
3036
3037/*[clinic input]
3038_asyncio._unregister_task
3039
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003040 task: object
3041
3042Unregister a task.
3043
3044Returns None.
3045[clinic start generated code]*/
3046
3047static PyObject *
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003048_asyncio__unregister_task_impl(PyObject *module, PyObject *task)
3049/*[clinic end generated code: output=6e5585706d568a46 input=28fb98c3975f7bdc]*/
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003050{
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003051 if (unregister_task(task) < 0) {
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003052 return NULL;
3053 }
3054 Py_RETURN_NONE;
3055}
3056
3057
3058/*[clinic input]
3059_asyncio._enter_task
3060
3061 loop: object
3062 task: object
3063
3064Enter into task execution or resume suspended task.
3065
3066Task belongs to loop.
3067
3068Returns None.
3069[clinic start generated code]*/
3070
3071static PyObject *
3072_asyncio__enter_task_impl(PyObject *module, PyObject *loop, PyObject *task)
3073/*[clinic end generated code: output=a22611c858035b73 input=de1b06dca70d8737]*/
3074{
3075 if (enter_task(loop, task) < 0) {
3076 return NULL;
3077 }
3078 Py_RETURN_NONE;
3079}
3080
3081
3082/*[clinic input]
3083_asyncio._leave_task
3084
3085 loop: object
3086 task: object
3087
3088Leave task execution or suspend a task.
3089
3090Task belongs to loop.
3091
3092Returns None.
3093[clinic start generated code]*/
3094
3095static PyObject *
3096_asyncio__leave_task_impl(PyObject *module, PyObject *loop, PyObject *task)
3097/*[clinic end generated code: output=0ebf6db4b858fb41 input=51296a46313d1ad8]*/
3098{
3099 if (leave_task(loop, task) < 0) {
3100 return NULL;
3101 }
3102 Py_RETURN_NONE;
3103}
3104
Yury Selivanova70232f2017-12-13 14:49:42 -05003105
Yury Selivanov9d411c12018-01-23 15:10:03 -05003106/*********************** PyRunningLoopHolder ********************/
3107
3108
3109static PyRunningLoopHolder *
3110new_running_loop_holder(PyObject *loop)
3111{
3112 PyRunningLoopHolder *rl = PyObject_New(
3113 PyRunningLoopHolder, &PyRunningLoopHolder_Type);
3114 if (rl == NULL) {
3115 return NULL;
3116 }
3117
3118#if defined(HAVE_GETPID) && !defined(MS_WINDOWS)
3119 rl->rl_pid = getpid();
3120#endif
3121
3122 Py_INCREF(loop);
3123 rl->rl_loop = loop;
3124
3125 return rl;
3126}
3127
3128
3129static void
3130PyRunningLoopHolder_tp_dealloc(PyRunningLoopHolder *rl)
3131{
3132 Py_CLEAR(rl->rl_loop);
3133 PyObject_Free(rl);
3134}
3135
3136
3137static PyTypeObject PyRunningLoopHolder_Type = {
3138 PyVarObject_HEAD_INIT(NULL, 0)
3139 "_RunningLoopHolder",
3140 sizeof(PyRunningLoopHolder),
3141 .tp_getattro = PyObject_GenericGetAttr,
3142 .tp_flags = Py_TPFLAGS_DEFAULT,
3143 .tp_dealloc = (destructor)PyRunningLoopHolder_tp_dealloc,
3144};
3145
3146
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003147/*********************** Module **************************/
3148
3149
3150static void
Zackery Spytze40ad792017-12-19 11:48:13 -07003151module_free_freelists(void)
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05003152{
3153 PyObject *next;
3154 PyObject *current;
3155
3156 next = (PyObject*) fi_freelist;
3157 while (next != NULL) {
3158 assert(fi_freelist_len > 0);
3159 fi_freelist_len--;
3160
3161 current = next;
3162 next = (PyObject*) ((futureiterobject*) current)->future;
3163 PyObject_GC_Del(current);
3164 }
3165 assert(fi_freelist_len == 0);
3166 fi_freelist = NULL;
3167}
3168
3169
3170static void
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003171module_free(void *m)
3172{
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003173 Py_CLEAR(asyncio_mod);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003174 Py_CLEAR(inspect_isgenerator);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003175 Py_CLEAR(traceback_extract_stack);
3176 Py_CLEAR(asyncio_future_repr_info_func);
3177 Py_CLEAR(asyncio_get_event_loop_policy);
3178 Py_CLEAR(asyncio_iscoroutine_func);
3179 Py_CLEAR(asyncio_task_get_stack_func);
3180 Py_CLEAR(asyncio_task_print_stack_func);
3181 Py_CLEAR(asyncio_task_repr_info_func);
3182 Py_CLEAR(asyncio_InvalidStateError);
3183 Py_CLEAR(asyncio_CancelledError);
3184
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003185 Py_CLEAR(all_tasks);
Yury Selivanova9d7e552017-12-19 07:18:45 -05003186 Py_CLEAR(current_tasks);
3187 Py_CLEAR(iscoroutine_typecache);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05003188
Yury Selivanovf23746a2018-01-22 19:11:18 -05003189 Py_CLEAR(context_kwname);
3190
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05003191 module_free_freelists();
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003192}
3193
3194static int
3195module_init(void)
3196{
3197 PyObject *module = NULL;
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003198
3199 asyncio_mod = PyImport_ImportModule("asyncio");
3200 if (asyncio_mod == NULL) {
3201 goto fail;
3202 }
3203
3204 current_tasks = PyDict_New();
3205 if (current_tasks == NULL) {
3206 goto fail;
3207 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003208
Yury Selivanova9d7e552017-12-19 07:18:45 -05003209 iscoroutine_typecache = PySet_New(NULL);
3210 if (iscoroutine_typecache == NULL) {
3211 goto fail;
3212 }
3213
Yury Selivanovf23746a2018-01-22 19:11:18 -05003214
3215 context_kwname = PyTuple_New(1);
3216 if (context_kwname == NULL) {
3217 goto fail;
3218 }
3219 PyObject *context_str = PyUnicode_FromString("context");
3220 if (context_str == NULL) {
3221 goto fail;
3222 }
3223 PyTuple_SET_ITEM(context_kwname, 0, context_str);
3224
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003225#define WITH_MOD(NAME) \
3226 Py_CLEAR(module); \
3227 module = PyImport_ImportModule(NAME); \
3228 if (module == NULL) { \
Serhiy Storchakabca49392017-09-03 08:10:14 +03003229 goto fail; \
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003230 }
3231
3232#define GET_MOD_ATTR(VAR, NAME) \
3233 VAR = PyObject_GetAttrString(module, NAME); \
3234 if (VAR == NULL) { \
3235 goto fail; \
3236 }
3237
3238 WITH_MOD("asyncio.events")
Yury Selivanova70232f2017-12-13 14:49:42 -05003239 GET_MOD_ATTR(asyncio_get_event_loop_policy, "get_event_loop_policy")
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003240
3241 WITH_MOD("asyncio.base_futures")
3242 GET_MOD_ATTR(asyncio_future_repr_info_func, "_future_repr_info")
3243 GET_MOD_ATTR(asyncio_InvalidStateError, "InvalidStateError")
3244 GET_MOD_ATTR(asyncio_CancelledError, "CancelledError")
3245
3246 WITH_MOD("asyncio.base_tasks")
3247 GET_MOD_ATTR(asyncio_task_repr_info_func, "_task_repr_info")
3248 GET_MOD_ATTR(asyncio_task_get_stack_func, "_task_get_stack")
3249 GET_MOD_ATTR(asyncio_task_print_stack_func, "_task_print_stack")
3250
Andrew Svetlovf74ef452017-12-15 07:04:38 +02003251 WITH_MOD("asyncio.coroutines")
3252 GET_MOD_ATTR(asyncio_iscoroutine_func, "iscoroutine")
3253
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003254 WITH_MOD("inspect")
3255 GET_MOD_ATTR(inspect_isgenerator, "isgenerator")
3256
3257 WITH_MOD("traceback")
3258 GET_MOD_ATTR(traceback_extract_stack, "extract_stack")
3259
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003260 PyObject *weak_set;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003261 WITH_MOD("weakref")
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003262 GET_MOD_ATTR(weak_set, "WeakSet");
3263 all_tasks = _PyObject_CallNoArg(weak_set);
3264 Py_CLEAR(weak_set);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003265 if (all_tasks == NULL) {
INADA Naokic411a7d2016-10-18 11:48:14 +09003266 goto fail;
3267 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003268
Serhiy Storchakabca49392017-09-03 08:10:14 +03003269 Py_DECREF(module);
INADA Naokic411a7d2016-10-18 11:48:14 +09003270 return 0;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003271
INADA Naokic411a7d2016-10-18 11:48:14 +09003272fail:
INADA Naokic411a7d2016-10-18 11:48:14 +09003273 Py_CLEAR(module);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003274 module_free(NULL);
INADA Naokic411a7d2016-10-18 11:48:14 +09003275 return -1;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003276
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003277#undef WITH_MOD
3278#undef GET_MOD_ATTR
3279}
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003280
INADA Naokic411a7d2016-10-18 11:48:14 +09003281PyDoc_STRVAR(module_doc, "Accelerator module for asyncio");
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003282
Yury Selivanova70232f2017-12-13 14:49:42 -05003283static PyMethodDef asyncio_methods[] = {
3284 _ASYNCIO_GET_EVENT_LOOP_METHODDEF
3285 _ASYNCIO_GET_RUNNING_LOOP_METHODDEF
3286 _ASYNCIO__GET_RUNNING_LOOP_METHODDEF
3287 _ASYNCIO__SET_RUNNING_LOOP_METHODDEF
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003288 _ASYNCIO__REGISTER_TASK_METHODDEF
3289 _ASYNCIO__UNREGISTER_TASK_METHODDEF
3290 _ASYNCIO__ENTER_TASK_METHODDEF
3291 _ASYNCIO__LEAVE_TASK_METHODDEF
Yury Selivanova70232f2017-12-13 14:49:42 -05003292 {NULL, NULL}
3293};
3294
INADA Naoki9f2ce252016-10-15 15:39:19 +09003295static struct PyModuleDef _asynciomodule = {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003296 PyModuleDef_HEAD_INIT, /* m_base */
INADA Naoki9f2ce252016-10-15 15:39:19 +09003297 "_asyncio", /* m_name */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003298 module_doc, /* m_doc */
3299 -1, /* m_size */
Yury Selivanova70232f2017-12-13 14:49:42 -05003300 asyncio_methods, /* m_methods */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003301 NULL, /* m_slots */
3302 NULL, /* m_traverse */
3303 NULL, /* m_clear */
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003304 (freefunc)module_free /* m_free */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003305};
3306
3307
3308PyMODINIT_FUNC
INADA Naoki9f2ce252016-10-15 15:39:19 +09003309PyInit__asyncio(void)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003310{
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003311 if (module_init() < 0) {
INADA Naokic411a7d2016-10-18 11:48:14 +09003312 return NULL;
3313 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003314 if (PyType_Ready(&FutureType) < 0) {
3315 return NULL;
3316 }
3317 if (PyType_Ready(&FutureIterType) < 0) {
3318 return NULL;
3319 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03003320 if (PyType_Ready(&TaskStepMethWrapper_Type) < 0) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003321 return NULL;
3322 }
3323 if(PyType_Ready(&TaskWakeupMethWrapper_Type) < 0) {
3324 return NULL;
3325 }
3326 if (PyType_Ready(&TaskType) < 0) {
3327 return NULL;
3328 }
Yury Selivanov9d411c12018-01-23 15:10:03 -05003329 if (PyType_Ready(&PyRunningLoopHolder_Type) < 0) {
3330 return NULL;
3331 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003332
INADA Naoki9f2ce252016-10-15 15:39:19 +09003333 PyObject *m = PyModule_Create(&_asynciomodule);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003334 if (m == NULL) {
3335 return NULL;
3336 }
3337
3338 Py_INCREF(&FutureType);
3339 if (PyModule_AddObject(m, "Future", (PyObject *)&FutureType) < 0) {
3340 Py_DECREF(&FutureType);
3341 return NULL;
3342 }
3343
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003344 Py_INCREF(&TaskType);
3345 if (PyModule_AddObject(m, "Task", (PyObject *)&TaskType) < 0) {
3346 Py_DECREF(&TaskType);
3347 return NULL;
3348 }
3349
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003350 Py_INCREF(all_tasks);
3351 if (PyModule_AddObject(m, "_all_tasks", all_tasks) < 0) {
3352 Py_DECREF(all_tasks);
3353 return NULL;
3354 }
3355
3356 Py_INCREF(current_tasks);
3357 if (PyModule_AddObject(m, "_current_tasks", current_tasks) < 0) {
3358 Py_DECREF(current_tasks);
3359 return NULL;
3360 }
3361
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003362 return m;
3363}