blob: ebda10404eb5dfdfd0457041be4f5e8e96ede2e4 [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);
Yury Selivanov416c1eb2018-05-28 17:54:02 -040014_Py_IDENTIFIER(_all_tasks_compat);
INADA Naoki9e4e38e2016-10-09 14:44:47 +090015_Py_IDENTIFIER(call_soon);
Yury Selivanova0c1ba62016-10-28 12:52:37 -040016_Py_IDENTIFIER(cancel);
Andrew Svetlov44d1a592017-12-16 21:58:38 +020017_Py_IDENTIFIER(current_task);
Yury Selivanova70232f2017-12-13 14:49:42 -050018_Py_IDENTIFIER(get_event_loop);
Yury Selivanova0c1ba62016-10-28 12:52:37 -040019_Py_IDENTIFIER(send);
20_Py_IDENTIFIER(throw);
INADA Naoki9e4e38e2016-10-09 14:44:47 +090021
22
INADA Naoki9f2ce252016-10-15 15:39:19 +090023/* State of the _asyncio module */
Andrew Svetlov44d1a592017-12-16 21:58:38 +020024static PyObject *asyncio_mod;
Yury Selivanova0c1ba62016-10-28 12:52:37 -040025static PyObject *inspect_isgenerator;
Andrew Svetlov44d1a592017-12-16 21:58:38 +020026static PyObject *traceback_extract_stack;
27static PyObject *asyncio_get_event_loop_policy;
28static PyObject *asyncio_future_repr_info_func;
29static PyObject *asyncio_iscoroutine_func;
30static PyObject *asyncio_task_get_stack_func;
31static PyObject *asyncio_task_print_stack_func;
32static PyObject *asyncio_task_repr_info_func;
33static PyObject *asyncio_InvalidStateError;
34static PyObject *asyncio_CancelledError;
Yury Selivanovf23746a2018-01-22 19:11:18 -050035static PyObject *context_kwname;
Andrew Svetlov44d1a592017-12-16 21:58:38 +020036
Yury Selivanov9d411c12018-01-23 15:10:03 -050037static PyObject *cached_running_holder;
38static volatile uint64_t cached_running_holder_tsid;
39
Andrew Svetlov44d1a592017-12-16 21:58:38 +020040
Yury Selivanovca9b36c2017-12-23 15:04:15 -050041/* WeakSet containing all alive tasks. */
42static PyObject *all_tasks;
Andrew Svetlov44d1a592017-12-16 21:58:38 +020043
44/* Dictionary containing tasks that are currently active in
45 all running event loops. {EventLoop: Task} */
Yury Selivanovca9b36c2017-12-23 15:04:15 -050046static PyObject *current_tasks;
INADA Naoki9e4e38e2016-10-09 14:44:47 +090047
Yury Selivanova9d7e552017-12-19 07:18:45 -050048/* An isinstance type cache for the 'is_coroutine()' function. */
49static PyObject *iscoroutine_typecache;
50
INADA Naoki9e4e38e2016-10-09 14:44:47 +090051
INADA Naoki9e4e38e2016-10-09 14:44:47 +090052typedef enum {
53 STATE_PENDING,
54 STATE_CANCELLED,
55 STATE_FINISHED
56} fut_state;
57
Yury Selivanova0c1ba62016-10-28 12:52:37 -040058#define FutureObj_HEAD(prefix) \
59 PyObject_HEAD \
60 PyObject *prefix##_loop; \
Yury Selivanov1b7c11f2017-12-17 20:19:47 -050061 PyObject *prefix##_callback0; \
Yury 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 }
Yury Selivanov35230d02018-05-28 11:11:31 -0400504 if (is_true && !_Py_IsFinalizing()) {
505 /* Only try to capture the traceback if the interpreter is not being
506 finalized. The original motivation to add a `_Py_IsFinalizing()`
507 call was to prevent SIGSEGV when a Future is created in a __del__
508 method, which is called during the interpreter shutdown and the
509 traceback module is already unloaded.
510 */
Oren Milmand019bc82018-02-13 12:28:33 +0200511 fut->fut_source_tb = _PyObject_CallNoArg(traceback_extract_stack);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900512 if (fut->fut_source_tb == NULL) {
513 return -1;
514 }
515 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900516
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900517 return 0;
518}
519
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900520static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400521future_set_result(FutureObj *fut, PyObject *res)
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900522{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500523 if (future_ensure_alive(fut)) {
524 return NULL;
525 }
526
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900527 if (fut->fut_state != STATE_PENDING) {
528 PyErr_SetString(asyncio_InvalidStateError, "invalid state");
529 return NULL;
530 }
531
Serhiy Storchakabca49392017-09-03 08:10:14 +0300532 assert(!fut->fut_result);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900533 Py_INCREF(res);
534 fut->fut_result = res;
535 fut->fut_state = STATE_FINISHED;
536
Yury Selivanov22feeb82018-01-24 11:31:01 -0500537 if (future_schedule_callbacks(fut) == -1) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900538 return NULL;
539 }
540 Py_RETURN_NONE;
541}
542
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900543static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400544future_set_exception(FutureObj *fut, PyObject *exc)
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900545{
546 PyObject *exc_val = NULL;
547
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900548 if (fut->fut_state != STATE_PENDING) {
549 PyErr_SetString(asyncio_InvalidStateError, "invalid state");
550 return NULL;
551 }
552
553 if (PyExceptionClass_Check(exc)) {
Victor Stinnera5ed5f02016-12-06 18:45:50 +0100554 exc_val = _PyObject_CallNoArg(exc);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900555 if (exc_val == NULL) {
556 return NULL;
557 }
Serhiy Storchakabca49392017-09-03 08:10:14 +0300558 if (fut->fut_state != STATE_PENDING) {
559 Py_DECREF(exc_val);
560 PyErr_SetString(asyncio_InvalidStateError, "invalid state");
561 return NULL;
562 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900563 }
564 else {
565 exc_val = exc;
566 Py_INCREF(exc_val);
567 }
568 if (!PyExceptionInstance_Check(exc_val)) {
569 Py_DECREF(exc_val);
570 PyErr_SetString(PyExc_TypeError, "invalid exception object");
571 return NULL;
572 }
573 if ((PyObject*)Py_TYPE(exc_val) == PyExc_StopIteration) {
574 Py_DECREF(exc_val);
575 PyErr_SetString(PyExc_TypeError,
576 "StopIteration interacts badly with generators "
577 "and cannot be raised into a Future");
578 return NULL;
579 }
580
Serhiy Storchakabca49392017-09-03 08:10:14 +0300581 assert(!fut->fut_exception);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900582 fut->fut_exception = exc_val;
583 fut->fut_state = STATE_FINISHED;
584
Yury Selivanov22feeb82018-01-24 11:31:01 -0500585 if (future_schedule_callbacks(fut) == -1) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900586 return NULL;
587 }
588
589 fut->fut_log_tb = 1;
590 Py_RETURN_NONE;
591}
592
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400593static int
594future_get_result(FutureObj *fut, PyObject **result)
595{
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400596 if (fut->fut_state == STATE_CANCELLED) {
Serhiy Storchakabca49392017-09-03 08:10:14 +0300597 PyErr_SetNone(asyncio_CancelledError);
598 return -1;
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400599 }
600
601 if (fut->fut_state != STATE_FINISHED) {
Serhiy Storchakabca49392017-09-03 08:10:14 +0300602 PyErr_SetString(asyncio_InvalidStateError, "Result is not set.");
603 return -1;
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400604 }
605
606 fut->fut_log_tb = 0;
607 if (fut->fut_exception != NULL) {
608 Py_INCREF(fut->fut_exception);
609 *result = fut->fut_exception;
610 return 1;
611 }
612
613 Py_INCREF(fut->fut_result);
614 *result = fut->fut_result;
615 return 0;
616}
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900617
618static PyObject *
Yury Selivanovf23746a2018-01-22 19:11:18 -0500619future_add_done_callback(FutureObj *fut, PyObject *arg, PyContext *ctx)
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900620{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500621 if (!future_is_alive(fut)) {
622 PyErr_SetString(PyExc_RuntimeError, "uninitialized Future object");
623 return NULL;
624 }
625
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900626 if (fut->fut_state != STATE_PENDING) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500627 /* The future is done/cancelled, so schedule the callback
628 right away. */
Yury Selivanovf23746a2018-01-22 19:11:18 -0500629 if (call_soon(fut->fut_loop, arg, (PyObject*) fut, ctx)) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900630 return NULL;
631 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900632 }
633 else {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500634 /* The future is pending, add a callback.
635
636 Callbacks in the future object are stored as follows:
637
638 callback0 -- a pointer to the first callback
639 callbacks -- a list of 2nd, 3rd, ... callbacks
640
641 Invariants:
642
643 * callbacks != NULL:
644 There are some callbacks in in the list. Just
645 add the new callback to it.
646
647 * callbacks == NULL and callback0 == NULL:
648 This is the first callback. Set it to callback0.
649
650 * callbacks == NULL and callback0 != NULL:
651 This is a second callback. Initialize callbacks
652 with a new list and add the new callback to it.
653 */
654
Yury Selivanovf23746a2018-01-22 19:11:18 -0500655 if (fut->fut_callbacks == NULL && fut->fut_callback0 == NULL) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500656 Py_INCREF(arg);
657 fut->fut_callback0 = arg;
Yury Selivanovf23746a2018-01-22 19:11:18 -0500658 Py_INCREF(ctx);
659 fut->fut_context0 = ctx;
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500660 }
661 else {
Yury Selivanovf23746a2018-01-22 19:11:18 -0500662 PyObject *tup = PyTuple_New(2);
663 if (tup == NULL) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500664 return NULL;
665 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500666 Py_INCREF(arg);
Yury Selivanovf23746a2018-01-22 19:11:18 -0500667 PyTuple_SET_ITEM(tup, 0, arg);
668 Py_INCREF(ctx);
669 PyTuple_SET_ITEM(tup, 1, (PyObject *)ctx);
670
671 if (fut->fut_callbacks != NULL) {
672 int err = PyList_Append(fut->fut_callbacks, tup);
673 if (err) {
674 Py_DECREF(tup);
675 return NULL;
676 }
677 Py_DECREF(tup);
678 }
679 else {
680 fut->fut_callbacks = PyList_New(1);
681 if (fut->fut_callbacks == NULL) {
682 return NULL;
683 }
684
685 PyList_SET_ITEM(fut->fut_callbacks, 0, tup); /* borrow */
686 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900687 }
688 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500689
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900690 Py_RETURN_NONE;
691}
692
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400693static PyObject *
694future_cancel(FutureObj *fut)
695{
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +0000696 fut->fut_log_tb = 0;
697
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400698 if (fut->fut_state != STATE_PENDING) {
699 Py_RETURN_FALSE;
700 }
701 fut->fut_state = STATE_CANCELLED;
702
Yury Selivanov22feeb82018-01-24 11:31:01 -0500703 if (future_schedule_callbacks(fut) == -1) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400704 return NULL;
705 }
706
707 Py_RETURN_TRUE;
708}
709
710/*[clinic input]
711_asyncio.Future.__init__
712
713 *
Serhiy Storchakabca49392017-09-03 08:10:14 +0300714 loop: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400715
716This class is *almost* compatible with concurrent.futures.Future.
717
718 Differences:
719
720 - result() and exception() do not take a timeout argument and
721 raise an exception when the future isn't done yet.
722
723 - Callbacks registered with add_done_callback() are always called
724 via the event loop's call_soon_threadsafe().
725
726 - This class is not compatible with the wait() and as_completed()
727 methods in the concurrent.futures package.
728[clinic start generated code]*/
729
730static int
731_asyncio_Future___init___impl(FutureObj *self, PyObject *loop)
Serhiy Storchakabca49392017-09-03 08:10:14 +0300732/*[clinic end generated code: output=9ed75799eaccb5d6 input=89af317082bc0bf8]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400733
734{
735 return future_init(self, loop);
736}
737
738static int
739FutureObj_clear(FutureObj *fut)
740{
741 Py_CLEAR(fut->fut_loop);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500742 Py_CLEAR(fut->fut_callback0);
Yury Selivanovf23746a2018-01-22 19:11:18 -0500743 Py_CLEAR(fut->fut_context0);
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400744 Py_CLEAR(fut->fut_callbacks);
745 Py_CLEAR(fut->fut_result);
746 Py_CLEAR(fut->fut_exception);
747 Py_CLEAR(fut->fut_source_tb);
748 Py_CLEAR(fut->dict);
749 return 0;
750}
751
752static int
753FutureObj_traverse(FutureObj *fut, visitproc visit, void *arg)
754{
755 Py_VISIT(fut->fut_loop);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500756 Py_VISIT(fut->fut_callback0);
Yury Selivanovf23746a2018-01-22 19:11:18 -0500757 Py_VISIT(fut->fut_context0);
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400758 Py_VISIT(fut->fut_callbacks);
759 Py_VISIT(fut->fut_result);
760 Py_VISIT(fut->fut_exception);
761 Py_VISIT(fut->fut_source_tb);
762 Py_VISIT(fut->dict);
763 return 0;
764}
765
766/*[clinic input]
767_asyncio.Future.result
768
769Return the result this future represents.
770
771If the future has been cancelled, raises CancelledError. If the
772future's result isn't yet available, raises InvalidStateError. If
773the future is done and has an exception set, this exception is raised.
774[clinic start generated code]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900775
776static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400777_asyncio_Future_result_impl(FutureObj *self)
778/*[clinic end generated code: output=f35f940936a4b1e5 input=49ecf9cf5ec50dc5]*/
779{
780 PyObject *result;
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500781
782 if (!future_is_alive(self)) {
783 PyErr_SetString(asyncio_InvalidStateError,
784 "Future object is not initialized.");
785 return NULL;
786 }
787
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400788 int res = future_get_result(self, &result);
789
790 if (res == -1) {
791 return NULL;
792 }
793
794 if (res == 0) {
795 return result;
796 }
797
798 assert(res == 1);
799
800 PyErr_SetObject(PyExceptionInstance_Class(result), result);
801 Py_DECREF(result);
802 return NULL;
803}
804
805/*[clinic input]
806_asyncio.Future.exception
807
808Return the exception that was set on this future.
809
810The exception (or None if no exception was set) is returned only if
811the future is done. If the future has been cancelled, raises
812CancelledError. If the future isn't done yet, raises
813InvalidStateError.
814[clinic start generated code]*/
815
816static PyObject *
817_asyncio_Future_exception_impl(FutureObj *self)
818/*[clinic end generated code: output=88b20d4f855e0710 input=733547a70c841c68]*/
819{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500820 if (!future_is_alive(self)) {
821 PyErr_SetString(asyncio_InvalidStateError,
822 "Future object is not initialized.");
823 return NULL;
824 }
825
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400826 if (self->fut_state == STATE_CANCELLED) {
Serhiy Storchakabca49392017-09-03 08:10:14 +0300827 PyErr_SetNone(asyncio_CancelledError);
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400828 return NULL;
829 }
830
831 if (self->fut_state != STATE_FINISHED) {
Serhiy Storchakabca49392017-09-03 08:10:14 +0300832 PyErr_SetString(asyncio_InvalidStateError, "Exception is not set.");
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400833 return NULL;
834 }
835
836 if (self->fut_exception != NULL) {
837 self->fut_log_tb = 0;
838 Py_INCREF(self->fut_exception);
839 return self->fut_exception;
840 }
841
842 Py_RETURN_NONE;
843}
844
845/*[clinic input]
846_asyncio.Future.set_result
847
Yury Selivanov0cf16f92017-12-25 10:48:15 -0500848 result: object
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400849 /
850
851Mark the future done and set its result.
852
853If the future is already done when this method is called, raises
854InvalidStateError.
855[clinic start generated code]*/
856
857static PyObject *
Yury Selivanov0cf16f92017-12-25 10:48:15 -0500858_asyncio_Future_set_result(FutureObj *self, PyObject *result)
859/*[clinic end generated code: output=1ec2e6bcccd6f2ce input=8b75172c2a7b05f1]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400860{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500861 ENSURE_FUTURE_ALIVE(self)
Yury Selivanov0cf16f92017-12-25 10:48:15 -0500862 return future_set_result(self, result);
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400863}
864
865/*[clinic input]
866_asyncio.Future.set_exception
867
Serhiy Storchakabca49392017-09-03 08:10:14 +0300868 exception: object
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400869 /
870
871Mark the future done and set an exception.
872
873If the future is already done when this method is called, raises
874InvalidStateError.
875[clinic start generated code]*/
876
877static PyObject *
878_asyncio_Future_set_exception(FutureObj *self, PyObject *exception)
Serhiy Storchakabca49392017-09-03 08:10:14 +0300879/*[clinic end generated code: output=f1c1b0cd321be360 input=e45b7d7aa71cc66d]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400880{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500881 ENSURE_FUTURE_ALIVE(self)
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400882 return future_set_exception(self, exception);
883}
884
885/*[clinic input]
886_asyncio.Future.add_done_callback
887
Serhiy Storchakabca49392017-09-03 08:10:14 +0300888 fn: object
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400889 /
Yury Selivanovf23746a2018-01-22 19:11:18 -0500890 *
891 context: object = NULL
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400892
893Add a callback to be run when the future becomes done.
894
895The callback is called with a single argument - the future object. If
896the future is already done when this is called, the callback is
897scheduled with call_soon.
898[clinic start generated code]*/
899
900static PyObject *
Yury Selivanovf23746a2018-01-22 19:11:18 -0500901_asyncio_Future_add_done_callback_impl(FutureObj *self, PyObject *fn,
902 PyObject *context)
903/*[clinic end generated code: output=7ce635bbc9554c1e input=15ab0693a96e9533]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400904{
Yury Selivanovf23746a2018-01-22 19:11:18 -0500905 if (context == NULL) {
906 context = (PyObject *)PyContext_CopyCurrent();
907 if (context == NULL) {
908 return NULL;
909 }
910 PyObject *res = future_add_done_callback(
911 self, fn, (PyContext *)context);
912 Py_DECREF(context);
913 return res;
914 }
915 return future_add_done_callback(self, fn, (PyContext *)context);
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400916}
917
918/*[clinic input]
919_asyncio.Future.remove_done_callback
920
Serhiy Storchakabca49392017-09-03 08:10:14 +0300921 fn: object
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400922 /
923
924Remove all instances of a callback from the "call when done" list.
925
926Returns the number of callbacks removed.
927[clinic start generated code]*/
928
929static PyObject *
930_asyncio_Future_remove_done_callback(FutureObj *self, PyObject *fn)
Serhiy Storchakabca49392017-09-03 08:10:14 +0300931/*[clinic end generated code: output=5ab1fb52b24ef31f input=0a43280a149d505b]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900932{
933 PyObject *newlist;
934 Py_ssize_t len, i, j=0;
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500935 Py_ssize_t cleared_callback0 = 0;
936
937 ENSURE_FUTURE_ALIVE(self)
938
939 if (self->fut_callback0 != NULL) {
940 int cmp = PyObject_RichCompareBool(fn, self->fut_callback0, Py_EQ);
941 if (cmp == -1) {
942 return NULL;
943 }
944 if (cmp == 1) {
945 /* callback0 == fn */
946 Py_CLEAR(self->fut_callback0);
Yury Selivanovf23746a2018-01-22 19:11:18 -0500947 Py_CLEAR(self->fut_context0);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500948 cleared_callback0 = 1;
949 }
950 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900951
Serhiy Storchakabca49392017-09-03 08:10:14 +0300952 if (self->fut_callbacks == NULL) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500953 return PyLong_FromSsize_t(cleared_callback0);
Serhiy Storchakabca49392017-09-03 08:10:14 +0300954 }
955
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400956 len = PyList_GET_SIZE(self->fut_callbacks);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900957 if (len == 0) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500958 Py_CLEAR(self->fut_callbacks);
959 return PyLong_FromSsize_t(cleared_callback0);
960 }
961
962 if (len == 1) {
Yury Selivanovf23746a2018-01-22 19:11:18 -0500963 PyObject *cb_tup = PyList_GET_ITEM(self->fut_callbacks, 0);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500964 int cmp = PyObject_RichCompareBool(
Yury Selivanovf23746a2018-01-22 19:11:18 -0500965 fn, PyTuple_GET_ITEM(cb_tup, 0), Py_EQ);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500966 if (cmp == -1) {
967 return NULL;
968 }
969 if (cmp == 1) {
970 /* callbacks[0] == fn */
971 Py_CLEAR(self->fut_callbacks);
972 return PyLong_FromSsize_t(1 + cleared_callback0);
973 }
974 /* callbacks[0] != fn and len(callbacks) == 1 */
975 return PyLong_FromSsize_t(cleared_callback0);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900976 }
977
978 newlist = PyList_New(len);
979 if (newlist == NULL) {
980 return NULL;
981 }
982
Yury Selivanov84af9032017-03-02 23:46:56 -0500983 for (i = 0; i < PyList_GET_SIZE(self->fut_callbacks); i++) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900984 int ret;
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400985 PyObject *item = PyList_GET_ITEM(self->fut_callbacks, i);
Serhiy Storchakabca49392017-09-03 08:10:14 +0300986 Py_INCREF(item);
Yury Selivanovf23746a2018-01-22 19:11:18 -0500987 ret = PyObject_RichCompareBool(fn, PyTuple_GET_ITEM(item, 0), Py_EQ);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900988 if (ret == 0) {
Yury Selivanov833a3b02017-07-05 13:32:03 -0400989 if (j < len) {
Yury Selivanov833a3b02017-07-05 13:32:03 -0400990 PyList_SET_ITEM(newlist, j, item);
991 j++;
Serhiy Storchakabca49392017-09-03 08:10:14 +0300992 continue;
Yury Selivanov833a3b02017-07-05 13:32:03 -0400993 }
Serhiy Storchakabca49392017-09-03 08:10:14 +0300994 ret = PyList_Append(newlist, item);
995 }
996 Py_DECREF(item);
997 if (ret < 0) {
998 goto fail;
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900999 }
1000 }
1001
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001002 if (j == 0) {
1003 Py_CLEAR(self->fut_callbacks);
1004 Py_DECREF(newlist);
1005 return PyLong_FromSsize_t(len + cleared_callback0);
1006 }
1007
Serhiy Storchakabca49392017-09-03 08:10:14 +03001008 if (j < len) {
1009 Py_SIZE(newlist) = j;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001010 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03001011 j = PyList_GET_SIZE(newlist);
1012 len = PyList_GET_SIZE(self->fut_callbacks);
1013 if (j != len) {
1014 if (PyList_SetSlice(self->fut_callbacks, 0, len, newlist) < 0) {
1015 goto fail;
1016 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001017 }
1018 Py_DECREF(newlist);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001019 return PyLong_FromSsize_t(len - j + cleared_callback0);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001020
1021fail:
1022 Py_DECREF(newlist);
1023 return NULL;
1024}
1025
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001026/*[clinic input]
1027_asyncio.Future.cancel
1028
1029Cancel the future and schedule callbacks.
1030
1031If the future is already done or cancelled, return False. Otherwise,
1032change the future's state to cancelled, schedule the callbacks and
1033return True.
1034[clinic start generated code]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001035
1036static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001037_asyncio_Future_cancel_impl(FutureObj *self)
1038/*[clinic end generated code: output=e45b932ba8bd68a1 input=515709a127995109]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001039{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001040 ENSURE_FUTURE_ALIVE(self)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001041 return future_cancel(self);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001042}
1043
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001044/*[clinic input]
1045_asyncio.Future.cancelled
1046
1047Return True if the future was cancelled.
1048[clinic start generated code]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001049
1050static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001051_asyncio_Future_cancelled_impl(FutureObj *self)
1052/*[clinic end generated code: output=145197ced586357d input=943ab8b7b7b17e45]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001053{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001054 if (future_is_alive(self) && self->fut_state == STATE_CANCELLED) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001055 Py_RETURN_TRUE;
1056 }
1057 else {
1058 Py_RETURN_FALSE;
1059 }
1060}
1061
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001062/*[clinic input]
1063_asyncio.Future.done
1064
1065Return True if the future is done.
1066
1067Done means either that a result / exception are available, or that the
1068future was cancelled.
1069[clinic start generated code]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001070
1071static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001072_asyncio_Future_done_impl(FutureObj *self)
1073/*[clinic end generated code: output=244c5ac351145096 input=28d7b23fdb65d2ac]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001074{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001075 if (!future_is_alive(self) || self->fut_state == STATE_PENDING) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001076 Py_RETURN_FALSE;
1077 }
1078 else {
1079 Py_RETURN_TRUE;
1080 }
1081}
1082
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001083/*[clinic input]
1084_asyncio.Future.get_loop
1085
1086Return the event loop the Future is bound to.
1087[clinic start generated code]*/
1088
1089static PyObject *
1090_asyncio_Future_get_loop_impl(FutureObj *self)
1091/*[clinic end generated code: output=119b6ea0c9816c3f input=cba48c2136c79d1f]*/
1092{
1093 Py_INCREF(self->fut_loop);
1094 return self->fut_loop;
1095}
1096
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001097static PyObject *
1098FutureObj_get_blocking(FutureObj *fut)
1099{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001100 if (future_is_alive(fut) && fut->fut_blocking) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001101 Py_RETURN_TRUE;
1102 }
1103 else {
1104 Py_RETURN_FALSE;
1105 }
1106}
1107
1108static int
1109FutureObj_set_blocking(FutureObj *fut, PyObject *val)
1110{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001111 if (future_ensure_alive(fut)) {
1112 return -1;
1113 }
1114
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001115 int is_true = PyObject_IsTrue(val);
1116 if (is_true < 0) {
1117 return -1;
1118 }
1119 fut->fut_blocking = is_true;
1120 return 0;
1121}
1122
1123static PyObject *
1124FutureObj_get_log_traceback(FutureObj *fut)
1125{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001126 ENSURE_FUTURE_ALIVE(fut)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001127 if (fut->fut_log_tb) {
1128 Py_RETURN_TRUE;
1129 }
1130 else {
1131 Py_RETURN_FALSE;
1132 }
1133}
1134
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +00001135static int
1136FutureObj_set_log_traceback(FutureObj *fut, PyObject *val)
1137{
1138 int is_true = PyObject_IsTrue(val);
1139 if (is_true < 0) {
1140 return -1;
1141 }
Yury Selivanove0aef4f2017-12-25 16:16:10 -05001142 if (is_true) {
1143 PyErr_SetString(PyExc_ValueError,
1144 "_log_traceback can only be set to False");
1145 return -1;
1146 }
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +00001147 fut->fut_log_tb = is_true;
1148 return 0;
1149}
1150
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001151static PyObject *
1152FutureObj_get_loop(FutureObj *fut)
1153{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001154 if (!future_is_alive(fut)) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001155 Py_RETURN_NONE;
1156 }
1157 Py_INCREF(fut->fut_loop);
1158 return fut->fut_loop;
1159}
1160
1161static PyObject *
1162FutureObj_get_callbacks(FutureObj *fut)
1163{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001164 Py_ssize_t i;
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001165
1166 ENSURE_FUTURE_ALIVE(fut)
1167
Yury Selivanovf23746a2018-01-22 19:11:18 -05001168 if (fut->fut_callback0 == NULL) {
1169 if (fut->fut_callbacks == NULL) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001170 Py_RETURN_NONE;
1171 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001172
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001173 Py_INCREF(fut->fut_callbacks);
1174 return fut->fut_callbacks;
1175 }
1176
Yury Selivanovf23746a2018-01-22 19:11:18 -05001177 Py_ssize_t len = 1;
1178 if (fut->fut_callbacks != NULL) {
1179 len += PyList_GET_SIZE(fut->fut_callbacks);
1180 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001181
Yury Selivanovf23746a2018-01-22 19:11:18 -05001182
1183 PyObject *new_list = PyList_New(len);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001184 if (new_list == NULL) {
1185 return NULL;
1186 }
1187
Yury Selivanovf23746a2018-01-22 19:11:18 -05001188 PyObject *tup0 = PyTuple_New(2);
1189 if (tup0 == NULL) {
1190 Py_DECREF(new_list);
1191 return NULL;
1192 }
1193
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001194 Py_INCREF(fut->fut_callback0);
Yury Selivanovf23746a2018-01-22 19:11:18 -05001195 PyTuple_SET_ITEM(tup0, 0, fut->fut_callback0);
1196 assert(fut->fut_context0 != NULL);
1197 Py_INCREF(fut->fut_context0);
1198 PyTuple_SET_ITEM(tup0, 1, (PyObject *)fut->fut_context0);
1199
1200 PyList_SET_ITEM(new_list, 0, tup0);
1201
1202 if (fut->fut_callbacks != NULL) {
1203 for (i = 0; i < PyList_GET_SIZE(fut->fut_callbacks); i++) {
1204 PyObject *cb = PyList_GET_ITEM(fut->fut_callbacks, i);
1205 Py_INCREF(cb);
1206 PyList_SET_ITEM(new_list, i + 1, cb);
1207 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001208 }
1209
1210 return new_list;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001211}
1212
1213static PyObject *
1214FutureObj_get_result(FutureObj *fut)
1215{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001216 ENSURE_FUTURE_ALIVE(fut)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001217 if (fut->fut_result == NULL) {
1218 Py_RETURN_NONE;
1219 }
1220 Py_INCREF(fut->fut_result);
1221 return fut->fut_result;
1222}
1223
1224static PyObject *
1225FutureObj_get_exception(FutureObj *fut)
1226{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001227 ENSURE_FUTURE_ALIVE(fut)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001228 if (fut->fut_exception == NULL) {
1229 Py_RETURN_NONE;
1230 }
1231 Py_INCREF(fut->fut_exception);
1232 return fut->fut_exception;
1233}
1234
1235static PyObject *
1236FutureObj_get_source_traceback(FutureObj *fut)
1237{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001238 if (!future_is_alive(fut) || fut->fut_source_tb == NULL) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001239 Py_RETURN_NONE;
1240 }
1241 Py_INCREF(fut->fut_source_tb);
1242 return fut->fut_source_tb;
1243}
1244
1245static PyObject *
1246FutureObj_get_state(FutureObj *fut)
1247{
1248 _Py_IDENTIFIER(PENDING);
1249 _Py_IDENTIFIER(CANCELLED);
1250 _Py_IDENTIFIER(FINISHED);
1251 PyObject *ret = NULL;
1252
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001253 ENSURE_FUTURE_ALIVE(fut)
1254
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001255 switch (fut->fut_state) {
1256 case STATE_PENDING:
1257 ret = _PyUnicode_FromId(&PyId_PENDING);
1258 break;
1259 case STATE_CANCELLED:
1260 ret = _PyUnicode_FromId(&PyId_CANCELLED);
1261 break;
1262 case STATE_FINISHED:
1263 ret = _PyUnicode_FromId(&PyId_FINISHED);
1264 break;
1265 default:
1266 assert (0);
1267 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03001268 Py_XINCREF(ret);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001269 return ret;
1270}
1271
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001272/*[clinic input]
1273_asyncio.Future._repr_info
1274[clinic start generated code]*/
1275
1276static PyObject *
1277_asyncio_Future__repr_info_impl(FutureObj *self)
1278/*[clinic end generated code: output=fa69e901bd176cfb input=f21504d8e2ae1ca2]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001279{
Victor Stinnerde4ae3d2016-12-04 22:59:09 +01001280 return PyObject_CallFunctionObjArgs(
1281 asyncio_future_repr_info_func, self, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001282}
1283
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001284static PyObject *
1285FutureObj_repr(FutureObj *fut)
1286{
1287 _Py_IDENTIFIER(_repr_info);
1288
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001289 ENSURE_FUTURE_ALIVE(fut)
1290
Serhiy Storchakabca49392017-09-03 08:10:14 +03001291 PyObject *rinfo = _PyObject_CallMethodIdObjArgs((PyObject*)fut,
1292 &PyId__repr_info,
1293 NULL);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001294 if (rinfo == NULL) {
1295 return NULL;
1296 }
1297
Serhiy Storchakabca49392017-09-03 08:10:14 +03001298 PyObject *rinfo_s = PyUnicode_Join(NULL, rinfo);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001299 Py_DECREF(rinfo);
1300 if (rinfo_s == NULL) {
1301 return NULL;
1302 }
1303
1304 PyObject *rstr = NULL;
1305 PyObject *type_name = PyObject_GetAttrString((PyObject*)Py_TYPE(fut),
1306 "__name__");
1307 if (type_name != NULL) {
Serhiy Storchakabca49392017-09-03 08:10:14 +03001308 rstr = PyUnicode_FromFormat("<%S %U>", type_name, rinfo_s);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001309 Py_DECREF(type_name);
1310 }
1311 Py_DECREF(rinfo_s);
1312 return rstr;
1313}
1314
1315static void
1316FutureObj_finalize(FutureObj *fut)
1317{
1318 _Py_IDENTIFIER(call_exception_handler);
1319 _Py_IDENTIFIER(message);
1320 _Py_IDENTIFIER(exception);
1321 _Py_IDENTIFIER(future);
1322 _Py_IDENTIFIER(source_traceback);
1323
Serhiy Storchakabca49392017-09-03 08:10:14 +03001324 PyObject *error_type, *error_value, *error_traceback;
1325 PyObject *context;
1326 PyObject *type_name;
1327 PyObject *message = NULL;
1328 PyObject *func;
1329
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001330 if (!fut->fut_log_tb) {
1331 return;
1332 }
1333 assert(fut->fut_exception != NULL);
Serhiy Storchakabca49392017-09-03 08:10:14 +03001334 fut->fut_log_tb = 0;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001335
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001336 /* Save the current exception, if any. */
1337 PyErr_Fetch(&error_type, &error_value, &error_traceback);
1338
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001339 context = PyDict_New();
1340 if (context == NULL) {
1341 goto finally;
1342 }
1343
1344 type_name = PyObject_GetAttrString((PyObject*)Py_TYPE(fut), "__name__");
1345 if (type_name == NULL) {
1346 goto finally;
1347 }
1348
1349 message = PyUnicode_FromFormat(
1350 "%S exception was never retrieved", type_name);
Serhiy Storchakabca49392017-09-03 08:10:14 +03001351 Py_DECREF(type_name);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001352 if (message == NULL) {
1353 goto finally;
1354 }
1355
1356 if (_PyDict_SetItemId(context, &PyId_message, message) < 0 ||
1357 _PyDict_SetItemId(context, &PyId_exception, fut->fut_exception) < 0 ||
1358 _PyDict_SetItemId(context, &PyId_future, (PyObject*)fut) < 0) {
1359 goto finally;
1360 }
1361 if (fut->fut_source_tb != NULL) {
1362 if (_PyDict_SetItemId(context, &PyId_source_traceback,
1363 fut->fut_source_tb) < 0) {
1364 goto finally;
1365 }
1366 }
1367
1368 func = _PyObject_GetAttrId(fut->fut_loop, &PyId_call_exception_handler);
1369 if (func != NULL) {
Serhiy Storchakabca49392017-09-03 08:10:14 +03001370 PyObject *res = PyObject_CallFunctionObjArgs(func, context, NULL);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001371 if (res == NULL) {
1372 PyErr_WriteUnraisable(func);
1373 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03001374 else {
1375 Py_DECREF(res);
1376 }
1377 Py_DECREF(func);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001378 }
1379
1380finally:
Serhiy Storchakabca49392017-09-03 08:10:14 +03001381 Py_XDECREF(context);
1382 Py_XDECREF(message);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001383
1384 /* Restore the saved exception. */
1385 PyErr_Restore(error_type, error_value, error_traceback);
1386}
1387
1388
1389static PyAsyncMethods FutureType_as_async = {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001390 (unaryfunc)future_new_iter, /* am_await */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001391 0, /* am_aiter */
1392 0 /* am_anext */
1393};
1394
1395static PyMethodDef FutureType_methods[] = {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001396 _ASYNCIO_FUTURE_RESULT_METHODDEF
1397 _ASYNCIO_FUTURE_EXCEPTION_METHODDEF
1398 _ASYNCIO_FUTURE_SET_RESULT_METHODDEF
1399 _ASYNCIO_FUTURE_SET_EXCEPTION_METHODDEF
1400 _ASYNCIO_FUTURE_ADD_DONE_CALLBACK_METHODDEF
1401 _ASYNCIO_FUTURE_REMOVE_DONE_CALLBACK_METHODDEF
1402 _ASYNCIO_FUTURE_CANCEL_METHODDEF
1403 _ASYNCIO_FUTURE_CANCELLED_METHODDEF
1404 _ASYNCIO_FUTURE_DONE_METHODDEF
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001405 _ASYNCIO_FUTURE_GET_LOOP_METHODDEF
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001406 _ASYNCIO_FUTURE__REPR_INFO_METHODDEF
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001407 {NULL, NULL} /* Sentinel */
1408};
1409
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001410#define FUTURE_COMMON_GETSETLIST \
1411 {"_state", (getter)FutureObj_get_state, NULL, NULL}, \
1412 {"_asyncio_future_blocking", (getter)FutureObj_get_blocking, \
1413 (setter)FutureObj_set_blocking, NULL}, \
1414 {"_loop", (getter)FutureObj_get_loop, NULL, NULL}, \
1415 {"_callbacks", (getter)FutureObj_get_callbacks, NULL, NULL}, \
1416 {"_result", (getter)FutureObj_get_result, NULL, NULL}, \
1417 {"_exception", (getter)FutureObj_get_exception, NULL, NULL}, \
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +00001418 {"_log_traceback", (getter)FutureObj_get_log_traceback, \
1419 (setter)FutureObj_set_log_traceback, NULL}, \
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001420 {"_source_traceback", (getter)FutureObj_get_source_traceback, NULL, NULL},
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001421
1422static PyGetSetDef FutureType_getsetlist[] = {
1423 FUTURE_COMMON_GETSETLIST
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001424 {NULL} /* Sentinel */
1425};
1426
1427static void FutureObj_dealloc(PyObject *self);
1428
1429static PyTypeObject FutureType = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02001430 PyVarObject_HEAD_INIT(NULL, 0)
INADA Naoki9f2ce252016-10-15 15:39:19 +09001431 "_asyncio.Future",
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001432 sizeof(FutureObj), /* tp_basicsize */
1433 .tp_dealloc = FutureObj_dealloc,
1434 .tp_as_async = &FutureType_as_async,
1435 .tp_repr = (reprfunc)FutureObj_repr,
1436 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE
1437 | Py_TPFLAGS_HAVE_FINALIZE,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001438 .tp_doc = _asyncio_Future___init____doc__,
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001439 .tp_traverse = (traverseproc)FutureObj_traverse,
1440 .tp_clear = (inquiry)FutureObj_clear,
1441 .tp_weaklistoffset = offsetof(FutureObj, fut_weakreflist),
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001442 .tp_iter = (getiterfunc)future_new_iter,
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001443 .tp_methods = FutureType_methods,
1444 .tp_getset = FutureType_getsetlist,
1445 .tp_dictoffset = offsetof(FutureObj, dict),
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001446 .tp_init = (initproc)_asyncio_Future___init__,
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001447 .tp_new = PyType_GenericNew,
1448 .tp_finalize = (destructor)FutureObj_finalize,
1449};
1450
1451static void
1452FutureObj_dealloc(PyObject *self)
1453{
1454 FutureObj *fut = (FutureObj *)self;
1455
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001456 if (Future_CheckExact(fut)) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001457 /* When fut is subclass of Future, finalizer is called from
1458 * subtype_dealloc.
1459 */
1460 if (PyObject_CallFinalizerFromDealloc(self) < 0) {
1461 // resurrected.
1462 return;
1463 }
1464 }
1465
Alexander Mohrde34cbe2017-08-01 23:31:07 -07001466 PyObject_GC_UnTrack(self);
1467
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001468 if (fut->fut_weakreflist != NULL) {
1469 PyObject_ClearWeakRefs(self);
1470 }
1471
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001472 (void)FutureObj_clear(fut);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001473 Py_TYPE(fut)->tp_free(fut);
1474}
1475
1476
1477/*********************** Future Iterator **************************/
1478
1479typedef struct {
1480 PyObject_HEAD
1481 FutureObj *future;
1482} futureiterobject;
1483
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001484
1485#define FI_FREELIST_MAXLEN 255
1486static futureiterobject *fi_freelist = NULL;
1487static Py_ssize_t fi_freelist_len = 0;
1488
1489
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001490static void
1491FutureIter_dealloc(futureiterobject *it)
1492{
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001493 PyObject_GC_UnTrack(it);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001494 Py_CLEAR(it->future);
1495
1496 if (fi_freelist_len < FI_FREELIST_MAXLEN) {
1497 fi_freelist_len++;
1498 it->future = (FutureObj*) fi_freelist;
1499 fi_freelist = it;
1500 }
1501 else {
1502 PyObject_GC_Del(it);
1503 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001504}
1505
1506static PyObject *
1507FutureIter_iternext(futureiterobject *it)
1508{
1509 PyObject *res;
1510 FutureObj *fut = it->future;
1511
1512 if (fut == NULL) {
1513 return NULL;
1514 }
1515
1516 if (fut->fut_state == STATE_PENDING) {
1517 if (!fut->fut_blocking) {
1518 fut->fut_blocking = 1;
1519 Py_INCREF(fut);
1520 return (PyObject *)fut;
1521 }
Yury Selivanov0cf16f92017-12-25 10:48:15 -05001522 PyErr_SetString(PyExc_RuntimeError,
1523 "await wasn't used with future");
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001524 return NULL;
1525 }
1526
Serhiy Storchakabca49392017-09-03 08:10:14 +03001527 it->future = NULL;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001528 res = _asyncio_Future_result_impl(fut);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001529 if (res != NULL) {
Serhiy Storchaka60e49aa2016-11-06 18:47:03 +02001530 /* The result of the Future is not an exception. */
Serhiy Storchakabca49392017-09-03 08:10:14 +03001531 (void)_PyGen_SetStopIterationValue(res);
Serhiy Storchaka60e49aa2016-11-06 18:47:03 +02001532 Py_DECREF(res);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001533 }
1534
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001535 Py_DECREF(fut);
1536 return NULL;
1537}
1538
1539static PyObject *
INADA Naoki74c17532016-10-25 19:00:45 +09001540FutureIter_send(futureiterobject *self, PyObject *unused)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001541{
INADA Naoki74c17532016-10-25 19:00:45 +09001542 /* Future.__iter__ doesn't care about values that are pushed to the
1543 * generator, it just returns "self.result().
1544 */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001545 return FutureIter_iternext(self);
1546}
1547
1548static PyObject *
1549FutureIter_throw(futureiterobject *self, PyObject *args)
1550{
Serhiy Storchakabca49392017-09-03 08:10:14 +03001551 PyObject *type, *val = NULL, *tb = NULL;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001552 if (!PyArg_ParseTuple(args, "O|OO", &type, &val, &tb))
1553 return NULL;
1554
1555 if (val == Py_None) {
1556 val = NULL;
1557 }
1558 if (tb == Py_None) {
1559 tb = NULL;
Benjamin Peterson996fc1f2016-11-14 00:15:44 -08001560 } else if (tb != NULL && !PyTraceBack_Check(tb)) {
1561 PyErr_SetString(PyExc_TypeError, "throw() third argument must be a traceback");
1562 return NULL;
1563 }
1564
1565 Py_INCREF(type);
1566 Py_XINCREF(val);
1567 Py_XINCREF(tb);
1568
1569 if (PyExceptionClass_Check(type)) {
1570 PyErr_NormalizeException(&type, &val, &tb);
Yury Selivanovedfe8862016-12-01 11:37:47 -05001571 /* No need to call PyException_SetTraceback since we'll be calling
1572 PyErr_Restore for `type`, `val`, and `tb`. */
Benjamin Peterson996fc1f2016-11-14 00:15:44 -08001573 } else if (PyExceptionInstance_Check(type)) {
1574 if (val) {
1575 PyErr_SetString(PyExc_TypeError,
1576 "instance exception may not have a separate value");
1577 goto fail;
1578 }
1579 val = type;
1580 type = PyExceptionInstance_Class(type);
1581 Py_INCREF(type);
1582 if (tb == NULL)
1583 tb = PyException_GetTraceback(val);
1584 } else {
1585 PyErr_SetString(PyExc_TypeError,
1586 "exceptions must be classes deriving BaseException or "
1587 "instances of such a class");
1588 goto fail;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001589 }
1590
1591 Py_CLEAR(self->future);
1592
Benjamin Peterson996fc1f2016-11-14 00:15:44 -08001593 PyErr_Restore(type, val, tb);
1594
Serhiy Storchakabca49392017-09-03 08:10:14 +03001595 return NULL;
Benjamin Peterson996fc1f2016-11-14 00:15:44 -08001596
1597 fail:
1598 Py_DECREF(type);
1599 Py_XDECREF(val);
1600 Py_XDECREF(tb);
1601 return NULL;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001602}
1603
1604static PyObject *
1605FutureIter_close(futureiterobject *self, PyObject *arg)
1606{
1607 Py_CLEAR(self->future);
1608 Py_RETURN_NONE;
1609}
1610
1611static int
1612FutureIter_traverse(futureiterobject *it, visitproc visit, void *arg)
1613{
1614 Py_VISIT(it->future);
1615 return 0;
1616}
1617
1618static PyMethodDef FutureIter_methods[] = {
1619 {"send", (PyCFunction)FutureIter_send, METH_O, NULL},
1620 {"throw", (PyCFunction)FutureIter_throw, METH_VARARGS, NULL},
1621 {"close", (PyCFunction)FutureIter_close, METH_NOARGS, NULL},
1622 {NULL, NULL} /* Sentinel */
1623};
1624
1625static PyTypeObject FutureIterType = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02001626 PyVarObject_HEAD_INIT(NULL, 0)
INADA Naoki9f2ce252016-10-15 15:39:19 +09001627 "_asyncio.FutureIter",
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001628 .tp_basicsize = sizeof(futureiterobject),
1629 .tp_itemsize = 0,
1630 .tp_dealloc = (destructor)FutureIter_dealloc,
1631 .tp_getattro = PyObject_GenericGetAttr,
1632 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
1633 .tp_traverse = (traverseproc)FutureIter_traverse,
1634 .tp_iter = PyObject_SelfIter,
1635 .tp_iternext = (iternextfunc)FutureIter_iternext,
1636 .tp_methods = FutureIter_methods,
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001637};
1638
1639static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001640future_new_iter(PyObject *fut)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001641{
1642 futureiterobject *it;
1643
1644 if (!PyObject_TypeCheck(fut, &FutureType)) {
1645 PyErr_BadInternalCall();
1646 return NULL;
1647 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001648
1649 ENSURE_FUTURE_ALIVE(fut)
1650
1651 if (fi_freelist_len) {
1652 fi_freelist_len--;
1653 it = fi_freelist;
1654 fi_freelist = (futureiterobject*) it->future;
1655 it->future = NULL;
1656 _Py_NewReference((PyObject*) it);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001657 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001658 else {
1659 it = PyObject_GC_New(futureiterobject, &FutureIterType);
1660 if (it == NULL) {
1661 return NULL;
1662 }
1663 }
1664
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001665 Py_INCREF(fut);
1666 it->future = (FutureObj*)fut;
INADA Naoki1be427b2016-10-11 02:12:34 +09001667 PyObject_GC_Track(it);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001668 return (PyObject*)it;
1669}
1670
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001671
1672/*********************** Task **************************/
1673
1674
1675/*[clinic input]
1676class _asyncio.Task "TaskObj *" "&Task_Type"
1677[clinic start generated code]*/
1678/*[clinic end generated code: output=da39a3ee5e6b4b0d input=719dcef0fcc03b37]*/
1679
1680static int task_call_step_soon(TaskObj *, PyObject *);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001681static PyObject * task_wakeup(TaskObj *, PyObject *);
1682static PyObject * task_step(TaskObj *, PyObject *);
1683
1684/* ----- Task._step wrapper */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001685
INADA Naokic411a7d2016-10-18 11:48:14 +09001686static int
Serhiy Storchakabca49392017-09-03 08:10:14 +03001687TaskStepMethWrapper_clear(TaskStepMethWrapper *o)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001688{
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001689 Py_CLEAR(o->sw_task);
1690 Py_CLEAR(o->sw_arg);
1691 return 0;
1692}
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001693
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001694static void
Serhiy Storchakabca49392017-09-03 08:10:14 +03001695TaskStepMethWrapper_dealloc(TaskStepMethWrapper *o)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001696{
1697 PyObject_GC_UnTrack(o);
Serhiy Storchakabca49392017-09-03 08:10:14 +03001698 (void)TaskStepMethWrapper_clear(o);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001699 Py_TYPE(o)->tp_free(o);
1700}
1701
1702static PyObject *
Serhiy Storchakabca49392017-09-03 08:10:14 +03001703TaskStepMethWrapper_call(TaskStepMethWrapper *o,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001704 PyObject *args, PyObject *kwds)
1705{
Serhiy Storchakabca49392017-09-03 08:10:14 +03001706 if (kwds != NULL && PyDict_GET_SIZE(kwds) != 0) {
1707 PyErr_SetString(PyExc_TypeError, "function takes no keyword arguments");
1708 return NULL;
1709 }
1710 if (args != NULL && PyTuple_GET_SIZE(args) != 0) {
1711 PyErr_SetString(PyExc_TypeError, "function takes no positional arguments");
1712 return NULL;
1713 }
Yury Selivanov22feeb82018-01-24 11:31:01 -05001714 return task_step(o->sw_task, o->sw_arg);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001715}
1716
1717static int
Serhiy Storchakabca49392017-09-03 08:10:14 +03001718TaskStepMethWrapper_traverse(TaskStepMethWrapper *o,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001719 visitproc visit, void *arg)
1720{
1721 Py_VISIT(o->sw_task);
1722 Py_VISIT(o->sw_arg);
1723 return 0;
1724}
1725
1726static PyObject *
Serhiy Storchakabca49392017-09-03 08:10:14 +03001727TaskStepMethWrapper_get___self__(TaskStepMethWrapper *o)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001728{
1729 if (o->sw_task) {
1730 Py_INCREF(o->sw_task);
1731 return (PyObject*)o->sw_task;
1732 }
1733 Py_RETURN_NONE;
1734}
1735
Serhiy Storchakabca49392017-09-03 08:10:14 +03001736static PyGetSetDef TaskStepMethWrapper_getsetlist[] = {
1737 {"__self__", (getter)TaskStepMethWrapper_get___self__, NULL, NULL},
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001738 {NULL} /* Sentinel */
1739};
1740
Benjamin Peterson3c8aae92018-07-05 22:39:34 -07001741static PyTypeObject TaskStepMethWrapper_Type = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02001742 PyVarObject_HEAD_INIT(NULL, 0)
Serhiy Storchakabca49392017-09-03 08:10:14 +03001743 "TaskStepMethWrapper",
1744 .tp_basicsize = sizeof(TaskStepMethWrapper),
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001745 .tp_itemsize = 0,
Serhiy Storchakabca49392017-09-03 08:10:14 +03001746 .tp_getset = TaskStepMethWrapper_getsetlist,
1747 .tp_dealloc = (destructor)TaskStepMethWrapper_dealloc,
1748 .tp_call = (ternaryfunc)TaskStepMethWrapper_call,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001749 .tp_getattro = PyObject_GenericGetAttr,
1750 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
Serhiy Storchakabca49392017-09-03 08:10:14 +03001751 .tp_traverse = (traverseproc)TaskStepMethWrapper_traverse,
1752 .tp_clear = (inquiry)TaskStepMethWrapper_clear,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001753};
1754
1755static PyObject *
Serhiy Storchakabca49392017-09-03 08:10:14 +03001756TaskStepMethWrapper_new(TaskObj *task, PyObject *arg)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001757{
Serhiy Storchakabca49392017-09-03 08:10:14 +03001758 TaskStepMethWrapper *o;
1759 o = PyObject_GC_New(TaskStepMethWrapper, &TaskStepMethWrapper_Type);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001760 if (o == NULL) {
1761 return NULL;
1762 }
1763
1764 Py_INCREF(task);
1765 o->sw_task = task;
1766
1767 Py_XINCREF(arg);
1768 o->sw_arg = arg;
1769
1770 PyObject_GC_Track(o);
1771 return (PyObject*) o;
1772}
1773
1774/* ----- Task._wakeup wrapper */
1775
1776static PyObject *
1777TaskWakeupMethWrapper_call(TaskWakeupMethWrapper *o,
1778 PyObject *args, PyObject *kwds)
1779{
1780 PyObject *fut;
1781
Serhiy Storchakabca49392017-09-03 08:10:14 +03001782 if (kwds != NULL && PyDict_GET_SIZE(kwds) != 0) {
1783 PyErr_SetString(PyExc_TypeError, "function takes no keyword arguments");
1784 return NULL;
1785 }
1786 if (!PyArg_ParseTuple(args, "O", &fut)) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001787 return NULL;
1788 }
1789
Yury Selivanov22feeb82018-01-24 11:31:01 -05001790 return task_wakeup(o->ww_task, fut);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001791}
1792
1793static int
1794TaskWakeupMethWrapper_clear(TaskWakeupMethWrapper *o)
1795{
1796 Py_CLEAR(o->ww_task);
1797 return 0;
1798}
1799
1800static int
1801TaskWakeupMethWrapper_traverse(TaskWakeupMethWrapper *o,
1802 visitproc visit, void *arg)
1803{
1804 Py_VISIT(o->ww_task);
1805 return 0;
1806}
1807
1808static void
1809TaskWakeupMethWrapper_dealloc(TaskWakeupMethWrapper *o)
1810{
1811 PyObject_GC_UnTrack(o);
1812 (void)TaskWakeupMethWrapper_clear(o);
1813 Py_TYPE(o)->tp_free(o);
1814}
1815
Benjamin Peterson3c8aae92018-07-05 22:39:34 -07001816static PyTypeObject TaskWakeupMethWrapper_Type = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02001817 PyVarObject_HEAD_INIT(NULL, 0)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001818 "TaskWakeupMethWrapper",
1819 .tp_basicsize = sizeof(TaskWakeupMethWrapper),
1820 .tp_itemsize = 0,
1821 .tp_dealloc = (destructor)TaskWakeupMethWrapper_dealloc,
1822 .tp_call = (ternaryfunc)TaskWakeupMethWrapper_call,
1823 .tp_getattro = PyObject_GenericGetAttr,
1824 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
1825 .tp_traverse = (traverseproc)TaskWakeupMethWrapper_traverse,
1826 .tp_clear = (inquiry)TaskWakeupMethWrapper_clear,
1827};
1828
1829static PyObject *
1830TaskWakeupMethWrapper_new(TaskObj *task)
1831{
1832 TaskWakeupMethWrapper *o;
1833 o = PyObject_GC_New(TaskWakeupMethWrapper, &TaskWakeupMethWrapper_Type);
1834 if (o == NULL) {
1835 return NULL;
1836 }
1837
1838 Py_INCREF(task);
1839 o->ww_task = task;
1840
1841 PyObject_GC_Track(o);
1842 return (PyObject*) o;
1843}
1844
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001845/* ----- Task introspection helpers */
1846
1847static int
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001848register_task(PyObject *task)
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001849{
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001850 _Py_IDENTIFIER(add);
1851
1852 PyObject *res = _PyObject_CallMethodIdObjArgs(
1853 all_tasks, &PyId_add, task, NULL);
1854 if (res == NULL) {
1855 return -1;
1856 }
1857 Py_DECREF(res);
1858 return 0;
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001859}
1860
1861
1862static int
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001863unregister_task(PyObject *task)
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001864{
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001865 _Py_IDENTIFIER(discard);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001866
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001867 PyObject *res = _PyObject_CallMethodIdObjArgs(
1868 all_tasks, &PyId_discard, task, NULL);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001869 if (res == NULL) {
1870 return -1;
1871 }
1872 Py_DECREF(res);
1873 return 0;
1874}
1875
1876
1877static int
1878enter_task(PyObject *loop, PyObject *task)
1879{
1880 PyObject *item;
1881 Py_hash_t hash;
1882 hash = PyObject_Hash(loop);
1883 if (hash == -1) {
1884 return -1;
1885 }
1886 item = _PyDict_GetItem_KnownHash(current_tasks, loop, hash);
1887 if (item != NULL) {
Serhiy Storchaka66553542018-05-20 16:30:31 +03001888 Py_INCREF(item);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001889 PyErr_Format(
1890 PyExc_RuntimeError,
1891 "Cannot enter into task %R while another " \
1892 "task %R is being executed.",
1893 task, item, NULL);
Serhiy Storchaka66553542018-05-20 16:30:31 +03001894 Py_DECREF(item);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001895 return -1;
1896 }
Serhiy Storchaka66553542018-05-20 16:30:31 +03001897 if (PyErr_Occurred()) {
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001898 return -1;
1899 }
Serhiy Storchaka66553542018-05-20 16:30:31 +03001900 return _PyDict_SetItem_KnownHash(current_tasks, loop, task, hash);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001901}
1902
1903
1904static int
1905leave_task(PyObject *loop, PyObject *task)
1906/*[clinic end generated code: output=0ebf6db4b858fb41 input=51296a46313d1ad8]*/
1907{
1908 PyObject *item;
1909 Py_hash_t hash;
1910 hash = PyObject_Hash(loop);
1911 if (hash == -1) {
1912 return -1;
1913 }
1914 item = _PyDict_GetItem_KnownHash(current_tasks, loop, hash);
1915 if (item != task) {
1916 if (item == NULL) {
1917 /* Not entered, replace with None */
1918 item = Py_None;
1919 }
1920 PyErr_Format(
1921 PyExc_RuntimeError,
1922 "Leaving task %R does not match the current task %R.",
1923 task, item, NULL);
1924 return -1;
1925 }
1926 return _PyDict_DelItem_KnownHash(current_tasks, loop, hash);
1927}
1928
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001929/* ----- Task */
1930
1931/*[clinic input]
1932_asyncio.Task.__init__
1933
Serhiy Storchakabca49392017-09-03 08:10:14 +03001934 coro: object
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001935 *
Serhiy Storchakabca49392017-09-03 08:10:14 +03001936 loop: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001937
1938A coroutine wrapped in a Future.
1939[clinic start generated code]*/
1940
1941static int
1942_asyncio_Task___init___impl(TaskObj *self, PyObject *coro, PyObject *loop)
Serhiy Storchakabca49392017-09-03 08:10:14 +03001943/*[clinic end generated code: output=9f24774c2287fc2f input=8d132974b049593e]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001944{
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001945 if (future_init((FutureObj*)self, loop)) {
INADA Naokic411a7d2016-10-18 11:48:14 +09001946 return -1;
1947 }
INADA Naokic411a7d2016-10-18 11:48:14 +09001948
Yury Selivanova9d7e552017-12-19 07:18:45 -05001949 int is_coro = is_coroutine(coro);
1950 if (is_coro == -1) {
1951 return -1;
1952 }
1953 if (is_coro == 0) {
1954 self->task_log_destroy_pending = 0;
1955 PyErr_Format(PyExc_TypeError,
1956 "a coroutine was expected, got %R",
1957 coro, NULL);
1958 return -1;
Andrew Svetlovf74ef452017-12-15 07:04:38 +02001959 }
1960
Oren Milmand019bc82018-02-13 12:28:33 +02001961 Py_XSETREF(self->task_context, PyContext_CopyCurrent());
Yury Selivanovf23746a2018-01-22 19:11:18 -05001962 if (self->task_context == NULL) {
1963 return -1;
1964 }
1965
Oren Milmand019bc82018-02-13 12:28:33 +02001966 Py_CLEAR(self->task_fut_waiter);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001967 self->task_must_cancel = 0;
1968 self->task_log_destroy_pending = 1;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001969 Py_INCREF(coro);
Oren Milmand019bc82018-02-13 12:28:33 +02001970 Py_XSETREF(self->task_coro, coro);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001971
1972 if (task_call_step_soon(self, NULL)) {
1973 return -1;
INADA Naokic411a7d2016-10-18 11:48:14 +09001974 }
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001975 return register_task((PyObject*)self);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001976}
1977
1978static int
1979TaskObj_clear(TaskObj *task)
1980{
1981 (void)FutureObj_clear((FutureObj*) task);
Yury Selivanovf23746a2018-01-22 19:11:18 -05001982 Py_CLEAR(task->task_context);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001983 Py_CLEAR(task->task_coro);
1984 Py_CLEAR(task->task_fut_waiter);
1985 return 0;
1986}
1987
1988static int
1989TaskObj_traverse(TaskObj *task, visitproc visit, void *arg)
1990{
Yury Selivanovf23746a2018-01-22 19:11:18 -05001991 Py_VISIT(task->task_context);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001992 Py_VISIT(task->task_coro);
1993 Py_VISIT(task->task_fut_waiter);
1994 (void)FutureObj_traverse((FutureObj*) task, visit, arg);
1995 return 0;
1996}
1997
1998static PyObject *
1999TaskObj_get_log_destroy_pending(TaskObj *task)
2000{
2001 if (task->task_log_destroy_pending) {
2002 Py_RETURN_TRUE;
2003 }
2004 else {
2005 Py_RETURN_FALSE;
2006 }
2007}
2008
2009static int
2010TaskObj_set_log_destroy_pending(TaskObj *task, PyObject *val)
2011{
2012 int is_true = PyObject_IsTrue(val);
2013 if (is_true < 0) {
2014 return -1;
2015 }
2016 task->task_log_destroy_pending = is_true;
2017 return 0;
2018}
2019
2020static PyObject *
2021TaskObj_get_must_cancel(TaskObj *task)
2022{
2023 if (task->task_must_cancel) {
2024 Py_RETURN_TRUE;
2025 }
2026 else {
2027 Py_RETURN_FALSE;
2028 }
2029}
2030
2031static PyObject *
2032TaskObj_get_coro(TaskObj *task)
2033{
2034 if (task->task_coro) {
2035 Py_INCREF(task->task_coro);
2036 return task->task_coro;
2037 }
2038
2039 Py_RETURN_NONE;
2040}
2041
2042static PyObject *
2043TaskObj_get_fut_waiter(TaskObj *task)
2044{
2045 if (task->task_fut_waiter) {
2046 Py_INCREF(task->task_fut_waiter);
2047 return task->task_fut_waiter;
2048 }
2049
2050 Py_RETURN_NONE;
2051}
2052
2053/*[clinic input]
2054@classmethod
2055_asyncio.Task.current_task
2056
Serhiy Storchakabca49392017-09-03 08:10:14 +03002057 loop: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002058
2059Return the currently running task in an event loop or None.
2060
2061By default the current task for the current event loop is returned.
2062
2063None is returned when called not in the context of a Task.
2064[clinic start generated code]*/
2065
2066static PyObject *
2067_asyncio_Task_current_task_impl(PyTypeObject *type, PyObject *loop)
Serhiy Storchakabca49392017-09-03 08:10:14 +03002068/*[clinic end generated code: output=99fbe7332c516e03 input=cd14770c5b79c7eb]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002069{
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002070 PyObject *ret;
2071 PyObject *current_task_func;
2072
2073 if (PyErr_WarnEx(PyExc_PendingDeprecationWarning,
2074 "Task.current_task() is deprecated, " \
2075 "use asyncio.current_task() instead",
2076 1) < 0) {
2077 return NULL;
2078 }
2079
2080 current_task_func = _PyObject_GetAttrId(asyncio_mod, &PyId_current_task);
2081 if (current_task_func == NULL) {
2082 return NULL;
2083 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002084
Yury Selivanov8d26aa92017-03-02 22:16:33 -05002085 if (loop == Py_None) {
Yury Selivanova70232f2017-12-13 14:49:42 -05002086 loop = get_event_loop();
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002087 if (loop == NULL) {
Serhiy Storchaka66553542018-05-20 16:30:31 +03002088 Py_DECREF(current_task_func);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002089 return NULL;
2090 }
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002091 ret = PyObject_CallFunctionObjArgs(current_task_func, loop, NULL);
2092 Py_DECREF(current_task_func);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002093 Py_DECREF(loop);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002094 return ret;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002095 }
2096 else {
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002097 ret = PyObject_CallFunctionObjArgs(current_task_func, loop, NULL);
2098 Py_DECREF(current_task_func);
2099 return ret;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002100 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002101}
2102
2103/*[clinic input]
2104@classmethod
2105_asyncio.Task.all_tasks
2106
Serhiy Storchakabca49392017-09-03 08:10:14 +03002107 loop: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002108
2109Return a set of all tasks for an event loop.
2110
2111By default all tasks for the current event loop are returned.
2112[clinic start generated code]*/
2113
2114static PyObject *
2115_asyncio_Task_all_tasks_impl(PyTypeObject *type, PyObject *loop)
Serhiy Storchakabca49392017-09-03 08:10:14 +03002116/*[clinic end generated code: output=11f9b20749ccca5d input=497f80bc9ce726b5]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002117{
2118 PyObject *res;
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002119 PyObject *all_tasks_func;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002120
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002121 if (PyErr_WarnEx(PyExc_PendingDeprecationWarning,
2122 "Task.all_tasks() is deprecated, " \
2123 "use asyncio.all_tasks() instead",
2124 1) < 0) {
2125 return NULL;
2126 }
2127
Yury Selivanov416c1eb2018-05-28 17:54:02 -04002128 all_tasks_func = _PyObject_GetAttrId(asyncio_mod, &PyId__all_tasks_compat);
Serhiy Storchaka66553542018-05-20 16:30:31 +03002129 if (all_tasks_func == NULL) {
2130 return NULL;
2131 }
2132
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002133 res = PyObject_CallFunctionObjArgs(all_tasks_func, loop, NULL);
2134 Py_DECREF(all_tasks_func);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002135 return res;
2136}
2137
2138/*[clinic input]
2139_asyncio.Task._repr_info
2140[clinic start generated code]*/
2141
2142static PyObject *
2143_asyncio_Task__repr_info_impl(TaskObj *self)
2144/*[clinic end generated code: output=6a490eb66d5ba34b input=3c6d051ed3ddec8b]*/
2145{
Victor Stinnerde4ae3d2016-12-04 22:59:09 +01002146 return PyObject_CallFunctionObjArgs(
2147 asyncio_task_repr_info_func, self, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002148}
2149
2150/*[clinic input]
2151_asyncio.Task.cancel
2152
2153Request that this task cancel itself.
2154
2155This arranges for a CancelledError to be thrown into the
2156wrapped coroutine on the next cycle through the event loop.
2157The coroutine then has a chance to clean up or even deny
2158the request using try/except/finally.
2159
2160Unlike Future.cancel, this does not guarantee that the
2161task will be cancelled: the exception might be caught and
2162acted upon, delaying cancellation of the task or preventing
2163cancellation completely. The task may also return a value or
2164raise a different exception.
2165
2166Immediately after this method is called, Task.cancelled() will
2167not return True (unless the task was already cancelled). A
2168task will be marked as cancelled when the wrapped coroutine
2169terminates with a CancelledError exception (even if cancel()
2170was not called).
2171[clinic start generated code]*/
2172
2173static PyObject *
2174_asyncio_Task_cancel_impl(TaskObj *self)
2175/*[clinic end generated code: output=6bfc0479da9d5757 input=13f9bf496695cb52]*/
2176{
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +00002177 self->task_log_tb = 0;
2178
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002179 if (self->task_state != STATE_PENDING) {
2180 Py_RETURN_FALSE;
2181 }
2182
2183 if (self->task_fut_waiter) {
2184 PyObject *res;
2185 int is_true;
2186
2187 res = _PyObject_CallMethodId(
2188 self->task_fut_waiter, &PyId_cancel, NULL);
2189 if (res == NULL) {
2190 return NULL;
2191 }
2192
2193 is_true = PyObject_IsTrue(res);
2194 Py_DECREF(res);
2195 if (is_true < 0) {
2196 return NULL;
2197 }
2198
2199 if (is_true) {
2200 Py_RETURN_TRUE;
2201 }
2202 }
2203
2204 self->task_must_cancel = 1;
2205 Py_RETURN_TRUE;
2206}
2207
2208/*[clinic input]
2209_asyncio.Task.get_stack
2210
2211 *
Serhiy Storchakabca49392017-09-03 08:10:14 +03002212 limit: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002213
2214Return the list of stack frames for this task's coroutine.
2215
2216If the coroutine is not done, this returns the stack where it is
2217suspended. If the coroutine has completed successfully or was
2218cancelled, this returns an empty list. If the coroutine was
2219terminated by an exception, this returns the list of traceback
2220frames.
2221
2222The frames are always ordered from oldest to newest.
2223
2224The optional limit gives the maximum number of frames to
2225return; by default all available frames are returned. Its
2226meaning differs depending on whether a stack or a traceback is
2227returned: the newest frames of a stack are returned, but the
2228oldest frames of a traceback are returned. (This matches the
2229behavior of the traceback module.)
2230
2231For reasons beyond our control, only one stack frame is
2232returned for a suspended coroutine.
2233[clinic start generated code]*/
2234
2235static PyObject *
2236_asyncio_Task_get_stack_impl(TaskObj *self, PyObject *limit)
Serhiy Storchakabca49392017-09-03 08:10:14 +03002237/*[clinic end generated code: output=c9aeeeebd1e18118 input=05b323d42b809b90]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002238{
2239 return PyObject_CallFunctionObjArgs(
2240 asyncio_task_get_stack_func, self, limit, NULL);
2241}
2242
2243/*[clinic input]
2244_asyncio.Task.print_stack
2245
2246 *
Serhiy Storchakabca49392017-09-03 08:10:14 +03002247 limit: object = None
2248 file: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002249
2250Print the stack or traceback for this task's coroutine.
2251
2252This produces output similar to that of the traceback module,
2253for the frames retrieved by get_stack(). The limit argument
2254is passed to get_stack(). The file argument is an I/O stream
2255to which the output is written; by default output is written
2256to sys.stderr.
2257[clinic start generated code]*/
2258
2259static PyObject *
2260_asyncio_Task_print_stack_impl(TaskObj *self, PyObject *limit,
2261 PyObject *file)
Serhiy Storchakabca49392017-09-03 08:10:14 +03002262/*[clinic end generated code: output=7339e10314cd3f4d input=1a0352913b7fcd92]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002263{
2264 return PyObject_CallFunctionObjArgs(
2265 asyncio_task_print_stack_func, self, limit, file, NULL);
2266}
2267
2268/*[clinic input]
Yury Selivanov0cf16f92017-12-25 10:48:15 -05002269_asyncio.Task.set_result
2270
2271 result: object
2272 /
2273[clinic start generated code]*/
2274
2275static PyObject *
2276_asyncio_Task_set_result(TaskObj *self, PyObject *result)
2277/*[clinic end generated code: output=1dcae308bfcba318 input=9d1a00c07be41bab]*/
2278{
2279 PyErr_SetString(PyExc_RuntimeError,
2280 "Task does not support set_result operation");
2281 return NULL;
2282}
2283
2284/*[clinic input]
2285_asyncio.Task.set_exception
2286
2287 exception: object
2288 /
2289[clinic start generated code]*/
2290
2291static PyObject *
2292_asyncio_Task_set_exception(TaskObj *self, PyObject *exception)
2293/*[clinic end generated code: output=bc377fc28067303d input=9a8f65c83dcf893a]*/
2294{
2295 PyErr_SetString(PyExc_RuntimeError,
Andrew Svetlovfc359322017-12-30 15:40:27 +02002296 "Task does not support set_exception operation");
Yury Selivanov0cf16f92017-12-25 10:48:15 -05002297 return NULL;
2298}
2299
2300
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002301static void
2302TaskObj_finalize(TaskObj *task)
2303{
2304 _Py_IDENTIFIER(call_exception_handler);
2305 _Py_IDENTIFIER(task);
2306 _Py_IDENTIFIER(message);
2307 _Py_IDENTIFIER(source_traceback);
2308
Serhiy Storchakabca49392017-09-03 08:10:14 +03002309 PyObject *context;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002310 PyObject *message = NULL;
Serhiy Storchakabca49392017-09-03 08:10:14 +03002311 PyObject *func;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002312 PyObject *error_type, *error_value, *error_traceback;
2313
2314 if (task->task_state != STATE_PENDING || !task->task_log_destroy_pending) {
2315 goto done;
2316 }
2317
2318 /* Save the current exception, if any. */
2319 PyErr_Fetch(&error_type, &error_value, &error_traceback);
2320
2321 context = PyDict_New();
2322 if (context == NULL) {
2323 goto finally;
2324 }
2325
2326 message = PyUnicode_FromString("Task was destroyed but it is pending!");
2327 if (message == NULL) {
2328 goto finally;
2329 }
2330
2331 if (_PyDict_SetItemId(context, &PyId_message, message) < 0 ||
2332 _PyDict_SetItemId(context, &PyId_task, (PyObject*)task) < 0)
2333 {
2334 goto finally;
2335 }
2336
2337 if (task->task_source_tb != NULL) {
2338 if (_PyDict_SetItemId(context, &PyId_source_traceback,
2339 task->task_source_tb) < 0)
2340 {
2341 goto finally;
2342 }
2343 }
2344
2345 func = _PyObject_GetAttrId(task->task_loop, &PyId_call_exception_handler);
2346 if (func != NULL) {
Serhiy Storchakabca49392017-09-03 08:10:14 +03002347 PyObject *res = PyObject_CallFunctionObjArgs(func, context, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002348 if (res == NULL) {
2349 PyErr_WriteUnraisable(func);
2350 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03002351 else {
2352 Py_DECREF(res);
2353 }
2354 Py_DECREF(func);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002355 }
2356
2357finally:
Serhiy Storchakabca49392017-09-03 08:10:14 +03002358 Py_XDECREF(context);
2359 Py_XDECREF(message);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002360
2361 /* Restore the saved exception. */
2362 PyErr_Restore(error_type, error_value, error_traceback);
2363
2364done:
2365 FutureObj_finalize((FutureObj*)task);
2366}
2367
2368static void TaskObj_dealloc(PyObject *); /* Needs Task_CheckExact */
2369
2370static PyMethodDef TaskType_methods[] = {
2371 _ASYNCIO_FUTURE_RESULT_METHODDEF
2372 _ASYNCIO_FUTURE_EXCEPTION_METHODDEF
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002373 _ASYNCIO_FUTURE_ADD_DONE_CALLBACK_METHODDEF
2374 _ASYNCIO_FUTURE_REMOVE_DONE_CALLBACK_METHODDEF
2375 _ASYNCIO_FUTURE_CANCELLED_METHODDEF
2376 _ASYNCIO_FUTURE_DONE_METHODDEF
Yury Selivanov0cf16f92017-12-25 10:48:15 -05002377 _ASYNCIO_TASK_SET_RESULT_METHODDEF
2378 _ASYNCIO_TASK_SET_EXCEPTION_METHODDEF
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002379 _ASYNCIO_TASK_CURRENT_TASK_METHODDEF
2380 _ASYNCIO_TASK_ALL_TASKS_METHODDEF
2381 _ASYNCIO_TASK_CANCEL_METHODDEF
2382 _ASYNCIO_TASK_GET_STACK_METHODDEF
2383 _ASYNCIO_TASK_PRINT_STACK_METHODDEF
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002384 _ASYNCIO_TASK__REPR_INFO_METHODDEF
2385 {NULL, NULL} /* Sentinel */
2386};
2387
2388static PyGetSetDef TaskType_getsetlist[] = {
2389 FUTURE_COMMON_GETSETLIST
2390 {"_log_destroy_pending", (getter)TaskObj_get_log_destroy_pending,
2391 (setter)TaskObj_set_log_destroy_pending, NULL},
2392 {"_must_cancel", (getter)TaskObj_get_must_cancel, NULL, NULL},
2393 {"_coro", (getter)TaskObj_get_coro, NULL, NULL},
2394 {"_fut_waiter", (getter)TaskObj_get_fut_waiter, NULL, NULL},
2395 {NULL} /* Sentinel */
2396};
2397
2398static PyTypeObject TaskType = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02002399 PyVarObject_HEAD_INIT(NULL, 0)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002400 "_asyncio.Task",
2401 sizeof(TaskObj), /* tp_basicsize */
2402 .tp_base = &FutureType,
2403 .tp_dealloc = TaskObj_dealloc,
2404 .tp_as_async = &FutureType_as_async,
2405 .tp_repr = (reprfunc)FutureObj_repr,
2406 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE
2407 | Py_TPFLAGS_HAVE_FINALIZE,
2408 .tp_doc = _asyncio_Task___init____doc__,
2409 .tp_traverse = (traverseproc)TaskObj_traverse,
2410 .tp_clear = (inquiry)TaskObj_clear,
2411 .tp_weaklistoffset = offsetof(TaskObj, task_weakreflist),
2412 .tp_iter = (getiterfunc)future_new_iter,
2413 .tp_methods = TaskType_methods,
2414 .tp_getset = TaskType_getsetlist,
2415 .tp_dictoffset = offsetof(TaskObj, dict),
2416 .tp_init = (initproc)_asyncio_Task___init__,
2417 .tp_new = PyType_GenericNew,
2418 .tp_finalize = (destructor)TaskObj_finalize,
2419};
2420
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002421static void
2422TaskObj_dealloc(PyObject *self)
2423{
2424 TaskObj *task = (TaskObj *)self;
2425
2426 if (Task_CheckExact(self)) {
2427 /* When fut is subclass of Task, finalizer is called from
2428 * subtype_dealloc.
2429 */
2430 if (PyObject_CallFinalizerFromDealloc(self) < 0) {
2431 // resurrected.
2432 return;
2433 }
2434 }
2435
Alexander Mohrde34cbe2017-08-01 23:31:07 -07002436 PyObject_GC_UnTrack(self);
2437
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002438 if (task->task_weakreflist != NULL) {
2439 PyObject_ClearWeakRefs(self);
2440 }
2441
2442 (void)TaskObj_clear(task);
2443 Py_TYPE(task)->tp_free(task);
2444}
2445
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002446static int
2447task_call_step_soon(TaskObj *task, PyObject *arg)
2448{
Serhiy Storchakabca49392017-09-03 08:10:14 +03002449 PyObject *cb = TaskStepMethWrapper_new(task, arg);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002450 if (cb == NULL) {
2451 return -1;
2452 }
2453
Yury Selivanovf23746a2018-01-22 19:11:18 -05002454 int ret = call_soon(task->task_loop, cb, NULL, task->task_context);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002455 Py_DECREF(cb);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05002456 return ret;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002457}
2458
2459static PyObject *
2460task_set_error_soon(TaskObj *task, PyObject *et, const char *format, ...)
2461{
2462 PyObject* msg;
2463
2464 va_list vargs;
2465#ifdef HAVE_STDARG_PROTOTYPES
2466 va_start(vargs, format);
2467#else
2468 va_start(vargs);
2469#endif
2470 msg = PyUnicode_FromFormatV(format, vargs);
2471 va_end(vargs);
2472
2473 if (msg == NULL) {
2474 return NULL;
2475 }
2476
Victor Stinnerde4ae3d2016-12-04 22:59:09 +01002477 PyObject *e = PyObject_CallFunctionObjArgs(et, msg, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002478 Py_DECREF(msg);
2479 if (e == NULL) {
2480 return NULL;
2481 }
2482
2483 if (task_call_step_soon(task, e) == -1) {
2484 Py_DECREF(e);
2485 return NULL;
2486 }
2487
2488 Py_DECREF(e);
2489 Py_RETURN_NONE;
2490}
2491
2492static PyObject *
2493task_step_impl(TaskObj *task, PyObject *exc)
2494{
2495 int res;
2496 int clear_exc = 0;
2497 PyObject *result = NULL;
Serhiy Storchakabca49392017-09-03 08:10:14 +03002498 PyObject *coro;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002499 PyObject *o;
2500
2501 if (task->task_state != STATE_PENDING) {
Yury Selivanov0cf16f92017-12-25 10:48:15 -05002502 PyErr_Format(asyncio_InvalidStateError,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002503 "_step(): already done: %R %R",
2504 task,
2505 exc ? exc : Py_None);
INADA Naokic411a7d2016-10-18 11:48:14 +09002506 goto fail;
2507 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09002508
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002509 if (task->task_must_cancel) {
2510 assert(exc != Py_None);
2511
2512 if (exc) {
2513 /* Check if exc is a CancelledError */
2514 res = PyObject_IsInstance(exc, asyncio_CancelledError);
2515 if (res == -1) {
2516 /* An error occurred, abort */
2517 goto fail;
2518 }
2519 if (res == 0) {
2520 /* exc is not CancelledError; reset it to NULL */
2521 exc = NULL;
2522 }
2523 }
2524
2525 if (!exc) {
2526 /* exc was not a CancelledError */
Victor Stinnerf17c3de2016-12-06 18:46:19 +01002527 exc = _PyObject_CallNoArg(asyncio_CancelledError);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002528 if (!exc) {
2529 goto fail;
2530 }
2531 clear_exc = 1;
2532 }
2533
2534 task->task_must_cancel = 0;
2535 }
2536
2537 Py_CLEAR(task->task_fut_waiter);
2538
Serhiy Storchakabca49392017-09-03 08:10:14 +03002539 coro = task->task_coro;
2540 if (coro == NULL) {
2541 PyErr_SetString(PyExc_RuntimeError, "uninitialized Task object");
2542 return NULL;
2543 }
2544
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002545 if (exc == NULL) {
2546 if (PyGen_CheckExact(coro) || PyCoro_CheckExact(coro)) {
2547 result = _PyGen_Send((PyGenObject*)coro, Py_None);
2548 }
2549 else {
Victor Stinnerb6ed57d2016-12-09 14:24:02 +01002550 result = _PyObject_CallMethodIdObjArgs(coro, &PyId_send,
2551 Py_None, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002552 }
2553 }
2554 else {
Victor Stinnerb6ed57d2016-12-09 14:24:02 +01002555 result = _PyObject_CallMethodIdObjArgs(coro, &PyId_throw,
2556 exc, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002557 if (clear_exc) {
2558 /* We created 'exc' during this call */
Serhiy Storchakabca49392017-09-03 08:10:14 +03002559 Py_DECREF(exc);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002560 }
2561 }
2562
2563 if (result == NULL) {
2564 PyObject *et, *ev, *tb;
2565
2566 if (_PyGen_FetchStopIterationValue(&o) == 0) {
2567 /* The error is StopIteration and that means that
2568 the underlying coroutine has resolved */
INADA Naoki991adca2017-05-11 21:18:38 +09002569 if (task->task_must_cancel) {
2570 // Task is cancelled right before coro stops.
2571 Py_DECREF(o);
2572 task->task_must_cancel = 0;
2573 et = asyncio_CancelledError;
2574 Py_INCREF(et);
2575 ev = NULL;
2576 tb = NULL;
2577 goto set_exception;
2578 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002579 PyObject *res = future_set_result((FutureObj*)task, o);
2580 Py_DECREF(o);
2581 if (res == NULL) {
2582 return NULL;
2583 }
2584 Py_DECREF(res);
2585 Py_RETURN_NONE;
2586 }
2587
2588 if (PyErr_ExceptionMatches(asyncio_CancelledError)) {
2589 /* CancelledError */
2590 PyErr_Clear();
2591 return future_cancel((FutureObj*)task);
2592 }
2593
2594 /* Some other exception; pop it and call Task.set_exception() */
2595 PyErr_Fetch(&et, &ev, &tb);
INADA Naoki991adca2017-05-11 21:18:38 +09002596
2597set_exception:
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002598 assert(et);
2599 if (!ev || !PyObject_TypeCheck(ev, (PyTypeObject *) et)) {
2600 PyErr_NormalizeException(&et, &ev, &tb);
2601 }
Yury Selivanovedfe8862016-12-01 11:37:47 -05002602 if (tb != NULL) {
2603 PyException_SetTraceback(ev, tb);
2604 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002605 o = future_set_exception((FutureObj*)task, ev);
2606 if (!o) {
2607 /* An exception in Task.set_exception() */
Serhiy Storchakabca49392017-09-03 08:10:14 +03002608 Py_DECREF(et);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002609 Py_XDECREF(tb);
2610 Py_XDECREF(ev);
2611 goto fail;
2612 }
2613 assert(o == Py_None);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002614 Py_DECREF(o);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002615
2616 if (!PyErr_GivenExceptionMatches(et, PyExc_Exception)) {
2617 /* We've got a BaseException; re-raise it */
2618 PyErr_Restore(et, ev, tb);
2619 goto fail;
2620 }
2621
Serhiy Storchakabca49392017-09-03 08:10:14 +03002622 Py_DECREF(et);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002623 Py_XDECREF(tb);
2624 Py_XDECREF(ev);
2625
2626 Py_RETURN_NONE;
2627 }
2628
2629 if (result == (PyObject*)task) {
2630 /* We have a task that wants to await on itself */
2631 goto self_await;
2632 }
2633
2634 /* Check if `result` is FutureObj or TaskObj (and not a subclass) */
2635 if (Future_CheckExact(result) || Task_CheckExact(result)) {
2636 PyObject *wrapper;
2637 PyObject *res;
2638 FutureObj *fut = (FutureObj*)result;
2639
2640 /* Check if `result` future is attached to a different loop */
2641 if (fut->fut_loop != task->task_loop) {
2642 goto different_loop;
2643 }
2644
2645 if (fut->fut_blocking) {
2646 fut->fut_blocking = 0;
2647
2648 /* result.add_done_callback(task._wakeup) */
2649 wrapper = TaskWakeupMethWrapper_new(task);
2650 if (wrapper == NULL) {
2651 goto fail;
2652 }
Yury Selivanovf23746a2018-01-22 19:11:18 -05002653 res = future_add_done_callback(
2654 (FutureObj*)result, wrapper, task->task_context);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002655 Py_DECREF(wrapper);
2656 if (res == NULL) {
2657 goto fail;
2658 }
2659 Py_DECREF(res);
2660
2661 /* task._fut_waiter = result */
2662 task->task_fut_waiter = result; /* no incref is necessary */
2663
2664 if (task->task_must_cancel) {
2665 PyObject *r;
2666 r = future_cancel(fut);
2667 if (r == NULL) {
2668 return NULL;
2669 }
2670 if (r == Py_True) {
2671 task->task_must_cancel = 0;
2672 }
2673 Py_DECREF(r);
2674 }
2675
2676 Py_RETURN_NONE;
2677 }
2678 else {
2679 goto yield_insteadof_yf;
2680 }
2681 }
2682
2683 /* Check if `result` is a Future-compatible object */
2684 o = PyObject_GetAttrString(result, "_asyncio_future_blocking");
2685 if (o == NULL) {
2686 if (PyErr_ExceptionMatches(PyExc_AttributeError)) {
2687 PyErr_Clear();
2688 }
2689 else {
2690 goto fail;
2691 }
2692 }
2693 else {
2694 if (o == Py_None) {
Serhiy Storchakabca49392017-09-03 08:10:14 +03002695 Py_DECREF(o);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002696 }
2697 else {
2698 /* `result` is a Future-compatible object */
2699 PyObject *wrapper;
2700 PyObject *res;
2701
2702 int blocking = PyObject_IsTrue(o);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002703 Py_DECREF(o);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002704 if (blocking < 0) {
2705 goto fail;
2706 }
2707
2708 /* Check if `result` future is attached to a different loop */
Yury Selivanovca9b36c2017-12-23 15:04:15 -05002709 PyObject *oloop = get_future_loop(result);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002710 if (oloop == NULL) {
2711 goto fail;
2712 }
2713 if (oloop != task->task_loop) {
2714 Py_DECREF(oloop);
2715 goto different_loop;
2716 }
2717 else {
2718 Py_DECREF(oloop);
2719 }
2720
2721 if (blocking) {
2722 /* result._asyncio_future_blocking = False */
2723 if (PyObject_SetAttrString(
2724 result, "_asyncio_future_blocking", Py_False) == -1) {
2725 goto fail;
2726 }
2727
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002728 wrapper = TaskWakeupMethWrapper_new(task);
2729 if (wrapper == NULL) {
2730 goto fail;
2731 }
Yury Selivanovf23746a2018-01-22 19:11:18 -05002732
2733 /* result.add_done_callback(task._wakeup) */
2734 PyObject *add_cb = _PyObject_GetAttrId(
2735 result, &PyId_add_done_callback);
2736 if (add_cb == NULL) {
Serhiy Storchaka66553542018-05-20 16:30:31 +03002737 Py_DECREF(wrapper);
Yury Selivanovf23746a2018-01-22 19:11:18 -05002738 goto fail;
2739 }
2740 PyObject *stack[2];
2741 stack[0] = wrapper;
2742 stack[1] = (PyObject *)task->task_context;
2743 res = _PyObject_FastCallKeywords(
2744 add_cb, stack, 1, context_kwname);
2745 Py_DECREF(add_cb);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002746 Py_DECREF(wrapper);
2747 if (res == NULL) {
2748 goto fail;
2749 }
2750 Py_DECREF(res);
2751
2752 /* task._fut_waiter = result */
2753 task->task_fut_waiter = result; /* no incref is necessary */
2754
2755 if (task->task_must_cancel) {
2756 PyObject *r;
2757 int is_true;
2758 r = _PyObject_CallMethodId(result, &PyId_cancel, NULL);
2759 if (r == NULL) {
2760 return NULL;
2761 }
2762 is_true = PyObject_IsTrue(r);
2763 Py_DECREF(r);
2764 if (is_true < 0) {
2765 return NULL;
2766 }
2767 else if (is_true) {
2768 task->task_must_cancel = 0;
2769 }
2770 }
2771
2772 Py_RETURN_NONE;
2773 }
2774 else {
2775 goto yield_insteadof_yf;
2776 }
2777 }
2778 }
2779
2780 /* Check if `result` is None */
2781 if (result == Py_None) {
2782 /* Bare yield relinquishes control for one event loop iteration. */
2783 if (task_call_step_soon(task, NULL)) {
2784 goto fail;
2785 }
2786 return result;
2787 }
2788
2789 /* Check if `result` is a generator */
Victor Stinnerde4ae3d2016-12-04 22:59:09 +01002790 o = PyObject_CallFunctionObjArgs(inspect_isgenerator, result, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002791 if (o == NULL) {
2792 /* An exception in inspect.isgenerator */
2793 goto fail;
2794 }
2795 res = PyObject_IsTrue(o);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002796 Py_DECREF(o);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002797 if (res == -1) {
2798 /* An exception while checking if 'val' is True */
2799 goto fail;
2800 }
2801 if (res == 1) {
2802 /* `result` is a generator */
Serhiy Storchaka66553542018-05-20 16:30:31 +03002803 o = task_set_error_soon(
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002804 task, PyExc_RuntimeError,
2805 "yield was used instead of yield from for "
Serhiy Storchaka66553542018-05-20 16:30:31 +03002806 "generator in task %R with %R", task, result);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002807 Py_DECREF(result);
Serhiy Storchaka66553542018-05-20 16:30:31 +03002808 return o;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002809 }
2810
2811 /* The `result` is none of the above */
Serhiy Storchaka66553542018-05-20 16:30:31 +03002812 o = task_set_error_soon(
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002813 task, PyExc_RuntimeError, "Task got bad yield: %R", result);
Serhiy Storchaka66553542018-05-20 16:30:31 +03002814 Py_DECREF(result);
2815 return o;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002816
2817self_await:
2818 o = task_set_error_soon(
2819 task, PyExc_RuntimeError,
2820 "Task cannot await on itself: %R", task);
2821 Py_DECREF(result);
2822 return o;
2823
2824yield_insteadof_yf:
2825 o = task_set_error_soon(
2826 task, PyExc_RuntimeError,
2827 "yield was used instead of yield from "
2828 "in task %R with %R",
2829 task, result);
2830 Py_DECREF(result);
2831 return o;
2832
2833different_loop:
2834 o = task_set_error_soon(
2835 task, PyExc_RuntimeError,
2836 "Task %R got Future %R attached to a different loop",
2837 task, result);
2838 Py_DECREF(result);
2839 return o;
2840
2841fail:
2842 Py_XDECREF(result);
2843 return NULL;
2844}
2845
2846static PyObject *
2847task_step(TaskObj *task, PyObject *exc)
2848{
2849 PyObject *res;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002850
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002851 if (enter_task(task->task_loop, (PyObject*)task) < 0) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002852 return NULL;
2853 }
2854
2855 res = task_step_impl(task, exc);
2856
2857 if (res == NULL) {
2858 PyObject *et, *ev, *tb;
2859 PyErr_Fetch(&et, &ev, &tb);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002860 leave_task(task->task_loop, (PyObject*)task);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002861 _PyErr_ChainExceptions(et, ev, tb);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002862 return NULL;
2863 }
2864 else {
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002865 if(leave_task(task->task_loop, (PyObject*)task) < 0) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002866 Py_DECREF(res);
2867 return NULL;
2868 }
2869 else {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002870 return res;
2871 }
2872 }
2873}
2874
2875static PyObject *
2876task_wakeup(TaskObj *task, PyObject *o)
2877{
Serhiy Storchakabca49392017-09-03 08:10:14 +03002878 PyObject *et, *ev, *tb;
2879 PyObject *result;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002880 assert(o);
2881
2882 if (Future_CheckExact(o) || Task_CheckExact(o)) {
2883 PyObject *fut_result = NULL;
2884 int res = future_get_result((FutureObj*)o, &fut_result);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002885
2886 switch(res) {
2887 case -1:
2888 assert(fut_result == NULL);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002889 break; /* exception raised */
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002890 case 0:
2891 Py_DECREF(fut_result);
Yury Selivanov22feeb82018-01-24 11:31:01 -05002892 return task_step(task, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002893 default:
2894 assert(res == 1);
Yury Selivanov22feeb82018-01-24 11:31:01 -05002895 result = task_step(task, fut_result);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002896 Py_DECREF(fut_result);
2897 return result;
2898 }
2899 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002900 else {
Serhiy Storchakabca49392017-09-03 08:10:14 +03002901 PyObject *fut_result = PyObject_CallMethod(o, "result", NULL);
2902 if (fut_result != NULL) {
2903 Py_DECREF(fut_result);
Yury Selivanov22feeb82018-01-24 11:31:01 -05002904 return task_step(task, NULL);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002905 }
2906 /* exception raised */
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002907 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03002908
2909 PyErr_Fetch(&et, &ev, &tb);
2910 if (!PyErr_GivenExceptionMatches(et, PyExc_Exception)) {
2911 /* We've got a BaseException; re-raise it */
2912 PyErr_Restore(et, ev, tb);
2913 return NULL;
2914 }
2915 if (!ev || !PyObject_TypeCheck(ev, (PyTypeObject *) et)) {
2916 PyErr_NormalizeException(&et, &ev, &tb);
2917 }
2918
Yury Selivanov22feeb82018-01-24 11:31:01 -05002919 result = task_step(task, ev);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002920
2921 Py_DECREF(et);
2922 Py_XDECREF(tb);
2923 Py_XDECREF(ev);
2924
2925 return result;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002926}
2927
2928
Yury Selivanova70232f2017-12-13 14:49:42 -05002929/*********************** Functions **************************/
2930
2931
2932/*[clinic input]
2933_asyncio._get_running_loop
2934
2935Return the running event loop or None.
2936
2937This is a low-level function intended to be used by event loops.
2938This function is thread-specific.
2939
2940[clinic start generated code]*/
2941
2942static PyObject *
2943_asyncio__get_running_loop_impl(PyObject *module)
2944/*[clinic end generated code: output=b4390af721411a0a input=0a21627e25a4bd43]*/
2945{
2946 PyObject *loop;
2947 if (get_running_loop(&loop)) {
2948 return NULL;
2949 }
2950 if (loop == NULL) {
2951 /* There's no currently running event loop */
2952 Py_RETURN_NONE;
2953 }
2954 return loop;
2955}
2956
2957/*[clinic input]
2958_asyncio._set_running_loop
2959 loop: 'O'
2960 /
2961
2962Set the running event loop.
2963
2964This is a low-level function intended to be used by event loops.
2965This function is thread-specific.
2966[clinic start generated code]*/
2967
2968static PyObject *
2969_asyncio__set_running_loop(PyObject *module, PyObject *loop)
2970/*[clinic end generated code: output=ae56bf7a28ca189a input=4c9720233d606604]*/
2971{
2972 if (set_running_loop(loop)) {
2973 return NULL;
2974 }
2975 Py_RETURN_NONE;
2976}
2977
2978/*[clinic input]
2979_asyncio.get_event_loop
2980
2981Return an asyncio event loop.
2982
2983When called from a coroutine or a callback (e.g. scheduled with
2984call_soon or similar API), this function will always return the
2985running event loop.
2986
2987If there is no running event loop set, the function will return
2988the result of `get_event_loop_policy().get_event_loop()` call.
2989[clinic start generated code]*/
2990
2991static PyObject *
2992_asyncio_get_event_loop_impl(PyObject *module)
2993/*[clinic end generated code: output=2a2d8b2f824c648b input=9364bf2916c8655d]*/
2994{
2995 return get_event_loop();
2996}
2997
2998/*[clinic input]
2999_asyncio.get_running_loop
3000
3001Return the running event loop. Raise a RuntimeError if there is none.
3002
3003This function is thread-specific.
3004[clinic start generated code]*/
3005
3006static PyObject *
3007_asyncio_get_running_loop_impl(PyObject *module)
3008/*[clinic end generated code: output=c247b5f9e529530e input=2a3bf02ba39f173d]*/
3009{
3010 PyObject *loop;
3011 if (get_running_loop(&loop)) {
3012 return NULL;
3013 }
3014 if (loop == NULL) {
3015 /* There's no currently running event loop */
3016 PyErr_SetString(
3017 PyExc_RuntimeError, "no running event loop");
3018 }
3019 return loop;
3020}
3021
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003022/*[clinic input]
3023_asyncio._register_task
3024
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003025 task: object
3026
3027Register a new task in asyncio as executed by loop.
3028
3029Returns None.
3030[clinic start generated code]*/
3031
3032static PyObject *
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003033_asyncio__register_task_impl(PyObject *module, PyObject *task)
3034/*[clinic end generated code: output=8672dadd69a7d4e2 input=21075aaea14dfbad]*/
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003035{
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003036 if (register_task(task) < 0) {
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003037 return NULL;
3038 }
3039 Py_RETURN_NONE;
3040}
3041
3042
3043/*[clinic input]
3044_asyncio._unregister_task
3045
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003046 task: object
3047
3048Unregister a task.
3049
3050Returns None.
3051[clinic start generated code]*/
3052
3053static PyObject *
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003054_asyncio__unregister_task_impl(PyObject *module, PyObject *task)
3055/*[clinic end generated code: output=6e5585706d568a46 input=28fb98c3975f7bdc]*/
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003056{
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003057 if (unregister_task(task) < 0) {
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003058 return NULL;
3059 }
3060 Py_RETURN_NONE;
3061}
3062
3063
3064/*[clinic input]
3065_asyncio._enter_task
3066
3067 loop: object
3068 task: object
3069
3070Enter into task execution or resume suspended task.
3071
3072Task belongs to loop.
3073
3074Returns None.
3075[clinic start generated code]*/
3076
3077static PyObject *
3078_asyncio__enter_task_impl(PyObject *module, PyObject *loop, PyObject *task)
3079/*[clinic end generated code: output=a22611c858035b73 input=de1b06dca70d8737]*/
3080{
3081 if (enter_task(loop, task) < 0) {
3082 return NULL;
3083 }
3084 Py_RETURN_NONE;
3085}
3086
3087
3088/*[clinic input]
3089_asyncio._leave_task
3090
3091 loop: object
3092 task: object
3093
3094Leave task execution or suspend a task.
3095
3096Task belongs to loop.
3097
3098Returns None.
3099[clinic start generated code]*/
3100
3101static PyObject *
3102_asyncio__leave_task_impl(PyObject *module, PyObject *loop, PyObject *task)
3103/*[clinic end generated code: output=0ebf6db4b858fb41 input=51296a46313d1ad8]*/
3104{
3105 if (leave_task(loop, task) < 0) {
3106 return NULL;
3107 }
3108 Py_RETURN_NONE;
3109}
3110
Yury Selivanova70232f2017-12-13 14:49:42 -05003111
Yury Selivanov9d411c12018-01-23 15:10:03 -05003112/*********************** PyRunningLoopHolder ********************/
3113
3114
3115static PyRunningLoopHolder *
3116new_running_loop_holder(PyObject *loop)
3117{
3118 PyRunningLoopHolder *rl = PyObject_New(
3119 PyRunningLoopHolder, &PyRunningLoopHolder_Type);
3120 if (rl == NULL) {
3121 return NULL;
3122 }
3123
3124#if defined(HAVE_GETPID) && !defined(MS_WINDOWS)
3125 rl->rl_pid = getpid();
3126#endif
3127
3128 Py_INCREF(loop);
3129 rl->rl_loop = loop;
3130
3131 return rl;
3132}
3133
3134
3135static void
3136PyRunningLoopHolder_tp_dealloc(PyRunningLoopHolder *rl)
3137{
3138 Py_CLEAR(rl->rl_loop);
3139 PyObject_Free(rl);
3140}
3141
3142
3143static PyTypeObject PyRunningLoopHolder_Type = {
3144 PyVarObject_HEAD_INIT(NULL, 0)
3145 "_RunningLoopHolder",
3146 sizeof(PyRunningLoopHolder),
3147 .tp_getattro = PyObject_GenericGetAttr,
3148 .tp_flags = Py_TPFLAGS_DEFAULT,
3149 .tp_dealloc = (destructor)PyRunningLoopHolder_tp_dealloc,
3150};
3151
3152
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003153/*********************** Module **************************/
3154
3155
3156static void
Zackery Spytze40ad792017-12-19 11:48:13 -07003157module_free_freelists(void)
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05003158{
3159 PyObject *next;
3160 PyObject *current;
3161
3162 next = (PyObject*) fi_freelist;
3163 while (next != NULL) {
3164 assert(fi_freelist_len > 0);
3165 fi_freelist_len--;
3166
3167 current = next;
3168 next = (PyObject*) ((futureiterobject*) current)->future;
3169 PyObject_GC_Del(current);
3170 }
3171 assert(fi_freelist_len == 0);
3172 fi_freelist = NULL;
3173}
3174
3175
3176static void
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003177module_free(void *m)
3178{
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003179 Py_CLEAR(asyncio_mod);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003180 Py_CLEAR(inspect_isgenerator);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003181 Py_CLEAR(traceback_extract_stack);
3182 Py_CLEAR(asyncio_future_repr_info_func);
3183 Py_CLEAR(asyncio_get_event_loop_policy);
3184 Py_CLEAR(asyncio_iscoroutine_func);
3185 Py_CLEAR(asyncio_task_get_stack_func);
3186 Py_CLEAR(asyncio_task_print_stack_func);
3187 Py_CLEAR(asyncio_task_repr_info_func);
3188 Py_CLEAR(asyncio_InvalidStateError);
3189 Py_CLEAR(asyncio_CancelledError);
3190
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003191 Py_CLEAR(all_tasks);
Yury Selivanova9d7e552017-12-19 07:18:45 -05003192 Py_CLEAR(current_tasks);
3193 Py_CLEAR(iscoroutine_typecache);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05003194
Yury Selivanovf23746a2018-01-22 19:11:18 -05003195 Py_CLEAR(context_kwname);
3196
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05003197 module_free_freelists();
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003198}
3199
3200static int
3201module_init(void)
3202{
3203 PyObject *module = NULL;
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003204
3205 asyncio_mod = PyImport_ImportModule("asyncio");
3206 if (asyncio_mod == NULL) {
3207 goto fail;
3208 }
3209
3210 current_tasks = PyDict_New();
3211 if (current_tasks == NULL) {
3212 goto fail;
3213 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003214
Yury Selivanova9d7e552017-12-19 07:18:45 -05003215 iscoroutine_typecache = PySet_New(NULL);
3216 if (iscoroutine_typecache == NULL) {
3217 goto fail;
3218 }
3219
Yury Selivanovf23746a2018-01-22 19:11:18 -05003220
3221 context_kwname = PyTuple_New(1);
3222 if (context_kwname == NULL) {
3223 goto fail;
3224 }
3225 PyObject *context_str = PyUnicode_FromString("context");
3226 if (context_str == NULL) {
3227 goto fail;
3228 }
3229 PyTuple_SET_ITEM(context_kwname, 0, context_str);
3230
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003231#define WITH_MOD(NAME) \
3232 Py_CLEAR(module); \
3233 module = PyImport_ImportModule(NAME); \
3234 if (module == NULL) { \
Serhiy Storchakabca49392017-09-03 08:10:14 +03003235 goto fail; \
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003236 }
3237
3238#define GET_MOD_ATTR(VAR, NAME) \
3239 VAR = PyObject_GetAttrString(module, NAME); \
3240 if (VAR == NULL) { \
3241 goto fail; \
3242 }
3243
3244 WITH_MOD("asyncio.events")
Yury Selivanova70232f2017-12-13 14:49:42 -05003245 GET_MOD_ATTR(asyncio_get_event_loop_policy, "get_event_loop_policy")
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003246
3247 WITH_MOD("asyncio.base_futures")
3248 GET_MOD_ATTR(asyncio_future_repr_info_func, "_future_repr_info")
3249 GET_MOD_ATTR(asyncio_InvalidStateError, "InvalidStateError")
3250 GET_MOD_ATTR(asyncio_CancelledError, "CancelledError")
3251
3252 WITH_MOD("asyncio.base_tasks")
3253 GET_MOD_ATTR(asyncio_task_repr_info_func, "_task_repr_info")
3254 GET_MOD_ATTR(asyncio_task_get_stack_func, "_task_get_stack")
3255 GET_MOD_ATTR(asyncio_task_print_stack_func, "_task_print_stack")
3256
Andrew Svetlovf74ef452017-12-15 07:04:38 +02003257 WITH_MOD("asyncio.coroutines")
3258 GET_MOD_ATTR(asyncio_iscoroutine_func, "iscoroutine")
3259
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003260 WITH_MOD("inspect")
3261 GET_MOD_ATTR(inspect_isgenerator, "isgenerator")
3262
3263 WITH_MOD("traceback")
3264 GET_MOD_ATTR(traceback_extract_stack, "extract_stack")
3265
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003266 PyObject *weak_set;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003267 WITH_MOD("weakref")
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003268 GET_MOD_ATTR(weak_set, "WeakSet");
3269 all_tasks = _PyObject_CallNoArg(weak_set);
3270 Py_CLEAR(weak_set);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003271 if (all_tasks == NULL) {
INADA Naokic411a7d2016-10-18 11:48:14 +09003272 goto fail;
3273 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003274
Serhiy Storchakabca49392017-09-03 08:10:14 +03003275 Py_DECREF(module);
INADA Naokic411a7d2016-10-18 11:48:14 +09003276 return 0;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003277
INADA Naokic411a7d2016-10-18 11:48:14 +09003278fail:
INADA Naokic411a7d2016-10-18 11:48:14 +09003279 Py_CLEAR(module);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003280 module_free(NULL);
INADA Naokic411a7d2016-10-18 11:48:14 +09003281 return -1;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003282
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003283#undef WITH_MOD
3284#undef GET_MOD_ATTR
3285}
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003286
INADA Naokic411a7d2016-10-18 11:48:14 +09003287PyDoc_STRVAR(module_doc, "Accelerator module for asyncio");
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003288
Yury Selivanova70232f2017-12-13 14:49:42 -05003289static PyMethodDef asyncio_methods[] = {
3290 _ASYNCIO_GET_EVENT_LOOP_METHODDEF
3291 _ASYNCIO_GET_RUNNING_LOOP_METHODDEF
3292 _ASYNCIO__GET_RUNNING_LOOP_METHODDEF
3293 _ASYNCIO__SET_RUNNING_LOOP_METHODDEF
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003294 _ASYNCIO__REGISTER_TASK_METHODDEF
3295 _ASYNCIO__UNREGISTER_TASK_METHODDEF
3296 _ASYNCIO__ENTER_TASK_METHODDEF
3297 _ASYNCIO__LEAVE_TASK_METHODDEF
Yury Selivanova70232f2017-12-13 14:49:42 -05003298 {NULL, NULL}
3299};
3300
INADA Naoki9f2ce252016-10-15 15:39:19 +09003301static struct PyModuleDef _asynciomodule = {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003302 PyModuleDef_HEAD_INIT, /* m_base */
INADA Naoki9f2ce252016-10-15 15:39:19 +09003303 "_asyncio", /* m_name */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003304 module_doc, /* m_doc */
3305 -1, /* m_size */
Yury Selivanova70232f2017-12-13 14:49:42 -05003306 asyncio_methods, /* m_methods */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003307 NULL, /* m_slots */
3308 NULL, /* m_traverse */
3309 NULL, /* m_clear */
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003310 (freefunc)module_free /* m_free */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003311};
3312
3313
3314PyMODINIT_FUNC
INADA Naoki9f2ce252016-10-15 15:39:19 +09003315PyInit__asyncio(void)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003316{
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003317 if (module_init() < 0) {
INADA Naokic411a7d2016-10-18 11:48:14 +09003318 return NULL;
3319 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003320 if (PyType_Ready(&FutureType) < 0) {
3321 return NULL;
3322 }
3323 if (PyType_Ready(&FutureIterType) < 0) {
3324 return NULL;
3325 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03003326 if (PyType_Ready(&TaskStepMethWrapper_Type) < 0) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003327 return NULL;
3328 }
3329 if(PyType_Ready(&TaskWakeupMethWrapper_Type) < 0) {
3330 return NULL;
3331 }
3332 if (PyType_Ready(&TaskType) < 0) {
3333 return NULL;
3334 }
Yury Selivanov9d411c12018-01-23 15:10:03 -05003335 if (PyType_Ready(&PyRunningLoopHolder_Type) < 0) {
3336 return NULL;
3337 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003338
INADA Naoki9f2ce252016-10-15 15:39:19 +09003339 PyObject *m = PyModule_Create(&_asynciomodule);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003340 if (m == NULL) {
3341 return NULL;
3342 }
3343
3344 Py_INCREF(&FutureType);
3345 if (PyModule_AddObject(m, "Future", (PyObject *)&FutureType) < 0) {
3346 Py_DECREF(&FutureType);
3347 return NULL;
3348 }
3349
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003350 Py_INCREF(&TaskType);
3351 if (PyModule_AddObject(m, "Task", (PyObject *)&TaskType) < 0) {
3352 Py_DECREF(&TaskType);
3353 return NULL;
3354 }
3355
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003356 Py_INCREF(all_tasks);
3357 if (PyModule_AddObject(m, "_all_tasks", all_tasks) < 0) {
3358 Py_DECREF(all_tasks);
3359 return NULL;
3360 }
3361
3362 Py_INCREF(current_tasks);
3363 if (PyModule_AddObject(m, "_current_tasks", current_tasks) < 0) {
3364 Py_DECREF(current_tasks);
3365 return NULL;
3366 }
3367
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003368 return m;
3369}