blob: e82425bf2fd7cdae3293a54bf17dc7c9aad33ace [file] [log] [blame]
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001#include "Python.h"
2#include "structmember.h"
3
4
Yury Selivanova0c1ba62016-10-28 12:52:37 -04005/*[clinic input]
6module _asyncio
7[clinic start generated code]*/
8/*[clinic end generated code: output=da39a3ee5e6b4b0d input=8fd17862aa989c69]*/
9
10
INADA Naoki9e4e38e2016-10-09 14:44:47 +090011/* identifiers used from some functions */
Yury Selivanova70232f2017-12-13 14:49:42 -050012_Py_IDENTIFIER(__asyncio_running_event_loop__);
Yury Selivanova0c1ba62016-10-28 12:52:37 -040013_Py_IDENTIFIER(add_done_callback);
Andrew Svetlov44d1a592017-12-16 21:58:38 +020014_Py_IDENTIFIER(all_tasks);
INADA Naoki9e4e38e2016-10-09 14:44:47 +090015_Py_IDENTIFIER(call_soon);
Yury Selivanova0c1ba62016-10-28 12:52:37 -040016_Py_IDENTIFIER(cancel);
Andrew Svetlov44d1a592017-12-16 21:58:38 +020017_Py_IDENTIFIER(current_task);
Yury Selivanova70232f2017-12-13 14:49:42 -050018_Py_IDENTIFIER(get_event_loop);
Yury Selivanova0c1ba62016-10-28 12:52:37 -040019_Py_IDENTIFIER(send);
20_Py_IDENTIFIER(throw);
INADA Naoki9e4e38e2016-10-09 14:44:47 +090021
22
INADA Naoki9f2ce252016-10-15 15:39:19 +090023/* State of the _asyncio module */
Andrew Svetlov44d1a592017-12-16 21:58:38 +020024static PyObject *asyncio_mod;
Yury Selivanova0c1ba62016-10-28 12:52:37 -040025static PyObject *inspect_isgenerator;
Andrew Svetlov44d1a592017-12-16 21:58:38 +020026static PyObject *traceback_extract_stack;
27static PyObject *asyncio_get_event_loop_policy;
28static PyObject *asyncio_future_repr_info_func;
29static PyObject *asyncio_iscoroutine_func;
30static PyObject *asyncio_task_get_stack_func;
31static PyObject *asyncio_task_print_stack_func;
32static PyObject *asyncio_task_repr_info_func;
33static PyObject *asyncio_InvalidStateError;
34static PyObject *asyncio_CancelledError;
Yury Selivanovf23746a2018-01-22 19:11:18 -050035static PyObject *context_kwname;
Andrew Svetlov44d1a592017-12-16 21:58:38 +020036
Yury Selivanov9d411c12018-01-23 15:10:03 -050037static PyObject *cached_running_holder;
38static volatile uint64_t cached_running_holder_tsid;
39
Andrew Svetlov44d1a592017-12-16 21:58:38 +020040
Yury Selivanovca9b36c2017-12-23 15:04:15 -050041/* WeakSet containing all alive tasks. */
42static PyObject *all_tasks;
Andrew Svetlov44d1a592017-12-16 21:58:38 +020043
44/* Dictionary containing tasks that are currently active in
45 all running event loops. {EventLoop: Task} */
Yury Selivanovca9b36c2017-12-23 15:04:15 -050046static PyObject *current_tasks;
INADA Naoki9e4e38e2016-10-09 14:44:47 +090047
Yury Selivanova9d7e552017-12-19 07:18:45 -050048/* An isinstance type cache for the 'is_coroutine()' function. */
49static PyObject *iscoroutine_typecache;
50
INADA Naoki9e4e38e2016-10-09 14:44:47 +090051
INADA Naoki9e4e38e2016-10-09 14:44:47 +090052typedef enum {
53 STATE_PENDING,
54 STATE_CANCELLED,
55 STATE_FINISHED
56} fut_state;
57
Yury Selivanova0c1ba62016-10-28 12:52:37 -040058#define FutureObj_HEAD(prefix) \
59 PyObject_HEAD \
60 PyObject *prefix##_loop; \
Yury Selivanov1b7c11f2017-12-17 20:19:47 -050061 PyObject *prefix##_callback0; \
Yury Selivanovf23746a2018-01-22 19:11:18 -050062 PyContext *prefix##_context0; \
Yury Selivanova0c1ba62016-10-28 12:52:37 -040063 PyObject *prefix##_callbacks; \
64 PyObject *prefix##_exception; \
65 PyObject *prefix##_result; \
66 PyObject *prefix##_source_tb; \
67 fut_state prefix##_state; \
68 int prefix##_log_tb; \
69 int prefix##_blocking; \
70 PyObject *dict; \
71 PyObject *prefix##_weakreflist;
72
73typedef struct {
74 FutureObj_HEAD(fut)
75} FutureObj;
76
77typedef struct {
78 FutureObj_HEAD(task)
79 PyObject *task_fut_waiter;
80 PyObject *task_coro;
Yury Selivanovf23746a2018-01-22 19:11:18 -050081 PyContext *task_context;
Yury Selivanova0c1ba62016-10-28 12:52:37 -040082 int task_must_cancel;
83 int task_log_destroy_pending;
84} TaskObj;
INADA Naoki9e4e38e2016-10-09 14:44:47 +090085
86typedef struct {
87 PyObject_HEAD
Yury Selivanova0c1ba62016-10-28 12:52:37 -040088 TaskObj *sw_task;
89 PyObject *sw_arg;
Serhiy Storchakabca49392017-09-03 08:10:14 +030090} TaskStepMethWrapper;
INADA Naoki9e4e38e2016-10-09 14:44:47 +090091
Yury Selivanova0c1ba62016-10-28 12:52:37 -040092typedef struct {
93 PyObject_HEAD
94 TaskObj *ww_task;
95} TaskWakeupMethWrapper;
96
Yury Selivanov9d411c12018-01-23 15:10:03 -050097typedef struct {
98 PyObject_HEAD
99 PyObject *rl_loop;
100#if defined(HAVE_GETPID) && !defined(MS_WINDOWS)
101 pid_t rl_pid;
102#endif
103} PyRunningLoopHolder;
104
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400105
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500106static PyTypeObject FutureType;
107static PyTypeObject TaskType;
Yury Selivanov9d411c12018-01-23 15:10:03 -0500108static PyTypeObject PyRunningLoopHolder_Type;
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500109
110
111#define Future_CheckExact(obj) (Py_TYPE(obj) == &FutureType)
112#define Task_CheckExact(obj) (Py_TYPE(obj) == &TaskType)
113
114#define Future_Check(obj) PyObject_TypeCheck(obj, &FutureType)
115#define Task_Check(obj) PyObject_TypeCheck(obj, &TaskType)
116
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400117#include "clinic/_asynciomodule.c.h"
118
119
120/*[clinic input]
121class _asyncio.Future "FutureObj *" "&Future_Type"
122[clinic start generated code]*/
123/*[clinic end generated code: output=da39a3ee5e6b4b0d input=00d3e4abca711e0f]*/
124
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500125
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400126/* Get FutureIter from Future */
Yury Selivanov9d411c12018-01-23 15:10:03 -0500127static PyObject * future_new_iter(PyObject *);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900128
Yury Selivanov9d411c12018-01-23 15:10:03 -0500129static PyRunningLoopHolder * new_running_loop_holder(PyObject *);
130
Yury Selivanova70232f2017-12-13 14:49:42 -0500131
132static int
Yury Selivanova9d7e552017-12-19 07:18:45 -0500133_is_coroutine(PyObject *coro)
134{
135 /* 'coro' is not a native coroutine, call asyncio.iscoroutine()
136 to check if it's another coroutine flavour.
137
138 Do this check after 'future_init()'; in case we need to raise
139 an error, __del__ needs a properly initialized object.
140 */
141 PyObject *res = PyObject_CallFunctionObjArgs(
142 asyncio_iscoroutine_func, coro, NULL);
143 if (res == NULL) {
144 return -1;
145 }
146
147 int is_res_true = PyObject_IsTrue(res);
148 Py_DECREF(res);
149 if (is_res_true <= 0) {
150 return is_res_true;
151 }
152
Andrew Svetlov0f47fa22017-12-23 22:06:46 +0200153 if (PySet_GET_SIZE(iscoroutine_typecache) < 100) {
Yury Selivanova9d7e552017-12-19 07:18:45 -0500154 /* Just in case we don't want to cache more than 100
155 positive types. That shouldn't ever happen, unless
156 someone stressing the system on purpose.
157 */
158 if (PySet_Add(iscoroutine_typecache, (PyObject*) Py_TYPE(coro))) {
159 return -1;
160 }
161 }
162
163 return 1;
164}
165
166
167static inline int
168is_coroutine(PyObject *coro)
169{
170 if (PyCoro_CheckExact(coro)) {
171 return 1;
172 }
173
174 /* Check if `type(coro)` is in the cache.
175 Caching makes is_coroutine() function almost as fast as
176 PyCoro_CheckExact() for non-native coroutine-like objects
177 (like coroutines compiled with Cython).
178
179 asyncio.iscoroutine() has its own type caching mechanism.
180 This cache allows us to avoid the cost of even calling
181 a pure-Python function in 99.9% cases.
182 */
183 int has_it = PySet_Contains(
184 iscoroutine_typecache, (PyObject*) Py_TYPE(coro));
185 if (has_it == 0) {
186 /* type(coro) is not in iscoroutine_typecache */
187 return _is_coroutine(coro);
188 }
189
Miss Islington (bot)e86db342018-02-03 17:41:43 -0800190 /* either an error has occurred or
Yury Selivanova9d7e552017-12-19 07:18:45 -0500191 type(coro) is in iscoroutine_typecache
192 */
193 return has_it;
194}
195
196
Yury Selivanovca9b36c2017-12-23 15:04:15 -0500197static PyObject *
198get_future_loop(PyObject *fut)
199{
200 /* Implementation of `asyncio.futures._get_loop` */
201
202 _Py_IDENTIFIER(get_loop);
203 _Py_IDENTIFIER(_loop);
204
205 if (Future_CheckExact(fut) || Task_CheckExact(fut)) {
206 PyObject *loop = ((FutureObj *)fut)->fut_loop;
207 Py_INCREF(loop);
208 return loop;
209 }
210
211 PyObject *getloop = _PyObject_GetAttrId(fut, &PyId_get_loop);
212 if (getloop != NULL) {
213 PyObject *res = _PyObject_CallNoArg(getloop);
214 Py_DECREF(getloop);
215 return res;
216 }
217
Yury Selivanov719ccbc2017-12-23 16:29:26 -0500218 PyErr_Clear();
Yury Selivanovca9b36c2017-12-23 15:04:15 -0500219 return _PyObject_GetAttrId(fut, &PyId__loop);
220}
221
222
Yury Selivanova9d7e552017-12-19 07:18:45 -0500223static int
Yury Selivanova70232f2017-12-13 14:49:42 -0500224get_running_loop(PyObject **loop)
225{
Yury Selivanov9d411c12018-01-23 15:10:03 -0500226 PyObject *rl;
Yury Selivanova70232f2017-12-13 14:49:42 -0500227
Yury Selivanov9d411c12018-01-23 15:10:03 -0500228 PyThreadState *ts = PyThreadState_Get();
229 if (ts->id == cached_running_holder_tsid && cached_running_holder != NULL) {
230 // Fast path, check the cache.
231 rl = cached_running_holder; // borrowed
232 }
233 else {
234 if (ts->dict == NULL) {
235 goto not_found;
236 }
237
238 rl = _PyDict_GetItemIdWithError(
239 ts->dict, &PyId___asyncio_running_event_loop__); // borrowed
240 if (rl == NULL) {
241 if (PyErr_Occurred()) {
242 goto error;
243 }
244 else {
245 goto not_found;
246 }
247 }
248
249 cached_running_holder = rl; // borrowed
250 cached_running_holder_tsid = ts->id;
Yury Selivanova70232f2017-12-13 14:49:42 -0500251 }
252
Yury Selivanov9d411c12018-01-23 15:10:03 -0500253 assert(Py_TYPE(rl) == &PyRunningLoopHolder_Type);
254 PyObject *running_loop = ((PyRunningLoopHolder *)rl)->rl_loop;
Yury Selivanova70232f2017-12-13 14:49:42 -0500255
256 if (running_loop == Py_None) {
257 goto not_found;
258 }
259
Yury Selivanov9d411c12018-01-23 15:10:03 -0500260#if defined(HAVE_GETPID) && !defined(MS_WINDOWS)
261 /* On Windows there is no getpid, but there is also no os.fork(),
262 so there is no need for this check.
263 */
264 if (getpid() != ((PyRunningLoopHolder *)rl)->rl_pid) {
265 goto not_found;
Yury Selivanova70232f2017-12-13 14:49:42 -0500266 }
Yury Selivanov9d411c12018-01-23 15:10:03 -0500267#endif
Yury Selivanova70232f2017-12-13 14:49:42 -0500268
Yury Selivanov9d411c12018-01-23 15:10:03 -0500269 Py_INCREF(running_loop);
270 *loop = running_loop;
271 return 0;
Yury Selivanova70232f2017-12-13 14:49:42 -0500272
273not_found:
274 *loop = NULL;
275 return 0;
276
Yury Selivanova70232f2017-12-13 14:49:42 -0500277error:
278 *loop = NULL;
279 return -1;
280}
281
282
283static int
284set_running_loop(PyObject *loop)
285{
Yury Selivanov9d411c12018-01-23 15:10:03 -0500286 cached_running_holder = NULL;
287 cached_running_holder_tsid = 0;
Yury Selivanova70232f2017-12-13 14:49:42 -0500288
Yury Selivanov9d411c12018-01-23 15:10:03 -0500289 PyObject *ts_dict = PyThreadState_GetDict(); // borrowed
Yury Selivanova70232f2017-12-13 14:49:42 -0500290 if (ts_dict == NULL) {
291 PyErr_SetString(
292 PyExc_RuntimeError, "thread-local storage is not available");
293 return -1;
294 }
295
Yury Selivanov9d411c12018-01-23 15:10:03 -0500296 PyRunningLoopHolder *rl = new_running_loop_holder(loop);
297 if (rl == NULL) {
Yury Selivanova70232f2017-12-13 14:49:42 -0500298 return -1;
299 }
300
Yury Selivanova70232f2017-12-13 14:49:42 -0500301 if (_PyDict_SetItemId(
Yury Selivanov9d411c12018-01-23 15:10:03 -0500302 ts_dict, &PyId___asyncio_running_event_loop__, (PyObject *)rl) < 0)
303 {
304 Py_DECREF(rl); // will cleanup loop & current_pid
Yury Selivanova70232f2017-12-13 14:49:42 -0500305 return -1;
306 }
Yury Selivanov9d411c12018-01-23 15:10:03 -0500307 Py_DECREF(rl);
Yury Selivanova70232f2017-12-13 14:49:42 -0500308
309 return 0;
310}
311
312
313static PyObject *
314get_event_loop(void)
315{
316 PyObject *loop;
317 PyObject *policy;
318
319 if (get_running_loop(&loop)) {
320 return NULL;
321 }
322 if (loop != NULL) {
323 return loop;
324 }
325
326 policy = _PyObject_CallNoArg(asyncio_get_event_loop_policy);
327 if (policy == NULL) {
328 return NULL;
329 }
330
331 loop = _PyObject_CallMethodId(policy, &PyId_get_event_loop, NULL);
332 Py_DECREF(policy);
333 return loop;
334}
335
336
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900337static int
Yury Selivanovf23746a2018-01-22 19:11:18 -0500338call_soon(PyObject *loop, PyObject *func, PyObject *arg, PyContext *ctx)
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500339{
340 PyObject *handle;
Yury Selivanovf23746a2018-01-22 19:11:18 -0500341 PyObject *stack[3];
342 Py_ssize_t nargs;
343
344 if (ctx == NULL) {
345 handle = _PyObject_CallMethodIdObjArgs(
346 loop, &PyId_call_soon, func, arg, NULL);
347 }
348 else {
349 /* Use FASTCALL to pass a keyword-only argument to call_soon */
350
351 PyObject *callable = _PyObject_GetAttrId(loop, &PyId_call_soon);
352 if (callable == NULL) {
353 return -1;
354 }
355
356 /* All refs in 'stack' are borrowed. */
357 nargs = 1;
358 stack[0] = func;
359 if (arg != NULL) {
360 stack[1] = arg;
361 nargs++;
362 }
363 stack[nargs] = (PyObject *)ctx;
364
365 handle = _PyObject_FastCallKeywords(
366 callable, stack, nargs, context_kwname);
367 Py_DECREF(callable);
368 }
369
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500370 if (handle == NULL) {
371 return -1;
372 }
373 Py_DECREF(handle);
374 return 0;
375}
376
377
378static inline int
379future_is_alive(FutureObj *fut)
380{
381 return fut->fut_loop != NULL;
382}
383
384
385static inline int
386future_ensure_alive(FutureObj *fut)
387{
388 if (!future_is_alive(fut)) {
389 PyErr_SetString(PyExc_RuntimeError,
390 "Future object is not initialized.");
391 return -1;
392 }
393 return 0;
394}
395
396
397#define ENSURE_FUTURE_ALIVE(fut) \
398 do { \
399 assert(Future_Check(fut) || Task_Check(fut)); \
400 if (future_ensure_alive((FutureObj*)fut)) { \
401 return NULL; \
402 } \
403 } while(0);
404
405
406static int
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400407future_schedule_callbacks(FutureObj *fut)
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900408{
409 Py_ssize_t len;
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500410 Py_ssize_t i;
411
412 if (fut->fut_callback0 != NULL) {
413 /* There's a 1st callback */
414
415 int ret = call_soon(
Yury Selivanovf23746a2018-01-22 19:11:18 -0500416 fut->fut_loop, fut->fut_callback0,
417 (PyObject *)fut, fut->fut_context0);
418
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500419 Py_CLEAR(fut->fut_callback0);
Yury Selivanovf23746a2018-01-22 19:11:18 -0500420 Py_CLEAR(fut->fut_context0);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500421 if (ret) {
422 /* If an error occurs in pure-Python implementation,
423 all callbacks are cleared. */
424 Py_CLEAR(fut->fut_callbacks);
425 return ret;
426 }
427
428 /* we called the first callback, now try calling
429 callbacks from the 'fut_callbacks' list. */
430 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900431
432 if (fut->fut_callbacks == NULL) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500433 /* No more callbacks, return. */
434 return 0;
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900435 }
436
437 len = PyList_GET_SIZE(fut->fut_callbacks);
438 if (len == 0) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500439 /* The list of callbacks was empty; clear it and return. */
440 Py_CLEAR(fut->fut_callbacks);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900441 return 0;
442 }
443
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900444 for (i = 0; i < len; i++) {
Yury Selivanovf23746a2018-01-22 19:11:18 -0500445 PyObject *cb_tup = PyList_GET_ITEM(fut->fut_callbacks, i);
446 PyObject *cb = PyTuple_GET_ITEM(cb_tup, 0);
447 PyObject *ctx = PyTuple_GET_ITEM(cb_tup, 1);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900448
Yury Selivanovf23746a2018-01-22 19:11:18 -0500449 if (call_soon(fut->fut_loop, cb, (PyObject *)fut, (PyContext *)ctx)) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500450 /* If an error occurs in pure-Python implementation,
451 all callbacks are cleared. */
452 Py_CLEAR(fut->fut_callbacks);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900453 return -1;
454 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900455 }
456
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500457 Py_CLEAR(fut->fut_callbacks);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900458 return 0;
459}
460
461static int
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400462future_init(FutureObj *fut, PyObject *loop)
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900463{
Serhiy Storchakabca49392017-09-03 08:10:14 +0300464 PyObject *res;
465 int is_true;
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900466 _Py_IDENTIFIER(get_debug);
467
Serhiy Storchakabca49392017-09-03 08:10:14 +0300468 if (loop == Py_None) {
Yury Selivanova70232f2017-12-13 14:49:42 -0500469 loop = get_event_loop();
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900470 if (loop == NULL) {
471 return -1;
472 }
473 }
474 else {
475 Py_INCREF(loop);
476 }
Serhiy Storchakabca49392017-09-03 08:10:14 +0300477 Py_XSETREF(fut->fut_loop, loop);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900478
Victor Stinnerf94d1ee2016-10-29 09:05:39 +0200479 res = _PyObject_CallMethodId(fut->fut_loop, &PyId_get_debug, NULL);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900480 if (res == NULL) {
481 return -1;
482 }
Serhiy Storchakabca49392017-09-03 08:10:14 +0300483 is_true = PyObject_IsTrue(res);
484 Py_DECREF(res);
485 if (is_true < 0) {
486 return -1;
487 }
488 if (is_true) {
489 Py_XSETREF(fut->fut_source_tb, _PyObject_CallNoArg(traceback_extract_stack));
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900490 if (fut->fut_source_tb == NULL) {
491 return -1;
492 }
493 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900494
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500495 fut->fut_callback0 = NULL;
Yury Selivanovf23746a2018-01-22 19:11:18 -0500496 fut->fut_context0 = NULL;
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500497 fut->fut_callbacks = NULL;
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400498
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900499 return 0;
500}
501
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900502static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400503future_set_result(FutureObj *fut, PyObject *res)
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900504{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500505 if (future_ensure_alive(fut)) {
506 return NULL;
507 }
508
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900509 if (fut->fut_state != STATE_PENDING) {
510 PyErr_SetString(asyncio_InvalidStateError, "invalid state");
511 return NULL;
512 }
513
Serhiy Storchakabca49392017-09-03 08:10:14 +0300514 assert(!fut->fut_result);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900515 Py_INCREF(res);
516 fut->fut_result = res;
517 fut->fut_state = STATE_FINISHED;
518
Yury Selivanov22feeb82018-01-24 11:31:01 -0500519 if (future_schedule_callbacks(fut) == -1) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900520 return NULL;
521 }
522 Py_RETURN_NONE;
523}
524
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900525static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400526future_set_exception(FutureObj *fut, PyObject *exc)
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900527{
528 PyObject *exc_val = NULL;
529
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900530 if (fut->fut_state != STATE_PENDING) {
531 PyErr_SetString(asyncio_InvalidStateError, "invalid state");
532 return NULL;
533 }
534
535 if (PyExceptionClass_Check(exc)) {
Victor Stinnera5ed5f02016-12-06 18:45:50 +0100536 exc_val = _PyObject_CallNoArg(exc);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900537 if (exc_val == NULL) {
538 return NULL;
539 }
Serhiy Storchakabca49392017-09-03 08:10:14 +0300540 if (fut->fut_state != STATE_PENDING) {
541 Py_DECREF(exc_val);
542 PyErr_SetString(asyncio_InvalidStateError, "invalid state");
543 return NULL;
544 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900545 }
546 else {
547 exc_val = exc;
548 Py_INCREF(exc_val);
549 }
550 if (!PyExceptionInstance_Check(exc_val)) {
551 Py_DECREF(exc_val);
552 PyErr_SetString(PyExc_TypeError, "invalid exception object");
553 return NULL;
554 }
555 if ((PyObject*)Py_TYPE(exc_val) == PyExc_StopIteration) {
556 Py_DECREF(exc_val);
557 PyErr_SetString(PyExc_TypeError,
558 "StopIteration interacts badly with generators "
559 "and cannot be raised into a Future");
560 return NULL;
561 }
562
Serhiy Storchakabca49392017-09-03 08:10:14 +0300563 assert(!fut->fut_exception);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900564 fut->fut_exception = exc_val;
565 fut->fut_state = STATE_FINISHED;
566
Yury Selivanov22feeb82018-01-24 11:31:01 -0500567 if (future_schedule_callbacks(fut) == -1) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900568 return NULL;
569 }
570
571 fut->fut_log_tb = 1;
572 Py_RETURN_NONE;
573}
574
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400575static int
576future_get_result(FutureObj *fut, PyObject **result)
577{
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400578 if (fut->fut_state == STATE_CANCELLED) {
Serhiy Storchakabca49392017-09-03 08:10:14 +0300579 PyErr_SetNone(asyncio_CancelledError);
580 return -1;
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400581 }
582
583 if (fut->fut_state != STATE_FINISHED) {
Serhiy Storchakabca49392017-09-03 08:10:14 +0300584 PyErr_SetString(asyncio_InvalidStateError, "Result is not set.");
585 return -1;
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400586 }
587
588 fut->fut_log_tb = 0;
589 if (fut->fut_exception != NULL) {
590 Py_INCREF(fut->fut_exception);
591 *result = fut->fut_exception;
592 return 1;
593 }
594
595 Py_INCREF(fut->fut_result);
596 *result = fut->fut_result;
597 return 0;
598}
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900599
600static PyObject *
Yury Selivanovf23746a2018-01-22 19:11:18 -0500601future_add_done_callback(FutureObj *fut, PyObject *arg, PyContext *ctx)
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900602{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500603 if (!future_is_alive(fut)) {
604 PyErr_SetString(PyExc_RuntimeError, "uninitialized Future object");
605 return NULL;
606 }
607
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900608 if (fut->fut_state != STATE_PENDING) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500609 /* The future is done/cancelled, so schedule the callback
610 right away. */
Yury Selivanovf23746a2018-01-22 19:11:18 -0500611 if (call_soon(fut->fut_loop, arg, (PyObject*) fut, ctx)) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900612 return NULL;
613 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900614 }
615 else {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500616 /* The future is pending, add a callback.
617
618 Callbacks in the future object are stored as follows:
619
620 callback0 -- a pointer to the first callback
621 callbacks -- a list of 2nd, 3rd, ... callbacks
622
623 Invariants:
624
625 * callbacks != NULL:
626 There are some callbacks in in the list. Just
627 add the new callback to it.
628
629 * callbacks == NULL and callback0 == NULL:
630 This is the first callback. Set it to callback0.
631
632 * callbacks == NULL and callback0 != NULL:
633 This is a second callback. Initialize callbacks
634 with a new list and add the new callback to it.
635 */
636
Yury Selivanovf23746a2018-01-22 19:11:18 -0500637 if (fut->fut_callbacks == NULL && fut->fut_callback0 == NULL) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500638 Py_INCREF(arg);
639 fut->fut_callback0 = arg;
Yury Selivanovf23746a2018-01-22 19:11:18 -0500640 Py_INCREF(ctx);
641 fut->fut_context0 = ctx;
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500642 }
643 else {
Yury Selivanovf23746a2018-01-22 19:11:18 -0500644 PyObject *tup = PyTuple_New(2);
645 if (tup == NULL) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500646 return NULL;
647 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500648 Py_INCREF(arg);
Yury Selivanovf23746a2018-01-22 19:11:18 -0500649 PyTuple_SET_ITEM(tup, 0, arg);
650 Py_INCREF(ctx);
651 PyTuple_SET_ITEM(tup, 1, (PyObject *)ctx);
652
653 if (fut->fut_callbacks != NULL) {
654 int err = PyList_Append(fut->fut_callbacks, tup);
655 if (err) {
656 Py_DECREF(tup);
657 return NULL;
658 }
659 Py_DECREF(tup);
660 }
661 else {
662 fut->fut_callbacks = PyList_New(1);
663 if (fut->fut_callbacks == NULL) {
664 return NULL;
665 }
666
667 PyList_SET_ITEM(fut->fut_callbacks, 0, tup); /* borrow */
668 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900669 }
670 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500671
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900672 Py_RETURN_NONE;
673}
674
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400675static PyObject *
676future_cancel(FutureObj *fut)
677{
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +0000678 fut->fut_log_tb = 0;
679
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400680 if (fut->fut_state != STATE_PENDING) {
681 Py_RETURN_FALSE;
682 }
683 fut->fut_state = STATE_CANCELLED;
684
Yury Selivanov22feeb82018-01-24 11:31:01 -0500685 if (future_schedule_callbacks(fut) == -1) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400686 return NULL;
687 }
688
689 Py_RETURN_TRUE;
690}
691
692/*[clinic input]
693_asyncio.Future.__init__
694
695 *
Serhiy Storchakabca49392017-09-03 08:10:14 +0300696 loop: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400697
698This class is *almost* compatible with concurrent.futures.Future.
699
700 Differences:
701
702 - result() and exception() do not take a timeout argument and
703 raise an exception when the future isn't done yet.
704
705 - Callbacks registered with add_done_callback() are always called
706 via the event loop's call_soon_threadsafe().
707
708 - This class is not compatible with the wait() and as_completed()
709 methods in the concurrent.futures package.
710[clinic start generated code]*/
711
712static int
713_asyncio_Future___init___impl(FutureObj *self, PyObject *loop)
Serhiy Storchakabca49392017-09-03 08:10:14 +0300714/*[clinic end generated code: output=9ed75799eaccb5d6 input=89af317082bc0bf8]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400715
716{
717 return future_init(self, loop);
718}
719
720static int
721FutureObj_clear(FutureObj *fut)
722{
723 Py_CLEAR(fut->fut_loop);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500724 Py_CLEAR(fut->fut_callback0);
Yury Selivanovf23746a2018-01-22 19:11:18 -0500725 Py_CLEAR(fut->fut_context0);
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400726 Py_CLEAR(fut->fut_callbacks);
727 Py_CLEAR(fut->fut_result);
728 Py_CLEAR(fut->fut_exception);
729 Py_CLEAR(fut->fut_source_tb);
730 Py_CLEAR(fut->dict);
731 return 0;
732}
733
734static int
735FutureObj_traverse(FutureObj *fut, visitproc visit, void *arg)
736{
737 Py_VISIT(fut->fut_loop);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500738 Py_VISIT(fut->fut_callback0);
Yury Selivanovf23746a2018-01-22 19:11:18 -0500739 Py_VISIT(fut->fut_context0);
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400740 Py_VISIT(fut->fut_callbacks);
741 Py_VISIT(fut->fut_result);
742 Py_VISIT(fut->fut_exception);
743 Py_VISIT(fut->fut_source_tb);
744 Py_VISIT(fut->dict);
745 return 0;
746}
747
748/*[clinic input]
749_asyncio.Future.result
750
751Return the result this future represents.
752
753If the future has been cancelled, raises CancelledError. If the
754future's result isn't yet available, raises InvalidStateError. If
755the future is done and has an exception set, this exception is raised.
756[clinic start generated code]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900757
758static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400759_asyncio_Future_result_impl(FutureObj *self)
760/*[clinic end generated code: output=f35f940936a4b1e5 input=49ecf9cf5ec50dc5]*/
761{
762 PyObject *result;
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500763
764 if (!future_is_alive(self)) {
765 PyErr_SetString(asyncio_InvalidStateError,
766 "Future object is not initialized.");
767 return NULL;
768 }
769
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400770 int res = future_get_result(self, &result);
771
772 if (res == -1) {
773 return NULL;
774 }
775
776 if (res == 0) {
777 return result;
778 }
779
780 assert(res == 1);
781
782 PyErr_SetObject(PyExceptionInstance_Class(result), result);
783 Py_DECREF(result);
784 return NULL;
785}
786
787/*[clinic input]
788_asyncio.Future.exception
789
790Return the exception that was set on this future.
791
792The exception (or None if no exception was set) is returned only if
793the future is done. If the future has been cancelled, raises
794CancelledError. If the future isn't done yet, raises
795InvalidStateError.
796[clinic start generated code]*/
797
798static PyObject *
799_asyncio_Future_exception_impl(FutureObj *self)
800/*[clinic end generated code: output=88b20d4f855e0710 input=733547a70c841c68]*/
801{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500802 if (!future_is_alive(self)) {
803 PyErr_SetString(asyncio_InvalidStateError,
804 "Future object is not initialized.");
805 return NULL;
806 }
807
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400808 if (self->fut_state == STATE_CANCELLED) {
Serhiy Storchakabca49392017-09-03 08:10:14 +0300809 PyErr_SetNone(asyncio_CancelledError);
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400810 return NULL;
811 }
812
813 if (self->fut_state != STATE_FINISHED) {
Serhiy Storchakabca49392017-09-03 08:10:14 +0300814 PyErr_SetString(asyncio_InvalidStateError, "Exception is not set.");
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400815 return NULL;
816 }
817
818 if (self->fut_exception != NULL) {
819 self->fut_log_tb = 0;
820 Py_INCREF(self->fut_exception);
821 return self->fut_exception;
822 }
823
824 Py_RETURN_NONE;
825}
826
827/*[clinic input]
828_asyncio.Future.set_result
829
Yury Selivanov0cf16f92017-12-25 10:48:15 -0500830 result: object
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400831 /
832
833Mark the future done and set its result.
834
835If the future is already done when this method is called, raises
836InvalidStateError.
837[clinic start generated code]*/
838
839static PyObject *
Yury Selivanov0cf16f92017-12-25 10:48:15 -0500840_asyncio_Future_set_result(FutureObj *self, PyObject *result)
841/*[clinic end generated code: output=1ec2e6bcccd6f2ce input=8b75172c2a7b05f1]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400842{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500843 ENSURE_FUTURE_ALIVE(self)
Yury Selivanov0cf16f92017-12-25 10:48:15 -0500844 return future_set_result(self, result);
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400845}
846
847/*[clinic input]
848_asyncio.Future.set_exception
849
Serhiy Storchakabca49392017-09-03 08:10:14 +0300850 exception: object
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400851 /
852
853Mark the future done and set an exception.
854
855If the future is already done when this method is called, raises
856InvalidStateError.
857[clinic start generated code]*/
858
859static PyObject *
860_asyncio_Future_set_exception(FutureObj *self, PyObject *exception)
Serhiy Storchakabca49392017-09-03 08:10:14 +0300861/*[clinic end generated code: output=f1c1b0cd321be360 input=e45b7d7aa71cc66d]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400862{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500863 ENSURE_FUTURE_ALIVE(self)
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400864 return future_set_exception(self, exception);
865}
866
867/*[clinic input]
868_asyncio.Future.add_done_callback
869
Serhiy Storchakabca49392017-09-03 08:10:14 +0300870 fn: object
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400871 /
Yury Selivanovf23746a2018-01-22 19:11:18 -0500872 *
873 context: object = NULL
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400874
875Add a callback to be run when the future becomes done.
876
877The callback is called with a single argument - the future object. If
878the future is already done when this is called, the callback is
879scheduled with call_soon.
880[clinic start generated code]*/
881
882static PyObject *
Yury Selivanovf23746a2018-01-22 19:11:18 -0500883_asyncio_Future_add_done_callback_impl(FutureObj *self, PyObject *fn,
884 PyObject *context)
885/*[clinic end generated code: output=7ce635bbc9554c1e input=15ab0693a96e9533]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400886{
Yury Selivanovf23746a2018-01-22 19:11:18 -0500887 if (context == NULL) {
888 context = (PyObject *)PyContext_CopyCurrent();
889 if (context == NULL) {
890 return NULL;
891 }
892 PyObject *res = future_add_done_callback(
893 self, fn, (PyContext *)context);
894 Py_DECREF(context);
895 return res;
896 }
897 return future_add_done_callback(self, fn, (PyContext *)context);
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400898}
899
900/*[clinic input]
901_asyncio.Future.remove_done_callback
902
Serhiy Storchakabca49392017-09-03 08:10:14 +0300903 fn: object
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400904 /
905
906Remove all instances of a callback from the "call when done" list.
907
908Returns the number of callbacks removed.
909[clinic start generated code]*/
910
911static PyObject *
912_asyncio_Future_remove_done_callback(FutureObj *self, PyObject *fn)
Serhiy Storchakabca49392017-09-03 08:10:14 +0300913/*[clinic end generated code: output=5ab1fb52b24ef31f input=0a43280a149d505b]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900914{
915 PyObject *newlist;
916 Py_ssize_t len, i, j=0;
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500917 Py_ssize_t cleared_callback0 = 0;
918
919 ENSURE_FUTURE_ALIVE(self)
920
921 if (self->fut_callback0 != NULL) {
922 int cmp = PyObject_RichCompareBool(fn, self->fut_callback0, Py_EQ);
923 if (cmp == -1) {
924 return NULL;
925 }
926 if (cmp == 1) {
927 /* callback0 == fn */
928 Py_CLEAR(self->fut_callback0);
Yury Selivanovf23746a2018-01-22 19:11:18 -0500929 Py_CLEAR(self->fut_context0);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500930 cleared_callback0 = 1;
931 }
932 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900933
Serhiy Storchakabca49392017-09-03 08:10:14 +0300934 if (self->fut_callbacks == NULL) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500935 return PyLong_FromSsize_t(cleared_callback0);
Serhiy Storchakabca49392017-09-03 08:10:14 +0300936 }
937
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400938 len = PyList_GET_SIZE(self->fut_callbacks);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900939 if (len == 0) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500940 Py_CLEAR(self->fut_callbacks);
941 return PyLong_FromSsize_t(cleared_callback0);
942 }
943
944 if (len == 1) {
Yury Selivanovf23746a2018-01-22 19:11:18 -0500945 PyObject *cb_tup = PyList_GET_ITEM(self->fut_callbacks, 0);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500946 int cmp = PyObject_RichCompareBool(
Yury Selivanovf23746a2018-01-22 19:11:18 -0500947 fn, PyTuple_GET_ITEM(cb_tup, 0), Py_EQ);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500948 if (cmp == -1) {
949 return NULL;
950 }
951 if (cmp == 1) {
952 /* callbacks[0] == fn */
953 Py_CLEAR(self->fut_callbacks);
954 return PyLong_FromSsize_t(1 + cleared_callback0);
955 }
956 /* callbacks[0] != fn and len(callbacks) == 1 */
957 return PyLong_FromSsize_t(cleared_callback0);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900958 }
959
960 newlist = PyList_New(len);
961 if (newlist == NULL) {
962 return NULL;
963 }
964
Yury Selivanov84af9032017-03-02 23:46:56 -0500965 for (i = 0; i < PyList_GET_SIZE(self->fut_callbacks); i++) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900966 int ret;
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400967 PyObject *item = PyList_GET_ITEM(self->fut_callbacks, i);
Serhiy Storchakabca49392017-09-03 08:10:14 +0300968 Py_INCREF(item);
Yury Selivanovf23746a2018-01-22 19:11:18 -0500969 ret = PyObject_RichCompareBool(fn, PyTuple_GET_ITEM(item, 0), Py_EQ);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900970 if (ret == 0) {
Yury Selivanov833a3b02017-07-05 13:32:03 -0400971 if (j < len) {
Yury Selivanov833a3b02017-07-05 13:32:03 -0400972 PyList_SET_ITEM(newlist, j, item);
973 j++;
Serhiy Storchakabca49392017-09-03 08:10:14 +0300974 continue;
Yury Selivanov833a3b02017-07-05 13:32:03 -0400975 }
Serhiy Storchakabca49392017-09-03 08:10:14 +0300976 ret = PyList_Append(newlist, item);
977 }
978 Py_DECREF(item);
979 if (ret < 0) {
980 goto fail;
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900981 }
982 }
983
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500984 if (j == 0) {
985 Py_CLEAR(self->fut_callbacks);
986 Py_DECREF(newlist);
987 return PyLong_FromSsize_t(len + cleared_callback0);
988 }
989
Serhiy Storchakabca49392017-09-03 08:10:14 +0300990 if (j < len) {
991 Py_SIZE(newlist) = j;
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900992 }
Serhiy Storchakabca49392017-09-03 08:10:14 +0300993 j = PyList_GET_SIZE(newlist);
994 len = PyList_GET_SIZE(self->fut_callbacks);
995 if (j != len) {
996 if (PyList_SetSlice(self->fut_callbacks, 0, len, newlist) < 0) {
997 goto fail;
998 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900999 }
1000 Py_DECREF(newlist);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001001 return PyLong_FromSsize_t(len - j + cleared_callback0);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001002
1003fail:
1004 Py_DECREF(newlist);
1005 return NULL;
1006}
1007
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001008/*[clinic input]
1009_asyncio.Future.cancel
1010
1011Cancel the future and schedule callbacks.
1012
1013If the future is already done or cancelled, return False. Otherwise,
1014change the future's state to cancelled, schedule the callbacks and
1015return True.
1016[clinic start generated code]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001017
1018static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001019_asyncio_Future_cancel_impl(FutureObj *self)
1020/*[clinic end generated code: output=e45b932ba8bd68a1 input=515709a127995109]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001021{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001022 ENSURE_FUTURE_ALIVE(self)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001023 return future_cancel(self);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001024}
1025
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001026/*[clinic input]
1027_asyncio.Future.cancelled
1028
1029Return True if the future was cancelled.
1030[clinic start generated code]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001031
1032static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001033_asyncio_Future_cancelled_impl(FutureObj *self)
1034/*[clinic end generated code: output=145197ced586357d input=943ab8b7b7b17e45]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001035{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001036 if (future_is_alive(self) && self->fut_state == STATE_CANCELLED) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001037 Py_RETURN_TRUE;
1038 }
1039 else {
1040 Py_RETURN_FALSE;
1041 }
1042}
1043
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001044/*[clinic input]
1045_asyncio.Future.done
1046
1047Return True if the future is done.
1048
1049Done means either that a result / exception are available, or that the
1050future was cancelled.
1051[clinic start generated code]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001052
1053static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001054_asyncio_Future_done_impl(FutureObj *self)
1055/*[clinic end generated code: output=244c5ac351145096 input=28d7b23fdb65d2ac]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001056{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001057 if (!future_is_alive(self) || self->fut_state == STATE_PENDING) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001058 Py_RETURN_FALSE;
1059 }
1060 else {
1061 Py_RETURN_TRUE;
1062 }
1063}
1064
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001065/*[clinic input]
1066_asyncio.Future.get_loop
1067
1068Return the event loop the Future is bound to.
1069[clinic start generated code]*/
1070
1071static PyObject *
1072_asyncio_Future_get_loop_impl(FutureObj *self)
1073/*[clinic end generated code: output=119b6ea0c9816c3f input=cba48c2136c79d1f]*/
1074{
1075 Py_INCREF(self->fut_loop);
1076 return self->fut_loop;
1077}
1078
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001079static PyObject *
1080FutureObj_get_blocking(FutureObj *fut)
1081{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001082 if (future_is_alive(fut) && fut->fut_blocking) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001083 Py_RETURN_TRUE;
1084 }
1085 else {
1086 Py_RETURN_FALSE;
1087 }
1088}
1089
1090static int
1091FutureObj_set_blocking(FutureObj *fut, PyObject *val)
1092{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001093 if (future_ensure_alive(fut)) {
1094 return -1;
1095 }
1096
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001097 int is_true = PyObject_IsTrue(val);
1098 if (is_true < 0) {
1099 return -1;
1100 }
1101 fut->fut_blocking = is_true;
1102 return 0;
1103}
1104
1105static PyObject *
1106FutureObj_get_log_traceback(FutureObj *fut)
1107{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001108 ENSURE_FUTURE_ALIVE(fut)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001109 if (fut->fut_log_tb) {
1110 Py_RETURN_TRUE;
1111 }
1112 else {
1113 Py_RETURN_FALSE;
1114 }
1115}
1116
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +00001117static int
1118FutureObj_set_log_traceback(FutureObj *fut, PyObject *val)
1119{
1120 int is_true = PyObject_IsTrue(val);
1121 if (is_true < 0) {
1122 return -1;
1123 }
Yury Selivanove0aef4f2017-12-25 16:16:10 -05001124 if (is_true) {
1125 PyErr_SetString(PyExc_ValueError,
1126 "_log_traceback can only be set to False");
1127 return -1;
1128 }
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +00001129 fut->fut_log_tb = is_true;
1130 return 0;
1131}
1132
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001133static PyObject *
1134FutureObj_get_loop(FutureObj *fut)
1135{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001136 if (!future_is_alive(fut)) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001137 Py_RETURN_NONE;
1138 }
1139 Py_INCREF(fut->fut_loop);
1140 return fut->fut_loop;
1141}
1142
1143static PyObject *
1144FutureObj_get_callbacks(FutureObj *fut)
1145{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001146 Py_ssize_t i;
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001147
1148 ENSURE_FUTURE_ALIVE(fut)
1149
Yury Selivanovf23746a2018-01-22 19:11:18 -05001150 if (fut->fut_callback0 == NULL) {
1151 if (fut->fut_callbacks == NULL) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001152 Py_RETURN_NONE;
1153 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001154
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001155 Py_INCREF(fut->fut_callbacks);
1156 return fut->fut_callbacks;
1157 }
1158
Yury Selivanovf23746a2018-01-22 19:11:18 -05001159 Py_ssize_t len = 1;
1160 if (fut->fut_callbacks != NULL) {
1161 len += PyList_GET_SIZE(fut->fut_callbacks);
1162 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001163
Yury Selivanovf23746a2018-01-22 19:11:18 -05001164
1165 PyObject *new_list = PyList_New(len);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001166 if (new_list == NULL) {
1167 return NULL;
1168 }
1169
Yury Selivanovf23746a2018-01-22 19:11:18 -05001170 PyObject *tup0 = PyTuple_New(2);
1171 if (tup0 == NULL) {
1172 Py_DECREF(new_list);
1173 return NULL;
1174 }
1175
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001176 Py_INCREF(fut->fut_callback0);
Yury Selivanovf23746a2018-01-22 19:11:18 -05001177 PyTuple_SET_ITEM(tup0, 0, fut->fut_callback0);
1178 assert(fut->fut_context0 != NULL);
1179 Py_INCREF(fut->fut_context0);
1180 PyTuple_SET_ITEM(tup0, 1, (PyObject *)fut->fut_context0);
1181
1182 PyList_SET_ITEM(new_list, 0, tup0);
1183
1184 if (fut->fut_callbacks != NULL) {
1185 for (i = 0; i < PyList_GET_SIZE(fut->fut_callbacks); i++) {
1186 PyObject *cb = PyList_GET_ITEM(fut->fut_callbacks, i);
1187 Py_INCREF(cb);
1188 PyList_SET_ITEM(new_list, i + 1, cb);
1189 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001190 }
1191
1192 return new_list;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001193}
1194
1195static PyObject *
1196FutureObj_get_result(FutureObj *fut)
1197{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001198 ENSURE_FUTURE_ALIVE(fut)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001199 if (fut->fut_result == NULL) {
1200 Py_RETURN_NONE;
1201 }
1202 Py_INCREF(fut->fut_result);
1203 return fut->fut_result;
1204}
1205
1206static PyObject *
1207FutureObj_get_exception(FutureObj *fut)
1208{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001209 ENSURE_FUTURE_ALIVE(fut)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001210 if (fut->fut_exception == NULL) {
1211 Py_RETURN_NONE;
1212 }
1213 Py_INCREF(fut->fut_exception);
1214 return fut->fut_exception;
1215}
1216
1217static PyObject *
1218FutureObj_get_source_traceback(FutureObj *fut)
1219{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001220 if (!future_is_alive(fut) || fut->fut_source_tb == NULL) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001221 Py_RETURN_NONE;
1222 }
1223 Py_INCREF(fut->fut_source_tb);
1224 return fut->fut_source_tb;
1225}
1226
1227static PyObject *
1228FutureObj_get_state(FutureObj *fut)
1229{
1230 _Py_IDENTIFIER(PENDING);
1231 _Py_IDENTIFIER(CANCELLED);
1232 _Py_IDENTIFIER(FINISHED);
1233 PyObject *ret = NULL;
1234
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001235 ENSURE_FUTURE_ALIVE(fut)
1236
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001237 switch (fut->fut_state) {
1238 case STATE_PENDING:
1239 ret = _PyUnicode_FromId(&PyId_PENDING);
1240 break;
1241 case STATE_CANCELLED:
1242 ret = _PyUnicode_FromId(&PyId_CANCELLED);
1243 break;
1244 case STATE_FINISHED:
1245 ret = _PyUnicode_FromId(&PyId_FINISHED);
1246 break;
1247 default:
1248 assert (0);
1249 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03001250 Py_XINCREF(ret);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001251 return ret;
1252}
1253
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001254/*[clinic input]
1255_asyncio.Future._repr_info
1256[clinic start generated code]*/
1257
1258static PyObject *
1259_asyncio_Future__repr_info_impl(FutureObj *self)
1260/*[clinic end generated code: output=fa69e901bd176cfb input=f21504d8e2ae1ca2]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001261{
Victor Stinnerde4ae3d2016-12-04 22:59:09 +01001262 return PyObject_CallFunctionObjArgs(
1263 asyncio_future_repr_info_func, self, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001264}
1265
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001266static PyObject *
1267FutureObj_repr(FutureObj *fut)
1268{
1269 _Py_IDENTIFIER(_repr_info);
1270
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001271 ENSURE_FUTURE_ALIVE(fut)
1272
Serhiy Storchakabca49392017-09-03 08:10:14 +03001273 PyObject *rinfo = _PyObject_CallMethodIdObjArgs((PyObject*)fut,
1274 &PyId__repr_info,
1275 NULL);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001276 if (rinfo == NULL) {
1277 return NULL;
1278 }
1279
Serhiy Storchakabca49392017-09-03 08:10:14 +03001280 PyObject *rinfo_s = PyUnicode_Join(NULL, rinfo);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001281 Py_DECREF(rinfo);
1282 if (rinfo_s == NULL) {
1283 return NULL;
1284 }
1285
1286 PyObject *rstr = NULL;
1287 PyObject *type_name = PyObject_GetAttrString((PyObject*)Py_TYPE(fut),
1288 "__name__");
1289 if (type_name != NULL) {
Serhiy Storchakabca49392017-09-03 08:10:14 +03001290 rstr = PyUnicode_FromFormat("<%S %U>", type_name, rinfo_s);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001291 Py_DECREF(type_name);
1292 }
1293 Py_DECREF(rinfo_s);
1294 return rstr;
1295}
1296
1297static void
1298FutureObj_finalize(FutureObj *fut)
1299{
1300 _Py_IDENTIFIER(call_exception_handler);
1301 _Py_IDENTIFIER(message);
1302 _Py_IDENTIFIER(exception);
1303 _Py_IDENTIFIER(future);
1304 _Py_IDENTIFIER(source_traceback);
1305
Serhiy Storchakabca49392017-09-03 08:10:14 +03001306 PyObject *error_type, *error_value, *error_traceback;
1307 PyObject *context;
1308 PyObject *type_name;
1309 PyObject *message = NULL;
1310 PyObject *func;
1311
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001312 if (!fut->fut_log_tb) {
1313 return;
1314 }
1315 assert(fut->fut_exception != NULL);
Serhiy Storchakabca49392017-09-03 08:10:14 +03001316 fut->fut_log_tb = 0;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001317
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001318 /* Save the current exception, if any. */
1319 PyErr_Fetch(&error_type, &error_value, &error_traceback);
1320
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001321 context = PyDict_New();
1322 if (context == NULL) {
1323 goto finally;
1324 }
1325
1326 type_name = PyObject_GetAttrString((PyObject*)Py_TYPE(fut), "__name__");
1327 if (type_name == NULL) {
1328 goto finally;
1329 }
1330
1331 message = PyUnicode_FromFormat(
1332 "%S exception was never retrieved", type_name);
Serhiy Storchakabca49392017-09-03 08:10:14 +03001333 Py_DECREF(type_name);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001334 if (message == NULL) {
1335 goto finally;
1336 }
1337
1338 if (_PyDict_SetItemId(context, &PyId_message, message) < 0 ||
1339 _PyDict_SetItemId(context, &PyId_exception, fut->fut_exception) < 0 ||
1340 _PyDict_SetItemId(context, &PyId_future, (PyObject*)fut) < 0) {
1341 goto finally;
1342 }
1343 if (fut->fut_source_tb != NULL) {
1344 if (_PyDict_SetItemId(context, &PyId_source_traceback,
1345 fut->fut_source_tb) < 0) {
1346 goto finally;
1347 }
1348 }
1349
1350 func = _PyObject_GetAttrId(fut->fut_loop, &PyId_call_exception_handler);
1351 if (func != NULL) {
Serhiy Storchakabca49392017-09-03 08:10:14 +03001352 PyObject *res = PyObject_CallFunctionObjArgs(func, context, NULL);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001353 if (res == NULL) {
1354 PyErr_WriteUnraisable(func);
1355 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03001356 else {
1357 Py_DECREF(res);
1358 }
1359 Py_DECREF(func);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001360 }
1361
1362finally:
Serhiy Storchakabca49392017-09-03 08:10:14 +03001363 Py_XDECREF(context);
1364 Py_XDECREF(message);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001365
1366 /* Restore the saved exception. */
1367 PyErr_Restore(error_type, error_value, error_traceback);
1368}
1369
1370
1371static PyAsyncMethods FutureType_as_async = {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001372 (unaryfunc)future_new_iter, /* am_await */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001373 0, /* am_aiter */
1374 0 /* am_anext */
1375};
1376
1377static PyMethodDef FutureType_methods[] = {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001378 _ASYNCIO_FUTURE_RESULT_METHODDEF
1379 _ASYNCIO_FUTURE_EXCEPTION_METHODDEF
1380 _ASYNCIO_FUTURE_SET_RESULT_METHODDEF
1381 _ASYNCIO_FUTURE_SET_EXCEPTION_METHODDEF
1382 _ASYNCIO_FUTURE_ADD_DONE_CALLBACK_METHODDEF
1383 _ASYNCIO_FUTURE_REMOVE_DONE_CALLBACK_METHODDEF
1384 _ASYNCIO_FUTURE_CANCEL_METHODDEF
1385 _ASYNCIO_FUTURE_CANCELLED_METHODDEF
1386 _ASYNCIO_FUTURE_DONE_METHODDEF
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001387 _ASYNCIO_FUTURE_GET_LOOP_METHODDEF
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001388 _ASYNCIO_FUTURE__REPR_INFO_METHODDEF
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001389 {NULL, NULL} /* Sentinel */
1390};
1391
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001392#define FUTURE_COMMON_GETSETLIST \
1393 {"_state", (getter)FutureObj_get_state, NULL, NULL}, \
1394 {"_asyncio_future_blocking", (getter)FutureObj_get_blocking, \
1395 (setter)FutureObj_set_blocking, NULL}, \
1396 {"_loop", (getter)FutureObj_get_loop, NULL, NULL}, \
1397 {"_callbacks", (getter)FutureObj_get_callbacks, NULL, NULL}, \
1398 {"_result", (getter)FutureObj_get_result, NULL, NULL}, \
1399 {"_exception", (getter)FutureObj_get_exception, NULL, NULL}, \
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +00001400 {"_log_traceback", (getter)FutureObj_get_log_traceback, \
1401 (setter)FutureObj_set_log_traceback, NULL}, \
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001402 {"_source_traceback", (getter)FutureObj_get_source_traceback, NULL, NULL},
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001403
1404static PyGetSetDef FutureType_getsetlist[] = {
1405 FUTURE_COMMON_GETSETLIST
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001406 {NULL} /* Sentinel */
1407};
1408
1409static void FutureObj_dealloc(PyObject *self);
1410
1411static PyTypeObject FutureType = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02001412 PyVarObject_HEAD_INIT(NULL, 0)
INADA Naoki9f2ce252016-10-15 15:39:19 +09001413 "_asyncio.Future",
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001414 sizeof(FutureObj), /* tp_basicsize */
1415 .tp_dealloc = FutureObj_dealloc,
1416 .tp_as_async = &FutureType_as_async,
1417 .tp_repr = (reprfunc)FutureObj_repr,
1418 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE
1419 | Py_TPFLAGS_HAVE_FINALIZE,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001420 .tp_doc = _asyncio_Future___init____doc__,
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001421 .tp_traverse = (traverseproc)FutureObj_traverse,
1422 .tp_clear = (inquiry)FutureObj_clear,
1423 .tp_weaklistoffset = offsetof(FutureObj, fut_weakreflist),
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001424 .tp_iter = (getiterfunc)future_new_iter,
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001425 .tp_methods = FutureType_methods,
1426 .tp_getset = FutureType_getsetlist,
1427 .tp_dictoffset = offsetof(FutureObj, dict),
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001428 .tp_init = (initproc)_asyncio_Future___init__,
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001429 .tp_new = PyType_GenericNew,
1430 .tp_finalize = (destructor)FutureObj_finalize,
1431};
1432
1433static void
1434FutureObj_dealloc(PyObject *self)
1435{
1436 FutureObj *fut = (FutureObj *)self;
1437
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001438 if (Future_CheckExact(fut)) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001439 /* When fut is subclass of Future, finalizer is called from
1440 * subtype_dealloc.
1441 */
1442 if (PyObject_CallFinalizerFromDealloc(self) < 0) {
1443 // resurrected.
1444 return;
1445 }
1446 }
1447
Alexander Mohrde34cbe2017-08-01 23:31:07 -07001448 PyObject_GC_UnTrack(self);
1449
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001450 if (fut->fut_weakreflist != NULL) {
1451 PyObject_ClearWeakRefs(self);
1452 }
1453
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001454 (void)FutureObj_clear(fut);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001455 Py_TYPE(fut)->tp_free(fut);
1456}
1457
1458
1459/*********************** Future Iterator **************************/
1460
1461typedef struct {
1462 PyObject_HEAD
1463 FutureObj *future;
1464} futureiterobject;
1465
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001466
1467#define FI_FREELIST_MAXLEN 255
1468static futureiterobject *fi_freelist = NULL;
1469static Py_ssize_t fi_freelist_len = 0;
1470
1471
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001472static void
1473FutureIter_dealloc(futureiterobject *it)
1474{
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001475 PyObject_GC_UnTrack(it);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001476 Py_CLEAR(it->future);
1477
1478 if (fi_freelist_len < FI_FREELIST_MAXLEN) {
1479 fi_freelist_len++;
1480 it->future = (FutureObj*) fi_freelist;
1481 fi_freelist = it;
1482 }
1483 else {
1484 PyObject_GC_Del(it);
1485 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001486}
1487
1488static PyObject *
1489FutureIter_iternext(futureiterobject *it)
1490{
1491 PyObject *res;
1492 FutureObj *fut = it->future;
1493
1494 if (fut == NULL) {
1495 return NULL;
1496 }
1497
1498 if (fut->fut_state == STATE_PENDING) {
1499 if (!fut->fut_blocking) {
1500 fut->fut_blocking = 1;
1501 Py_INCREF(fut);
1502 return (PyObject *)fut;
1503 }
Yury Selivanov0cf16f92017-12-25 10:48:15 -05001504 PyErr_SetString(PyExc_RuntimeError,
1505 "await wasn't used with future");
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001506 return NULL;
1507 }
1508
Serhiy Storchakabca49392017-09-03 08:10:14 +03001509 it->future = NULL;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001510 res = _asyncio_Future_result_impl(fut);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001511 if (res != NULL) {
Serhiy Storchaka60e49aa2016-11-06 18:47:03 +02001512 /* The result of the Future is not an exception. */
Serhiy Storchakabca49392017-09-03 08:10:14 +03001513 (void)_PyGen_SetStopIterationValue(res);
Serhiy Storchaka60e49aa2016-11-06 18:47:03 +02001514 Py_DECREF(res);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001515 }
1516
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001517 Py_DECREF(fut);
1518 return NULL;
1519}
1520
1521static PyObject *
INADA Naoki74c17532016-10-25 19:00:45 +09001522FutureIter_send(futureiterobject *self, PyObject *unused)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001523{
INADA Naoki74c17532016-10-25 19:00:45 +09001524 /* Future.__iter__ doesn't care about values that are pushed to the
1525 * generator, it just returns "self.result().
1526 */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001527 return FutureIter_iternext(self);
1528}
1529
1530static PyObject *
1531FutureIter_throw(futureiterobject *self, PyObject *args)
1532{
Serhiy Storchakabca49392017-09-03 08:10:14 +03001533 PyObject *type, *val = NULL, *tb = NULL;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001534 if (!PyArg_ParseTuple(args, "O|OO", &type, &val, &tb))
1535 return NULL;
1536
1537 if (val == Py_None) {
1538 val = NULL;
1539 }
1540 if (tb == Py_None) {
1541 tb = NULL;
Benjamin Peterson996fc1f2016-11-14 00:15:44 -08001542 } else if (tb != NULL && !PyTraceBack_Check(tb)) {
1543 PyErr_SetString(PyExc_TypeError, "throw() third argument must be a traceback");
1544 return NULL;
1545 }
1546
1547 Py_INCREF(type);
1548 Py_XINCREF(val);
1549 Py_XINCREF(tb);
1550
1551 if (PyExceptionClass_Check(type)) {
1552 PyErr_NormalizeException(&type, &val, &tb);
Yury Selivanovedfe8862016-12-01 11:37:47 -05001553 /* No need to call PyException_SetTraceback since we'll be calling
1554 PyErr_Restore for `type`, `val`, and `tb`. */
Benjamin Peterson996fc1f2016-11-14 00:15:44 -08001555 } else if (PyExceptionInstance_Check(type)) {
1556 if (val) {
1557 PyErr_SetString(PyExc_TypeError,
1558 "instance exception may not have a separate value");
1559 goto fail;
1560 }
1561 val = type;
1562 type = PyExceptionInstance_Class(type);
1563 Py_INCREF(type);
1564 if (tb == NULL)
1565 tb = PyException_GetTraceback(val);
1566 } else {
1567 PyErr_SetString(PyExc_TypeError,
1568 "exceptions must be classes deriving BaseException or "
1569 "instances of such a class");
1570 goto fail;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001571 }
1572
1573 Py_CLEAR(self->future);
1574
Benjamin Peterson996fc1f2016-11-14 00:15:44 -08001575 PyErr_Restore(type, val, tb);
1576
Serhiy Storchakabca49392017-09-03 08:10:14 +03001577 return NULL;
Benjamin Peterson996fc1f2016-11-14 00:15:44 -08001578
1579 fail:
1580 Py_DECREF(type);
1581 Py_XDECREF(val);
1582 Py_XDECREF(tb);
1583 return NULL;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001584}
1585
1586static PyObject *
1587FutureIter_close(futureiterobject *self, PyObject *arg)
1588{
1589 Py_CLEAR(self->future);
1590 Py_RETURN_NONE;
1591}
1592
1593static int
1594FutureIter_traverse(futureiterobject *it, visitproc visit, void *arg)
1595{
1596 Py_VISIT(it->future);
1597 return 0;
1598}
1599
1600static PyMethodDef FutureIter_methods[] = {
1601 {"send", (PyCFunction)FutureIter_send, METH_O, NULL},
1602 {"throw", (PyCFunction)FutureIter_throw, METH_VARARGS, NULL},
1603 {"close", (PyCFunction)FutureIter_close, METH_NOARGS, NULL},
1604 {NULL, NULL} /* Sentinel */
1605};
1606
1607static PyTypeObject FutureIterType = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02001608 PyVarObject_HEAD_INIT(NULL, 0)
INADA Naoki9f2ce252016-10-15 15:39:19 +09001609 "_asyncio.FutureIter",
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001610 .tp_basicsize = sizeof(futureiterobject),
1611 .tp_itemsize = 0,
1612 .tp_dealloc = (destructor)FutureIter_dealloc,
1613 .tp_getattro = PyObject_GenericGetAttr,
1614 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
1615 .tp_traverse = (traverseproc)FutureIter_traverse,
1616 .tp_iter = PyObject_SelfIter,
1617 .tp_iternext = (iternextfunc)FutureIter_iternext,
1618 .tp_methods = FutureIter_methods,
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001619};
1620
1621static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001622future_new_iter(PyObject *fut)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001623{
1624 futureiterobject *it;
1625
1626 if (!PyObject_TypeCheck(fut, &FutureType)) {
1627 PyErr_BadInternalCall();
1628 return NULL;
1629 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001630
1631 ENSURE_FUTURE_ALIVE(fut)
1632
1633 if (fi_freelist_len) {
1634 fi_freelist_len--;
1635 it = fi_freelist;
1636 fi_freelist = (futureiterobject*) it->future;
1637 it->future = NULL;
1638 _Py_NewReference((PyObject*) it);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001639 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001640 else {
1641 it = PyObject_GC_New(futureiterobject, &FutureIterType);
1642 if (it == NULL) {
1643 return NULL;
1644 }
1645 }
1646
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001647 Py_INCREF(fut);
1648 it->future = (FutureObj*)fut;
INADA Naoki1be427b2016-10-11 02:12:34 +09001649 PyObject_GC_Track(it);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001650 return (PyObject*)it;
1651}
1652
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001653
1654/*********************** Task **************************/
1655
1656
1657/*[clinic input]
1658class _asyncio.Task "TaskObj *" "&Task_Type"
1659[clinic start generated code]*/
1660/*[clinic end generated code: output=da39a3ee5e6b4b0d input=719dcef0fcc03b37]*/
1661
1662static int task_call_step_soon(TaskObj *, PyObject *);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001663static PyObject * task_wakeup(TaskObj *, PyObject *);
1664static PyObject * task_step(TaskObj *, PyObject *);
1665
1666/* ----- Task._step wrapper */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001667
INADA Naokic411a7d2016-10-18 11:48:14 +09001668static int
Serhiy Storchakabca49392017-09-03 08:10:14 +03001669TaskStepMethWrapper_clear(TaskStepMethWrapper *o)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001670{
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001671 Py_CLEAR(o->sw_task);
1672 Py_CLEAR(o->sw_arg);
1673 return 0;
1674}
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001675
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001676static void
Serhiy Storchakabca49392017-09-03 08:10:14 +03001677TaskStepMethWrapper_dealloc(TaskStepMethWrapper *o)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001678{
1679 PyObject_GC_UnTrack(o);
Serhiy Storchakabca49392017-09-03 08:10:14 +03001680 (void)TaskStepMethWrapper_clear(o);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001681 Py_TYPE(o)->tp_free(o);
1682}
1683
1684static PyObject *
Serhiy Storchakabca49392017-09-03 08:10:14 +03001685TaskStepMethWrapper_call(TaskStepMethWrapper *o,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001686 PyObject *args, PyObject *kwds)
1687{
Serhiy Storchakabca49392017-09-03 08:10:14 +03001688 if (kwds != NULL && PyDict_GET_SIZE(kwds) != 0) {
1689 PyErr_SetString(PyExc_TypeError, "function takes no keyword arguments");
1690 return NULL;
1691 }
1692 if (args != NULL && PyTuple_GET_SIZE(args) != 0) {
1693 PyErr_SetString(PyExc_TypeError, "function takes no positional arguments");
1694 return NULL;
1695 }
Yury Selivanov22feeb82018-01-24 11:31:01 -05001696 return task_step(o->sw_task, o->sw_arg);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001697}
1698
1699static int
Serhiy Storchakabca49392017-09-03 08:10:14 +03001700TaskStepMethWrapper_traverse(TaskStepMethWrapper *o,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001701 visitproc visit, void *arg)
1702{
1703 Py_VISIT(o->sw_task);
1704 Py_VISIT(o->sw_arg);
1705 return 0;
1706}
1707
1708static PyObject *
Serhiy Storchakabca49392017-09-03 08:10:14 +03001709TaskStepMethWrapper_get___self__(TaskStepMethWrapper *o)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001710{
1711 if (o->sw_task) {
1712 Py_INCREF(o->sw_task);
1713 return (PyObject*)o->sw_task;
1714 }
1715 Py_RETURN_NONE;
1716}
1717
Serhiy Storchakabca49392017-09-03 08:10:14 +03001718static PyGetSetDef TaskStepMethWrapper_getsetlist[] = {
1719 {"__self__", (getter)TaskStepMethWrapper_get___self__, NULL, NULL},
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001720 {NULL} /* Sentinel */
1721};
1722
Serhiy Storchakabca49392017-09-03 08:10:14 +03001723PyTypeObject TaskStepMethWrapper_Type = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02001724 PyVarObject_HEAD_INIT(NULL, 0)
Serhiy Storchakabca49392017-09-03 08:10:14 +03001725 "TaskStepMethWrapper",
1726 .tp_basicsize = sizeof(TaskStepMethWrapper),
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001727 .tp_itemsize = 0,
Serhiy Storchakabca49392017-09-03 08:10:14 +03001728 .tp_getset = TaskStepMethWrapper_getsetlist,
1729 .tp_dealloc = (destructor)TaskStepMethWrapper_dealloc,
1730 .tp_call = (ternaryfunc)TaskStepMethWrapper_call,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001731 .tp_getattro = PyObject_GenericGetAttr,
1732 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
Serhiy Storchakabca49392017-09-03 08:10:14 +03001733 .tp_traverse = (traverseproc)TaskStepMethWrapper_traverse,
1734 .tp_clear = (inquiry)TaskStepMethWrapper_clear,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001735};
1736
1737static PyObject *
Serhiy Storchakabca49392017-09-03 08:10:14 +03001738TaskStepMethWrapper_new(TaskObj *task, PyObject *arg)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001739{
Serhiy Storchakabca49392017-09-03 08:10:14 +03001740 TaskStepMethWrapper *o;
1741 o = PyObject_GC_New(TaskStepMethWrapper, &TaskStepMethWrapper_Type);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001742 if (o == NULL) {
1743 return NULL;
1744 }
1745
1746 Py_INCREF(task);
1747 o->sw_task = task;
1748
1749 Py_XINCREF(arg);
1750 o->sw_arg = arg;
1751
1752 PyObject_GC_Track(o);
1753 return (PyObject*) o;
1754}
1755
1756/* ----- Task._wakeup wrapper */
1757
1758static PyObject *
1759TaskWakeupMethWrapper_call(TaskWakeupMethWrapper *o,
1760 PyObject *args, PyObject *kwds)
1761{
1762 PyObject *fut;
1763
Serhiy Storchakabca49392017-09-03 08:10:14 +03001764 if (kwds != NULL && PyDict_GET_SIZE(kwds) != 0) {
1765 PyErr_SetString(PyExc_TypeError, "function takes no keyword arguments");
1766 return NULL;
1767 }
1768 if (!PyArg_ParseTuple(args, "O", &fut)) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001769 return NULL;
1770 }
1771
Yury Selivanov22feeb82018-01-24 11:31:01 -05001772 return task_wakeup(o->ww_task, fut);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001773}
1774
1775static int
1776TaskWakeupMethWrapper_clear(TaskWakeupMethWrapper *o)
1777{
1778 Py_CLEAR(o->ww_task);
1779 return 0;
1780}
1781
1782static int
1783TaskWakeupMethWrapper_traverse(TaskWakeupMethWrapper *o,
1784 visitproc visit, void *arg)
1785{
1786 Py_VISIT(o->ww_task);
1787 return 0;
1788}
1789
1790static void
1791TaskWakeupMethWrapper_dealloc(TaskWakeupMethWrapper *o)
1792{
1793 PyObject_GC_UnTrack(o);
1794 (void)TaskWakeupMethWrapper_clear(o);
1795 Py_TYPE(o)->tp_free(o);
1796}
1797
1798PyTypeObject TaskWakeupMethWrapper_Type = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02001799 PyVarObject_HEAD_INIT(NULL, 0)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001800 "TaskWakeupMethWrapper",
1801 .tp_basicsize = sizeof(TaskWakeupMethWrapper),
1802 .tp_itemsize = 0,
1803 .tp_dealloc = (destructor)TaskWakeupMethWrapper_dealloc,
1804 .tp_call = (ternaryfunc)TaskWakeupMethWrapper_call,
1805 .tp_getattro = PyObject_GenericGetAttr,
1806 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
1807 .tp_traverse = (traverseproc)TaskWakeupMethWrapper_traverse,
1808 .tp_clear = (inquiry)TaskWakeupMethWrapper_clear,
1809};
1810
1811static PyObject *
1812TaskWakeupMethWrapper_new(TaskObj *task)
1813{
1814 TaskWakeupMethWrapper *o;
1815 o = PyObject_GC_New(TaskWakeupMethWrapper, &TaskWakeupMethWrapper_Type);
1816 if (o == NULL) {
1817 return NULL;
1818 }
1819
1820 Py_INCREF(task);
1821 o->ww_task = task;
1822
1823 PyObject_GC_Track(o);
1824 return (PyObject*) o;
1825}
1826
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001827/* ----- Task introspection helpers */
1828
1829static int
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001830register_task(PyObject *task)
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001831{
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001832 _Py_IDENTIFIER(add);
1833
1834 PyObject *res = _PyObject_CallMethodIdObjArgs(
1835 all_tasks, &PyId_add, task, NULL);
1836 if (res == NULL) {
1837 return -1;
1838 }
1839 Py_DECREF(res);
1840 return 0;
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001841}
1842
1843
1844static int
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001845unregister_task(PyObject *task)
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001846{
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001847 _Py_IDENTIFIER(discard);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001848
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001849 PyObject *res = _PyObject_CallMethodIdObjArgs(
1850 all_tasks, &PyId_discard, task, NULL);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001851 if (res == NULL) {
1852 return -1;
1853 }
1854 Py_DECREF(res);
1855 return 0;
1856}
1857
1858
1859static int
1860enter_task(PyObject *loop, PyObject *task)
1861{
1862 PyObject *item;
1863 Py_hash_t hash;
1864 hash = PyObject_Hash(loop);
1865 if (hash == -1) {
1866 return -1;
1867 }
1868 item = _PyDict_GetItem_KnownHash(current_tasks, loop, hash);
1869 if (item != NULL) {
1870 PyErr_Format(
1871 PyExc_RuntimeError,
1872 "Cannot enter into task %R while another " \
1873 "task %R is being executed.",
1874 task, item, NULL);
1875 return -1;
1876 }
1877 if (_PyDict_SetItem_KnownHash(current_tasks, loop, task, hash) < 0) {
1878 return -1;
1879 }
1880 return 0;
1881}
1882
1883
1884static int
1885leave_task(PyObject *loop, PyObject *task)
1886/*[clinic end generated code: output=0ebf6db4b858fb41 input=51296a46313d1ad8]*/
1887{
1888 PyObject *item;
1889 Py_hash_t hash;
1890 hash = PyObject_Hash(loop);
1891 if (hash == -1) {
1892 return -1;
1893 }
1894 item = _PyDict_GetItem_KnownHash(current_tasks, loop, hash);
1895 if (item != task) {
1896 if (item == NULL) {
1897 /* Not entered, replace with None */
1898 item = Py_None;
1899 }
1900 PyErr_Format(
1901 PyExc_RuntimeError,
1902 "Leaving task %R does not match the current task %R.",
1903 task, item, NULL);
1904 return -1;
1905 }
1906 return _PyDict_DelItem_KnownHash(current_tasks, loop, hash);
1907}
1908
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001909/* ----- Task */
1910
1911/*[clinic input]
1912_asyncio.Task.__init__
1913
Serhiy Storchakabca49392017-09-03 08:10:14 +03001914 coro: object
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001915 *
Serhiy Storchakabca49392017-09-03 08:10:14 +03001916 loop: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001917
1918A coroutine wrapped in a Future.
1919[clinic start generated code]*/
1920
1921static int
1922_asyncio_Task___init___impl(TaskObj *self, PyObject *coro, PyObject *loop)
Serhiy Storchakabca49392017-09-03 08:10:14 +03001923/*[clinic end generated code: output=9f24774c2287fc2f input=8d132974b049593e]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001924{
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001925 if (future_init((FutureObj*)self, loop)) {
INADA Naokic411a7d2016-10-18 11:48:14 +09001926 return -1;
1927 }
INADA Naokic411a7d2016-10-18 11:48:14 +09001928
Yury Selivanova9d7e552017-12-19 07:18:45 -05001929 int is_coro = is_coroutine(coro);
1930 if (is_coro == -1) {
1931 return -1;
1932 }
1933 if (is_coro == 0) {
1934 self->task_log_destroy_pending = 0;
1935 PyErr_Format(PyExc_TypeError,
1936 "a coroutine was expected, got %R",
1937 coro, NULL);
1938 return -1;
Andrew Svetlovf74ef452017-12-15 07:04:38 +02001939 }
1940
Yury Selivanovf23746a2018-01-22 19:11:18 -05001941 self->task_context = PyContext_CopyCurrent();
1942 if (self->task_context == NULL) {
1943 return -1;
1944 }
1945
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001946 self->task_fut_waiter = NULL;
1947 self->task_must_cancel = 0;
1948 self->task_log_destroy_pending = 1;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001949 Py_INCREF(coro);
1950 self->task_coro = coro;
1951
1952 if (task_call_step_soon(self, NULL)) {
1953 return -1;
INADA Naokic411a7d2016-10-18 11:48:14 +09001954 }
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001955 return register_task((PyObject*)self);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001956}
1957
1958static int
1959TaskObj_clear(TaskObj *task)
1960{
1961 (void)FutureObj_clear((FutureObj*) task);
Yury Selivanovf23746a2018-01-22 19:11:18 -05001962 Py_CLEAR(task->task_context);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001963 Py_CLEAR(task->task_coro);
1964 Py_CLEAR(task->task_fut_waiter);
1965 return 0;
1966}
1967
1968static int
1969TaskObj_traverse(TaskObj *task, visitproc visit, void *arg)
1970{
Yury Selivanovf23746a2018-01-22 19:11:18 -05001971 Py_VISIT(task->task_context);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001972 Py_VISIT(task->task_coro);
1973 Py_VISIT(task->task_fut_waiter);
1974 (void)FutureObj_traverse((FutureObj*) task, visit, arg);
1975 return 0;
1976}
1977
1978static PyObject *
1979TaskObj_get_log_destroy_pending(TaskObj *task)
1980{
1981 if (task->task_log_destroy_pending) {
1982 Py_RETURN_TRUE;
1983 }
1984 else {
1985 Py_RETURN_FALSE;
1986 }
1987}
1988
1989static int
1990TaskObj_set_log_destroy_pending(TaskObj *task, PyObject *val)
1991{
1992 int is_true = PyObject_IsTrue(val);
1993 if (is_true < 0) {
1994 return -1;
1995 }
1996 task->task_log_destroy_pending = is_true;
1997 return 0;
1998}
1999
2000static PyObject *
2001TaskObj_get_must_cancel(TaskObj *task)
2002{
2003 if (task->task_must_cancel) {
2004 Py_RETURN_TRUE;
2005 }
2006 else {
2007 Py_RETURN_FALSE;
2008 }
2009}
2010
2011static PyObject *
2012TaskObj_get_coro(TaskObj *task)
2013{
2014 if (task->task_coro) {
2015 Py_INCREF(task->task_coro);
2016 return task->task_coro;
2017 }
2018
2019 Py_RETURN_NONE;
2020}
2021
2022static PyObject *
2023TaskObj_get_fut_waiter(TaskObj *task)
2024{
2025 if (task->task_fut_waiter) {
2026 Py_INCREF(task->task_fut_waiter);
2027 return task->task_fut_waiter;
2028 }
2029
2030 Py_RETURN_NONE;
2031}
2032
2033/*[clinic input]
2034@classmethod
2035_asyncio.Task.current_task
2036
Serhiy Storchakabca49392017-09-03 08:10:14 +03002037 loop: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002038
2039Return the currently running task in an event loop or None.
2040
2041By default the current task for the current event loop is returned.
2042
2043None is returned when called not in the context of a Task.
2044[clinic start generated code]*/
2045
2046static PyObject *
2047_asyncio_Task_current_task_impl(PyTypeObject *type, PyObject *loop)
Serhiy Storchakabca49392017-09-03 08:10:14 +03002048/*[clinic end generated code: output=99fbe7332c516e03 input=cd14770c5b79c7eb]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002049{
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002050 PyObject *ret;
2051 PyObject *current_task_func;
2052
2053 if (PyErr_WarnEx(PyExc_PendingDeprecationWarning,
2054 "Task.current_task() is deprecated, " \
2055 "use asyncio.current_task() instead",
2056 1) < 0) {
2057 return NULL;
2058 }
2059
2060 current_task_func = _PyObject_GetAttrId(asyncio_mod, &PyId_current_task);
2061 if (current_task_func == NULL) {
2062 return NULL;
2063 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002064
Yury Selivanov8d26aa92017-03-02 22:16:33 -05002065 if (loop == Py_None) {
Yury Selivanova70232f2017-12-13 14:49:42 -05002066 loop = get_event_loop();
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002067 if (loop == NULL) {
2068 return NULL;
2069 }
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002070 ret = PyObject_CallFunctionObjArgs(current_task_func, loop, NULL);
2071 Py_DECREF(current_task_func);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002072 Py_DECREF(loop);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002073 return ret;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002074 }
2075 else {
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002076 ret = PyObject_CallFunctionObjArgs(current_task_func, loop, NULL);
2077 Py_DECREF(current_task_func);
2078 return ret;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002079 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002080}
2081
2082/*[clinic input]
2083@classmethod
2084_asyncio.Task.all_tasks
2085
Serhiy Storchakabca49392017-09-03 08:10:14 +03002086 loop: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002087
2088Return a set of all tasks for an event loop.
2089
2090By default all tasks for the current event loop are returned.
2091[clinic start generated code]*/
2092
2093static PyObject *
2094_asyncio_Task_all_tasks_impl(PyTypeObject *type, PyObject *loop)
Serhiy Storchakabca49392017-09-03 08:10:14 +03002095/*[clinic end generated code: output=11f9b20749ccca5d input=497f80bc9ce726b5]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002096{
2097 PyObject *res;
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002098 PyObject *all_tasks_func;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002099
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002100 all_tasks_func = _PyObject_GetAttrId(asyncio_mod, &PyId_all_tasks);
2101 if (all_tasks_func == NULL) {
2102 return NULL;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002103 }
2104
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002105 if (PyErr_WarnEx(PyExc_PendingDeprecationWarning,
2106 "Task.all_tasks() is deprecated, " \
2107 "use asyncio.all_tasks() instead",
2108 1) < 0) {
2109 return NULL;
2110 }
2111
2112 res = PyObject_CallFunctionObjArgs(all_tasks_func, loop, NULL);
2113 Py_DECREF(all_tasks_func);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002114 return res;
2115}
2116
2117/*[clinic input]
2118_asyncio.Task._repr_info
2119[clinic start generated code]*/
2120
2121static PyObject *
2122_asyncio_Task__repr_info_impl(TaskObj *self)
2123/*[clinic end generated code: output=6a490eb66d5ba34b input=3c6d051ed3ddec8b]*/
2124{
Victor Stinnerde4ae3d2016-12-04 22:59:09 +01002125 return PyObject_CallFunctionObjArgs(
2126 asyncio_task_repr_info_func, self, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002127}
2128
2129/*[clinic input]
2130_asyncio.Task.cancel
2131
2132Request that this task cancel itself.
2133
2134This arranges for a CancelledError to be thrown into the
2135wrapped coroutine on the next cycle through the event loop.
2136The coroutine then has a chance to clean up or even deny
2137the request using try/except/finally.
2138
2139Unlike Future.cancel, this does not guarantee that the
2140task will be cancelled: the exception might be caught and
2141acted upon, delaying cancellation of the task or preventing
2142cancellation completely. The task may also return a value or
2143raise a different exception.
2144
2145Immediately after this method is called, Task.cancelled() will
2146not return True (unless the task was already cancelled). A
2147task will be marked as cancelled when the wrapped coroutine
2148terminates with a CancelledError exception (even if cancel()
2149was not called).
2150[clinic start generated code]*/
2151
2152static PyObject *
2153_asyncio_Task_cancel_impl(TaskObj *self)
2154/*[clinic end generated code: output=6bfc0479da9d5757 input=13f9bf496695cb52]*/
2155{
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +00002156 self->task_log_tb = 0;
2157
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002158 if (self->task_state != STATE_PENDING) {
2159 Py_RETURN_FALSE;
2160 }
2161
2162 if (self->task_fut_waiter) {
2163 PyObject *res;
2164 int is_true;
2165
2166 res = _PyObject_CallMethodId(
2167 self->task_fut_waiter, &PyId_cancel, NULL);
2168 if (res == NULL) {
2169 return NULL;
2170 }
2171
2172 is_true = PyObject_IsTrue(res);
2173 Py_DECREF(res);
2174 if (is_true < 0) {
2175 return NULL;
2176 }
2177
2178 if (is_true) {
2179 Py_RETURN_TRUE;
2180 }
2181 }
2182
2183 self->task_must_cancel = 1;
2184 Py_RETURN_TRUE;
2185}
2186
2187/*[clinic input]
2188_asyncio.Task.get_stack
2189
2190 *
Serhiy Storchakabca49392017-09-03 08:10:14 +03002191 limit: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002192
2193Return the list of stack frames for this task's coroutine.
2194
2195If the coroutine is not done, this returns the stack where it is
2196suspended. If the coroutine has completed successfully or was
2197cancelled, this returns an empty list. If the coroutine was
2198terminated by an exception, this returns the list of traceback
2199frames.
2200
2201The frames are always ordered from oldest to newest.
2202
2203The optional limit gives the maximum number of frames to
2204return; by default all available frames are returned. Its
2205meaning differs depending on whether a stack or a traceback is
2206returned: the newest frames of a stack are returned, but the
2207oldest frames of a traceback are returned. (This matches the
2208behavior of the traceback module.)
2209
2210For reasons beyond our control, only one stack frame is
2211returned for a suspended coroutine.
2212[clinic start generated code]*/
2213
2214static PyObject *
2215_asyncio_Task_get_stack_impl(TaskObj *self, PyObject *limit)
Serhiy Storchakabca49392017-09-03 08:10:14 +03002216/*[clinic end generated code: output=c9aeeeebd1e18118 input=05b323d42b809b90]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002217{
2218 return PyObject_CallFunctionObjArgs(
2219 asyncio_task_get_stack_func, self, limit, NULL);
2220}
2221
2222/*[clinic input]
2223_asyncio.Task.print_stack
2224
2225 *
Serhiy Storchakabca49392017-09-03 08:10:14 +03002226 limit: object = None
2227 file: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002228
2229Print the stack or traceback for this task's coroutine.
2230
2231This produces output similar to that of the traceback module,
2232for the frames retrieved by get_stack(). The limit argument
2233is passed to get_stack(). The file argument is an I/O stream
2234to which the output is written; by default output is written
2235to sys.stderr.
2236[clinic start generated code]*/
2237
2238static PyObject *
2239_asyncio_Task_print_stack_impl(TaskObj *self, PyObject *limit,
2240 PyObject *file)
Serhiy Storchakabca49392017-09-03 08:10:14 +03002241/*[clinic end generated code: output=7339e10314cd3f4d input=1a0352913b7fcd92]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002242{
2243 return PyObject_CallFunctionObjArgs(
2244 asyncio_task_print_stack_func, self, limit, file, NULL);
2245}
2246
2247/*[clinic input]
Yury Selivanov0cf16f92017-12-25 10:48:15 -05002248_asyncio.Task.set_result
2249
2250 result: object
2251 /
2252[clinic start generated code]*/
2253
2254static PyObject *
2255_asyncio_Task_set_result(TaskObj *self, PyObject *result)
2256/*[clinic end generated code: output=1dcae308bfcba318 input=9d1a00c07be41bab]*/
2257{
2258 PyErr_SetString(PyExc_RuntimeError,
2259 "Task does not support set_result operation");
2260 return NULL;
2261}
2262
2263/*[clinic input]
2264_asyncio.Task.set_exception
2265
2266 exception: object
2267 /
2268[clinic start generated code]*/
2269
2270static PyObject *
2271_asyncio_Task_set_exception(TaskObj *self, PyObject *exception)
2272/*[clinic end generated code: output=bc377fc28067303d input=9a8f65c83dcf893a]*/
2273{
2274 PyErr_SetString(PyExc_RuntimeError,
Andrew Svetlovfc359322017-12-30 15:40:27 +02002275 "Task does not support set_exception operation");
Yury Selivanov0cf16f92017-12-25 10:48:15 -05002276 return NULL;
2277}
2278
2279
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002280static void
2281TaskObj_finalize(TaskObj *task)
2282{
2283 _Py_IDENTIFIER(call_exception_handler);
2284 _Py_IDENTIFIER(task);
2285 _Py_IDENTIFIER(message);
2286 _Py_IDENTIFIER(source_traceback);
2287
Serhiy Storchakabca49392017-09-03 08:10:14 +03002288 PyObject *context;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002289 PyObject *message = NULL;
Serhiy Storchakabca49392017-09-03 08:10:14 +03002290 PyObject *func;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002291 PyObject *error_type, *error_value, *error_traceback;
2292
2293 if (task->task_state != STATE_PENDING || !task->task_log_destroy_pending) {
2294 goto done;
2295 }
2296
2297 /* Save the current exception, if any. */
2298 PyErr_Fetch(&error_type, &error_value, &error_traceback);
2299
2300 context = PyDict_New();
2301 if (context == NULL) {
2302 goto finally;
2303 }
2304
2305 message = PyUnicode_FromString("Task was destroyed but it is pending!");
2306 if (message == NULL) {
2307 goto finally;
2308 }
2309
2310 if (_PyDict_SetItemId(context, &PyId_message, message) < 0 ||
2311 _PyDict_SetItemId(context, &PyId_task, (PyObject*)task) < 0)
2312 {
2313 goto finally;
2314 }
2315
2316 if (task->task_source_tb != NULL) {
2317 if (_PyDict_SetItemId(context, &PyId_source_traceback,
2318 task->task_source_tb) < 0)
2319 {
2320 goto finally;
2321 }
2322 }
2323
2324 func = _PyObject_GetAttrId(task->task_loop, &PyId_call_exception_handler);
2325 if (func != NULL) {
Serhiy Storchakabca49392017-09-03 08:10:14 +03002326 PyObject *res = PyObject_CallFunctionObjArgs(func, context, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002327 if (res == NULL) {
2328 PyErr_WriteUnraisable(func);
2329 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03002330 else {
2331 Py_DECREF(res);
2332 }
2333 Py_DECREF(func);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002334 }
2335
2336finally:
Serhiy Storchakabca49392017-09-03 08:10:14 +03002337 Py_XDECREF(context);
2338 Py_XDECREF(message);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002339
2340 /* Restore the saved exception. */
2341 PyErr_Restore(error_type, error_value, error_traceback);
2342
2343done:
2344 FutureObj_finalize((FutureObj*)task);
2345}
2346
2347static void TaskObj_dealloc(PyObject *); /* Needs Task_CheckExact */
2348
2349static PyMethodDef TaskType_methods[] = {
2350 _ASYNCIO_FUTURE_RESULT_METHODDEF
2351 _ASYNCIO_FUTURE_EXCEPTION_METHODDEF
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002352 _ASYNCIO_FUTURE_ADD_DONE_CALLBACK_METHODDEF
2353 _ASYNCIO_FUTURE_REMOVE_DONE_CALLBACK_METHODDEF
2354 _ASYNCIO_FUTURE_CANCELLED_METHODDEF
2355 _ASYNCIO_FUTURE_DONE_METHODDEF
Yury Selivanov0cf16f92017-12-25 10:48:15 -05002356 _ASYNCIO_TASK_SET_RESULT_METHODDEF
2357 _ASYNCIO_TASK_SET_EXCEPTION_METHODDEF
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002358 _ASYNCIO_TASK_CURRENT_TASK_METHODDEF
2359 _ASYNCIO_TASK_ALL_TASKS_METHODDEF
2360 _ASYNCIO_TASK_CANCEL_METHODDEF
2361 _ASYNCIO_TASK_GET_STACK_METHODDEF
2362 _ASYNCIO_TASK_PRINT_STACK_METHODDEF
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002363 _ASYNCIO_TASK__REPR_INFO_METHODDEF
2364 {NULL, NULL} /* Sentinel */
2365};
2366
2367static PyGetSetDef TaskType_getsetlist[] = {
2368 FUTURE_COMMON_GETSETLIST
2369 {"_log_destroy_pending", (getter)TaskObj_get_log_destroy_pending,
2370 (setter)TaskObj_set_log_destroy_pending, NULL},
2371 {"_must_cancel", (getter)TaskObj_get_must_cancel, NULL, NULL},
2372 {"_coro", (getter)TaskObj_get_coro, NULL, NULL},
2373 {"_fut_waiter", (getter)TaskObj_get_fut_waiter, NULL, NULL},
2374 {NULL} /* Sentinel */
2375};
2376
2377static PyTypeObject TaskType = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02002378 PyVarObject_HEAD_INIT(NULL, 0)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002379 "_asyncio.Task",
2380 sizeof(TaskObj), /* tp_basicsize */
2381 .tp_base = &FutureType,
2382 .tp_dealloc = TaskObj_dealloc,
2383 .tp_as_async = &FutureType_as_async,
2384 .tp_repr = (reprfunc)FutureObj_repr,
2385 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE
2386 | Py_TPFLAGS_HAVE_FINALIZE,
2387 .tp_doc = _asyncio_Task___init____doc__,
2388 .tp_traverse = (traverseproc)TaskObj_traverse,
2389 .tp_clear = (inquiry)TaskObj_clear,
2390 .tp_weaklistoffset = offsetof(TaskObj, task_weakreflist),
2391 .tp_iter = (getiterfunc)future_new_iter,
2392 .tp_methods = TaskType_methods,
2393 .tp_getset = TaskType_getsetlist,
2394 .tp_dictoffset = offsetof(TaskObj, dict),
2395 .tp_init = (initproc)_asyncio_Task___init__,
2396 .tp_new = PyType_GenericNew,
2397 .tp_finalize = (destructor)TaskObj_finalize,
2398};
2399
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002400static void
2401TaskObj_dealloc(PyObject *self)
2402{
2403 TaskObj *task = (TaskObj *)self;
2404
2405 if (Task_CheckExact(self)) {
2406 /* When fut is subclass of Task, finalizer is called from
2407 * subtype_dealloc.
2408 */
2409 if (PyObject_CallFinalizerFromDealloc(self) < 0) {
2410 // resurrected.
2411 return;
2412 }
2413 }
2414
Alexander Mohrde34cbe2017-08-01 23:31:07 -07002415 PyObject_GC_UnTrack(self);
2416
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002417 if (task->task_weakreflist != NULL) {
2418 PyObject_ClearWeakRefs(self);
2419 }
2420
2421 (void)TaskObj_clear(task);
2422 Py_TYPE(task)->tp_free(task);
2423}
2424
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002425static int
2426task_call_step_soon(TaskObj *task, PyObject *arg)
2427{
Serhiy Storchakabca49392017-09-03 08:10:14 +03002428 PyObject *cb = TaskStepMethWrapper_new(task, arg);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002429 if (cb == NULL) {
2430 return -1;
2431 }
2432
Yury Selivanovf23746a2018-01-22 19:11:18 -05002433 int ret = call_soon(task->task_loop, cb, NULL, task->task_context);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002434 Py_DECREF(cb);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05002435 return ret;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002436}
2437
2438static PyObject *
2439task_set_error_soon(TaskObj *task, PyObject *et, const char *format, ...)
2440{
2441 PyObject* msg;
2442
2443 va_list vargs;
2444#ifdef HAVE_STDARG_PROTOTYPES
2445 va_start(vargs, format);
2446#else
2447 va_start(vargs);
2448#endif
2449 msg = PyUnicode_FromFormatV(format, vargs);
2450 va_end(vargs);
2451
2452 if (msg == NULL) {
2453 return NULL;
2454 }
2455
Victor Stinnerde4ae3d2016-12-04 22:59:09 +01002456 PyObject *e = PyObject_CallFunctionObjArgs(et, msg, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002457 Py_DECREF(msg);
2458 if (e == NULL) {
2459 return NULL;
2460 }
2461
2462 if (task_call_step_soon(task, e) == -1) {
2463 Py_DECREF(e);
2464 return NULL;
2465 }
2466
2467 Py_DECREF(e);
2468 Py_RETURN_NONE;
2469}
2470
2471static PyObject *
2472task_step_impl(TaskObj *task, PyObject *exc)
2473{
2474 int res;
2475 int clear_exc = 0;
2476 PyObject *result = NULL;
Serhiy Storchakabca49392017-09-03 08:10:14 +03002477 PyObject *coro;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002478 PyObject *o;
2479
2480 if (task->task_state != STATE_PENDING) {
Yury Selivanov0cf16f92017-12-25 10:48:15 -05002481 PyErr_Format(asyncio_InvalidStateError,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002482 "_step(): already done: %R %R",
2483 task,
2484 exc ? exc : Py_None);
INADA Naokic411a7d2016-10-18 11:48:14 +09002485 goto fail;
2486 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09002487
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002488 if (task->task_must_cancel) {
2489 assert(exc != Py_None);
2490
2491 if (exc) {
2492 /* Check if exc is a CancelledError */
2493 res = PyObject_IsInstance(exc, asyncio_CancelledError);
2494 if (res == -1) {
2495 /* An error occurred, abort */
2496 goto fail;
2497 }
2498 if (res == 0) {
2499 /* exc is not CancelledError; reset it to NULL */
2500 exc = NULL;
2501 }
2502 }
2503
2504 if (!exc) {
2505 /* exc was not a CancelledError */
Victor Stinnerf17c3de2016-12-06 18:46:19 +01002506 exc = _PyObject_CallNoArg(asyncio_CancelledError);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002507 if (!exc) {
2508 goto fail;
2509 }
2510 clear_exc = 1;
2511 }
2512
2513 task->task_must_cancel = 0;
2514 }
2515
2516 Py_CLEAR(task->task_fut_waiter);
2517
Serhiy Storchakabca49392017-09-03 08:10:14 +03002518 coro = task->task_coro;
2519 if (coro == NULL) {
2520 PyErr_SetString(PyExc_RuntimeError, "uninitialized Task object");
2521 return NULL;
2522 }
2523
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002524 if (exc == NULL) {
2525 if (PyGen_CheckExact(coro) || PyCoro_CheckExact(coro)) {
2526 result = _PyGen_Send((PyGenObject*)coro, Py_None);
2527 }
2528 else {
Victor Stinnerb6ed57d2016-12-09 14:24:02 +01002529 result = _PyObject_CallMethodIdObjArgs(coro, &PyId_send,
2530 Py_None, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002531 }
2532 }
2533 else {
Victor Stinnerb6ed57d2016-12-09 14:24:02 +01002534 result = _PyObject_CallMethodIdObjArgs(coro, &PyId_throw,
2535 exc, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002536 if (clear_exc) {
2537 /* We created 'exc' during this call */
Serhiy Storchakabca49392017-09-03 08:10:14 +03002538 Py_DECREF(exc);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002539 }
2540 }
2541
2542 if (result == NULL) {
2543 PyObject *et, *ev, *tb;
2544
2545 if (_PyGen_FetchStopIterationValue(&o) == 0) {
2546 /* The error is StopIteration and that means that
2547 the underlying coroutine has resolved */
INADA Naoki991adca2017-05-11 21:18:38 +09002548 if (task->task_must_cancel) {
2549 // Task is cancelled right before coro stops.
2550 Py_DECREF(o);
2551 task->task_must_cancel = 0;
2552 et = asyncio_CancelledError;
2553 Py_INCREF(et);
2554 ev = NULL;
2555 tb = NULL;
2556 goto set_exception;
2557 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002558 PyObject *res = future_set_result((FutureObj*)task, o);
2559 Py_DECREF(o);
2560 if (res == NULL) {
2561 return NULL;
2562 }
2563 Py_DECREF(res);
2564 Py_RETURN_NONE;
2565 }
2566
2567 if (PyErr_ExceptionMatches(asyncio_CancelledError)) {
2568 /* CancelledError */
2569 PyErr_Clear();
2570 return future_cancel((FutureObj*)task);
2571 }
2572
2573 /* Some other exception; pop it and call Task.set_exception() */
2574 PyErr_Fetch(&et, &ev, &tb);
INADA Naoki991adca2017-05-11 21:18:38 +09002575
2576set_exception:
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002577 assert(et);
2578 if (!ev || !PyObject_TypeCheck(ev, (PyTypeObject *) et)) {
2579 PyErr_NormalizeException(&et, &ev, &tb);
2580 }
Yury Selivanovedfe8862016-12-01 11:37:47 -05002581 if (tb != NULL) {
2582 PyException_SetTraceback(ev, tb);
2583 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002584 o = future_set_exception((FutureObj*)task, ev);
2585 if (!o) {
2586 /* An exception in Task.set_exception() */
Serhiy Storchakabca49392017-09-03 08:10:14 +03002587 Py_DECREF(et);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002588 Py_XDECREF(tb);
2589 Py_XDECREF(ev);
2590 goto fail;
2591 }
2592 assert(o == Py_None);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002593 Py_DECREF(o);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002594
2595 if (!PyErr_GivenExceptionMatches(et, PyExc_Exception)) {
2596 /* We've got a BaseException; re-raise it */
2597 PyErr_Restore(et, ev, tb);
2598 goto fail;
2599 }
2600
Serhiy Storchakabca49392017-09-03 08:10:14 +03002601 Py_DECREF(et);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002602 Py_XDECREF(tb);
2603 Py_XDECREF(ev);
2604
2605 Py_RETURN_NONE;
2606 }
2607
2608 if (result == (PyObject*)task) {
2609 /* We have a task that wants to await on itself */
2610 goto self_await;
2611 }
2612
2613 /* Check if `result` is FutureObj or TaskObj (and not a subclass) */
2614 if (Future_CheckExact(result) || Task_CheckExact(result)) {
2615 PyObject *wrapper;
2616 PyObject *res;
2617 FutureObj *fut = (FutureObj*)result;
2618
2619 /* Check if `result` future is attached to a different loop */
2620 if (fut->fut_loop != task->task_loop) {
2621 goto different_loop;
2622 }
2623
2624 if (fut->fut_blocking) {
2625 fut->fut_blocking = 0;
2626
2627 /* result.add_done_callback(task._wakeup) */
2628 wrapper = TaskWakeupMethWrapper_new(task);
2629 if (wrapper == NULL) {
2630 goto fail;
2631 }
Yury Selivanovf23746a2018-01-22 19:11:18 -05002632 res = future_add_done_callback(
2633 (FutureObj*)result, wrapper, task->task_context);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002634 Py_DECREF(wrapper);
2635 if (res == NULL) {
2636 goto fail;
2637 }
2638 Py_DECREF(res);
2639
2640 /* task._fut_waiter = result */
2641 task->task_fut_waiter = result; /* no incref is necessary */
2642
2643 if (task->task_must_cancel) {
2644 PyObject *r;
2645 r = future_cancel(fut);
2646 if (r == NULL) {
2647 return NULL;
2648 }
2649 if (r == Py_True) {
2650 task->task_must_cancel = 0;
2651 }
2652 Py_DECREF(r);
2653 }
2654
2655 Py_RETURN_NONE;
2656 }
2657 else {
2658 goto yield_insteadof_yf;
2659 }
2660 }
2661
2662 /* Check if `result` is a Future-compatible object */
2663 o = PyObject_GetAttrString(result, "_asyncio_future_blocking");
2664 if (o == NULL) {
2665 if (PyErr_ExceptionMatches(PyExc_AttributeError)) {
2666 PyErr_Clear();
2667 }
2668 else {
2669 goto fail;
2670 }
2671 }
2672 else {
2673 if (o == Py_None) {
Serhiy Storchakabca49392017-09-03 08:10:14 +03002674 Py_DECREF(o);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002675 }
2676 else {
2677 /* `result` is a Future-compatible object */
2678 PyObject *wrapper;
2679 PyObject *res;
2680
2681 int blocking = PyObject_IsTrue(o);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002682 Py_DECREF(o);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002683 if (blocking < 0) {
2684 goto fail;
2685 }
2686
2687 /* Check if `result` future is attached to a different loop */
Yury Selivanovca9b36c2017-12-23 15:04:15 -05002688 PyObject *oloop = get_future_loop(result);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002689 if (oloop == NULL) {
2690 goto fail;
2691 }
2692 if (oloop != task->task_loop) {
2693 Py_DECREF(oloop);
2694 goto different_loop;
2695 }
2696 else {
2697 Py_DECREF(oloop);
2698 }
2699
2700 if (blocking) {
2701 /* result._asyncio_future_blocking = False */
2702 if (PyObject_SetAttrString(
2703 result, "_asyncio_future_blocking", Py_False) == -1) {
2704 goto fail;
2705 }
2706
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002707 wrapper = TaskWakeupMethWrapper_new(task);
2708 if (wrapper == NULL) {
2709 goto fail;
2710 }
Yury Selivanovf23746a2018-01-22 19:11:18 -05002711
2712 /* result.add_done_callback(task._wakeup) */
2713 PyObject *add_cb = _PyObject_GetAttrId(
2714 result, &PyId_add_done_callback);
2715 if (add_cb == NULL) {
2716 goto fail;
2717 }
2718 PyObject *stack[2];
2719 stack[0] = wrapper;
2720 stack[1] = (PyObject *)task->task_context;
2721 res = _PyObject_FastCallKeywords(
2722 add_cb, stack, 1, context_kwname);
2723 Py_DECREF(add_cb);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002724 Py_DECREF(wrapper);
2725 if (res == NULL) {
2726 goto fail;
2727 }
2728 Py_DECREF(res);
2729
2730 /* task._fut_waiter = result */
2731 task->task_fut_waiter = result; /* no incref is necessary */
2732
2733 if (task->task_must_cancel) {
2734 PyObject *r;
2735 int is_true;
2736 r = _PyObject_CallMethodId(result, &PyId_cancel, NULL);
2737 if (r == NULL) {
2738 return NULL;
2739 }
2740 is_true = PyObject_IsTrue(r);
2741 Py_DECREF(r);
2742 if (is_true < 0) {
2743 return NULL;
2744 }
2745 else if (is_true) {
2746 task->task_must_cancel = 0;
2747 }
2748 }
2749
2750 Py_RETURN_NONE;
2751 }
2752 else {
2753 goto yield_insteadof_yf;
2754 }
2755 }
2756 }
2757
2758 /* Check if `result` is None */
2759 if (result == Py_None) {
2760 /* Bare yield relinquishes control for one event loop iteration. */
2761 if (task_call_step_soon(task, NULL)) {
2762 goto fail;
2763 }
2764 return result;
2765 }
2766
2767 /* Check if `result` is a generator */
Victor Stinnerde4ae3d2016-12-04 22:59:09 +01002768 o = PyObject_CallFunctionObjArgs(inspect_isgenerator, result, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002769 if (o == NULL) {
2770 /* An exception in inspect.isgenerator */
2771 goto fail;
2772 }
2773 res = PyObject_IsTrue(o);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002774 Py_DECREF(o);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002775 if (res == -1) {
2776 /* An exception while checking if 'val' is True */
2777 goto fail;
2778 }
2779 if (res == 1) {
2780 /* `result` is a generator */
2781 PyObject *ret;
2782 ret = task_set_error_soon(
2783 task, PyExc_RuntimeError,
2784 "yield was used instead of yield from for "
2785 "generator in task %R with %S", task, result);
2786 Py_DECREF(result);
2787 return ret;
2788 }
2789
2790 /* The `result` is none of the above */
2791 Py_DECREF(result);
2792 return task_set_error_soon(
2793 task, PyExc_RuntimeError, "Task got bad yield: %R", result);
2794
2795self_await:
2796 o = task_set_error_soon(
2797 task, PyExc_RuntimeError,
2798 "Task cannot await on itself: %R", task);
2799 Py_DECREF(result);
2800 return o;
2801
2802yield_insteadof_yf:
2803 o = task_set_error_soon(
2804 task, PyExc_RuntimeError,
2805 "yield was used instead of yield from "
2806 "in task %R with %R",
2807 task, result);
2808 Py_DECREF(result);
2809 return o;
2810
2811different_loop:
2812 o = task_set_error_soon(
2813 task, PyExc_RuntimeError,
2814 "Task %R got Future %R attached to a different loop",
2815 task, result);
2816 Py_DECREF(result);
2817 return o;
2818
2819fail:
2820 Py_XDECREF(result);
2821 return NULL;
2822}
2823
2824static PyObject *
2825task_step(TaskObj *task, PyObject *exc)
2826{
2827 PyObject *res;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002828
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002829 if (enter_task(task->task_loop, (PyObject*)task) < 0) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002830 return NULL;
2831 }
2832
2833 res = task_step_impl(task, exc);
2834
2835 if (res == NULL) {
2836 PyObject *et, *ev, *tb;
2837 PyErr_Fetch(&et, &ev, &tb);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002838 leave_task(task->task_loop, (PyObject*)task);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002839 _PyErr_ChainExceptions(et, ev, tb);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002840 return NULL;
2841 }
2842 else {
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002843 if(leave_task(task->task_loop, (PyObject*)task) < 0) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002844 Py_DECREF(res);
2845 return NULL;
2846 }
2847 else {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002848 return res;
2849 }
2850 }
2851}
2852
2853static PyObject *
2854task_wakeup(TaskObj *task, PyObject *o)
2855{
Serhiy Storchakabca49392017-09-03 08:10:14 +03002856 PyObject *et, *ev, *tb;
2857 PyObject *result;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002858 assert(o);
2859
2860 if (Future_CheckExact(o) || Task_CheckExact(o)) {
2861 PyObject *fut_result = NULL;
2862 int res = future_get_result((FutureObj*)o, &fut_result);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002863
2864 switch(res) {
2865 case -1:
2866 assert(fut_result == NULL);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002867 break; /* exception raised */
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002868 case 0:
2869 Py_DECREF(fut_result);
Yury Selivanov22feeb82018-01-24 11:31:01 -05002870 return task_step(task, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002871 default:
2872 assert(res == 1);
Yury Selivanov22feeb82018-01-24 11:31:01 -05002873 result = task_step(task, fut_result);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002874 Py_DECREF(fut_result);
2875 return result;
2876 }
2877 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002878 else {
Serhiy Storchakabca49392017-09-03 08:10:14 +03002879 PyObject *fut_result = PyObject_CallMethod(o, "result", NULL);
2880 if (fut_result != NULL) {
2881 Py_DECREF(fut_result);
Yury Selivanov22feeb82018-01-24 11:31:01 -05002882 return task_step(task, NULL);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002883 }
2884 /* exception raised */
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002885 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03002886
2887 PyErr_Fetch(&et, &ev, &tb);
2888 if (!PyErr_GivenExceptionMatches(et, PyExc_Exception)) {
2889 /* We've got a BaseException; re-raise it */
2890 PyErr_Restore(et, ev, tb);
2891 return NULL;
2892 }
2893 if (!ev || !PyObject_TypeCheck(ev, (PyTypeObject *) et)) {
2894 PyErr_NormalizeException(&et, &ev, &tb);
2895 }
2896
Yury Selivanov22feeb82018-01-24 11:31:01 -05002897 result = task_step(task, ev);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002898
2899 Py_DECREF(et);
2900 Py_XDECREF(tb);
2901 Py_XDECREF(ev);
2902
2903 return result;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002904}
2905
2906
Yury Selivanova70232f2017-12-13 14:49:42 -05002907/*********************** Functions **************************/
2908
2909
2910/*[clinic input]
2911_asyncio._get_running_loop
2912
2913Return the running event loop or None.
2914
2915This is a low-level function intended to be used by event loops.
2916This function is thread-specific.
2917
2918[clinic start generated code]*/
2919
2920static PyObject *
2921_asyncio__get_running_loop_impl(PyObject *module)
2922/*[clinic end generated code: output=b4390af721411a0a input=0a21627e25a4bd43]*/
2923{
2924 PyObject *loop;
2925 if (get_running_loop(&loop)) {
2926 return NULL;
2927 }
2928 if (loop == NULL) {
2929 /* There's no currently running event loop */
2930 Py_RETURN_NONE;
2931 }
2932 return loop;
2933}
2934
2935/*[clinic input]
2936_asyncio._set_running_loop
2937 loop: 'O'
2938 /
2939
2940Set the running event loop.
2941
2942This is a low-level function intended to be used by event loops.
2943This function is thread-specific.
2944[clinic start generated code]*/
2945
2946static PyObject *
2947_asyncio__set_running_loop(PyObject *module, PyObject *loop)
2948/*[clinic end generated code: output=ae56bf7a28ca189a input=4c9720233d606604]*/
2949{
2950 if (set_running_loop(loop)) {
2951 return NULL;
2952 }
2953 Py_RETURN_NONE;
2954}
2955
2956/*[clinic input]
2957_asyncio.get_event_loop
2958
2959Return an asyncio event loop.
2960
2961When called from a coroutine or a callback (e.g. scheduled with
2962call_soon or similar API), this function will always return the
2963running event loop.
2964
2965If there is no running event loop set, the function will return
2966the result of `get_event_loop_policy().get_event_loop()` call.
2967[clinic start generated code]*/
2968
2969static PyObject *
2970_asyncio_get_event_loop_impl(PyObject *module)
2971/*[clinic end generated code: output=2a2d8b2f824c648b input=9364bf2916c8655d]*/
2972{
2973 return get_event_loop();
2974}
2975
2976/*[clinic input]
2977_asyncio.get_running_loop
2978
2979Return the running event loop. Raise a RuntimeError if there is none.
2980
2981This function is thread-specific.
2982[clinic start generated code]*/
2983
2984static PyObject *
2985_asyncio_get_running_loop_impl(PyObject *module)
2986/*[clinic end generated code: output=c247b5f9e529530e input=2a3bf02ba39f173d]*/
2987{
2988 PyObject *loop;
2989 if (get_running_loop(&loop)) {
2990 return NULL;
2991 }
2992 if (loop == NULL) {
2993 /* There's no currently running event loop */
2994 PyErr_SetString(
2995 PyExc_RuntimeError, "no running event loop");
2996 }
2997 return loop;
2998}
2999
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003000/*[clinic input]
3001_asyncio._register_task
3002
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003003 task: object
3004
3005Register a new task in asyncio as executed by loop.
3006
3007Returns None.
3008[clinic start generated code]*/
3009
3010static PyObject *
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003011_asyncio__register_task_impl(PyObject *module, PyObject *task)
3012/*[clinic end generated code: output=8672dadd69a7d4e2 input=21075aaea14dfbad]*/
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003013{
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003014 if (register_task(task) < 0) {
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003015 return NULL;
3016 }
3017 Py_RETURN_NONE;
3018}
3019
3020
3021/*[clinic input]
3022_asyncio._unregister_task
3023
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003024 task: object
3025
3026Unregister a task.
3027
3028Returns None.
3029[clinic start generated code]*/
3030
3031static PyObject *
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003032_asyncio__unregister_task_impl(PyObject *module, PyObject *task)
3033/*[clinic end generated code: output=6e5585706d568a46 input=28fb98c3975f7bdc]*/
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003034{
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003035 if (unregister_task(task) < 0) {
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003036 return NULL;
3037 }
3038 Py_RETURN_NONE;
3039}
3040
3041
3042/*[clinic input]
3043_asyncio._enter_task
3044
3045 loop: object
3046 task: object
3047
3048Enter into task execution or resume suspended task.
3049
3050Task belongs to loop.
3051
3052Returns None.
3053[clinic start generated code]*/
3054
3055static PyObject *
3056_asyncio__enter_task_impl(PyObject *module, PyObject *loop, PyObject *task)
3057/*[clinic end generated code: output=a22611c858035b73 input=de1b06dca70d8737]*/
3058{
3059 if (enter_task(loop, task) < 0) {
3060 return NULL;
3061 }
3062 Py_RETURN_NONE;
3063}
3064
3065
3066/*[clinic input]
3067_asyncio._leave_task
3068
3069 loop: object
3070 task: object
3071
3072Leave task execution or suspend a task.
3073
3074Task belongs to loop.
3075
3076Returns None.
3077[clinic start generated code]*/
3078
3079static PyObject *
3080_asyncio__leave_task_impl(PyObject *module, PyObject *loop, PyObject *task)
3081/*[clinic end generated code: output=0ebf6db4b858fb41 input=51296a46313d1ad8]*/
3082{
3083 if (leave_task(loop, task) < 0) {
3084 return NULL;
3085 }
3086 Py_RETURN_NONE;
3087}
3088
Yury Selivanova70232f2017-12-13 14:49:42 -05003089
Yury Selivanov9d411c12018-01-23 15:10:03 -05003090/*********************** PyRunningLoopHolder ********************/
3091
3092
3093static PyRunningLoopHolder *
3094new_running_loop_holder(PyObject *loop)
3095{
3096 PyRunningLoopHolder *rl = PyObject_New(
3097 PyRunningLoopHolder, &PyRunningLoopHolder_Type);
3098 if (rl == NULL) {
3099 return NULL;
3100 }
3101
3102#if defined(HAVE_GETPID) && !defined(MS_WINDOWS)
3103 rl->rl_pid = getpid();
3104#endif
3105
3106 Py_INCREF(loop);
3107 rl->rl_loop = loop;
3108
3109 return rl;
3110}
3111
3112
3113static void
3114PyRunningLoopHolder_tp_dealloc(PyRunningLoopHolder *rl)
3115{
3116 Py_CLEAR(rl->rl_loop);
3117 PyObject_Free(rl);
3118}
3119
3120
3121static PyTypeObject PyRunningLoopHolder_Type = {
3122 PyVarObject_HEAD_INIT(NULL, 0)
3123 "_RunningLoopHolder",
3124 sizeof(PyRunningLoopHolder),
3125 .tp_getattro = PyObject_GenericGetAttr,
3126 .tp_flags = Py_TPFLAGS_DEFAULT,
3127 .tp_dealloc = (destructor)PyRunningLoopHolder_tp_dealloc,
3128};
3129
3130
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003131/*********************** Module **************************/
3132
3133
3134static void
Zackery Spytze40ad792017-12-19 11:48:13 -07003135module_free_freelists(void)
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05003136{
3137 PyObject *next;
3138 PyObject *current;
3139
3140 next = (PyObject*) fi_freelist;
3141 while (next != NULL) {
3142 assert(fi_freelist_len > 0);
3143 fi_freelist_len--;
3144
3145 current = next;
3146 next = (PyObject*) ((futureiterobject*) current)->future;
3147 PyObject_GC_Del(current);
3148 }
3149 assert(fi_freelist_len == 0);
3150 fi_freelist = NULL;
3151}
3152
3153
3154static void
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003155module_free(void *m)
3156{
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003157 Py_CLEAR(asyncio_mod);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003158 Py_CLEAR(inspect_isgenerator);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003159 Py_CLEAR(traceback_extract_stack);
3160 Py_CLEAR(asyncio_future_repr_info_func);
3161 Py_CLEAR(asyncio_get_event_loop_policy);
3162 Py_CLEAR(asyncio_iscoroutine_func);
3163 Py_CLEAR(asyncio_task_get_stack_func);
3164 Py_CLEAR(asyncio_task_print_stack_func);
3165 Py_CLEAR(asyncio_task_repr_info_func);
3166 Py_CLEAR(asyncio_InvalidStateError);
3167 Py_CLEAR(asyncio_CancelledError);
3168
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003169 Py_CLEAR(all_tasks);
Yury Selivanova9d7e552017-12-19 07:18:45 -05003170 Py_CLEAR(current_tasks);
3171 Py_CLEAR(iscoroutine_typecache);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05003172
Yury Selivanovf23746a2018-01-22 19:11:18 -05003173 Py_CLEAR(context_kwname);
3174
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05003175 module_free_freelists();
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003176}
3177
3178static int
3179module_init(void)
3180{
3181 PyObject *module = NULL;
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003182
3183 asyncio_mod = PyImport_ImportModule("asyncio");
3184 if (asyncio_mod == NULL) {
3185 goto fail;
3186 }
3187
3188 current_tasks = PyDict_New();
3189 if (current_tasks == NULL) {
3190 goto fail;
3191 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003192
Yury Selivanova9d7e552017-12-19 07:18:45 -05003193 iscoroutine_typecache = PySet_New(NULL);
3194 if (iscoroutine_typecache == NULL) {
3195 goto fail;
3196 }
3197
Yury Selivanovf23746a2018-01-22 19:11:18 -05003198
3199 context_kwname = PyTuple_New(1);
3200 if (context_kwname == NULL) {
3201 goto fail;
3202 }
3203 PyObject *context_str = PyUnicode_FromString("context");
3204 if (context_str == NULL) {
3205 goto fail;
3206 }
3207 PyTuple_SET_ITEM(context_kwname, 0, context_str);
3208
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003209#define WITH_MOD(NAME) \
3210 Py_CLEAR(module); \
3211 module = PyImport_ImportModule(NAME); \
3212 if (module == NULL) { \
Serhiy Storchakabca49392017-09-03 08:10:14 +03003213 goto fail; \
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003214 }
3215
3216#define GET_MOD_ATTR(VAR, NAME) \
3217 VAR = PyObject_GetAttrString(module, NAME); \
3218 if (VAR == NULL) { \
3219 goto fail; \
3220 }
3221
3222 WITH_MOD("asyncio.events")
Yury Selivanova70232f2017-12-13 14:49:42 -05003223 GET_MOD_ATTR(asyncio_get_event_loop_policy, "get_event_loop_policy")
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003224
3225 WITH_MOD("asyncio.base_futures")
3226 GET_MOD_ATTR(asyncio_future_repr_info_func, "_future_repr_info")
3227 GET_MOD_ATTR(asyncio_InvalidStateError, "InvalidStateError")
3228 GET_MOD_ATTR(asyncio_CancelledError, "CancelledError")
3229
3230 WITH_MOD("asyncio.base_tasks")
3231 GET_MOD_ATTR(asyncio_task_repr_info_func, "_task_repr_info")
3232 GET_MOD_ATTR(asyncio_task_get_stack_func, "_task_get_stack")
3233 GET_MOD_ATTR(asyncio_task_print_stack_func, "_task_print_stack")
3234
Andrew Svetlovf74ef452017-12-15 07:04:38 +02003235 WITH_MOD("asyncio.coroutines")
3236 GET_MOD_ATTR(asyncio_iscoroutine_func, "iscoroutine")
3237
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003238 WITH_MOD("inspect")
3239 GET_MOD_ATTR(inspect_isgenerator, "isgenerator")
3240
3241 WITH_MOD("traceback")
3242 GET_MOD_ATTR(traceback_extract_stack, "extract_stack")
3243
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003244 PyObject *weak_set;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003245 WITH_MOD("weakref")
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003246 GET_MOD_ATTR(weak_set, "WeakSet");
3247 all_tasks = _PyObject_CallNoArg(weak_set);
3248 Py_CLEAR(weak_set);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003249 if (all_tasks == NULL) {
INADA Naokic411a7d2016-10-18 11:48:14 +09003250 goto fail;
3251 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003252
Serhiy Storchakabca49392017-09-03 08:10:14 +03003253 Py_DECREF(module);
INADA Naokic411a7d2016-10-18 11:48:14 +09003254 return 0;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003255
INADA Naokic411a7d2016-10-18 11:48:14 +09003256fail:
INADA Naokic411a7d2016-10-18 11:48:14 +09003257 Py_CLEAR(module);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003258 module_free(NULL);
INADA Naokic411a7d2016-10-18 11:48:14 +09003259 return -1;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003260
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003261#undef WITH_MOD
3262#undef GET_MOD_ATTR
3263}
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003264
INADA Naokic411a7d2016-10-18 11:48:14 +09003265PyDoc_STRVAR(module_doc, "Accelerator module for asyncio");
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003266
Yury Selivanova70232f2017-12-13 14:49:42 -05003267static PyMethodDef asyncio_methods[] = {
3268 _ASYNCIO_GET_EVENT_LOOP_METHODDEF
3269 _ASYNCIO_GET_RUNNING_LOOP_METHODDEF
3270 _ASYNCIO__GET_RUNNING_LOOP_METHODDEF
3271 _ASYNCIO__SET_RUNNING_LOOP_METHODDEF
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003272 _ASYNCIO__REGISTER_TASK_METHODDEF
3273 _ASYNCIO__UNREGISTER_TASK_METHODDEF
3274 _ASYNCIO__ENTER_TASK_METHODDEF
3275 _ASYNCIO__LEAVE_TASK_METHODDEF
Yury Selivanova70232f2017-12-13 14:49:42 -05003276 {NULL, NULL}
3277};
3278
INADA Naoki9f2ce252016-10-15 15:39:19 +09003279static struct PyModuleDef _asynciomodule = {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003280 PyModuleDef_HEAD_INIT, /* m_base */
INADA Naoki9f2ce252016-10-15 15:39:19 +09003281 "_asyncio", /* m_name */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003282 module_doc, /* m_doc */
3283 -1, /* m_size */
Yury Selivanova70232f2017-12-13 14:49:42 -05003284 asyncio_methods, /* m_methods */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003285 NULL, /* m_slots */
3286 NULL, /* m_traverse */
3287 NULL, /* m_clear */
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003288 (freefunc)module_free /* m_free */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003289};
3290
3291
3292PyMODINIT_FUNC
INADA Naoki9f2ce252016-10-15 15:39:19 +09003293PyInit__asyncio(void)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003294{
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003295 if (module_init() < 0) {
INADA Naokic411a7d2016-10-18 11:48:14 +09003296 return NULL;
3297 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003298 if (PyType_Ready(&FutureType) < 0) {
3299 return NULL;
3300 }
3301 if (PyType_Ready(&FutureIterType) < 0) {
3302 return NULL;
3303 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03003304 if (PyType_Ready(&TaskStepMethWrapper_Type) < 0) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003305 return NULL;
3306 }
3307 if(PyType_Ready(&TaskWakeupMethWrapper_Type) < 0) {
3308 return NULL;
3309 }
3310 if (PyType_Ready(&TaskType) < 0) {
3311 return NULL;
3312 }
Yury Selivanov9d411c12018-01-23 15:10:03 -05003313 if (PyType_Ready(&PyRunningLoopHolder_Type) < 0) {
3314 return NULL;
3315 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003316
INADA Naoki9f2ce252016-10-15 15:39:19 +09003317 PyObject *m = PyModule_Create(&_asynciomodule);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003318 if (m == NULL) {
3319 return NULL;
3320 }
3321
3322 Py_INCREF(&FutureType);
3323 if (PyModule_AddObject(m, "Future", (PyObject *)&FutureType) < 0) {
3324 Py_DECREF(&FutureType);
3325 return NULL;
3326 }
3327
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003328 Py_INCREF(&TaskType);
3329 if (PyModule_AddObject(m, "Task", (PyObject *)&TaskType) < 0) {
3330 Py_DECREF(&TaskType);
3331 return NULL;
3332 }
3333
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003334 Py_INCREF(all_tasks);
3335 if (PyModule_AddObject(m, "_all_tasks", all_tasks) < 0) {
3336 Py_DECREF(all_tasks);
3337 return NULL;
3338 }
3339
3340 Py_INCREF(current_tasks);
3341 if (PyModule_AddObject(m, "_current_tasks", current_tasks) < 0) {
3342 Py_DECREF(current_tasks);
3343 return NULL;
3344 }
3345
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003346 return m;
3347}