INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 1 | #include "Python.h" |
Chris Jerdonek | da742ba | 2020-05-17 22:47:31 -0700 | [diff] [blame] | 2 | #include "pycore_pyerrors.h" // _PyErr_ClearExcState() |
Victor Stinner | 4a21e57 | 2020-04-15 02:35:41 +0200 | [diff] [blame] | 3 | #include <stddef.h> // offsetof() |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 4 | |
| 5 | |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 6 | /*[clinic input] |
| 7 | module _asyncio |
| 8 | [clinic start generated code]*/ |
| 9 | /*[clinic end generated code: output=da39a3ee5e6b4b0d input=8fd17862aa989c69]*/ |
| 10 | |
| 11 | |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 12 | /* identifiers used from some functions */ |
Yury Selivanov | a70232f | 2017-12-13 14:49:42 -0500 | [diff] [blame] | 13 | _Py_IDENTIFIER(__asyncio_running_event_loop__); |
Serhiy Storchaka | fb3e9c0 | 2018-09-21 09:11:32 +0300 | [diff] [blame] | 14 | _Py_IDENTIFIER(_asyncio_future_blocking); |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 15 | _Py_IDENTIFIER(add_done_callback); |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 16 | _Py_IDENTIFIER(call_soon); |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 17 | _Py_IDENTIFIER(cancel); |
Yury Selivanov | a70232f | 2017-12-13 14:49:42 -0500 | [diff] [blame] | 18 | _Py_IDENTIFIER(get_event_loop); |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 19 | _Py_IDENTIFIER(send); |
| 20 | _Py_IDENTIFIER(throw); |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 21 | |
| 22 | |
INADA Naoki | 9f2ce25 | 2016-10-15 15:39:19 +0900 | [diff] [blame] | 23 | /* State of the _asyncio module */ |
Andrew Svetlov | 44d1a59 | 2017-12-16 21:58:38 +0200 | [diff] [blame] | 24 | static PyObject *asyncio_mod; |
Andrew Svetlov | 44d1a59 | 2017-12-16 21:58:38 +0200 | [diff] [blame] | 25 | static PyObject *traceback_extract_stack; |
| 26 | static PyObject *asyncio_get_event_loop_policy; |
| 27 | static PyObject *asyncio_future_repr_info_func; |
| 28 | static PyObject *asyncio_iscoroutine_func; |
| 29 | static PyObject *asyncio_task_get_stack_func; |
| 30 | static PyObject *asyncio_task_print_stack_func; |
| 31 | static PyObject *asyncio_task_repr_info_func; |
| 32 | static PyObject *asyncio_InvalidStateError; |
| 33 | static PyObject *asyncio_CancelledError; |
Yury Selivanov | f23746a | 2018-01-22 19:11:18 -0500 | [diff] [blame] | 34 | static PyObject *context_kwname; |
Ben Harper | 321def8 | 2019-10-07 12:19:58 -0400 | [diff] [blame] | 35 | static int module_initialized; |
Andrew Svetlov | 44d1a59 | 2017-12-16 21:58:38 +0200 | [diff] [blame] | 36 | |
Yury Selivanov | 9d411c1 | 2018-01-23 15:10:03 -0500 | [diff] [blame] | 37 | static PyObject *cached_running_holder; |
| 38 | static volatile uint64_t cached_running_holder_tsid; |
| 39 | |
Alex Grönholm | cca4eec | 2018-08-09 00:06:47 +0300 | [diff] [blame] | 40 | /* Counter for autogenerated Task names */ |
| 41 | static uint64_t task_name_counter = 0; |
Andrew Svetlov | 44d1a59 | 2017-12-16 21:58:38 +0200 | [diff] [blame] | 42 | |
Yury Selivanov | ca9b36c | 2017-12-23 15:04:15 -0500 | [diff] [blame] | 43 | /* WeakSet containing all alive tasks. */ |
| 44 | static PyObject *all_tasks; |
Andrew Svetlov | 44d1a59 | 2017-12-16 21:58:38 +0200 | [diff] [blame] | 45 | |
| 46 | /* Dictionary containing tasks that are currently active in |
| 47 | all running event loops. {EventLoop: Task} */ |
Yury Selivanov | ca9b36c | 2017-12-23 15:04:15 -0500 | [diff] [blame] | 48 | static PyObject *current_tasks; |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 49 | |
Yury Selivanov | a9d7e55 | 2017-12-19 07:18:45 -0500 | [diff] [blame] | 50 | /* An isinstance type cache for the 'is_coroutine()' function. */ |
| 51 | static PyObject *iscoroutine_typecache; |
| 52 | |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 53 | |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 54 | typedef enum { |
| 55 | STATE_PENDING, |
| 56 | STATE_CANCELLED, |
| 57 | STATE_FINISHED |
| 58 | } fut_state; |
| 59 | |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 60 | #define FutureObj_HEAD(prefix) \ |
| 61 | PyObject_HEAD \ |
| 62 | PyObject *prefix##_loop; \ |
Yury Selivanov | 1b7c11f | 2017-12-17 20:19:47 -0500 | [diff] [blame] | 63 | PyObject *prefix##_callback0; \ |
Yury Selivanov | 994269c | 2018-09-27 14:55:55 -0400 | [diff] [blame] | 64 | PyObject *prefix##_context0; \ |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 65 | PyObject *prefix##_callbacks; \ |
| 66 | PyObject *prefix##_exception; \ |
| 67 | PyObject *prefix##_result; \ |
| 68 | PyObject *prefix##_source_tb; \ |
Chris Jerdonek | 1ce5841 | 2020-05-15 16:55:50 -0700 | [diff] [blame] | 69 | PyObject *prefix##_cancel_msg; \ |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 70 | fut_state prefix##_state; \ |
| 71 | int prefix##_log_tb; \ |
| 72 | int prefix##_blocking; \ |
| 73 | PyObject *dict; \ |
Chris Jerdonek | da742ba | 2020-05-17 22:47:31 -0700 | [diff] [blame] | 74 | PyObject *prefix##_weakreflist; \ |
| 75 | _PyErr_StackItem prefix##_cancelled_exc_state; |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 76 | |
| 77 | typedef struct { |
| 78 | FutureObj_HEAD(fut) |
| 79 | } FutureObj; |
| 80 | |
| 81 | typedef struct { |
| 82 | FutureObj_HEAD(task) |
| 83 | PyObject *task_fut_waiter; |
| 84 | PyObject *task_coro; |
Alex Grönholm | cca4eec | 2018-08-09 00:06:47 +0300 | [diff] [blame] | 85 | PyObject *task_name; |
Yury Selivanov | 994269c | 2018-09-27 14:55:55 -0400 | [diff] [blame] | 86 | PyObject *task_context; |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 87 | int task_must_cancel; |
| 88 | int task_log_destroy_pending; |
| 89 | } TaskObj; |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 90 | |
| 91 | typedef struct { |
| 92 | PyObject_HEAD |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 93 | TaskObj *sw_task; |
| 94 | PyObject *sw_arg; |
Serhiy Storchaka | bca4939 | 2017-09-03 08:10:14 +0300 | [diff] [blame] | 95 | } TaskStepMethWrapper; |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 96 | |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 97 | typedef struct { |
| 98 | PyObject_HEAD |
| 99 | TaskObj *ww_task; |
| 100 | } TaskWakeupMethWrapper; |
| 101 | |
Yury Selivanov | 9d411c1 | 2018-01-23 15:10:03 -0500 | [diff] [blame] | 102 | typedef struct { |
| 103 | PyObject_HEAD |
| 104 | PyObject *rl_loop; |
| 105 | #if defined(HAVE_GETPID) && !defined(MS_WINDOWS) |
| 106 | pid_t rl_pid; |
| 107 | #endif |
| 108 | } PyRunningLoopHolder; |
| 109 | |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 110 | |
Yury Selivanov | 1b7c11f | 2017-12-17 20:19:47 -0500 | [diff] [blame] | 111 | static PyTypeObject FutureType; |
| 112 | static PyTypeObject TaskType; |
Yury Selivanov | 9d411c1 | 2018-01-23 15:10:03 -0500 | [diff] [blame] | 113 | static PyTypeObject PyRunningLoopHolder_Type; |
Yury Selivanov | 1b7c11f | 2017-12-17 20:19:47 -0500 | [diff] [blame] | 114 | |
| 115 | |
Dong-hee Na | 1b55b65 | 2020-02-17 19:09:15 +0900 | [diff] [blame] | 116 | #define Future_CheckExact(obj) Py_IS_TYPE(obj, &FutureType) |
| 117 | #define Task_CheckExact(obj) Py_IS_TYPE(obj, &TaskType) |
Yury Selivanov | 1b7c11f | 2017-12-17 20:19:47 -0500 | [diff] [blame] | 118 | |
| 119 | #define Future_Check(obj) PyObject_TypeCheck(obj, &FutureType) |
| 120 | #define Task_Check(obj) PyObject_TypeCheck(obj, &TaskType) |
| 121 | |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 122 | #include "clinic/_asynciomodule.c.h" |
| 123 | |
| 124 | |
| 125 | /*[clinic input] |
| 126 | class _asyncio.Future "FutureObj *" "&Future_Type" |
| 127 | [clinic start generated code]*/ |
| 128 | /*[clinic end generated code: output=da39a3ee5e6b4b0d input=00d3e4abca711e0f]*/ |
| 129 | |
Yury Selivanov | 1b7c11f | 2017-12-17 20:19:47 -0500 | [diff] [blame] | 130 | |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 131 | /* Get FutureIter from Future */ |
Yury Selivanov | 9d411c1 | 2018-01-23 15:10:03 -0500 | [diff] [blame] | 132 | static PyObject * future_new_iter(PyObject *); |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 133 | |
Yury Selivanov | 9d411c1 | 2018-01-23 15:10:03 -0500 | [diff] [blame] | 134 | static PyRunningLoopHolder * new_running_loop_holder(PyObject *); |
| 135 | |
Yury Selivanov | a70232f | 2017-12-13 14:49:42 -0500 | [diff] [blame] | 136 | |
| 137 | static int |
Yury Selivanov | a9d7e55 | 2017-12-19 07:18:45 -0500 | [diff] [blame] | 138 | _is_coroutine(PyObject *coro) |
| 139 | { |
| 140 | /* 'coro' is not a native coroutine, call asyncio.iscoroutine() |
| 141 | to check if it's another coroutine flavour. |
| 142 | |
| 143 | Do this check after 'future_init()'; in case we need to raise |
| 144 | an error, __del__ needs a properly initialized object. |
| 145 | */ |
Petr Viktorin | ffd9753 | 2020-02-11 17:46:57 +0100 | [diff] [blame] | 146 | PyObject *res = PyObject_CallOneArg(asyncio_iscoroutine_func, coro); |
Yury Selivanov | a9d7e55 | 2017-12-19 07:18:45 -0500 | [diff] [blame] | 147 | if (res == NULL) { |
| 148 | return -1; |
| 149 | } |
| 150 | |
| 151 | int is_res_true = PyObject_IsTrue(res); |
| 152 | Py_DECREF(res); |
| 153 | if (is_res_true <= 0) { |
| 154 | return is_res_true; |
| 155 | } |
| 156 | |
Andrew Svetlov | 0f47fa2 | 2017-12-23 22:06:46 +0200 | [diff] [blame] | 157 | if (PySet_GET_SIZE(iscoroutine_typecache) < 100) { |
Yury Selivanov | a9d7e55 | 2017-12-19 07:18:45 -0500 | [diff] [blame] | 158 | /* Just in case we don't want to cache more than 100 |
| 159 | positive types. That shouldn't ever happen, unless |
| 160 | someone stressing the system on purpose. |
| 161 | */ |
| 162 | if (PySet_Add(iscoroutine_typecache, (PyObject*) Py_TYPE(coro))) { |
| 163 | return -1; |
| 164 | } |
| 165 | } |
| 166 | |
| 167 | return 1; |
| 168 | } |
| 169 | |
| 170 | |
| 171 | static inline int |
| 172 | is_coroutine(PyObject *coro) |
| 173 | { |
| 174 | if (PyCoro_CheckExact(coro)) { |
| 175 | return 1; |
| 176 | } |
| 177 | |
| 178 | /* Check if `type(coro)` is in the cache. |
| 179 | Caching makes is_coroutine() function almost as fast as |
| 180 | PyCoro_CheckExact() for non-native coroutine-like objects |
| 181 | (like coroutines compiled with Cython). |
| 182 | |
| 183 | asyncio.iscoroutine() has its own type caching mechanism. |
| 184 | This cache allows us to avoid the cost of even calling |
| 185 | a pure-Python function in 99.9% cases. |
| 186 | */ |
| 187 | int has_it = PySet_Contains( |
| 188 | iscoroutine_typecache, (PyObject*) Py_TYPE(coro)); |
| 189 | if (has_it == 0) { |
| 190 | /* type(coro) is not in iscoroutine_typecache */ |
| 191 | return _is_coroutine(coro); |
| 192 | } |
| 193 | |
Leo Arias | c3d9508 | 2018-02-03 18:36:10 -0600 | [diff] [blame] | 194 | /* either an error has occurred or |
Yury Selivanov | a9d7e55 | 2017-12-19 07:18:45 -0500 | [diff] [blame] | 195 | type(coro) is in iscoroutine_typecache |
| 196 | */ |
| 197 | return has_it; |
| 198 | } |
| 199 | |
| 200 | |
Yury Selivanov | ca9b36c | 2017-12-23 15:04:15 -0500 | [diff] [blame] | 201 | static PyObject * |
| 202 | get_future_loop(PyObject *fut) |
| 203 | { |
| 204 | /* Implementation of `asyncio.futures._get_loop` */ |
| 205 | |
| 206 | _Py_IDENTIFIER(get_loop); |
| 207 | _Py_IDENTIFIER(_loop); |
Serhiy Storchaka | 6655354 | 2018-05-20 16:30:31 +0300 | [diff] [blame] | 208 | PyObject *getloop; |
Yury Selivanov | ca9b36c | 2017-12-23 15:04:15 -0500 | [diff] [blame] | 209 | |
| 210 | if (Future_CheckExact(fut) || Task_CheckExact(fut)) { |
| 211 | PyObject *loop = ((FutureObj *)fut)->fut_loop; |
| 212 | Py_INCREF(loop); |
| 213 | return loop; |
| 214 | } |
| 215 | |
Serhiy Storchaka | 6655354 | 2018-05-20 16:30:31 +0300 | [diff] [blame] | 216 | if (_PyObject_LookupAttrId(fut, &PyId_get_loop, &getloop) < 0) { |
| 217 | return NULL; |
| 218 | } |
Yury Selivanov | ca9b36c | 2017-12-23 15:04:15 -0500 | [diff] [blame] | 219 | if (getloop != NULL) { |
Victor Stinner | 2ff58a2 | 2019-06-17 14:27:23 +0200 | [diff] [blame] | 220 | PyObject *res = PyObject_CallNoArgs(getloop); |
Yury Selivanov | ca9b36c | 2017-12-23 15:04:15 -0500 | [diff] [blame] | 221 | Py_DECREF(getloop); |
| 222 | return res; |
| 223 | } |
| 224 | |
| 225 | return _PyObject_GetAttrId(fut, &PyId__loop); |
| 226 | } |
| 227 | |
| 228 | |
Yury Selivanov | a9d7e55 | 2017-12-19 07:18:45 -0500 | [diff] [blame] | 229 | static int |
Yury Selivanov | a70232f | 2017-12-13 14:49:42 -0500 | [diff] [blame] | 230 | get_running_loop(PyObject **loop) |
| 231 | { |
Yury Selivanov | 9d411c1 | 2018-01-23 15:10:03 -0500 | [diff] [blame] | 232 | PyObject *rl; |
Yury Selivanov | a70232f | 2017-12-13 14:49:42 -0500 | [diff] [blame] | 233 | |
Yury Selivanov | 9d411c1 | 2018-01-23 15:10:03 -0500 | [diff] [blame] | 234 | PyThreadState *ts = PyThreadState_Get(); |
Victor Stinner | 5c3cda0 | 2020-03-25 21:23:53 +0100 | [diff] [blame] | 235 | uint64_t ts_id = PyThreadState_GetID(ts); |
| 236 | if (ts_id == cached_running_holder_tsid && cached_running_holder != NULL) { |
Yury Selivanov | 9d411c1 | 2018-01-23 15:10:03 -0500 | [diff] [blame] | 237 | // Fast path, check the cache. |
| 238 | rl = cached_running_holder; // borrowed |
| 239 | } |
| 240 | else { |
Victor Stinner | 0e427c6 | 2020-03-25 21:22:55 +0100 | [diff] [blame] | 241 | PyObject *ts_dict = _PyThreadState_GetDict(ts); // borrowed |
| 242 | if (ts_dict == NULL) { |
Yury Selivanov | 9d411c1 | 2018-01-23 15:10:03 -0500 | [diff] [blame] | 243 | goto not_found; |
| 244 | } |
| 245 | |
| 246 | rl = _PyDict_GetItemIdWithError( |
Victor Stinner | 0e427c6 | 2020-03-25 21:22:55 +0100 | [diff] [blame] | 247 | ts_dict, &PyId___asyncio_running_event_loop__); // borrowed |
Yury Selivanov | 9d411c1 | 2018-01-23 15:10:03 -0500 | [diff] [blame] | 248 | if (rl == NULL) { |
| 249 | if (PyErr_Occurred()) { |
| 250 | goto error; |
| 251 | } |
| 252 | else { |
| 253 | goto not_found; |
| 254 | } |
| 255 | } |
| 256 | |
| 257 | cached_running_holder = rl; // borrowed |
Victor Stinner | 5c3cda0 | 2020-03-25 21:23:53 +0100 | [diff] [blame] | 258 | cached_running_holder_tsid = ts_id; |
Yury Selivanov | a70232f | 2017-12-13 14:49:42 -0500 | [diff] [blame] | 259 | } |
| 260 | |
Dong-hee Na | 1b55b65 | 2020-02-17 19:09:15 +0900 | [diff] [blame] | 261 | assert(Py_IS_TYPE(rl, &PyRunningLoopHolder_Type)); |
Yury Selivanov | 9d411c1 | 2018-01-23 15:10:03 -0500 | [diff] [blame] | 262 | PyObject *running_loop = ((PyRunningLoopHolder *)rl)->rl_loop; |
Yury Selivanov | a70232f | 2017-12-13 14:49:42 -0500 | [diff] [blame] | 263 | |
| 264 | if (running_loop == Py_None) { |
| 265 | goto not_found; |
| 266 | } |
| 267 | |
Yury Selivanov | 9d411c1 | 2018-01-23 15:10:03 -0500 | [diff] [blame] | 268 | #if defined(HAVE_GETPID) && !defined(MS_WINDOWS) |
| 269 | /* On Windows there is no getpid, but there is also no os.fork(), |
| 270 | so there is no need for this check. |
| 271 | */ |
| 272 | if (getpid() != ((PyRunningLoopHolder *)rl)->rl_pid) { |
| 273 | goto not_found; |
Yury Selivanov | a70232f | 2017-12-13 14:49:42 -0500 | [diff] [blame] | 274 | } |
Yury Selivanov | 9d411c1 | 2018-01-23 15:10:03 -0500 | [diff] [blame] | 275 | #endif |
Yury Selivanov | a70232f | 2017-12-13 14:49:42 -0500 | [diff] [blame] | 276 | |
Yury Selivanov | 9d411c1 | 2018-01-23 15:10:03 -0500 | [diff] [blame] | 277 | Py_INCREF(running_loop); |
| 278 | *loop = running_loop; |
| 279 | return 0; |
Yury Selivanov | a70232f | 2017-12-13 14:49:42 -0500 | [diff] [blame] | 280 | |
| 281 | not_found: |
| 282 | *loop = NULL; |
| 283 | return 0; |
| 284 | |
Yury Selivanov | a70232f | 2017-12-13 14:49:42 -0500 | [diff] [blame] | 285 | error: |
| 286 | *loop = NULL; |
| 287 | return -1; |
| 288 | } |
| 289 | |
| 290 | |
| 291 | static int |
| 292 | set_running_loop(PyObject *loop) |
| 293 | { |
Yury Selivanov | 9d411c1 | 2018-01-23 15:10:03 -0500 | [diff] [blame] | 294 | cached_running_holder = NULL; |
| 295 | cached_running_holder_tsid = 0; |
Yury Selivanov | a70232f | 2017-12-13 14:49:42 -0500 | [diff] [blame] | 296 | |
Yury Selivanov | 9d411c1 | 2018-01-23 15:10:03 -0500 | [diff] [blame] | 297 | PyObject *ts_dict = PyThreadState_GetDict(); // borrowed |
Yury Selivanov | a70232f | 2017-12-13 14:49:42 -0500 | [diff] [blame] | 298 | if (ts_dict == NULL) { |
| 299 | PyErr_SetString( |
| 300 | PyExc_RuntimeError, "thread-local storage is not available"); |
| 301 | return -1; |
| 302 | } |
| 303 | |
Yury Selivanov | 9d411c1 | 2018-01-23 15:10:03 -0500 | [diff] [blame] | 304 | PyRunningLoopHolder *rl = new_running_loop_holder(loop); |
| 305 | if (rl == NULL) { |
Yury Selivanov | a70232f | 2017-12-13 14:49:42 -0500 | [diff] [blame] | 306 | return -1; |
| 307 | } |
| 308 | |
Yury Selivanov | a70232f | 2017-12-13 14:49:42 -0500 | [diff] [blame] | 309 | if (_PyDict_SetItemId( |
Yury Selivanov | 9d411c1 | 2018-01-23 15:10:03 -0500 | [diff] [blame] | 310 | ts_dict, &PyId___asyncio_running_event_loop__, (PyObject *)rl) < 0) |
| 311 | { |
| 312 | Py_DECREF(rl); // will cleanup loop & current_pid |
Yury Selivanov | a70232f | 2017-12-13 14:49:42 -0500 | [diff] [blame] | 313 | return -1; |
| 314 | } |
Yury Selivanov | 9d411c1 | 2018-01-23 15:10:03 -0500 | [diff] [blame] | 315 | Py_DECREF(rl); |
Yury Selivanov | a70232f | 2017-12-13 14:49:42 -0500 | [diff] [blame] | 316 | |
| 317 | return 0; |
| 318 | } |
| 319 | |
| 320 | |
| 321 | static PyObject * |
| 322 | get_event_loop(void) |
| 323 | { |
| 324 | PyObject *loop; |
| 325 | PyObject *policy; |
| 326 | |
| 327 | if (get_running_loop(&loop)) { |
| 328 | return NULL; |
| 329 | } |
| 330 | if (loop != NULL) { |
| 331 | return loop; |
| 332 | } |
| 333 | |
Victor Stinner | 2ff58a2 | 2019-06-17 14:27:23 +0200 | [diff] [blame] | 334 | policy = PyObject_CallNoArgs(asyncio_get_event_loop_policy); |
Yury Selivanov | a70232f | 2017-12-13 14:49:42 -0500 | [diff] [blame] | 335 | if (policy == NULL) { |
| 336 | return NULL; |
| 337 | } |
| 338 | |
Jeroen Demeyer | 762f93f | 2019-07-08 10:19:25 +0200 | [diff] [blame] | 339 | loop = _PyObject_CallMethodIdNoArgs(policy, &PyId_get_event_loop); |
Yury Selivanov | a70232f | 2017-12-13 14:49:42 -0500 | [diff] [blame] | 340 | Py_DECREF(policy); |
| 341 | return loop; |
| 342 | } |
| 343 | |
| 344 | |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 345 | static int |
Yury Selivanov | 994269c | 2018-09-27 14:55:55 -0400 | [diff] [blame] | 346 | call_soon(PyObject *loop, PyObject *func, PyObject *arg, PyObject *ctx) |
Yury Selivanov | 1b7c11f | 2017-12-17 20:19:47 -0500 | [diff] [blame] | 347 | { |
| 348 | PyObject *handle; |
Yury Selivanov | f23746a | 2018-01-22 19:11:18 -0500 | [diff] [blame] | 349 | PyObject *stack[3]; |
| 350 | Py_ssize_t nargs; |
| 351 | |
| 352 | if (ctx == NULL) { |
| 353 | handle = _PyObject_CallMethodIdObjArgs( |
| 354 | loop, &PyId_call_soon, func, arg, NULL); |
| 355 | } |
| 356 | else { |
| 357 | /* Use FASTCALL to pass a keyword-only argument to call_soon */ |
| 358 | |
| 359 | PyObject *callable = _PyObject_GetAttrId(loop, &PyId_call_soon); |
| 360 | if (callable == NULL) { |
| 361 | return -1; |
| 362 | } |
| 363 | |
| 364 | /* All refs in 'stack' are borrowed. */ |
| 365 | nargs = 1; |
| 366 | stack[0] = func; |
| 367 | if (arg != NULL) { |
| 368 | stack[1] = arg; |
| 369 | nargs++; |
| 370 | } |
| 371 | stack[nargs] = (PyObject *)ctx; |
| 372 | |
Petr Viktorin | ffd9753 | 2020-02-11 17:46:57 +0100 | [diff] [blame] | 373 | handle = PyObject_Vectorcall(callable, stack, nargs, context_kwname); |
Yury Selivanov | f23746a | 2018-01-22 19:11:18 -0500 | [diff] [blame] | 374 | Py_DECREF(callable); |
| 375 | } |
| 376 | |
Yury Selivanov | 1b7c11f | 2017-12-17 20:19:47 -0500 | [diff] [blame] | 377 | if (handle == NULL) { |
| 378 | return -1; |
| 379 | } |
| 380 | Py_DECREF(handle); |
| 381 | return 0; |
| 382 | } |
| 383 | |
| 384 | |
| 385 | static inline int |
| 386 | future_is_alive(FutureObj *fut) |
| 387 | { |
| 388 | return fut->fut_loop != NULL; |
| 389 | } |
| 390 | |
| 391 | |
| 392 | static inline int |
| 393 | future_ensure_alive(FutureObj *fut) |
| 394 | { |
| 395 | if (!future_is_alive(fut)) { |
| 396 | PyErr_SetString(PyExc_RuntimeError, |
| 397 | "Future object is not initialized."); |
| 398 | return -1; |
| 399 | } |
| 400 | return 0; |
| 401 | } |
| 402 | |
| 403 | |
| 404 | #define ENSURE_FUTURE_ALIVE(fut) \ |
| 405 | do { \ |
| 406 | assert(Future_Check(fut) || Task_Check(fut)); \ |
| 407 | if (future_ensure_alive((FutureObj*)fut)) { \ |
| 408 | return NULL; \ |
| 409 | } \ |
| 410 | } while(0); |
| 411 | |
| 412 | |
| 413 | static int |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 414 | future_schedule_callbacks(FutureObj *fut) |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 415 | { |
| 416 | Py_ssize_t len; |
Yury Selivanov | 1b7c11f | 2017-12-17 20:19:47 -0500 | [diff] [blame] | 417 | Py_ssize_t i; |
| 418 | |
| 419 | if (fut->fut_callback0 != NULL) { |
| 420 | /* There's a 1st callback */ |
| 421 | |
| 422 | int ret = call_soon( |
Yury Selivanov | f23746a | 2018-01-22 19:11:18 -0500 | [diff] [blame] | 423 | fut->fut_loop, fut->fut_callback0, |
| 424 | (PyObject *)fut, fut->fut_context0); |
| 425 | |
Yury Selivanov | 1b7c11f | 2017-12-17 20:19:47 -0500 | [diff] [blame] | 426 | Py_CLEAR(fut->fut_callback0); |
Yury Selivanov | f23746a | 2018-01-22 19:11:18 -0500 | [diff] [blame] | 427 | Py_CLEAR(fut->fut_context0); |
Yury Selivanov | 1b7c11f | 2017-12-17 20:19:47 -0500 | [diff] [blame] | 428 | if (ret) { |
| 429 | /* If an error occurs in pure-Python implementation, |
| 430 | all callbacks are cleared. */ |
| 431 | Py_CLEAR(fut->fut_callbacks); |
| 432 | return ret; |
| 433 | } |
| 434 | |
| 435 | /* we called the first callback, now try calling |
| 436 | callbacks from the 'fut_callbacks' list. */ |
| 437 | } |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 438 | |
| 439 | if (fut->fut_callbacks == NULL) { |
Yury Selivanov | 1b7c11f | 2017-12-17 20:19:47 -0500 | [diff] [blame] | 440 | /* No more callbacks, return. */ |
| 441 | return 0; |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 442 | } |
| 443 | |
| 444 | len = PyList_GET_SIZE(fut->fut_callbacks); |
| 445 | if (len == 0) { |
Yury Selivanov | 1b7c11f | 2017-12-17 20:19:47 -0500 | [diff] [blame] | 446 | /* The list of callbacks was empty; clear it and return. */ |
| 447 | Py_CLEAR(fut->fut_callbacks); |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 448 | return 0; |
| 449 | } |
| 450 | |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 451 | for (i = 0; i < len; i++) { |
Yury Selivanov | f23746a | 2018-01-22 19:11:18 -0500 | [diff] [blame] | 452 | PyObject *cb_tup = PyList_GET_ITEM(fut->fut_callbacks, i); |
| 453 | PyObject *cb = PyTuple_GET_ITEM(cb_tup, 0); |
| 454 | PyObject *ctx = PyTuple_GET_ITEM(cb_tup, 1); |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 455 | |
Yury Selivanov | 994269c | 2018-09-27 14:55:55 -0400 | [diff] [blame] | 456 | if (call_soon(fut->fut_loop, cb, (PyObject *)fut, ctx)) { |
Yury Selivanov | 1b7c11f | 2017-12-17 20:19:47 -0500 | [diff] [blame] | 457 | /* If an error occurs in pure-Python implementation, |
| 458 | all callbacks are cleared. */ |
| 459 | Py_CLEAR(fut->fut_callbacks); |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 460 | return -1; |
| 461 | } |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 462 | } |
| 463 | |
Yury Selivanov | 1b7c11f | 2017-12-17 20:19:47 -0500 | [diff] [blame] | 464 | Py_CLEAR(fut->fut_callbacks); |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 465 | return 0; |
| 466 | } |
| 467 | |
Oren Milman | d019bc8 | 2018-02-13 12:28:33 +0200 | [diff] [blame] | 468 | |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 469 | static int |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 470 | future_init(FutureObj *fut, PyObject *loop) |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 471 | { |
Serhiy Storchaka | bca4939 | 2017-09-03 08:10:14 +0300 | [diff] [blame] | 472 | PyObject *res; |
| 473 | int is_true; |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 474 | _Py_IDENTIFIER(get_debug); |
| 475 | |
Oren Milman | d019bc8 | 2018-02-13 12:28:33 +0200 | [diff] [blame] | 476 | // Same to FutureObj_clear() but not clearing fut->dict |
| 477 | Py_CLEAR(fut->fut_loop); |
| 478 | Py_CLEAR(fut->fut_callback0); |
| 479 | Py_CLEAR(fut->fut_context0); |
| 480 | Py_CLEAR(fut->fut_callbacks); |
| 481 | Py_CLEAR(fut->fut_result); |
| 482 | Py_CLEAR(fut->fut_exception); |
| 483 | Py_CLEAR(fut->fut_source_tb); |
Chris Jerdonek | 1ce5841 | 2020-05-15 16:55:50 -0700 | [diff] [blame] | 484 | Py_CLEAR(fut->fut_cancel_msg); |
Chris Jerdonek | da742ba | 2020-05-17 22:47:31 -0700 | [diff] [blame] | 485 | _PyErr_ClearExcState(&fut->fut_cancelled_exc_state); |
Oren Milman | d019bc8 | 2018-02-13 12:28:33 +0200 | [diff] [blame] | 486 | |
| 487 | fut->fut_state = STATE_PENDING; |
| 488 | fut->fut_log_tb = 0; |
| 489 | fut->fut_blocking = 0; |
| 490 | |
Serhiy Storchaka | bca4939 | 2017-09-03 08:10:14 +0300 | [diff] [blame] | 491 | if (loop == Py_None) { |
Yury Selivanov | a70232f | 2017-12-13 14:49:42 -0500 | [diff] [blame] | 492 | loop = get_event_loop(); |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 493 | if (loop == NULL) { |
| 494 | return -1; |
| 495 | } |
| 496 | } |
| 497 | else { |
| 498 | Py_INCREF(loop); |
| 499 | } |
Oren Milman | d019bc8 | 2018-02-13 12:28:33 +0200 | [diff] [blame] | 500 | fut->fut_loop = loop; |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 501 | |
Jeroen Demeyer | 762f93f | 2019-07-08 10:19:25 +0200 | [diff] [blame] | 502 | res = _PyObject_CallMethodIdNoArgs(fut->fut_loop, &PyId_get_debug); |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 503 | if (res == NULL) { |
| 504 | return -1; |
| 505 | } |
Serhiy Storchaka | bca4939 | 2017-09-03 08:10:14 +0300 | [diff] [blame] | 506 | is_true = PyObject_IsTrue(res); |
| 507 | Py_DECREF(res); |
| 508 | if (is_true < 0) { |
| 509 | return -1; |
| 510 | } |
Yury Selivanov | 35230d0 | 2018-05-28 11:11:31 -0400 | [diff] [blame] | 511 | if (is_true && !_Py_IsFinalizing()) { |
| 512 | /* Only try to capture the traceback if the interpreter is not being |
| 513 | finalized. The original motivation to add a `_Py_IsFinalizing()` |
| 514 | call was to prevent SIGSEGV when a Future is created in a __del__ |
| 515 | method, which is called during the interpreter shutdown and the |
| 516 | traceback module is already unloaded. |
| 517 | */ |
Victor Stinner | 2ff58a2 | 2019-06-17 14:27:23 +0200 | [diff] [blame] | 518 | fut->fut_source_tb = PyObject_CallNoArgs(traceback_extract_stack); |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 519 | if (fut->fut_source_tb == NULL) { |
| 520 | return -1; |
| 521 | } |
| 522 | } |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 523 | |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 524 | return 0; |
| 525 | } |
| 526 | |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 527 | static PyObject * |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 528 | future_set_result(FutureObj *fut, PyObject *res) |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 529 | { |
Yury Selivanov | 1b7c11f | 2017-12-17 20:19:47 -0500 | [diff] [blame] | 530 | if (future_ensure_alive(fut)) { |
| 531 | return NULL; |
| 532 | } |
| 533 | |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 534 | if (fut->fut_state != STATE_PENDING) { |
| 535 | PyErr_SetString(asyncio_InvalidStateError, "invalid state"); |
| 536 | return NULL; |
| 537 | } |
| 538 | |
Serhiy Storchaka | bca4939 | 2017-09-03 08:10:14 +0300 | [diff] [blame] | 539 | assert(!fut->fut_result); |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 540 | Py_INCREF(res); |
| 541 | fut->fut_result = res; |
| 542 | fut->fut_state = STATE_FINISHED; |
| 543 | |
Yury Selivanov | 22feeb8 | 2018-01-24 11:31:01 -0500 | [diff] [blame] | 544 | if (future_schedule_callbacks(fut) == -1) { |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 545 | return NULL; |
| 546 | } |
| 547 | Py_RETURN_NONE; |
| 548 | } |
| 549 | |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 550 | static PyObject * |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 551 | future_set_exception(FutureObj *fut, PyObject *exc) |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 552 | { |
| 553 | PyObject *exc_val = NULL; |
| 554 | |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 555 | if (fut->fut_state != STATE_PENDING) { |
| 556 | PyErr_SetString(asyncio_InvalidStateError, "invalid state"); |
| 557 | return NULL; |
| 558 | } |
| 559 | |
| 560 | if (PyExceptionClass_Check(exc)) { |
Victor Stinner | 2ff58a2 | 2019-06-17 14:27:23 +0200 | [diff] [blame] | 561 | exc_val = PyObject_CallNoArgs(exc); |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 562 | if (exc_val == NULL) { |
| 563 | return NULL; |
| 564 | } |
Serhiy Storchaka | bca4939 | 2017-09-03 08:10:14 +0300 | [diff] [blame] | 565 | if (fut->fut_state != STATE_PENDING) { |
| 566 | Py_DECREF(exc_val); |
| 567 | PyErr_SetString(asyncio_InvalidStateError, "invalid state"); |
| 568 | return NULL; |
| 569 | } |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 570 | } |
| 571 | else { |
| 572 | exc_val = exc; |
| 573 | Py_INCREF(exc_val); |
| 574 | } |
| 575 | if (!PyExceptionInstance_Check(exc_val)) { |
| 576 | Py_DECREF(exc_val); |
| 577 | PyErr_SetString(PyExc_TypeError, "invalid exception object"); |
| 578 | return NULL; |
| 579 | } |
Andy Lester | dffe4c0 | 2020-03-04 07:15:20 -0600 | [diff] [blame] | 580 | if (Py_IS_TYPE(exc_val, (PyTypeObject *)PyExc_StopIteration)) { |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 581 | Py_DECREF(exc_val); |
| 582 | PyErr_SetString(PyExc_TypeError, |
| 583 | "StopIteration interacts badly with generators " |
| 584 | "and cannot be raised into a Future"); |
| 585 | return NULL; |
| 586 | } |
| 587 | |
Serhiy Storchaka | bca4939 | 2017-09-03 08:10:14 +0300 | [diff] [blame] | 588 | assert(!fut->fut_exception); |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 589 | fut->fut_exception = exc_val; |
| 590 | fut->fut_state = STATE_FINISHED; |
| 591 | |
Yury Selivanov | 22feeb8 | 2018-01-24 11:31:01 -0500 | [diff] [blame] | 592 | if (future_schedule_callbacks(fut) == -1) { |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 593 | return NULL; |
| 594 | } |
| 595 | |
| 596 | fut->fut_log_tb = 1; |
| 597 | Py_RETURN_NONE; |
| 598 | } |
| 599 | |
Chris Jerdonek | 1ce5841 | 2020-05-15 16:55:50 -0700 | [diff] [blame] | 600 | static PyObject * |
| 601 | create_cancelled_error(PyObject *msg) |
| 602 | { |
| 603 | PyObject *exc; |
| 604 | if (msg == NULL || msg == Py_None) { |
Chris Jerdonek | da742ba | 2020-05-17 22:47:31 -0700 | [diff] [blame] | 605 | exc = PyObject_CallNoArgs(asyncio_CancelledError); |
Chris Jerdonek | 1ce5841 | 2020-05-15 16:55:50 -0700 | [diff] [blame] | 606 | } else { |
| 607 | exc = PyObject_CallOneArg(asyncio_CancelledError, msg); |
| 608 | } |
| 609 | return exc; |
| 610 | } |
| 611 | |
| 612 | static void |
Miss Islington (bot) | 7f77ac4 | 2020-05-22 14:35:22 -0700 | [diff] [blame] | 613 | future_set_cancelled_error(FutureObj *fut) |
Chris Jerdonek | 1ce5841 | 2020-05-15 16:55:50 -0700 | [diff] [blame] | 614 | { |
Miss Islington (bot) | 7f77ac4 | 2020-05-22 14:35:22 -0700 | [diff] [blame] | 615 | PyObject *exc = create_cancelled_error(fut->fut_cancel_msg); |
Chris Jerdonek | 1ce5841 | 2020-05-15 16:55:50 -0700 | [diff] [blame] | 616 | PyErr_SetObject(asyncio_CancelledError, exc); |
| 617 | Py_DECREF(exc); |
Miss Islington (bot) | 7f77ac4 | 2020-05-22 14:35:22 -0700 | [diff] [blame] | 618 | |
| 619 | _PyErr_ChainStackItem(&fut->fut_cancelled_exc_state); |
Chris Jerdonek | 1ce5841 | 2020-05-15 16:55:50 -0700 | [diff] [blame] | 620 | } |
| 621 | |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 622 | static int |
| 623 | future_get_result(FutureObj *fut, PyObject **result) |
| 624 | { |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 625 | if (fut->fut_state == STATE_CANCELLED) { |
Miss Islington (bot) | 7f77ac4 | 2020-05-22 14:35:22 -0700 | [diff] [blame] | 626 | future_set_cancelled_error(fut); |
Serhiy Storchaka | bca4939 | 2017-09-03 08:10:14 +0300 | [diff] [blame] | 627 | return -1; |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 628 | } |
| 629 | |
| 630 | if (fut->fut_state != STATE_FINISHED) { |
Serhiy Storchaka | bca4939 | 2017-09-03 08:10:14 +0300 | [diff] [blame] | 631 | PyErr_SetString(asyncio_InvalidStateError, "Result is not set."); |
| 632 | return -1; |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 633 | } |
| 634 | |
| 635 | fut->fut_log_tb = 0; |
| 636 | if (fut->fut_exception != NULL) { |
| 637 | Py_INCREF(fut->fut_exception); |
| 638 | *result = fut->fut_exception; |
| 639 | return 1; |
| 640 | } |
| 641 | |
| 642 | Py_INCREF(fut->fut_result); |
| 643 | *result = fut->fut_result; |
| 644 | return 0; |
| 645 | } |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 646 | |
| 647 | static PyObject * |
Yury Selivanov | 994269c | 2018-09-27 14:55:55 -0400 | [diff] [blame] | 648 | future_add_done_callback(FutureObj *fut, PyObject *arg, PyObject *ctx) |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 649 | { |
Yury Selivanov | 1b7c11f | 2017-12-17 20:19:47 -0500 | [diff] [blame] | 650 | if (!future_is_alive(fut)) { |
| 651 | PyErr_SetString(PyExc_RuntimeError, "uninitialized Future object"); |
| 652 | return NULL; |
| 653 | } |
| 654 | |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 655 | if (fut->fut_state != STATE_PENDING) { |
Yury Selivanov | 1b7c11f | 2017-12-17 20:19:47 -0500 | [diff] [blame] | 656 | /* The future is done/cancelled, so schedule the callback |
| 657 | right away. */ |
Yury Selivanov | f23746a | 2018-01-22 19:11:18 -0500 | [diff] [blame] | 658 | if (call_soon(fut->fut_loop, arg, (PyObject*) fut, ctx)) { |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 659 | return NULL; |
| 660 | } |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 661 | } |
| 662 | else { |
Yury Selivanov | 1b7c11f | 2017-12-17 20:19:47 -0500 | [diff] [blame] | 663 | /* The future is pending, add a callback. |
| 664 | |
| 665 | Callbacks in the future object are stored as follows: |
| 666 | |
| 667 | callback0 -- a pointer to the first callback |
| 668 | callbacks -- a list of 2nd, 3rd, ... callbacks |
| 669 | |
| 670 | Invariants: |
| 671 | |
| 672 | * callbacks != NULL: |
| 673 | There are some callbacks in in the list. Just |
| 674 | add the new callback to it. |
| 675 | |
| 676 | * callbacks == NULL and callback0 == NULL: |
| 677 | This is the first callback. Set it to callback0. |
| 678 | |
| 679 | * callbacks == NULL and callback0 != NULL: |
| 680 | This is a second callback. Initialize callbacks |
| 681 | with a new list and add the new callback to it. |
| 682 | */ |
| 683 | |
Yury Selivanov | f23746a | 2018-01-22 19:11:18 -0500 | [diff] [blame] | 684 | if (fut->fut_callbacks == NULL && fut->fut_callback0 == NULL) { |
Yury Selivanov | 1b7c11f | 2017-12-17 20:19:47 -0500 | [diff] [blame] | 685 | Py_INCREF(arg); |
| 686 | fut->fut_callback0 = arg; |
Yury Selivanov | f23746a | 2018-01-22 19:11:18 -0500 | [diff] [blame] | 687 | Py_INCREF(ctx); |
| 688 | fut->fut_context0 = ctx; |
Yury Selivanov | 1b7c11f | 2017-12-17 20:19:47 -0500 | [diff] [blame] | 689 | } |
| 690 | else { |
Yury Selivanov | f23746a | 2018-01-22 19:11:18 -0500 | [diff] [blame] | 691 | PyObject *tup = PyTuple_New(2); |
| 692 | if (tup == NULL) { |
Yury Selivanov | 1b7c11f | 2017-12-17 20:19:47 -0500 | [diff] [blame] | 693 | return NULL; |
| 694 | } |
Yury Selivanov | 1b7c11f | 2017-12-17 20:19:47 -0500 | [diff] [blame] | 695 | Py_INCREF(arg); |
Yury Selivanov | f23746a | 2018-01-22 19:11:18 -0500 | [diff] [blame] | 696 | PyTuple_SET_ITEM(tup, 0, arg); |
| 697 | Py_INCREF(ctx); |
| 698 | PyTuple_SET_ITEM(tup, 1, (PyObject *)ctx); |
| 699 | |
| 700 | if (fut->fut_callbacks != NULL) { |
| 701 | int err = PyList_Append(fut->fut_callbacks, tup); |
| 702 | if (err) { |
| 703 | Py_DECREF(tup); |
| 704 | return NULL; |
| 705 | } |
| 706 | Py_DECREF(tup); |
| 707 | } |
| 708 | else { |
| 709 | fut->fut_callbacks = PyList_New(1); |
| 710 | if (fut->fut_callbacks == NULL) { |
| 711 | return NULL; |
| 712 | } |
| 713 | |
| 714 | PyList_SET_ITEM(fut->fut_callbacks, 0, tup); /* borrow */ |
| 715 | } |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 716 | } |
| 717 | } |
Yury Selivanov | 1b7c11f | 2017-12-17 20:19:47 -0500 | [diff] [blame] | 718 | |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 719 | Py_RETURN_NONE; |
| 720 | } |
| 721 | |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 722 | static PyObject * |
Chris Jerdonek | 1ce5841 | 2020-05-15 16:55:50 -0700 | [diff] [blame] | 723 | future_cancel(FutureObj *fut, PyObject *msg) |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 724 | { |
Yury Selivanov | 7ce1c6f | 2017-06-11 13:49:18 +0000 | [diff] [blame] | 725 | fut->fut_log_tb = 0; |
| 726 | |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 727 | if (fut->fut_state != STATE_PENDING) { |
| 728 | Py_RETURN_FALSE; |
| 729 | } |
| 730 | fut->fut_state = STATE_CANCELLED; |
| 731 | |
Chris Jerdonek | 1ce5841 | 2020-05-15 16:55:50 -0700 | [diff] [blame] | 732 | Py_XINCREF(msg); |
| 733 | Py_XSETREF(fut->fut_cancel_msg, msg); |
| 734 | |
Yury Selivanov | 22feeb8 | 2018-01-24 11:31:01 -0500 | [diff] [blame] | 735 | if (future_schedule_callbacks(fut) == -1) { |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 736 | return NULL; |
| 737 | } |
| 738 | |
| 739 | Py_RETURN_TRUE; |
| 740 | } |
| 741 | |
| 742 | /*[clinic input] |
| 743 | _asyncio.Future.__init__ |
| 744 | |
| 745 | * |
Serhiy Storchaka | bca4939 | 2017-09-03 08:10:14 +0300 | [diff] [blame] | 746 | loop: object = None |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 747 | |
| 748 | This class is *almost* compatible with concurrent.futures.Future. |
| 749 | |
| 750 | Differences: |
| 751 | |
| 752 | - result() and exception() do not take a timeout argument and |
| 753 | raise an exception when the future isn't done yet. |
| 754 | |
| 755 | - Callbacks registered with add_done_callback() are always called |
| 756 | via the event loop's call_soon_threadsafe(). |
| 757 | |
| 758 | - This class is not compatible with the wait() and as_completed() |
| 759 | methods in the concurrent.futures package. |
| 760 | [clinic start generated code]*/ |
| 761 | |
| 762 | static int |
| 763 | _asyncio_Future___init___impl(FutureObj *self, PyObject *loop) |
Serhiy Storchaka | bca4939 | 2017-09-03 08:10:14 +0300 | [diff] [blame] | 764 | /*[clinic end generated code: output=9ed75799eaccb5d6 input=89af317082bc0bf8]*/ |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 765 | |
| 766 | { |
| 767 | return future_init(self, loop); |
| 768 | } |
| 769 | |
| 770 | static int |
| 771 | FutureObj_clear(FutureObj *fut) |
| 772 | { |
| 773 | Py_CLEAR(fut->fut_loop); |
Yury Selivanov | 1b7c11f | 2017-12-17 20:19:47 -0500 | [diff] [blame] | 774 | Py_CLEAR(fut->fut_callback0); |
Yury Selivanov | f23746a | 2018-01-22 19:11:18 -0500 | [diff] [blame] | 775 | Py_CLEAR(fut->fut_context0); |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 776 | Py_CLEAR(fut->fut_callbacks); |
| 777 | Py_CLEAR(fut->fut_result); |
| 778 | Py_CLEAR(fut->fut_exception); |
| 779 | Py_CLEAR(fut->fut_source_tb); |
Chris Jerdonek | 1ce5841 | 2020-05-15 16:55:50 -0700 | [diff] [blame] | 780 | Py_CLEAR(fut->fut_cancel_msg); |
Chris Jerdonek | da742ba | 2020-05-17 22:47:31 -0700 | [diff] [blame] | 781 | _PyErr_ClearExcState(&fut->fut_cancelled_exc_state); |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 782 | Py_CLEAR(fut->dict); |
| 783 | return 0; |
| 784 | } |
| 785 | |
| 786 | static int |
| 787 | FutureObj_traverse(FutureObj *fut, visitproc visit, void *arg) |
| 788 | { |
| 789 | Py_VISIT(fut->fut_loop); |
Yury Selivanov | 1b7c11f | 2017-12-17 20:19:47 -0500 | [diff] [blame] | 790 | Py_VISIT(fut->fut_callback0); |
Yury Selivanov | f23746a | 2018-01-22 19:11:18 -0500 | [diff] [blame] | 791 | Py_VISIT(fut->fut_context0); |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 792 | Py_VISIT(fut->fut_callbacks); |
| 793 | Py_VISIT(fut->fut_result); |
| 794 | Py_VISIT(fut->fut_exception); |
| 795 | Py_VISIT(fut->fut_source_tb); |
Chris Jerdonek | 1ce5841 | 2020-05-15 16:55:50 -0700 | [diff] [blame] | 796 | Py_VISIT(fut->fut_cancel_msg); |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 797 | Py_VISIT(fut->dict); |
Chris Jerdonek | da742ba | 2020-05-17 22:47:31 -0700 | [diff] [blame] | 798 | |
| 799 | _PyErr_StackItem *exc_state = &fut->fut_cancelled_exc_state; |
| 800 | Py_VISIT(exc_state->exc_type); |
| 801 | Py_VISIT(exc_state->exc_value); |
| 802 | Py_VISIT(exc_state->exc_traceback); |
| 803 | |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 804 | return 0; |
| 805 | } |
| 806 | |
| 807 | /*[clinic input] |
| 808 | _asyncio.Future.result |
| 809 | |
| 810 | Return the result this future represents. |
| 811 | |
| 812 | If the future has been cancelled, raises CancelledError. If the |
| 813 | future's result isn't yet available, raises InvalidStateError. If |
| 814 | the future is done and has an exception set, this exception is raised. |
| 815 | [clinic start generated code]*/ |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 816 | |
| 817 | static PyObject * |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 818 | _asyncio_Future_result_impl(FutureObj *self) |
| 819 | /*[clinic end generated code: output=f35f940936a4b1e5 input=49ecf9cf5ec50dc5]*/ |
| 820 | { |
| 821 | PyObject *result; |
Yury Selivanov | 1b7c11f | 2017-12-17 20:19:47 -0500 | [diff] [blame] | 822 | |
| 823 | if (!future_is_alive(self)) { |
| 824 | PyErr_SetString(asyncio_InvalidStateError, |
| 825 | "Future object is not initialized."); |
| 826 | return NULL; |
| 827 | } |
| 828 | |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 829 | int res = future_get_result(self, &result); |
| 830 | |
| 831 | if (res == -1) { |
| 832 | return NULL; |
| 833 | } |
| 834 | |
| 835 | if (res == 0) { |
| 836 | return result; |
| 837 | } |
| 838 | |
| 839 | assert(res == 1); |
| 840 | |
| 841 | PyErr_SetObject(PyExceptionInstance_Class(result), result); |
| 842 | Py_DECREF(result); |
| 843 | return NULL; |
| 844 | } |
| 845 | |
| 846 | /*[clinic input] |
| 847 | _asyncio.Future.exception |
| 848 | |
| 849 | Return the exception that was set on this future. |
| 850 | |
| 851 | The exception (or None if no exception was set) is returned only if |
| 852 | the future is done. If the future has been cancelled, raises |
| 853 | CancelledError. If the future isn't done yet, raises |
| 854 | InvalidStateError. |
| 855 | [clinic start generated code]*/ |
| 856 | |
| 857 | static PyObject * |
| 858 | _asyncio_Future_exception_impl(FutureObj *self) |
| 859 | /*[clinic end generated code: output=88b20d4f855e0710 input=733547a70c841c68]*/ |
| 860 | { |
Yury Selivanov | 1b7c11f | 2017-12-17 20:19:47 -0500 | [diff] [blame] | 861 | if (!future_is_alive(self)) { |
| 862 | PyErr_SetString(asyncio_InvalidStateError, |
| 863 | "Future object is not initialized."); |
| 864 | return NULL; |
| 865 | } |
| 866 | |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 867 | if (self->fut_state == STATE_CANCELLED) { |
Miss Islington (bot) | 7f77ac4 | 2020-05-22 14:35:22 -0700 | [diff] [blame] | 868 | future_set_cancelled_error(self); |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 869 | return NULL; |
| 870 | } |
| 871 | |
| 872 | if (self->fut_state != STATE_FINISHED) { |
Serhiy Storchaka | bca4939 | 2017-09-03 08:10:14 +0300 | [diff] [blame] | 873 | PyErr_SetString(asyncio_InvalidStateError, "Exception is not set."); |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 874 | return NULL; |
| 875 | } |
| 876 | |
| 877 | if (self->fut_exception != NULL) { |
| 878 | self->fut_log_tb = 0; |
| 879 | Py_INCREF(self->fut_exception); |
| 880 | return self->fut_exception; |
| 881 | } |
| 882 | |
| 883 | Py_RETURN_NONE; |
| 884 | } |
| 885 | |
| 886 | /*[clinic input] |
| 887 | _asyncio.Future.set_result |
| 888 | |
Yury Selivanov | 0cf16f9 | 2017-12-25 10:48:15 -0500 | [diff] [blame] | 889 | result: object |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 890 | / |
| 891 | |
| 892 | Mark the future done and set its result. |
| 893 | |
| 894 | If the future is already done when this method is called, raises |
| 895 | InvalidStateError. |
| 896 | [clinic start generated code]*/ |
| 897 | |
| 898 | static PyObject * |
Yury Selivanov | 0cf16f9 | 2017-12-25 10:48:15 -0500 | [diff] [blame] | 899 | _asyncio_Future_set_result(FutureObj *self, PyObject *result) |
| 900 | /*[clinic end generated code: output=1ec2e6bcccd6f2ce input=8b75172c2a7b05f1]*/ |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 901 | { |
Yury Selivanov | 1b7c11f | 2017-12-17 20:19:47 -0500 | [diff] [blame] | 902 | ENSURE_FUTURE_ALIVE(self) |
Yury Selivanov | 0cf16f9 | 2017-12-25 10:48:15 -0500 | [diff] [blame] | 903 | return future_set_result(self, result); |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 904 | } |
| 905 | |
| 906 | /*[clinic input] |
| 907 | _asyncio.Future.set_exception |
| 908 | |
Serhiy Storchaka | bca4939 | 2017-09-03 08:10:14 +0300 | [diff] [blame] | 909 | exception: object |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 910 | / |
| 911 | |
| 912 | Mark the future done and set an exception. |
| 913 | |
| 914 | If the future is already done when this method is called, raises |
| 915 | InvalidStateError. |
| 916 | [clinic start generated code]*/ |
| 917 | |
| 918 | static PyObject * |
| 919 | _asyncio_Future_set_exception(FutureObj *self, PyObject *exception) |
Serhiy Storchaka | bca4939 | 2017-09-03 08:10:14 +0300 | [diff] [blame] | 920 | /*[clinic end generated code: output=f1c1b0cd321be360 input=e45b7d7aa71cc66d]*/ |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 921 | { |
Yury Selivanov | 1b7c11f | 2017-12-17 20:19:47 -0500 | [diff] [blame] | 922 | ENSURE_FUTURE_ALIVE(self) |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 923 | return future_set_exception(self, exception); |
| 924 | } |
| 925 | |
| 926 | /*[clinic input] |
| 927 | _asyncio.Future.add_done_callback |
| 928 | |
Serhiy Storchaka | bca4939 | 2017-09-03 08:10:14 +0300 | [diff] [blame] | 929 | fn: object |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 930 | / |
Yury Selivanov | f23746a | 2018-01-22 19:11:18 -0500 | [diff] [blame] | 931 | * |
| 932 | context: object = NULL |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 933 | |
| 934 | Add a callback to be run when the future becomes done. |
| 935 | |
| 936 | The callback is called with a single argument - the future object. If |
| 937 | the future is already done when this is called, the callback is |
| 938 | scheduled with call_soon. |
| 939 | [clinic start generated code]*/ |
| 940 | |
| 941 | static PyObject * |
Yury Selivanov | f23746a | 2018-01-22 19:11:18 -0500 | [diff] [blame] | 942 | _asyncio_Future_add_done_callback_impl(FutureObj *self, PyObject *fn, |
| 943 | PyObject *context) |
| 944 | /*[clinic end generated code: output=7ce635bbc9554c1e input=15ab0693a96e9533]*/ |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 945 | { |
Yury Selivanov | f23746a | 2018-01-22 19:11:18 -0500 | [diff] [blame] | 946 | if (context == NULL) { |
Yury Selivanov | 994269c | 2018-09-27 14:55:55 -0400 | [diff] [blame] | 947 | context = PyContext_CopyCurrent(); |
Yury Selivanov | f23746a | 2018-01-22 19:11:18 -0500 | [diff] [blame] | 948 | if (context == NULL) { |
| 949 | return NULL; |
| 950 | } |
Yury Selivanov | 994269c | 2018-09-27 14:55:55 -0400 | [diff] [blame] | 951 | PyObject *res = future_add_done_callback(self, fn, context); |
Yury Selivanov | f23746a | 2018-01-22 19:11:18 -0500 | [diff] [blame] | 952 | Py_DECREF(context); |
| 953 | return res; |
| 954 | } |
Yury Selivanov | 994269c | 2018-09-27 14:55:55 -0400 | [diff] [blame] | 955 | return future_add_done_callback(self, fn, context); |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 956 | } |
| 957 | |
| 958 | /*[clinic input] |
| 959 | _asyncio.Future.remove_done_callback |
| 960 | |
Serhiy Storchaka | bca4939 | 2017-09-03 08:10:14 +0300 | [diff] [blame] | 961 | fn: object |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 962 | / |
| 963 | |
| 964 | Remove all instances of a callback from the "call when done" list. |
| 965 | |
| 966 | Returns the number of callbacks removed. |
| 967 | [clinic start generated code]*/ |
| 968 | |
| 969 | static PyObject * |
| 970 | _asyncio_Future_remove_done_callback(FutureObj *self, PyObject *fn) |
Serhiy Storchaka | bca4939 | 2017-09-03 08:10:14 +0300 | [diff] [blame] | 971 | /*[clinic end generated code: output=5ab1fb52b24ef31f input=0a43280a149d505b]*/ |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 972 | { |
| 973 | PyObject *newlist; |
| 974 | Py_ssize_t len, i, j=0; |
Yury Selivanov | 1b7c11f | 2017-12-17 20:19:47 -0500 | [diff] [blame] | 975 | Py_ssize_t cleared_callback0 = 0; |
| 976 | |
| 977 | ENSURE_FUTURE_ALIVE(self) |
| 978 | |
| 979 | if (self->fut_callback0 != NULL) { |
Serhiy Storchaka | 18b711c | 2019-08-04 14:12:48 +0300 | [diff] [blame] | 980 | int cmp = PyObject_RichCompareBool(self->fut_callback0, fn, Py_EQ); |
Yury Selivanov | 1b7c11f | 2017-12-17 20:19:47 -0500 | [diff] [blame] | 981 | if (cmp == -1) { |
| 982 | return NULL; |
| 983 | } |
| 984 | if (cmp == 1) { |
| 985 | /* callback0 == fn */ |
| 986 | Py_CLEAR(self->fut_callback0); |
Yury Selivanov | f23746a | 2018-01-22 19:11:18 -0500 | [diff] [blame] | 987 | Py_CLEAR(self->fut_context0); |
Yury Selivanov | 1b7c11f | 2017-12-17 20:19:47 -0500 | [diff] [blame] | 988 | cleared_callback0 = 1; |
| 989 | } |
| 990 | } |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 991 | |
Serhiy Storchaka | bca4939 | 2017-09-03 08:10:14 +0300 | [diff] [blame] | 992 | if (self->fut_callbacks == NULL) { |
Yury Selivanov | 1b7c11f | 2017-12-17 20:19:47 -0500 | [diff] [blame] | 993 | return PyLong_FromSsize_t(cleared_callback0); |
Serhiy Storchaka | bca4939 | 2017-09-03 08:10:14 +0300 | [diff] [blame] | 994 | } |
| 995 | |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 996 | len = PyList_GET_SIZE(self->fut_callbacks); |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 997 | if (len == 0) { |
Yury Selivanov | 1b7c11f | 2017-12-17 20:19:47 -0500 | [diff] [blame] | 998 | Py_CLEAR(self->fut_callbacks); |
| 999 | return PyLong_FromSsize_t(cleared_callback0); |
| 1000 | } |
| 1001 | |
| 1002 | if (len == 1) { |
Yury Selivanov | f23746a | 2018-01-22 19:11:18 -0500 | [diff] [blame] | 1003 | PyObject *cb_tup = PyList_GET_ITEM(self->fut_callbacks, 0); |
Yury Selivanov | 1b7c11f | 2017-12-17 20:19:47 -0500 | [diff] [blame] | 1004 | int cmp = PyObject_RichCompareBool( |
Serhiy Storchaka | 18b711c | 2019-08-04 14:12:48 +0300 | [diff] [blame] | 1005 | PyTuple_GET_ITEM(cb_tup, 0), fn, Py_EQ); |
Yury Selivanov | 1b7c11f | 2017-12-17 20:19:47 -0500 | [diff] [blame] | 1006 | if (cmp == -1) { |
| 1007 | return NULL; |
| 1008 | } |
| 1009 | if (cmp == 1) { |
| 1010 | /* callbacks[0] == fn */ |
| 1011 | Py_CLEAR(self->fut_callbacks); |
| 1012 | return PyLong_FromSsize_t(1 + cleared_callback0); |
| 1013 | } |
| 1014 | /* callbacks[0] != fn and len(callbacks) == 1 */ |
| 1015 | return PyLong_FromSsize_t(cleared_callback0); |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 1016 | } |
| 1017 | |
| 1018 | newlist = PyList_New(len); |
| 1019 | if (newlist == NULL) { |
| 1020 | return NULL; |
| 1021 | } |
| 1022 | |
Yury Selivanov | 84af903 | 2017-03-02 23:46:56 -0500 | [diff] [blame] | 1023 | for (i = 0; i < PyList_GET_SIZE(self->fut_callbacks); i++) { |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 1024 | int ret; |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 1025 | PyObject *item = PyList_GET_ITEM(self->fut_callbacks, i); |
Serhiy Storchaka | bca4939 | 2017-09-03 08:10:14 +0300 | [diff] [blame] | 1026 | Py_INCREF(item); |
Serhiy Storchaka | 18b711c | 2019-08-04 14:12:48 +0300 | [diff] [blame] | 1027 | ret = PyObject_RichCompareBool(PyTuple_GET_ITEM(item, 0), fn, Py_EQ); |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 1028 | if (ret == 0) { |
Yury Selivanov | 833a3b0 | 2017-07-05 13:32:03 -0400 | [diff] [blame] | 1029 | if (j < len) { |
Yury Selivanov | 833a3b0 | 2017-07-05 13:32:03 -0400 | [diff] [blame] | 1030 | PyList_SET_ITEM(newlist, j, item); |
| 1031 | j++; |
Serhiy Storchaka | bca4939 | 2017-09-03 08:10:14 +0300 | [diff] [blame] | 1032 | continue; |
Yury Selivanov | 833a3b0 | 2017-07-05 13:32:03 -0400 | [diff] [blame] | 1033 | } |
Serhiy Storchaka | bca4939 | 2017-09-03 08:10:14 +0300 | [diff] [blame] | 1034 | ret = PyList_Append(newlist, item); |
| 1035 | } |
| 1036 | Py_DECREF(item); |
| 1037 | if (ret < 0) { |
| 1038 | goto fail; |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 1039 | } |
| 1040 | } |
| 1041 | |
Yury Selivanov | 1b7c11f | 2017-12-17 20:19:47 -0500 | [diff] [blame] | 1042 | if (j == 0) { |
| 1043 | Py_CLEAR(self->fut_callbacks); |
| 1044 | Py_DECREF(newlist); |
| 1045 | return PyLong_FromSsize_t(len + cleared_callback0); |
| 1046 | } |
| 1047 | |
Serhiy Storchaka | bca4939 | 2017-09-03 08:10:14 +0300 | [diff] [blame] | 1048 | if (j < len) { |
Victor Stinner | 60ac6ed | 2020-02-07 23:18:08 +0100 | [diff] [blame] | 1049 | Py_SET_SIZE(newlist, j); |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 1050 | } |
Serhiy Storchaka | bca4939 | 2017-09-03 08:10:14 +0300 | [diff] [blame] | 1051 | j = PyList_GET_SIZE(newlist); |
| 1052 | len = PyList_GET_SIZE(self->fut_callbacks); |
| 1053 | if (j != len) { |
| 1054 | if (PyList_SetSlice(self->fut_callbacks, 0, len, newlist) < 0) { |
| 1055 | goto fail; |
| 1056 | } |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 1057 | } |
| 1058 | Py_DECREF(newlist); |
Yury Selivanov | 1b7c11f | 2017-12-17 20:19:47 -0500 | [diff] [blame] | 1059 | return PyLong_FromSsize_t(len - j + cleared_callback0); |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 1060 | |
| 1061 | fail: |
| 1062 | Py_DECREF(newlist); |
| 1063 | return NULL; |
| 1064 | } |
| 1065 | |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 1066 | /*[clinic input] |
| 1067 | _asyncio.Future.cancel |
| 1068 | |
Chris Jerdonek | 1ce5841 | 2020-05-15 16:55:50 -0700 | [diff] [blame] | 1069 | msg: object = None |
| 1070 | |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 1071 | Cancel the future and schedule callbacks. |
| 1072 | |
| 1073 | If the future is already done or cancelled, return False. Otherwise, |
| 1074 | change the future's state to cancelled, schedule the callbacks and |
| 1075 | return True. |
| 1076 | [clinic start generated code]*/ |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 1077 | |
| 1078 | static PyObject * |
Chris Jerdonek | 1ce5841 | 2020-05-15 16:55:50 -0700 | [diff] [blame] | 1079 | _asyncio_Future_cancel_impl(FutureObj *self, PyObject *msg) |
| 1080 | /*[clinic end generated code: output=3edebbc668e5aba3 input=925eb545251f2c5a]*/ |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 1081 | { |
Yury Selivanov | 1b7c11f | 2017-12-17 20:19:47 -0500 | [diff] [blame] | 1082 | ENSURE_FUTURE_ALIVE(self) |
Chris Jerdonek | 1ce5841 | 2020-05-15 16:55:50 -0700 | [diff] [blame] | 1083 | return future_cancel(self, msg); |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 1084 | } |
| 1085 | |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 1086 | /*[clinic input] |
| 1087 | _asyncio.Future.cancelled |
| 1088 | |
| 1089 | Return True if the future was cancelled. |
| 1090 | [clinic start generated code]*/ |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 1091 | |
| 1092 | static PyObject * |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 1093 | _asyncio_Future_cancelled_impl(FutureObj *self) |
| 1094 | /*[clinic end generated code: output=145197ced586357d input=943ab8b7b7b17e45]*/ |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 1095 | { |
Yury Selivanov | 1b7c11f | 2017-12-17 20:19:47 -0500 | [diff] [blame] | 1096 | if (future_is_alive(self) && self->fut_state == STATE_CANCELLED) { |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 1097 | Py_RETURN_TRUE; |
| 1098 | } |
| 1099 | else { |
| 1100 | Py_RETURN_FALSE; |
| 1101 | } |
| 1102 | } |
| 1103 | |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 1104 | /*[clinic input] |
| 1105 | _asyncio.Future.done |
| 1106 | |
| 1107 | Return True if the future is done. |
| 1108 | |
| 1109 | Done means either that a result / exception are available, or that the |
| 1110 | future was cancelled. |
| 1111 | [clinic start generated code]*/ |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 1112 | |
| 1113 | static PyObject * |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 1114 | _asyncio_Future_done_impl(FutureObj *self) |
| 1115 | /*[clinic end generated code: output=244c5ac351145096 input=28d7b23fdb65d2ac]*/ |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 1116 | { |
Yury Selivanov | 1b7c11f | 2017-12-17 20:19:47 -0500 | [diff] [blame] | 1117 | if (!future_is_alive(self) || self->fut_state == STATE_PENDING) { |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 1118 | Py_RETURN_FALSE; |
| 1119 | } |
| 1120 | else { |
| 1121 | Py_RETURN_TRUE; |
| 1122 | } |
| 1123 | } |
| 1124 | |
Yury Selivanov | ca9b36c | 2017-12-23 15:04:15 -0500 | [diff] [blame] | 1125 | /*[clinic input] |
| 1126 | _asyncio.Future.get_loop |
| 1127 | |
| 1128 | Return the event loop the Future is bound to. |
| 1129 | [clinic start generated code]*/ |
| 1130 | |
| 1131 | static PyObject * |
| 1132 | _asyncio_Future_get_loop_impl(FutureObj *self) |
| 1133 | /*[clinic end generated code: output=119b6ea0c9816c3f input=cba48c2136c79d1f]*/ |
| 1134 | { |
Andrew Svetlov | dad6be5 | 2019-11-13 23:36:46 +0200 | [diff] [blame] | 1135 | ENSURE_FUTURE_ALIVE(self) |
Yury Selivanov | ca9b36c | 2017-12-23 15:04:15 -0500 | [diff] [blame] | 1136 | Py_INCREF(self->fut_loop); |
| 1137 | return self->fut_loop; |
| 1138 | } |
| 1139 | |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 1140 | static PyObject * |
Serhiy Storchaka | d4f9cf5 | 2018-11-27 19:34:35 +0200 | [diff] [blame] | 1141 | FutureObj_get_blocking(FutureObj *fut, void *Py_UNUSED(ignored)) |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 1142 | { |
Yury Selivanov | 1b7c11f | 2017-12-17 20:19:47 -0500 | [diff] [blame] | 1143 | if (future_is_alive(fut) && fut->fut_blocking) { |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 1144 | Py_RETURN_TRUE; |
| 1145 | } |
| 1146 | else { |
| 1147 | Py_RETURN_FALSE; |
| 1148 | } |
| 1149 | } |
| 1150 | |
| 1151 | static int |
Serhiy Storchaka | d4f9cf5 | 2018-11-27 19:34:35 +0200 | [diff] [blame] | 1152 | FutureObj_set_blocking(FutureObj *fut, PyObject *val, void *Py_UNUSED(ignored)) |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 1153 | { |
Yury Selivanov | 1b7c11f | 2017-12-17 20:19:47 -0500 | [diff] [blame] | 1154 | if (future_ensure_alive(fut)) { |
| 1155 | return -1; |
| 1156 | } |
Zackery Spytz | 842acaa | 2018-12-17 07:52:45 -0700 | [diff] [blame] | 1157 | if (val == NULL) { |
| 1158 | PyErr_SetString(PyExc_AttributeError, "cannot delete attribute"); |
| 1159 | return -1; |
| 1160 | } |
Yury Selivanov | 1b7c11f | 2017-12-17 20:19:47 -0500 | [diff] [blame] | 1161 | |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 1162 | int is_true = PyObject_IsTrue(val); |
| 1163 | if (is_true < 0) { |
| 1164 | return -1; |
| 1165 | } |
| 1166 | fut->fut_blocking = is_true; |
| 1167 | return 0; |
| 1168 | } |
| 1169 | |
| 1170 | static PyObject * |
Serhiy Storchaka | d4f9cf5 | 2018-11-27 19:34:35 +0200 | [diff] [blame] | 1171 | FutureObj_get_log_traceback(FutureObj *fut, void *Py_UNUSED(ignored)) |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 1172 | { |
Yury Selivanov | 1b7c11f | 2017-12-17 20:19:47 -0500 | [diff] [blame] | 1173 | ENSURE_FUTURE_ALIVE(fut) |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 1174 | if (fut->fut_log_tb) { |
| 1175 | Py_RETURN_TRUE; |
| 1176 | } |
| 1177 | else { |
| 1178 | Py_RETURN_FALSE; |
| 1179 | } |
| 1180 | } |
| 1181 | |
Yury Selivanov | 7ce1c6f | 2017-06-11 13:49:18 +0000 | [diff] [blame] | 1182 | static int |
Serhiy Storchaka | d4f9cf5 | 2018-11-27 19:34:35 +0200 | [diff] [blame] | 1183 | FutureObj_set_log_traceback(FutureObj *fut, PyObject *val, void *Py_UNUSED(ignored)) |
Yury Selivanov | 7ce1c6f | 2017-06-11 13:49:18 +0000 | [diff] [blame] | 1184 | { |
Zackery Spytz | 842acaa | 2018-12-17 07:52:45 -0700 | [diff] [blame] | 1185 | if (val == NULL) { |
| 1186 | PyErr_SetString(PyExc_AttributeError, "cannot delete attribute"); |
| 1187 | return -1; |
| 1188 | } |
Yury Selivanov | 7ce1c6f | 2017-06-11 13:49:18 +0000 | [diff] [blame] | 1189 | int is_true = PyObject_IsTrue(val); |
| 1190 | if (is_true < 0) { |
| 1191 | return -1; |
| 1192 | } |
Yury Selivanov | e0aef4f | 2017-12-25 16:16:10 -0500 | [diff] [blame] | 1193 | if (is_true) { |
| 1194 | PyErr_SetString(PyExc_ValueError, |
| 1195 | "_log_traceback can only be set to False"); |
| 1196 | return -1; |
| 1197 | } |
Yury Selivanov | 7ce1c6f | 2017-06-11 13:49:18 +0000 | [diff] [blame] | 1198 | fut->fut_log_tb = is_true; |
| 1199 | return 0; |
| 1200 | } |
| 1201 | |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 1202 | static PyObject * |
Serhiy Storchaka | d4f9cf5 | 2018-11-27 19:34:35 +0200 | [diff] [blame] | 1203 | FutureObj_get_loop(FutureObj *fut, void *Py_UNUSED(ignored)) |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 1204 | { |
Yury Selivanov | 1b7c11f | 2017-12-17 20:19:47 -0500 | [diff] [blame] | 1205 | if (!future_is_alive(fut)) { |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 1206 | Py_RETURN_NONE; |
| 1207 | } |
| 1208 | Py_INCREF(fut->fut_loop); |
| 1209 | return fut->fut_loop; |
| 1210 | } |
| 1211 | |
| 1212 | static PyObject * |
Serhiy Storchaka | d4f9cf5 | 2018-11-27 19:34:35 +0200 | [diff] [blame] | 1213 | FutureObj_get_callbacks(FutureObj *fut, void *Py_UNUSED(ignored)) |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 1214 | { |
Yury Selivanov | 1b7c11f | 2017-12-17 20:19:47 -0500 | [diff] [blame] | 1215 | Py_ssize_t i; |
Yury Selivanov | 1b7c11f | 2017-12-17 20:19:47 -0500 | [diff] [blame] | 1216 | |
| 1217 | ENSURE_FUTURE_ALIVE(fut) |
| 1218 | |
Yury Selivanov | f23746a | 2018-01-22 19:11:18 -0500 | [diff] [blame] | 1219 | if (fut->fut_callback0 == NULL) { |
| 1220 | if (fut->fut_callbacks == NULL) { |
Yury Selivanov | 1b7c11f | 2017-12-17 20:19:47 -0500 | [diff] [blame] | 1221 | Py_RETURN_NONE; |
| 1222 | } |
Yury Selivanov | 1b7c11f | 2017-12-17 20:19:47 -0500 | [diff] [blame] | 1223 | |
Yury Selivanov | 1b7c11f | 2017-12-17 20:19:47 -0500 | [diff] [blame] | 1224 | Py_INCREF(fut->fut_callbacks); |
| 1225 | return fut->fut_callbacks; |
| 1226 | } |
| 1227 | |
Yury Selivanov | f23746a | 2018-01-22 19:11:18 -0500 | [diff] [blame] | 1228 | Py_ssize_t len = 1; |
| 1229 | if (fut->fut_callbacks != NULL) { |
| 1230 | len += PyList_GET_SIZE(fut->fut_callbacks); |
| 1231 | } |
Yury Selivanov | 1b7c11f | 2017-12-17 20:19:47 -0500 | [diff] [blame] | 1232 | |
Yury Selivanov | f23746a | 2018-01-22 19:11:18 -0500 | [diff] [blame] | 1233 | |
| 1234 | PyObject *new_list = PyList_New(len); |
Yury Selivanov | 1b7c11f | 2017-12-17 20:19:47 -0500 | [diff] [blame] | 1235 | if (new_list == NULL) { |
| 1236 | return NULL; |
| 1237 | } |
| 1238 | |
Yury Selivanov | f23746a | 2018-01-22 19:11:18 -0500 | [diff] [blame] | 1239 | PyObject *tup0 = PyTuple_New(2); |
| 1240 | if (tup0 == NULL) { |
| 1241 | Py_DECREF(new_list); |
| 1242 | return NULL; |
| 1243 | } |
| 1244 | |
Yury Selivanov | 1b7c11f | 2017-12-17 20:19:47 -0500 | [diff] [blame] | 1245 | Py_INCREF(fut->fut_callback0); |
Yury Selivanov | f23746a | 2018-01-22 19:11:18 -0500 | [diff] [blame] | 1246 | PyTuple_SET_ITEM(tup0, 0, fut->fut_callback0); |
| 1247 | assert(fut->fut_context0 != NULL); |
| 1248 | Py_INCREF(fut->fut_context0); |
| 1249 | PyTuple_SET_ITEM(tup0, 1, (PyObject *)fut->fut_context0); |
| 1250 | |
| 1251 | PyList_SET_ITEM(new_list, 0, tup0); |
| 1252 | |
| 1253 | if (fut->fut_callbacks != NULL) { |
| 1254 | for (i = 0; i < PyList_GET_SIZE(fut->fut_callbacks); i++) { |
| 1255 | PyObject *cb = PyList_GET_ITEM(fut->fut_callbacks, i); |
| 1256 | Py_INCREF(cb); |
| 1257 | PyList_SET_ITEM(new_list, i + 1, cb); |
| 1258 | } |
Yury Selivanov | 1b7c11f | 2017-12-17 20:19:47 -0500 | [diff] [blame] | 1259 | } |
| 1260 | |
| 1261 | return new_list; |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 1262 | } |
| 1263 | |
| 1264 | static PyObject * |
Serhiy Storchaka | d4f9cf5 | 2018-11-27 19:34:35 +0200 | [diff] [blame] | 1265 | FutureObj_get_result(FutureObj *fut, void *Py_UNUSED(ignored)) |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 1266 | { |
Yury Selivanov | 1b7c11f | 2017-12-17 20:19:47 -0500 | [diff] [blame] | 1267 | ENSURE_FUTURE_ALIVE(fut) |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 1268 | if (fut->fut_result == NULL) { |
| 1269 | Py_RETURN_NONE; |
| 1270 | } |
| 1271 | Py_INCREF(fut->fut_result); |
| 1272 | return fut->fut_result; |
| 1273 | } |
| 1274 | |
| 1275 | static PyObject * |
Serhiy Storchaka | d4f9cf5 | 2018-11-27 19:34:35 +0200 | [diff] [blame] | 1276 | FutureObj_get_exception(FutureObj *fut, void *Py_UNUSED(ignored)) |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 1277 | { |
Yury Selivanov | 1b7c11f | 2017-12-17 20:19:47 -0500 | [diff] [blame] | 1278 | ENSURE_FUTURE_ALIVE(fut) |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 1279 | if (fut->fut_exception == NULL) { |
| 1280 | Py_RETURN_NONE; |
| 1281 | } |
| 1282 | Py_INCREF(fut->fut_exception); |
| 1283 | return fut->fut_exception; |
| 1284 | } |
| 1285 | |
| 1286 | static PyObject * |
Serhiy Storchaka | d4f9cf5 | 2018-11-27 19:34:35 +0200 | [diff] [blame] | 1287 | FutureObj_get_source_traceback(FutureObj *fut, void *Py_UNUSED(ignored)) |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 1288 | { |
Yury Selivanov | 1b7c11f | 2017-12-17 20:19:47 -0500 | [diff] [blame] | 1289 | if (!future_is_alive(fut) || fut->fut_source_tb == NULL) { |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 1290 | Py_RETURN_NONE; |
| 1291 | } |
| 1292 | Py_INCREF(fut->fut_source_tb); |
| 1293 | return fut->fut_source_tb; |
| 1294 | } |
| 1295 | |
| 1296 | static PyObject * |
Chris Jerdonek | 1ce5841 | 2020-05-15 16:55:50 -0700 | [diff] [blame] | 1297 | FutureObj_get_cancel_message(FutureObj *fut, void *Py_UNUSED(ignored)) |
| 1298 | { |
| 1299 | if (fut->fut_cancel_msg == NULL) { |
| 1300 | Py_RETURN_NONE; |
| 1301 | } |
| 1302 | Py_INCREF(fut->fut_cancel_msg); |
| 1303 | return fut->fut_cancel_msg; |
| 1304 | } |
| 1305 | |
| 1306 | static int |
| 1307 | FutureObj_set_cancel_message(FutureObj *fut, PyObject *msg, |
| 1308 | void *Py_UNUSED(ignored)) |
| 1309 | { |
| 1310 | if (msg == NULL) { |
| 1311 | PyErr_SetString(PyExc_AttributeError, "cannot delete attribute"); |
| 1312 | return -1; |
| 1313 | } |
| 1314 | Py_INCREF(msg); |
| 1315 | Py_XSETREF(fut->fut_cancel_msg, msg); |
| 1316 | return 0; |
| 1317 | } |
| 1318 | |
| 1319 | static PyObject * |
Serhiy Storchaka | d4f9cf5 | 2018-11-27 19:34:35 +0200 | [diff] [blame] | 1320 | FutureObj_get_state(FutureObj *fut, void *Py_UNUSED(ignored)) |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 1321 | { |
| 1322 | _Py_IDENTIFIER(PENDING); |
| 1323 | _Py_IDENTIFIER(CANCELLED); |
| 1324 | _Py_IDENTIFIER(FINISHED); |
| 1325 | PyObject *ret = NULL; |
| 1326 | |
Yury Selivanov | 1b7c11f | 2017-12-17 20:19:47 -0500 | [diff] [blame] | 1327 | ENSURE_FUTURE_ALIVE(fut) |
| 1328 | |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 1329 | switch (fut->fut_state) { |
| 1330 | case STATE_PENDING: |
| 1331 | ret = _PyUnicode_FromId(&PyId_PENDING); |
| 1332 | break; |
| 1333 | case STATE_CANCELLED: |
| 1334 | ret = _PyUnicode_FromId(&PyId_CANCELLED); |
| 1335 | break; |
| 1336 | case STATE_FINISHED: |
| 1337 | ret = _PyUnicode_FromId(&PyId_FINISHED); |
| 1338 | break; |
| 1339 | default: |
| 1340 | assert (0); |
| 1341 | } |
Serhiy Storchaka | bca4939 | 2017-09-03 08:10:14 +0300 | [diff] [blame] | 1342 | Py_XINCREF(ret); |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 1343 | return ret; |
| 1344 | } |
| 1345 | |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 1346 | /*[clinic input] |
Chris Jerdonek | da742ba | 2020-05-17 22:47:31 -0700 | [diff] [blame] | 1347 | _asyncio.Future._make_cancelled_error |
| 1348 | |
| 1349 | Create the CancelledError to raise if the Future is cancelled. |
| 1350 | |
| 1351 | This should only be called once when handling a cancellation since |
| 1352 | it erases the context exception value. |
| 1353 | [clinic start generated code]*/ |
| 1354 | |
| 1355 | static PyObject * |
| 1356 | _asyncio_Future__make_cancelled_error_impl(FutureObj *self) |
| 1357 | /*[clinic end generated code: output=a5df276f6c1213de input=ac6effe4ba795ecc]*/ |
| 1358 | { |
| 1359 | PyObject *exc = create_cancelled_error(self->fut_cancel_msg); |
| 1360 | _PyErr_StackItem *exc_state = &self->fut_cancelled_exc_state; |
| 1361 | /* Transfer ownership of exc_value from exc_state to exc since we are |
| 1362 | done with it. */ |
| 1363 | PyException_SetContext(exc, exc_state->exc_value); |
| 1364 | exc_state->exc_value = NULL; |
| 1365 | |
| 1366 | return exc; |
| 1367 | } |
| 1368 | |
| 1369 | /*[clinic input] |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 1370 | _asyncio.Future._repr_info |
| 1371 | [clinic start generated code]*/ |
| 1372 | |
| 1373 | static PyObject * |
| 1374 | _asyncio_Future__repr_info_impl(FutureObj *self) |
| 1375 | /*[clinic end generated code: output=fa69e901bd176cfb input=f21504d8e2ae1ca2]*/ |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 1376 | { |
Petr Viktorin | ffd9753 | 2020-02-11 17:46:57 +0100 | [diff] [blame] | 1377 | return PyObject_CallOneArg(asyncio_future_repr_info_func, (PyObject *)self); |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 1378 | } |
| 1379 | |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 1380 | static PyObject * |
| 1381 | FutureObj_repr(FutureObj *fut) |
| 1382 | { |
| 1383 | _Py_IDENTIFIER(_repr_info); |
| 1384 | |
Yury Selivanov | 1b7c11f | 2017-12-17 20:19:47 -0500 | [diff] [blame] | 1385 | ENSURE_FUTURE_ALIVE(fut) |
| 1386 | |
Jeroen Demeyer | 762f93f | 2019-07-08 10:19:25 +0200 | [diff] [blame] | 1387 | PyObject *rinfo = _PyObject_CallMethodIdNoArgs((PyObject*)fut, |
| 1388 | &PyId__repr_info); |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 1389 | if (rinfo == NULL) { |
| 1390 | return NULL; |
| 1391 | } |
| 1392 | |
Serhiy Storchaka | bca4939 | 2017-09-03 08:10:14 +0300 | [diff] [blame] | 1393 | PyObject *rinfo_s = PyUnicode_Join(NULL, rinfo); |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 1394 | Py_DECREF(rinfo); |
| 1395 | if (rinfo_s == NULL) { |
| 1396 | return NULL; |
| 1397 | } |
| 1398 | |
Serhiy Storchaka | fb3e9c0 | 2018-09-21 09:11:32 +0300 | [diff] [blame] | 1399 | PyObject *rstr = PyUnicode_FromFormat("<%s %U>", |
| 1400 | _PyType_Name(Py_TYPE(fut)), rinfo_s); |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 1401 | Py_DECREF(rinfo_s); |
| 1402 | return rstr; |
| 1403 | } |
| 1404 | |
| 1405 | static void |
| 1406 | FutureObj_finalize(FutureObj *fut) |
| 1407 | { |
| 1408 | _Py_IDENTIFIER(call_exception_handler); |
| 1409 | _Py_IDENTIFIER(message); |
| 1410 | _Py_IDENTIFIER(exception); |
| 1411 | _Py_IDENTIFIER(future); |
| 1412 | _Py_IDENTIFIER(source_traceback); |
| 1413 | |
Serhiy Storchaka | bca4939 | 2017-09-03 08:10:14 +0300 | [diff] [blame] | 1414 | PyObject *error_type, *error_value, *error_traceback; |
| 1415 | PyObject *context; |
Serhiy Storchaka | bca4939 | 2017-09-03 08:10:14 +0300 | [diff] [blame] | 1416 | PyObject *message = NULL; |
| 1417 | PyObject *func; |
| 1418 | |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 1419 | if (!fut->fut_log_tb) { |
| 1420 | return; |
| 1421 | } |
| 1422 | assert(fut->fut_exception != NULL); |
Serhiy Storchaka | bca4939 | 2017-09-03 08:10:14 +0300 | [diff] [blame] | 1423 | fut->fut_log_tb = 0; |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 1424 | |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 1425 | /* Save the current exception, if any. */ |
| 1426 | PyErr_Fetch(&error_type, &error_value, &error_traceback); |
| 1427 | |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 1428 | context = PyDict_New(); |
| 1429 | if (context == NULL) { |
| 1430 | goto finally; |
| 1431 | } |
| 1432 | |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 1433 | message = PyUnicode_FromFormat( |
Serhiy Storchaka | fb3e9c0 | 2018-09-21 09:11:32 +0300 | [diff] [blame] | 1434 | "%s exception was never retrieved", _PyType_Name(Py_TYPE(fut))); |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 1435 | if (message == NULL) { |
| 1436 | goto finally; |
| 1437 | } |
| 1438 | |
| 1439 | if (_PyDict_SetItemId(context, &PyId_message, message) < 0 || |
| 1440 | _PyDict_SetItemId(context, &PyId_exception, fut->fut_exception) < 0 || |
| 1441 | _PyDict_SetItemId(context, &PyId_future, (PyObject*)fut) < 0) { |
| 1442 | goto finally; |
| 1443 | } |
| 1444 | if (fut->fut_source_tb != NULL) { |
| 1445 | if (_PyDict_SetItemId(context, &PyId_source_traceback, |
| 1446 | fut->fut_source_tb) < 0) { |
| 1447 | goto finally; |
| 1448 | } |
| 1449 | } |
| 1450 | |
| 1451 | func = _PyObject_GetAttrId(fut->fut_loop, &PyId_call_exception_handler); |
| 1452 | if (func != NULL) { |
Petr Viktorin | ffd9753 | 2020-02-11 17:46:57 +0100 | [diff] [blame] | 1453 | PyObject *res = PyObject_CallOneArg(func, context); |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 1454 | if (res == NULL) { |
| 1455 | PyErr_WriteUnraisable(func); |
| 1456 | } |
Serhiy Storchaka | bca4939 | 2017-09-03 08:10:14 +0300 | [diff] [blame] | 1457 | else { |
| 1458 | Py_DECREF(res); |
| 1459 | } |
| 1460 | Py_DECREF(func); |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 1461 | } |
| 1462 | |
| 1463 | finally: |
Serhiy Storchaka | bca4939 | 2017-09-03 08:10:14 +0300 | [diff] [blame] | 1464 | Py_XDECREF(context); |
| 1465 | Py_XDECREF(message); |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 1466 | |
| 1467 | /* Restore the saved exception. */ |
| 1468 | PyErr_Restore(error_type, error_value, error_traceback); |
| 1469 | } |
| 1470 | |
Batuhan TaÅŸkaya | dec3672 | 2019-12-07 14:05:07 +0300 | [diff] [blame] | 1471 | static PyObject * |
| 1472 | future_cls_getitem(PyObject *cls, PyObject *type) |
| 1473 | { |
| 1474 | Py_INCREF(cls); |
| 1475 | return cls; |
| 1476 | } |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 1477 | |
| 1478 | static PyAsyncMethods FutureType_as_async = { |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 1479 | (unaryfunc)future_new_iter, /* am_await */ |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 1480 | 0, /* am_aiter */ |
| 1481 | 0 /* am_anext */ |
| 1482 | }; |
| 1483 | |
| 1484 | static PyMethodDef FutureType_methods[] = { |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 1485 | _ASYNCIO_FUTURE_RESULT_METHODDEF |
| 1486 | _ASYNCIO_FUTURE_EXCEPTION_METHODDEF |
| 1487 | _ASYNCIO_FUTURE_SET_RESULT_METHODDEF |
| 1488 | _ASYNCIO_FUTURE_SET_EXCEPTION_METHODDEF |
| 1489 | _ASYNCIO_FUTURE_ADD_DONE_CALLBACK_METHODDEF |
| 1490 | _ASYNCIO_FUTURE_REMOVE_DONE_CALLBACK_METHODDEF |
| 1491 | _ASYNCIO_FUTURE_CANCEL_METHODDEF |
| 1492 | _ASYNCIO_FUTURE_CANCELLED_METHODDEF |
| 1493 | _ASYNCIO_FUTURE_DONE_METHODDEF |
Yury Selivanov | ca9b36c | 2017-12-23 15:04:15 -0500 | [diff] [blame] | 1494 | _ASYNCIO_FUTURE_GET_LOOP_METHODDEF |
Chris Jerdonek | da742ba | 2020-05-17 22:47:31 -0700 | [diff] [blame] | 1495 | _ASYNCIO_FUTURE__MAKE_CANCELLED_ERROR_METHODDEF |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 1496 | _ASYNCIO_FUTURE__REPR_INFO_METHODDEF |
Batuhan TaÅŸkaya | dec3672 | 2019-12-07 14:05:07 +0300 | [diff] [blame] | 1497 | {"__class_getitem__", future_cls_getitem, METH_O|METH_CLASS, NULL}, |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 1498 | {NULL, NULL} /* Sentinel */ |
| 1499 | }; |
| 1500 | |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 1501 | #define FUTURE_COMMON_GETSETLIST \ |
| 1502 | {"_state", (getter)FutureObj_get_state, NULL, NULL}, \ |
| 1503 | {"_asyncio_future_blocking", (getter)FutureObj_get_blocking, \ |
| 1504 | (setter)FutureObj_set_blocking, NULL}, \ |
| 1505 | {"_loop", (getter)FutureObj_get_loop, NULL, NULL}, \ |
| 1506 | {"_callbacks", (getter)FutureObj_get_callbacks, NULL, NULL}, \ |
| 1507 | {"_result", (getter)FutureObj_get_result, NULL, NULL}, \ |
| 1508 | {"_exception", (getter)FutureObj_get_exception, NULL, NULL}, \ |
Yury Selivanov | 7ce1c6f | 2017-06-11 13:49:18 +0000 | [diff] [blame] | 1509 | {"_log_traceback", (getter)FutureObj_get_log_traceback, \ |
| 1510 | (setter)FutureObj_set_log_traceback, NULL}, \ |
Chris Jerdonek | 1ce5841 | 2020-05-15 16:55:50 -0700 | [diff] [blame] | 1511 | {"_source_traceback", (getter)FutureObj_get_source_traceback, \ |
| 1512 | NULL, NULL}, \ |
| 1513 | {"_cancel_message", (getter)FutureObj_get_cancel_message, \ |
| 1514 | (setter)FutureObj_set_cancel_message, NULL}, |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 1515 | |
| 1516 | static PyGetSetDef FutureType_getsetlist[] = { |
| 1517 | FUTURE_COMMON_GETSETLIST |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 1518 | {NULL} /* Sentinel */ |
| 1519 | }; |
| 1520 | |
| 1521 | static void FutureObj_dealloc(PyObject *self); |
| 1522 | |
| 1523 | static PyTypeObject FutureType = { |
Victor Stinner | 1aea8fb | 2016-10-28 19:13:52 +0200 | [diff] [blame] | 1524 | PyVarObject_HEAD_INIT(NULL, 0) |
INADA Naoki | 9f2ce25 | 2016-10-15 15:39:19 +0900 | [diff] [blame] | 1525 | "_asyncio.Future", |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 1526 | sizeof(FutureObj), /* tp_basicsize */ |
| 1527 | .tp_dealloc = FutureObj_dealloc, |
| 1528 | .tp_as_async = &FutureType_as_async, |
| 1529 | .tp_repr = (reprfunc)FutureObj_repr, |
Antoine Pitrou | ada319b | 2019-05-29 22:12:38 +0200 | [diff] [blame] | 1530 | .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE, |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 1531 | .tp_doc = _asyncio_Future___init____doc__, |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 1532 | .tp_traverse = (traverseproc)FutureObj_traverse, |
| 1533 | .tp_clear = (inquiry)FutureObj_clear, |
| 1534 | .tp_weaklistoffset = offsetof(FutureObj, fut_weakreflist), |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 1535 | .tp_iter = (getiterfunc)future_new_iter, |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 1536 | .tp_methods = FutureType_methods, |
| 1537 | .tp_getset = FutureType_getsetlist, |
| 1538 | .tp_dictoffset = offsetof(FutureObj, dict), |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 1539 | .tp_init = (initproc)_asyncio_Future___init__, |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 1540 | .tp_new = PyType_GenericNew, |
| 1541 | .tp_finalize = (destructor)FutureObj_finalize, |
| 1542 | }; |
| 1543 | |
| 1544 | static void |
| 1545 | FutureObj_dealloc(PyObject *self) |
| 1546 | { |
| 1547 | FutureObj *fut = (FutureObj *)self; |
| 1548 | |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 1549 | if (Future_CheckExact(fut)) { |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 1550 | /* When fut is subclass of Future, finalizer is called from |
| 1551 | * subtype_dealloc. |
| 1552 | */ |
| 1553 | if (PyObject_CallFinalizerFromDealloc(self) < 0) { |
| 1554 | // resurrected. |
| 1555 | return; |
| 1556 | } |
| 1557 | } |
| 1558 | |
Alexander Mohr | de34cbe | 2017-08-01 23:31:07 -0700 | [diff] [blame] | 1559 | PyObject_GC_UnTrack(self); |
| 1560 | |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 1561 | if (fut->fut_weakreflist != NULL) { |
| 1562 | PyObject_ClearWeakRefs(self); |
| 1563 | } |
| 1564 | |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 1565 | (void)FutureObj_clear(fut); |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 1566 | Py_TYPE(fut)->tp_free(fut); |
| 1567 | } |
| 1568 | |
| 1569 | |
| 1570 | /*********************** Future Iterator **************************/ |
| 1571 | |
| 1572 | typedef struct { |
| 1573 | PyObject_HEAD |
| 1574 | FutureObj *future; |
| 1575 | } futureiterobject; |
| 1576 | |
Yury Selivanov | 1b7c11f | 2017-12-17 20:19:47 -0500 | [diff] [blame] | 1577 | |
| 1578 | #define FI_FREELIST_MAXLEN 255 |
| 1579 | static futureiterobject *fi_freelist = NULL; |
| 1580 | static Py_ssize_t fi_freelist_len = 0; |
| 1581 | |
| 1582 | |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 1583 | static void |
| 1584 | FutureIter_dealloc(futureiterobject *it) |
| 1585 | { |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 1586 | PyObject_GC_UnTrack(it); |
Yury Selivanov | 1b7c11f | 2017-12-17 20:19:47 -0500 | [diff] [blame] | 1587 | Py_CLEAR(it->future); |
| 1588 | |
| 1589 | if (fi_freelist_len < FI_FREELIST_MAXLEN) { |
| 1590 | fi_freelist_len++; |
| 1591 | it->future = (FutureObj*) fi_freelist; |
| 1592 | fi_freelist = it; |
| 1593 | } |
| 1594 | else { |
| 1595 | PyObject_GC_Del(it); |
| 1596 | } |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 1597 | } |
| 1598 | |
| 1599 | static PyObject * |
| 1600 | FutureIter_iternext(futureiterobject *it) |
| 1601 | { |
| 1602 | PyObject *res; |
| 1603 | FutureObj *fut = it->future; |
| 1604 | |
| 1605 | if (fut == NULL) { |
| 1606 | return NULL; |
| 1607 | } |
| 1608 | |
| 1609 | if (fut->fut_state == STATE_PENDING) { |
| 1610 | if (!fut->fut_blocking) { |
| 1611 | fut->fut_blocking = 1; |
| 1612 | Py_INCREF(fut); |
| 1613 | return (PyObject *)fut; |
| 1614 | } |
Yury Selivanov | 0cf16f9 | 2017-12-25 10:48:15 -0500 | [diff] [blame] | 1615 | PyErr_SetString(PyExc_RuntimeError, |
| 1616 | "await wasn't used with future"); |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 1617 | return NULL; |
| 1618 | } |
| 1619 | |
Serhiy Storchaka | bca4939 | 2017-09-03 08:10:14 +0300 | [diff] [blame] | 1620 | it->future = NULL; |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 1621 | res = _asyncio_Future_result_impl(fut); |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 1622 | if (res != NULL) { |
Serhiy Storchaka | 60e49aa | 2016-11-06 18:47:03 +0200 | [diff] [blame] | 1623 | /* The result of the Future is not an exception. */ |
Serhiy Storchaka | bca4939 | 2017-09-03 08:10:14 +0300 | [diff] [blame] | 1624 | (void)_PyGen_SetStopIterationValue(res); |
Serhiy Storchaka | 60e49aa | 2016-11-06 18:47:03 +0200 | [diff] [blame] | 1625 | Py_DECREF(res); |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 1626 | } |
| 1627 | |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 1628 | Py_DECREF(fut); |
| 1629 | return NULL; |
| 1630 | } |
| 1631 | |
| 1632 | static PyObject * |
INADA Naoki | 74c1753 | 2016-10-25 19:00:45 +0900 | [diff] [blame] | 1633 | FutureIter_send(futureiterobject *self, PyObject *unused) |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 1634 | { |
INADA Naoki | 74c1753 | 2016-10-25 19:00:45 +0900 | [diff] [blame] | 1635 | /* Future.__iter__ doesn't care about values that are pushed to the |
Serhiy Storchaka | fb3e9c0 | 2018-09-21 09:11:32 +0300 | [diff] [blame] | 1636 | * generator, it just returns self.result(). |
INADA Naoki | 74c1753 | 2016-10-25 19:00:45 +0900 | [diff] [blame] | 1637 | */ |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 1638 | return FutureIter_iternext(self); |
| 1639 | } |
| 1640 | |
| 1641 | static PyObject * |
| 1642 | FutureIter_throw(futureiterobject *self, PyObject *args) |
| 1643 | { |
Serhiy Storchaka | bca4939 | 2017-09-03 08:10:14 +0300 | [diff] [blame] | 1644 | PyObject *type, *val = NULL, *tb = NULL; |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 1645 | if (!PyArg_ParseTuple(args, "O|OO", &type, &val, &tb)) |
| 1646 | return NULL; |
| 1647 | |
| 1648 | if (val == Py_None) { |
| 1649 | val = NULL; |
| 1650 | } |
| 1651 | if (tb == Py_None) { |
| 1652 | tb = NULL; |
Benjamin Peterson | 996fc1f | 2016-11-14 00:15:44 -0800 | [diff] [blame] | 1653 | } else if (tb != NULL && !PyTraceBack_Check(tb)) { |
| 1654 | PyErr_SetString(PyExc_TypeError, "throw() third argument must be a traceback"); |
| 1655 | return NULL; |
| 1656 | } |
| 1657 | |
| 1658 | Py_INCREF(type); |
| 1659 | Py_XINCREF(val); |
| 1660 | Py_XINCREF(tb); |
| 1661 | |
| 1662 | if (PyExceptionClass_Check(type)) { |
| 1663 | PyErr_NormalizeException(&type, &val, &tb); |
Yury Selivanov | edfe886 | 2016-12-01 11:37:47 -0500 | [diff] [blame] | 1664 | /* No need to call PyException_SetTraceback since we'll be calling |
| 1665 | PyErr_Restore for `type`, `val`, and `tb`. */ |
Benjamin Peterson | 996fc1f | 2016-11-14 00:15:44 -0800 | [diff] [blame] | 1666 | } else if (PyExceptionInstance_Check(type)) { |
| 1667 | if (val) { |
| 1668 | PyErr_SetString(PyExc_TypeError, |
| 1669 | "instance exception may not have a separate value"); |
| 1670 | goto fail; |
| 1671 | } |
| 1672 | val = type; |
| 1673 | type = PyExceptionInstance_Class(type); |
| 1674 | Py_INCREF(type); |
| 1675 | if (tb == NULL) |
| 1676 | tb = PyException_GetTraceback(val); |
| 1677 | } else { |
| 1678 | PyErr_SetString(PyExc_TypeError, |
| 1679 | "exceptions must be classes deriving BaseException or " |
| 1680 | "instances of such a class"); |
| 1681 | goto fail; |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 1682 | } |
| 1683 | |
| 1684 | Py_CLEAR(self->future); |
| 1685 | |
Benjamin Peterson | 996fc1f | 2016-11-14 00:15:44 -0800 | [diff] [blame] | 1686 | PyErr_Restore(type, val, tb); |
| 1687 | |
Serhiy Storchaka | bca4939 | 2017-09-03 08:10:14 +0300 | [diff] [blame] | 1688 | return NULL; |
Benjamin Peterson | 996fc1f | 2016-11-14 00:15:44 -0800 | [diff] [blame] | 1689 | |
| 1690 | fail: |
| 1691 | Py_DECREF(type); |
| 1692 | Py_XDECREF(val); |
| 1693 | Py_XDECREF(tb); |
| 1694 | return NULL; |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 1695 | } |
| 1696 | |
| 1697 | static PyObject * |
| 1698 | FutureIter_close(futureiterobject *self, PyObject *arg) |
| 1699 | { |
| 1700 | Py_CLEAR(self->future); |
| 1701 | Py_RETURN_NONE; |
| 1702 | } |
| 1703 | |
| 1704 | static int |
| 1705 | FutureIter_traverse(futureiterobject *it, visitproc visit, void *arg) |
| 1706 | { |
| 1707 | Py_VISIT(it->future); |
| 1708 | return 0; |
| 1709 | } |
| 1710 | |
| 1711 | static PyMethodDef FutureIter_methods[] = { |
| 1712 | {"send", (PyCFunction)FutureIter_send, METH_O, NULL}, |
| 1713 | {"throw", (PyCFunction)FutureIter_throw, METH_VARARGS, NULL}, |
| 1714 | {"close", (PyCFunction)FutureIter_close, METH_NOARGS, NULL}, |
| 1715 | {NULL, NULL} /* Sentinel */ |
| 1716 | }; |
| 1717 | |
| 1718 | static PyTypeObject FutureIterType = { |
Victor Stinner | 1aea8fb | 2016-10-28 19:13:52 +0200 | [diff] [blame] | 1719 | PyVarObject_HEAD_INIT(NULL, 0) |
INADA Naoki | 9f2ce25 | 2016-10-15 15:39:19 +0900 | [diff] [blame] | 1720 | "_asyncio.FutureIter", |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 1721 | .tp_basicsize = sizeof(futureiterobject), |
| 1722 | .tp_itemsize = 0, |
| 1723 | .tp_dealloc = (destructor)FutureIter_dealloc, |
| 1724 | .tp_getattro = PyObject_GenericGetAttr, |
| 1725 | .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, |
| 1726 | .tp_traverse = (traverseproc)FutureIter_traverse, |
| 1727 | .tp_iter = PyObject_SelfIter, |
| 1728 | .tp_iternext = (iternextfunc)FutureIter_iternext, |
| 1729 | .tp_methods = FutureIter_methods, |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 1730 | }; |
| 1731 | |
| 1732 | static PyObject * |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 1733 | future_new_iter(PyObject *fut) |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 1734 | { |
| 1735 | futureiterobject *it; |
| 1736 | |
| 1737 | if (!PyObject_TypeCheck(fut, &FutureType)) { |
| 1738 | PyErr_BadInternalCall(); |
| 1739 | return NULL; |
| 1740 | } |
Yury Selivanov | 1b7c11f | 2017-12-17 20:19:47 -0500 | [diff] [blame] | 1741 | |
| 1742 | ENSURE_FUTURE_ALIVE(fut) |
| 1743 | |
| 1744 | if (fi_freelist_len) { |
| 1745 | fi_freelist_len--; |
| 1746 | it = fi_freelist; |
| 1747 | fi_freelist = (futureiterobject*) it->future; |
| 1748 | it->future = NULL; |
| 1749 | _Py_NewReference((PyObject*) it); |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 1750 | } |
Yury Selivanov | 1b7c11f | 2017-12-17 20:19:47 -0500 | [diff] [blame] | 1751 | else { |
| 1752 | it = PyObject_GC_New(futureiterobject, &FutureIterType); |
| 1753 | if (it == NULL) { |
| 1754 | return NULL; |
| 1755 | } |
| 1756 | } |
| 1757 | |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 1758 | Py_INCREF(fut); |
| 1759 | it->future = (FutureObj*)fut; |
INADA Naoki | 1be427b | 2016-10-11 02:12:34 +0900 | [diff] [blame] | 1760 | PyObject_GC_Track(it); |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 1761 | return (PyObject*)it; |
| 1762 | } |
| 1763 | |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 1764 | |
| 1765 | /*********************** Task **************************/ |
| 1766 | |
| 1767 | |
| 1768 | /*[clinic input] |
| 1769 | class _asyncio.Task "TaskObj *" "&Task_Type" |
| 1770 | [clinic start generated code]*/ |
| 1771 | /*[clinic end generated code: output=da39a3ee5e6b4b0d input=719dcef0fcc03b37]*/ |
| 1772 | |
| 1773 | static int task_call_step_soon(TaskObj *, PyObject *); |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 1774 | static PyObject * task_wakeup(TaskObj *, PyObject *); |
| 1775 | static PyObject * task_step(TaskObj *, PyObject *); |
| 1776 | |
| 1777 | /* ----- Task._step wrapper */ |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 1778 | |
INADA Naoki | c411a7d | 2016-10-18 11:48:14 +0900 | [diff] [blame] | 1779 | static int |
Serhiy Storchaka | bca4939 | 2017-09-03 08:10:14 +0300 | [diff] [blame] | 1780 | TaskStepMethWrapper_clear(TaskStepMethWrapper *o) |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 1781 | { |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 1782 | Py_CLEAR(o->sw_task); |
| 1783 | Py_CLEAR(o->sw_arg); |
| 1784 | return 0; |
| 1785 | } |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 1786 | |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 1787 | static void |
Serhiy Storchaka | bca4939 | 2017-09-03 08:10:14 +0300 | [diff] [blame] | 1788 | TaskStepMethWrapper_dealloc(TaskStepMethWrapper *o) |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 1789 | { |
| 1790 | PyObject_GC_UnTrack(o); |
Serhiy Storchaka | bca4939 | 2017-09-03 08:10:14 +0300 | [diff] [blame] | 1791 | (void)TaskStepMethWrapper_clear(o); |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 1792 | Py_TYPE(o)->tp_free(o); |
| 1793 | } |
| 1794 | |
| 1795 | static PyObject * |
Serhiy Storchaka | bca4939 | 2017-09-03 08:10:14 +0300 | [diff] [blame] | 1796 | TaskStepMethWrapper_call(TaskStepMethWrapper *o, |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 1797 | PyObject *args, PyObject *kwds) |
| 1798 | { |
Serhiy Storchaka | bca4939 | 2017-09-03 08:10:14 +0300 | [diff] [blame] | 1799 | if (kwds != NULL && PyDict_GET_SIZE(kwds) != 0) { |
| 1800 | PyErr_SetString(PyExc_TypeError, "function takes no keyword arguments"); |
| 1801 | return NULL; |
| 1802 | } |
| 1803 | if (args != NULL && PyTuple_GET_SIZE(args) != 0) { |
| 1804 | PyErr_SetString(PyExc_TypeError, "function takes no positional arguments"); |
| 1805 | return NULL; |
| 1806 | } |
Yury Selivanov | 22feeb8 | 2018-01-24 11:31:01 -0500 | [diff] [blame] | 1807 | return task_step(o->sw_task, o->sw_arg); |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 1808 | } |
| 1809 | |
| 1810 | static int |
Serhiy Storchaka | bca4939 | 2017-09-03 08:10:14 +0300 | [diff] [blame] | 1811 | TaskStepMethWrapper_traverse(TaskStepMethWrapper *o, |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 1812 | visitproc visit, void *arg) |
| 1813 | { |
| 1814 | Py_VISIT(o->sw_task); |
| 1815 | Py_VISIT(o->sw_arg); |
| 1816 | return 0; |
| 1817 | } |
| 1818 | |
| 1819 | static PyObject * |
Serhiy Storchaka | d4f9cf5 | 2018-11-27 19:34:35 +0200 | [diff] [blame] | 1820 | TaskStepMethWrapper_get___self__(TaskStepMethWrapper *o, void *Py_UNUSED(ignored)) |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 1821 | { |
| 1822 | if (o->sw_task) { |
| 1823 | Py_INCREF(o->sw_task); |
| 1824 | return (PyObject*)o->sw_task; |
| 1825 | } |
| 1826 | Py_RETURN_NONE; |
| 1827 | } |
| 1828 | |
Serhiy Storchaka | bca4939 | 2017-09-03 08:10:14 +0300 | [diff] [blame] | 1829 | static PyGetSetDef TaskStepMethWrapper_getsetlist[] = { |
| 1830 | {"__self__", (getter)TaskStepMethWrapper_get___self__, NULL, NULL}, |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 1831 | {NULL} /* Sentinel */ |
| 1832 | }; |
| 1833 | |
Benjamin Peterson | 3c8aae9 | 2018-07-05 22:39:34 -0700 | [diff] [blame] | 1834 | static PyTypeObject TaskStepMethWrapper_Type = { |
Victor Stinner | 1aea8fb | 2016-10-28 19:13:52 +0200 | [diff] [blame] | 1835 | PyVarObject_HEAD_INIT(NULL, 0) |
Serhiy Storchaka | bca4939 | 2017-09-03 08:10:14 +0300 | [diff] [blame] | 1836 | "TaskStepMethWrapper", |
| 1837 | .tp_basicsize = sizeof(TaskStepMethWrapper), |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 1838 | .tp_itemsize = 0, |
Serhiy Storchaka | bca4939 | 2017-09-03 08:10:14 +0300 | [diff] [blame] | 1839 | .tp_getset = TaskStepMethWrapper_getsetlist, |
| 1840 | .tp_dealloc = (destructor)TaskStepMethWrapper_dealloc, |
| 1841 | .tp_call = (ternaryfunc)TaskStepMethWrapper_call, |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 1842 | .tp_getattro = PyObject_GenericGetAttr, |
| 1843 | .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, |
Serhiy Storchaka | bca4939 | 2017-09-03 08:10:14 +0300 | [diff] [blame] | 1844 | .tp_traverse = (traverseproc)TaskStepMethWrapper_traverse, |
| 1845 | .tp_clear = (inquiry)TaskStepMethWrapper_clear, |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 1846 | }; |
| 1847 | |
| 1848 | static PyObject * |
Serhiy Storchaka | bca4939 | 2017-09-03 08:10:14 +0300 | [diff] [blame] | 1849 | TaskStepMethWrapper_new(TaskObj *task, PyObject *arg) |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 1850 | { |
Serhiy Storchaka | bca4939 | 2017-09-03 08:10:14 +0300 | [diff] [blame] | 1851 | TaskStepMethWrapper *o; |
| 1852 | o = PyObject_GC_New(TaskStepMethWrapper, &TaskStepMethWrapper_Type); |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 1853 | if (o == NULL) { |
| 1854 | return NULL; |
| 1855 | } |
| 1856 | |
| 1857 | Py_INCREF(task); |
| 1858 | o->sw_task = task; |
| 1859 | |
| 1860 | Py_XINCREF(arg); |
| 1861 | o->sw_arg = arg; |
| 1862 | |
| 1863 | PyObject_GC_Track(o); |
| 1864 | return (PyObject*) o; |
| 1865 | } |
| 1866 | |
| 1867 | /* ----- Task._wakeup wrapper */ |
| 1868 | |
| 1869 | static PyObject * |
| 1870 | TaskWakeupMethWrapper_call(TaskWakeupMethWrapper *o, |
| 1871 | PyObject *args, PyObject *kwds) |
| 1872 | { |
| 1873 | PyObject *fut; |
| 1874 | |
Serhiy Storchaka | bca4939 | 2017-09-03 08:10:14 +0300 | [diff] [blame] | 1875 | if (kwds != NULL && PyDict_GET_SIZE(kwds) != 0) { |
| 1876 | PyErr_SetString(PyExc_TypeError, "function takes no keyword arguments"); |
| 1877 | return NULL; |
| 1878 | } |
| 1879 | if (!PyArg_ParseTuple(args, "O", &fut)) { |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 1880 | return NULL; |
| 1881 | } |
| 1882 | |
Yury Selivanov | 22feeb8 | 2018-01-24 11:31:01 -0500 | [diff] [blame] | 1883 | return task_wakeup(o->ww_task, fut); |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 1884 | } |
| 1885 | |
| 1886 | static int |
| 1887 | TaskWakeupMethWrapper_clear(TaskWakeupMethWrapper *o) |
| 1888 | { |
| 1889 | Py_CLEAR(o->ww_task); |
| 1890 | return 0; |
| 1891 | } |
| 1892 | |
| 1893 | static int |
| 1894 | TaskWakeupMethWrapper_traverse(TaskWakeupMethWrapper *o, |
| 1895 | visitproc visit, void *arg) |
| 1896 | { |
| 1897 | Py_VISIT(o->ww_task); |
| 1898 | return 0; |
| 1899 | } |
| 1900 | |
| 1901 | static void |
| 1902 | TaskWakeupMethWrapper_dealloc(TaskWakeupMethWrapper *o) |
| 1903 | { |
| 1904 | PyObject_GC_UnTrack(o); |
| 1905 | (void)TaskWakeupMethWrapper_clear(o); |
| 1906 | Py_TYPE(o)->tp_free(o); |
| 1907 | } |
| 1908 | |
Andrew Svetlov | 969ae7a | 2019-12-07 13:23:21 +0200 | [diff] [blame] | 1909 | static PyObject * |
| 1910 | TaskWakeupMethWrapper_get___self__(TaskWakeupMethWrapper *o, void *Py_UNUSED(ignored)) |
| 1911 | { |
| 1912 | if (o->ww_task) { |
| 1913 | Py_INCREF(o->ww_task); |
| 1914 | return (PyObject*)o->ww_task; |
| 1915 | } |
| 1916 | Py_RETURN_NONE; |
| 1917 | } |
| 1918 | |
| 1919 | static PyGetSetDef TaskWakeupMethWrapper_getsetlist[] = { |
| 1920 | {"__self__", (getter)TaskWakeupMethWrapper_get___self__, NULL, NULL}, |
| 1921 | {NULL} /* Sentinel */ |
| 1922 | }; |
| 1923 | |
Benjamin Peterson | 3c8aae9 | 2018-07-05 22:39:34 -0700 | [diff] [blame] | 1924 | static PyTypeObject TaskWakeupMethWrapper_Type = { |
Victor Stinner | 1aea8fb | 2016-10-28 19:13:52 +0200 | [diff] [blame] | 1925 | PyVarObject_HEAD_INIT(NULL, 0) |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 1926 | "TaskWakeupMethWrapper", |
| 1927 | .tp_basicsize = sizeof(TaskWakeupMethWrapper), |
| 1928 | .tp_itemsize = 0, |
| 1929 | .tp_dealloc = (destructor)TaskWakeupMethWrapper_dealloc, |
| 1930 | .tp_call = (ternaryfunc)TaskWakeupMethWrapper_call, |
| 1931 | .tp_getattro = PyObject_GenericGetAttr, |
| 1932 | .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, |
| 1933 | .tp_traverse = (traverseproc)TaskWakeupMethWrapper_traverse, |
| 1934 | .tp_clear = (inquiry)TaskWakeupMethWrapper_clear, |
Andrew Svetlov | 969ae7a | 2019-12-07 13:23:21 +0200 | [diff] [blame] | 1935 | .tp_getset = TaskWakeupMethWrapper_getsetlist, |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 1936 | }; |
| 1937 | |
| 1938 | static PyObject * |
| 1939 | TaskWakeupMethWrapper_new(TaskObj *task) |
| 1940 | { |
| 1941 | TaskWakeupMethWrapper *o; |
| 1942 | o = PyObject_GC_New(TaskWakeupMethWrapper, &TaskWakeupMethWrapper_Type); |
| 1943 | if (o == NULL) { |
| 1944 | return NULL; |
| 1945 | } |
| 1946 | |
| 1947 | Py_INCREF(task); |
| 1948 | o->ww_task = task; |
| 1949 | |
| 1950 | PyObject_GC_Track(o); |
| 1951 | return (PyObject*) o; |
| 1952 | } |
| 1953 | |
Andrew Svetlov | 44d1a59 | 2017-12-16 21:58:38 +0200 | [diff] [blame] | 1954 | /* ----- Task introspection helpers */ |
| 1955 | |
| 1956 | static int |
Yury Selivanov | ca9b36c | 2017-12-23 15:04:15 -0500 | [diff] [blame] | 1957 | register_task(PyObject *task) |
Andrew Svetlov | 44d1a59 | 2017-12-16 21:58:38 +0200 | [diff] [blame] | 1958 | { |
Yury Selivanov | ca9b36c | 2017-12-23 15:04:15 -0500 | [diff] [blame] | 1959 | _Py_IDENTIFIER(add); |
| 1960 | |
Jeroen Demeyer | 59ad110 | 2019-07-11 10:59:05 +0200 | [diff] [blame] | 1961 | PyObject *res = _PyObject_CallMethodIdOneArg(all_tasks, |
| 1962 | &PyId_add, task); |
Yury Selivanov | ca9b36c | 2017-12-23 15:04:15 -0500 | [diff] [blame] | 1963 | if (res == NULL) { |
| 1964 | return -1; |
| 1965 | } |
| 1966 | Py_DECREF(res); |
| 1967 | return 0; |
Andrew Svetlov | 44d1a59 | 2017-12-16 21:58:38 +0200 | [diff] [blame] | 1968 | } |
| 1969 | |
| 1970 | |
| 1971 | static int |
Yury Selivanov | ca9b36c | 2017-12-23 15:04:15 -0500 | [diff] [blame] | 1972 | unregister_task(PyObject *task) |
Andrew Svetlov | 44d1a59 | 2017-12-16 21:58:38 +0200 | [diff] [blame] | 1973 | { |
Yury Selivanov | ca9b36c | 2017-12-23 15:04:15 -0500 | [diff] [blame] | 1974 | _Py_IDENTIFIER(discard); |
Andrew Svetlov | 44d1a59 | 2017-12-16 21:58:38 +0200 | [diff] [blame] | 1975 | |
Jeroen Demeyer | 59ad110 | 2019-07-11 10:59:05 +0200 | [diff] [blame] | 1976 | PyObject *res = _PyObject_CallMethodIdOneArg(all_tasks, |
| 1977 | &PyId_discard, task); |
Andrew Svetlov | 44d1a59 | 2017-12-16 21:58:38 +0200 | [diff] [blame] | 1978 | if (res == NULL) { |
| 1979 | return -1; |
| 1980 | } |
| 1981 | Py_DECREF(res); |
| 1982 | return 0; |
| 1983 | } |
| 1984 | |
| 1985 | |
| 1986 | static int |
| 1987 | enter_task(PyObject *loop, PyObject *task) |
| 1988 | { |
| 1989 | PyObject *item; |
| 1990 | Py_hash_t hash; |
| 1991 | hash = PyObject_Hash(loop); |
| 1992 | if (hash == -1) { |
| 1993 | return -1; |
| 1994 | } |
| 1995 | item = _PyDict_GetItem_KnownHash(current_tasks, loop, hash); |
| 1996 | if (item != NULL) { |
Serhiy Storchaka | 6655354 | 2018-05-20 16:30:31 +0300 | [diff] [blame] | 1997 | Py_INCREF(item); |
Andrew Svetlov | 44d1a59 | 2017-12-16 21:58:38 +0200 | [diff] [blame] | 1998 | PyErr_Format( |
| 1999 | PyExc_RuntimeError, |
| 2000 | "Cannot enter into task %R while another " \ |
| 2001 | "task %R is being executed.", |
| 2002 | task, item, NULL); |
Serhiy Storchaka | 6655354 | 2018-05-20 16:30:31 +0300 | [diff] [blame] | 2003 | Py_DECREF(item); |
Andrew Svetlov | 44d1a59 | 2017-12-16 21:58:38 +0200 | [diff] [blame] | 2004 | return -1; |
| 2005 | } |
Serhiy Storchaka | 6655354 | 2018-05-20 16:30:31 +0300 | [diff] [blame] | 2006 | if (PyErr_Occurred()) { |
Andrew Svetlov | 44d1a59 | 2017-12-16 21:58:38 +0200 | [diff] [blame] | 2007 | return -1; |
| 2008 | } |
Serhiy Storchaka | 6655354 | 2018-05-20 16:30:31 +0300 | [diff] [blame] | 2009 | return _PyDict_SetItem_KnownHash(current_tasks, loop, task, hash); |
Andrew Svetlov | 44d1a59 | 2017-12-16 21:58:38 +0200 | [diff] [blame] | 2010 | } |
| 2011 | |
| 2012 | |
| 2013 | static int |
| 2014 | leave_task(PyObject *loop, PyObject *task) |
| 2015 | /*[clinic end generated code: output=0ebf6db4b858fb41 input=51296a46313d1ad8]*/ |
| 2016 | { |
| 2017 | PyObject *item; |
| 2018 | Py_hash_t hash; |
| 2019 | hash = PyObject_Hash(loop); |
| 2020 | if (hash == -1) { |
| 2021 | return -1; |
| 2022 | } |
| 2023 | item = _PyDict_GetItem_KnownHash(current_tasks, loop, hash); |
| 2024 | if (item != task) { |
| 2025 | if (item == NULL) { |
| 2026 | /* Not entered, replace with None */ |
| 2027 | item = Py_None; |
| 2028 | } |
| 2029 | PyErr_Format( |
| 2030 | PyExc_RuntimeError, |
| 2031 | "Leaving task %R does not match the current task %R.", |
| 2032 | task, item, NULL); |
| 2033 | return -1; |
| 2034 | } |
| 2035 | return _PyDict_DelItem_KnownHash(current_tasks, loop, hash); |
| 2036 | } |
| 2037 | |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 2038 | /* ----- Task */ |
| 2039 | |
| 2040 | /*[clinic input] |
| 2041 | _asyncio.Task.__init__ |
| 2042 | |
Serhiy Storchaka | bca4939 | 2017-09-03 08:10:14 +0300 | [diff] [blame] | 2043 | coro: object |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 2044 | * |
Serhiy Storchaka | bca4939 | 2017-09-03 08:10:14 +0300 | [diff] [blame] | 2045 | loop: object = None |
Alex Grönholm | cca4eec | 2018-08-09 00:06:47 +0300 | [diff] [blame] | 2046 | name: object = None |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 2047 | |
| 2048 | A coroutine wrapped in a Future. |
| 2049 | [clinic start generated code]*/ |
| 2050 | |
| 2051 | static int |
Alex Grönholm | cca4eec | 2018-08-09 00:06:47 +0300 | [diff] [blame] | 2052 | _asyncio_Task___init___impl(TaskObj *self, PyObject *coro, PyObject *loop, |
| 2053 | PyObject *name) |
| 2054 | /*[clinic end generated code: output=88b12b83d570df50 input=352a3137fe60091d]*/ |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 2055 | { |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 2056 | if (future_init((FutureObj*)self, loop)) { |
INADA Naoki | c411a7d | 2016-10-18 11:48:14 +0900 | [diff] [blame] | 2057 | return -1; |
| 2058 | } |
INADA Naoki | c411a7d | 2016-10-18 11:48:14 +0900 | [diff] [blame] | 2059 | |
Yury Selivanov | a9d7e55 | 2017-12-19 07:18:45 -0500 | [diff] [blame] | 2060 | int is_coro = is_coroutine(coro); |
| 2061 | if (is_coro == -1) { |
| 2062 | return -1; |
| 2063 | } |
| 2064 | if (is_coro == 0) { |
| 2065 | self->task_log_destroy_pending = 0; |
| 2066 | PyErr_Format(PyExc_TypeError, |
| 2067 | "a coroutine was expected, got %R", |
| 2068 | coro, NULL); |
| 2069 | return -1; |
Andrew Svetlov | f74ef45 | 2017-12-15 07:04:38 +0200 | [diff] [blame] | 2070 | } |
| 2071 | |
Oren Milman | d019bc8 | 2018-02-13 12:28:33 +0200 | [diff] [blame] | 2072 | Py_XSETREF(self->task_context, PyContext_CopyCurrent()); |
Yury Selivanov | f23746a | 2018-01-22 19:11:18 -0500 | [diff] [blame] | 2073 | if (self->task_context == NULL) { |
| 2074 | return -1; |
| 2075 | } |
| 2076 | |
Oren Milman | d019bc8 | 2018-02-13 12:28:33 +0200 | [diff] [blame] | 2077 | Py_CLEAR(self->task_fut_waiter); |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 2078 | self->task_must_cancel = 0; |
| 2079 | self->task_log_destroy_pending = 1; |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 2080 | Py_INCREF(coro); |
Oren Milman | d019bc8 | 2018-02-13 12:28:33 +0200 | [diff] [blame] | 2081 | Py_XSETREF(self->task_coro, coro); |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 2082 | |
Alex Grönholm | cca4eec | 2018-08-09 00:06:47 +0300 | [diff] [blame] | 2083 | if (name == Py_None) { |
| 2084 | name = PyUnicode_FromFormat("Task-%" PRIu64, ++task_name_counter); |
Alex Grönholm | a754823 | 2018-08-09 23:49:49 +0300 | [diff] [blame] | 2085 | } else if (!PyUnicode_CheckExact(name)) { |
Alex Grönholm | cca4eec | 2018-08-09 00:06:47 +0300 | [diff] [blame] | 2086 | name = PyObject_Str(name); |
| 2087 | } else { |
| 2088 | Py_INCREF(name); |
| 2089 | } |
| 2090 | Py_XSETREF(self->task_name, name); |
| 2091 | if (self->task_name == NULL) { |
| 2092 | return -1; |
| 2093 | } |
| 2094 | |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 2095 | if (task_call_step_soon(self, NULL)) { |
| 2096 | return -1; |
INADA Naoki | c411a7d | 2016-10-18 11:48:14 +0900 | [diff] [blame] | 2097 | } |
Yury Selivanov | ca9b36c | 2017-12-23 15:04:15 -0500 | [diff] [blame] | 2098 | return register_task((PyObject*)self); |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 2099 | } |
| 2100 | |
| 2101 | static int |
| 2102 | TaskObj_clear(TaskObj *task) |
| 2103 | { |
| 2104 | (void)FutureObj_clear((FutureObj*) task); |
Yury Selivanov | f23746a | 2018-01-22 19:11:18 -0500 | [diff] [blame] | 2105 | Py_CLEAR(task->task_context); |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 2106 | Py_CLEAR(task->task_coro); |
Alex Grönholm | cca4eec | 2018-08-09 00:06:47 +0300 | [diff] [blame] | 2107 | Py_CLEAR(task->task_name); |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 2108 | Py_CLEAR(task->task_fut_waiter); |
| 2109 | return 0; |
| 2110 | } |
| 2111 | |
| 2112 | static int |
| 2113 | TaskObj_traverse(TaskObj *task, visitproc visit, void *arg) |
| 2114 | { |
Yury Selivanov | f23746a | 2018-01-22 19:11:18 -0500 | [diff] [blame] | 2115 | Py_VISIT(task->task_context); |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 2116 | Py_VISIT(task->task_coro); |
Alex Grönholm | cca4eec | 2018-08-09 00:06:47 +0300 | [diff] [blame] | 2117 | Py_VISIT(task->task_name); |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 2118 | Py_VISIT(task->task_fut_waiter); |
| 2119 | (void)FutureObj_traverse((FutureObj*) task, visit, arg); |
| 2120 | return 0; |
| 2121 | } |
| 2122 | |
| 2123 | static PyObject * |
Serhiy Storchaka | d4f9cf5 | 2018-11-27 19:34:35 +0200 | [diff] [blame] | 2124 | TaskObj_get_log_destroy_pending(TaskObj *task, void *Py_UNUSED(ignored)) |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 2125 | { |
| 2126 | if (task->task_log_destroy_pending) { |
| 2127 | Py_RETURN_TRUE; |
| 2128 | } |
| 2129 | else { |
| 2130 | Py_RETURN_FALSE; |
| 2131 | } |
| 2132 | } |
| 2133 | |
| 2134 | static int |
Serhiy Storchaka | d4f9cf5 | 2018-11-27 19:34:35 +0200 | [diff] [blame] | 2135 | TaskObj_set_log_destroy_pending(TaskObj *task, PyObject *val, void *Py_UNUSED(ignored)) |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 2136 | { |
Zackery Spytz | 842acaa | 2018-12-17 07:52:45 -0700 | [diff] [blame] | 2137 | if (val == NULL) { |
| 2138 | PyErr_SetString(PyExc_AttributeError, "cannot delete attribute"); |
| 2139 | return -1; |
| 2140 | } |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 2141 | int is_true = PyObject_IsTrue(val); |
| 2142 | if (is_true < 0) { |
| 2143 | return -1; |
| 2144 | } |
| 2145 | task->task_log_destroy_pending = is_true; |
| 2146 | return 0; |
| 2147 | } |
| 2148 | |
| 2149 | static PyObject * |
Serhiy Storchaka | d4f9cf5 | 2018-11-27 19:34:35 +0200 | [diff] [blame] | 2150 | TaskObj_get_must_cancel(TaskObj *task, void *Py_UNUSED(ignored)) |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 2151 | { |
| 2152 | if (task->task_must_cancel) { |
| 2153 | Py_RETURN_TRUE; |
| 2154 | } |
| 2155 | else { |
| 2156 | Py_RETURN_FALSE; |
| 2157 | } |
| 2158 | } |
| 2159 | |
| 2160 | static PyObject * |
Serhiy Storchaka | d4f9cf5 | 2018-11-27 19:34:35 +0200 | [diff] [blame] | 2161 | TaskObj_get_coro(TaskObj *task, void *Py_UNUSED(ignored)) |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 2162 | { |
| 2163 | if (task->task_coro) { |
| 2164 | Py_INCREF(task->task_coro); |
| 2165 | return task->task_coro; |
| 2166 | } |
| 2167 | |
| 2168 | Py_RETURN_NONE; |
| 2169 | } |
| 2170 | |
| 2171 | static PyObject * |
Serhiy Storchaka | d4f9cf5 | 2018-11-27 19:34:35 +0200 | [diff] [blame] | 2172 | TaskObj_get_fut_waiter(TaskObj *task, void *Py_UNUSED(ignored)) |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 2173 | { |
| 2174 | if (task->task_fut_waiter) { |
| 2175 | Py_INCREF(task->task_fut_waiter); |
| 2176 | return task->task_fut_waiter; |
| 2177 | } |
| 2178 | |
| 2179 | Py_RETURN_NONE; |
| 2180 | } |
| 2181 | |
| 2182 | /*[clinic input] |
Chris Jerdonek | da742ba | 2020-05-17 22:47:31 -0700 | [diff] [blame] | 2183 | _asyncio.Task._make_cancelled_error |
| 2184 | |
| 2185 | Create the CancelledError to raise if the Task is cancelled. |
| 2186 | |
| 2187 | This should only be called once when handling a cancellation since |
| 2188 | it erases the context exception value. |
| 2189 | [clinic start generated code]*/ |
| 2190 | |
| 2191 | static PyObject * |
| 2192 | _asyncio_Task__make_cancelled_error_impl(TaskObj *self) |
| 2193 | /*[clinic end generated code: output=55a819e8b4276fab input=52c0e32de8e2f840]*/ |
| 2194 | { |
| 2195 | FutureObj *fut = (FutureObj*)self; |
| 2196 | return _asyncio_Future__make_cancelled_error_impl(fut); |
| 2197 | } |
| 2198 | |
| 2199 | |
| 2200 | /*[clinic input] |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 2201 | _asyncio.Task._repr_info |
| 2202 | [clinic start generated code]*/ |
| 2203 | |
| 2204 | static PyObject * |
| 2205 | _asyncio_Task__repr_info_impl(TaskObj *self) |
| 2206 | /*[clinic end generated code: output=6a490eb66d5ba34b input=3c6d051ed3ddec8b]*/ |
| 2207 | { |
Petr Viktorin | ffd9753 | 2020-02-11 17:46:57 +0100 | [diff] [blame] | 2208 | return PyObject_CallOneArg(asyncio_task_repr_info_func, (PyObject *)self); |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 2209 | } |
| 2210 | |
| 2211 | /*[clinic input] |
| 2212 | _asyncio.Task.cancel |
| 2213 | |
Chris Jerdonek | 1ce5841 | 2020-05-15 16:55:50 -0700 | [diff] [blame] | 2214 | msg: object = None |
| 2215 | |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 2216 | Request that this task cancel itself. |
| 2217 | |
| 2218 | This arranges for a CancelledError to be thrown into the |
| 2219 | wrapped coroutine on the next cycle through the event loop. |
| 2220 | The coroutine then has a chance to clean up or even deny |
| 2221 | the request using try/except/finally. |
| 2222 | |
| 2223 | Unlike Future.cancel, this does not guarantee that the |
| 2224 | task will be cancelled: the exception might be caught and |
| 2225 | acted upon, delaying cancellation of the task or preventing |
| 2226 | cancellation completely. The task may also return a value or |
| 2227 | raise a different exception. |
| 2228 | |
| 2229 | Immediately after this method is called, Task.cancelled() will |
| 2230 | not return True (unless the task was already cancelled). A |
| 2231 | task will be marked as cancelled when the wrapped coroutine |
| 2232 | terminates with a CancelledError exception (even if cancel() |
| 2233 | was not called). |
| 2234 | [clinic start generated code]*/ |
| 2235 | |
| 2236 | static PyObject * |
Chris Jerdonek | 1ce5841 | 2020-05-15 16:55:50 -0700 | [diff] [blame] | 2237 | _asyncio_Task_cancel_impl(TaskObj *self, PyObject *msg) |
| 2238 | /*[clinic end generated code: output=c66b60d41c74f9f1 input=f4ff8e8ffc5f1c00]*/ |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 2239 | { |
Yury Selivanov | 7ce1c6f | 2017-06-11 13:49:18 +0000 | [diff] [blame] | 2240 | self->task_log_tb = 0; |
| 2241 | |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 2242 | if (self->task_state != STATE_PENDING) { |
| 2243 | Py_RETURN_FALSE; |
| 2244 | } |
| 2245 | |
| 2246 | if (self->task_fut_waiter) { |
| 2247 | PyObject *res; |
| 2248 | int is_true; |
| 2249 | |
Chris Jerdonek | 1ce5841 | 2020-05-15 16:55:50 -0700 | [diff] [blame] | 2250 | res = _PyObject_CallMethodIdOneArg(self->task_fut_waiter, |
| 2251 | &PyId_cancel, msg); |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 2252 | if (res == NULL) { |
| 2253 | return NULL; |
| 2254 | } |
| 2255 | |
| 2256 | is_true = PyObject_IsTrue(res); |
| 2257 | Py_DECREF(res); |
| 2258 | if (is_true < 0) { |
| 2259 | return NULL; |
| 2260 | } |
| 2261 | |
| 2262 | if (is_true) { |
| 2263 | Py_RETURN_TRUE; |
| 2264 | } |
| 2265 | } |
| 2266 | |
| 2267 | self->task_must_cancel = 1; |
Chris Jerdonek | 1ce5841 | 2020-05-15 16:55:50 -0700 | [diff] [blame] | 2268 | Py_XINCREF(msg); |
| 2269 | Py_XSETREF(self->task_cancel_msg, msg); |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 2270 | Py_RETURN_TRUE; |
| 2271 | } |
| 2272 | |
| 2273 | /*[clinic input] |
| 2274 | _asyncio.Task.get_stack |
| 2275 | |
| 2276 | * |
Serhiy Storchaka | bca4939 | 2017-09-03 08:10:14 +0300 | [diff] [blame] | 2277 | limit: object = None |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 2278 | |
| 2279 | Return the list of stack frames for this task's coroutine. |
| 2280 | |
| 2281 | If the coroutine is not done, this returns the stack where it is |
| 2282 | suspended. If the coroutine has completed successfully or was |
| 2283 | cancelled, this returns an empty list. If the coroutine was |
| 2284 | terminated by an exception, this returns the list of traceback |
| 2285 | frames. |
| 2286 | |
| 2287 | The frames are always ordered from oldest to newest. |
| 2288 | |
| 2289 | The optional limit gives the maximum number of frames to |
| 2290 | return; by default all available frames are returned. Its |
| 2291 | meaning differs depending on whether a stack or a traceback is |
| 2292 | returned: the newest frames of a stack are returned, but the |
| 2293 | oldest frames of a traceback are returned. (This matches the |
| 2294 | behavior of the traceback module.) |
| 2295 | |
| 2296 | For reasons beyond our control, only one stack frame is |
| 2297 | returned for a suspended coroutine. |
| 2298 | [clinic start generated code]*/ |
| 2299 | |
| 2300 | static PyObject * |
| 2301 | _asyncio_Task_get_stack_impl(TaskObj *self, PyObject *limit) |
Serhiy Storchaka | bca4939 | 2017-09-03 08:10:14 +0300 | [diff] [blame] | 2302 | /*[clinic end generated code: output=c9aeeeebd1e18118 input=05b323d42b809b90]*/ |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 2303 | { |
| 2304 | return PyObject_CallFunctionObjArgs( |
| 2305 | asyncio_task_get_stack_func, self, limit, NULL); |
| 2306 | } |
| 2307 | |
| 2308 | /*[clinic input] |
| 2309 | _asyncio.Task.print_stack |
| 2310 | |
| 2311 | * |
Serhiy Storchaka | bca4939 | 2017-09-03 08:10:14 +0300 | [diff] [blame] | 2312 | limit: object = None |
| 2313 | file: object = None |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 2314 | |
| 2315 | Print the stack or traceback for this task's coroutine. |
| 2316 | |
| 2317 | This produces output similar to that of the traceback module, |
| 2318 | for the frames retrieved by get_stack(). The limit argument |
| 2319 | is passed to get_stack(). The file argument is an I/O stream |
| 2320 | to which the output is written; by default output is written |
| 2321 | to sys.stderr. |
| 2322 | [clinic start generated code]*/ |
| 2323 | |
| 2324 | static PyObject * |
| 2325 | _asyncio_Task_print_stack_impl(TaskObj *self, PyObject *limit, |
| 2326 | PyObject *file) |
Serhiy Storchaka | bca4939 | 2017-09-03 08:10:14 +0300 | [diff] [blame] | 2327 | /*[clinic end generated code: output=7339e10314cd3f4d input=1a0352913b7fcd92]*/ |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 2328 | { |
| 2329 | return PyObject_CallFunctionObjArgs( |
| 2330 | asyncio_task_print_stack_func, self, limit, file, NULL); |
| 2331 | } |
| 2332 | |
| 2333 | /*[clinic input] |
Yury Selivanov | 0cf16f9 | 2017-12-25 10:48:15 -0500 | [diff] [blame] | 2334 | _asyncio.Task.set_result |
| 2335 | |
| 2336 | result: object |
| 2337 | / |
| 2338 | [clinic start generated code]*/ |
| 2339 | |
| 2340 | static PyObject * |
| 2341 | _asyncio_Task_set_result(TaskObj *self, PyObject *result) |
| 2342 | /*[clinic end generated code: output=1dcae308bfcba318 input=9d1a00c07be41bab]*/ |
| 2343 | { |
| 2344 | PyErr_SetString(PyExc_RuntimeError, |
| 2345 | "Task does not support set_result operation"); |
| 2346 | return NULL; |
| 2347 | } |
| 2348 | |
| 2349 | /*[clinic input] |
| 2350 | _asyncio.Task.set_exception |
| 2351 | |
| 2352 | exception: object |
| 2353 | / |
| 2354 | [clinic start generated code]*/ |
| 2355 | |
| 2356 | static PyObject * |
| 2357 | _asyncio_Task_set_exception(TaskObj *self, PyObject *exception) |
| 2358 | /*[clinic end generated code: output=bc377fc28067303d input=9a8f65c83dcf893a]*/ |
| 2359 | { |
| 2360 | PyErr_SetString(PyExc_RuntimeError, |
Andrew Svetlov | fc35932 | 2017-12-30 15:40:27 +0200 | [diff] [blame] | 2361 | "Task does not support set_exception operation"); |
Yury Selivanov | 0cf16f9 | 2017-12-25 10:48:15 -0500 | [diff] [blame] | 2362 | return NULL; |
| 2363 | } |
| 2364 | |
Alex Grönholm | cca4eec | 2018-08-09 00:06:47 +0300 | [diff] [blame] | 2365 | /*[clinic input] |
Alex Grönholm | 98ef920 | 2019-05-30 18:30:09 +0300 | [diff] [blame] | 2366 | _asyncio.Task.get_coro |
| 2367 | [clinic start generated code]*/ |
| 2368 | |
| 2369 | static PyObject * |
| 2370 | _asyncio_Task_get_coro_impl(TaskObj *self) |
| 2371 | /*[clinic end generated code: output=bcac27c8cc6c8073 input=d2e8606c42a7b403]*/ |
| 2372 | { |
| 2373 | Py_INCREF(self->task_coro); |
| 2374 | return self->task_coro; |
| 2375 | } |
| 2376 | |
| 2377 | /*[clinic input] |
Alex Grönholm | cca4eec | 2018-08-09 00:06:47 +0300 | [diff] [blame] | 2378 | _asyncio.Task.get_name |
| 2379 | [clinic start generated code]*/ |
| 2380 | |
| 2381 | static PyObject * |
| 2382 | _asyncio_Task_get_name_impl(TaskObj *self) |
| 2383 | /*[clinic end generated code: output=0ecf1570c3b37a8f input=a4a6595d12f4f0f8]*/ |
| 2384 | { |
| 2385 | if (self->task_name) { |
| 2386 | Py_INCREF(self->task_name); |
| 2387 | return self->task_name; |
| 2388 | } |
| 2389 | |
| 2390 | Py_RETURN_NONE; |
| 2391 | } |
| 2392 | |
| 2393 | /*[clinic input] |
| 2394 | _asyncio.Task.set_name |
| 2395 | |
| 2396 | value: object |
| 2397 | / |
| 2398 | [clinic start generated code]*/ |
| 2399 | |
| 2400 | static PyObject * |
| 2401 | _asyncio_Task_set_name(TaskObj *self, PyObject *value) |
| 2402 | /*[clinic end generated code: output=138a8d51e32057d6 input=a8359b6e65f8fd31]*/ |
| 2403 | { |
Alex Grönholm | a754823 | 2018-08-09 23:49:49 +0300 | [diff] [blame] | 2404 | if (!PyUnicode_CheckExact(value)) { |
| 2405 | value = PyObject_Str(value); |
| 2406 | if (value == NULL) { |
| 2407 | return NULL; |
| 2408 | } |
| 2409 | } else { |
| 2410 | Py_INCREF(value); |
Alex Grönholm | cca4eec | 2018-08-09 00:06:47 +0300 | [diff] [blame] | 2411 | } |
| 2412 | |
Alex Grönholm | a754823 | 2018-08-09 23:49:49 +0300 | [diff] [blame] | 2413 | Py_XSETREF(self->task_name, value); |
Alex Grönholm | cca4eec | 2018-08-09 00:06:47 +0300 | [diff] [blame] | 2414 | Py_RETURN_NONE; |
| 2415 | } |
Yury Selivanov | 0cf16f9 | 2017-12-25 10:48:15 -0500 | [diff] [blame] | 2416 | |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 2417 | static void |
| 2418 | TaskObj_finalize(TaskObj *task) |
| 2419 | { |
| 2420 | _Py_IDENTIFIER(call_exception_handler); |
| 2421 | _Py_IDENTIFIER(task); |
| 2422 | _Py_IDENTIFIER(message); |
| 2423 | _Py_IDENTIFIER(source_traceback); |
| 2424 | |
Serhiy Storchaka | bca4939 | 2017-09-03 08:10:14 +0300 | [diff] [blame] | 2425 | PyObject *context; |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 2426 | PyObject *message = NULL; |
Serhiy Storchaka | bca4939 | 2017-09-03 08:10:14 +0300 | [diff] [blame] | 2427 | PyObject *func; |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 2428 | PyObject *error_type, *error_value, *error_traceback; |
| 2429 | |
| 2430 | if (task->task_state != STATE_PENDING || !task->task_log_destroy_pending) { |
| 2431 | goto done; |
| 2432 | } |
| 2433 | |
| 2434 | /* Save the current exception, if any. */ |
| 2435 | PyErr_Fetch(&error_type, &error_value, &error_traceback); |
| 2436 | |
| 2437 | context = PyDict_New(); |
| 2438 | if (context == NULL) { |
| 2439 | goto finally; |
| 2440 | } |
| 2441 | |
| 2442 | message = PyUnicode_FromString("Task was destroyed but it is pending!"); |
| 2443 | if (message == NULL) { |
| 2444 | goto finally; |
| 2445 | } |
| 2446 | |
| 2447 | if (_PyDict_SetItemId(context, &PyId_message, message) < 0 || |
| 2448 | _PyDict_SetItemId(context, &PyId_task, (PyObject*)task) < 0) |
| 2449 | { |
| 2450 | goto finally; |
| 2451 | } |
| 2452 | |
| 2453 | if (task->task_source_tb != NULL) { |
| 2454 | if (_PyDict_SetItemId(context, &PyId_source_traceback, |
| 2455 | task->task_source_tb) < 0) |
| 2456 | { |
| 2457 | goto finally; |
| 2458 | } |
| 2459 | } |
| 2460 | |
| 2461 | func = _PyObject_GetAttrId(task->task_loop, &PyId_call_exception_handler); |
| 2462 | if (func != NULL) { |
Petr Viktorin | ffd9753 | 2020-02-11 17:46:57 +0100 | [diff] [blame] | 2463 | PyObject *res = PyObject_CallOneArg(func, context); |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 2464 | if (res == NULL) { |
| 2465 | PyErr_WriteUnraisable(func); |
| 2466 | } |
Serhiy Storchaka | bca4939 | 2017-09-03 08:10:14 +0300 | [diff] [blame] | 2467 | else { |
| 2468 | Py_DECREF(res); |
| 2469 | } |
| 2470 | Py_DECREF(func); |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 2471 | } |
| 2472 | |
| 2473 | finally: |
Serhiy Storchaka | bca4939 | 2017-09-03 08:10:14 +0300 | [diff] [blame] | 2474 | Py_XDECREF(context); |
| 2475 | Py_XDECREF(message); |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 2476 | |
| 2477 | /* Restore the saved exception. */ |
| 2478 | PyErr_Restore(error_type, error_value, error_traceback); |
| 2479 | |
| 2480 | done: |
| 2481 | FutureObj_finalize((FutureObj*)task); |
| 2482 | } |
| 2483 | |
Batuhan TaÅŸkaya | dec3672 | 2019-12-07 14:05:07 +0300 | [diff] [blame] | 2484 | static PyObject * |
| 2485 | task_cls_getitem(PyObject *cls, PyObject *type) |
| 2486 | { |
| 2487 | Py_INCREF(cls); |
| 2488 | return cls; |
| 2489 | } |
| 2490 | |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 2491 | static void TaskObj_dealloc(PyObject *); /* Needs Task_CheckExact */ |
| 2492 | |
| 2493 | static PyMethodDef TaskType_methods[] = { |
| 2494 | _ASYNCIO_FUTURE_RESULT_METHODDEF |
| 2495 | _ASYNCIO_FUTURE_EXCEPTION_METHODDEF |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 2496 | _ASYNCIO_FUTURE_ADD_DONE_CALLBACK_METHODDEF |
| 2497 | _ASYNCIO_FUTURE_REMOVE_DONE_CALLBACK_METHODDEF |
| 2498 | _ASYNCIO_FUTURE_CANCELLED_METHODDEF |
| 2499 | _ASYNCIO_FUTURE_DONE_METHODDEF |
Yury Selivanov | 0cf16f9 | 2017-12-25 10:48:15 -0500 | [diff] [blame] | 2500 | _ASYNCIO_TASK_SET_RESULT_METHODDEF |
| 2501 | _ASYNCIO_TASK_SET_EXCEPTION_METHODDEF |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 2502 | _ASYNCIO_TASK_CANCEL_METHODDEF |
| 2503 | _ASYNCIO_TASK_GET_STACK_METHODDEF |
| 2504 | _ASYNCIO_TASK_PRINT_STACK_METHODDEF |
Chris Jerdonek | da742ba | 2020-05-17 22:47:31 -0700 | [diff] [blame] | 2505 | _ASYNCIO_TASK__MAKE_CANCELLED_ERROR_METHODDEF |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 2506 | _ASYNCIO_TASK__REPR_INFO_METHODDEF |
Alex Grönholm | cca4eec | 2018-08-09 00:06:47 +0300 | [diff] [blame] | 2507 | _ASYNCIO_TASK_GET_NAME_METHODDEF |
| 2508 | _ASYNCIO_TASK_SET_NAME_METHODDEF |
Alex Grönholm | 98ef920 | 2019-05-30 18:30:09 +0300 | [diff] [blame] | 2509 | _ASYNCIO_TASK_GET_CORO_METHODDEF |
Batuhan TaÅŸkaya | dec3672 | 2019-12-07 14:05:07 +0300 | [diff] [blame] | 2510 | {"__class_getitem__", task_cls_getitem, METH_O|METH_CLASS, NULL}, |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 2511 | {NULL, NULL} /* Sentinel */ |
| 2512 | }; |
| 2513 | |
| 2514 | static PyGetSetDef TaskType_getsetlist[] = { |
| 2515 | FUTURE_COMMON_GETSETLIST |
| 2516 | {"_log_destroy_pending", (getter)TaskObj_get_log_destroy_pending, |
| 2517 | (setter)TaskObj_set_log_destroy_pending, NULL}, |
| 2518 | {"_must_cancel", (getter)TaskObj_get_must_cancel, NULL, NULL}, |
| 2519 | {"_coro", (getter)TaskObj_get_coro, NULL, NULL}, |
| 2520 | {"_fut_waiter", (getter)TaskObj_get_fut_waiter, NULL, NULL}, |
| 2521 | {NULL} /* Sentinel */ |
| 2522 | }; |
| 2523 | |
| 2524 | static PyTypeObject TaskType = { |
Victor Stinner | 1aea8fb | 2016-10-28 19:13:52 +0200 | [diff] [blame] | 2525 | PyVarObject_HEAD_INIT(NULL, 0) |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 2526 | "_asyncio.Task", |
| 2527 | sizeof(TaskObj), /* tp_basicsize */ |
| 2528 | .tp_base = &FutureType, |
| 2529 | .tp_dealloc = TaskObj_dealloc, |
| 2530 | .tp_as_async = &FutureType_as_async, |
| 2531 | .tp_repr = (reprfunc)FutureObj_repr, |
Antoine Pitrou | ada319b | 2019-05-29 22:12:38 +0200 | [diff] [blame] | 2532 | .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE, |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 2533 | .tp_doc = _asyncio_Task___init____doc__, |
| 2534 | .tp_traverse = (traverseproc)TaskObj_traverse, |
| 2535 | .tp_clear = (inquiry)TaskObj_clear, |
| 2536 | .tp_weaklistoffset = offsetof(TaskObj, task_weakreflist), |
| 2537 | .tp_iter = (getiterfunc)future_new_iter, |
| 2538 | .tp_methods = TaskType_methods, |
| 2539 | .tp_getset = TaskType_getsetlist, |
| 2540 | .tp_dictoffset = offsetof(TaskObj, dict), |
| 2541 | .tp_init = (initproc)_asyncio_Task___init__, |
| 2542 | .tp_new = PyType_GenericNew, |
| 2543 | .tp_finalize = (destructor)TaskObj_finalize, |
| 2544 | }; |
| 2545 | |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 2546 | static void |
| 2547 | TaskObj_dealloc(PyObject *self) |
| 2548 | { |
| 2549 | TaskObj *task = (TaskObj *)self; |
| 2550 | |
| 2551 | if (Task_CheckExact(self)) { |
| 2552 | /* When fut is subclass of Task, finalizer is called from |
| 2553 | * subtype_dealloc. |
| 2554 | */ |
| 2555 | if (PyObject_CallFinalizerFromDealloc(self) < 0) { |
| 2556 | // resurrected. |
| 2557 | return; |
| 2558 | } |
| 2559 | } |
| 2560 | |
Alexander Mohr | de34cbe | 2017-08-01 23:31:07 -0700 | [diff] [blame] | 2561 | PyObject_GC_UnTrack(self); |
| 2562 | |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 2563 | if (task->task_weakreflist != NULL) { |
| 2564 | PyObject_ClearWeakRefs(self); |
| 2565 | } |
| 2566 | |
| 2567 | (void)TaskObj_clear(task); |
| 2568 | Py_TYPE(task)->tp_free(task); |
| 2569 | } |
| 2570 | |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 2571 | static int |
| 2572 | task_call_step_soon(TaskObj *task, PyObject *arg) |
| 2573 | { |
Serhiy Storchaka | bca4939 | 2017-09-03 08:10:14 +0300 | [diff] [blame] | 2574 | PyObject *cb = TaskStepMethWrapper_new(task, arg); |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 2575 | if (cb == NULL) { |
| 2576 | return -1; |
| 2577 | } |
| 2578 | |
Yury Selivanov | f23746a | 2018-01-22 19:11:18 -0500 | [diff] [blame] | 2579 | int ret = call_soon(task->task_loop, cb, NULL, task->task_context); |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 2580 | Py_DECREF(cb); |
Yury Selivanov | 1b7c11f | 2017-12-17 20:19:47 -0500 | [diff] [blame] | 2581 | return ret; |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 2582 | } |
| 2583 | |
| 2584 | static PyObject * |
| 2585 | task_set_error_soon(TaskObj *task, PyObject *et, const char *format, ...) |
| 2586 | { |
| 2587 | PyObject* msg; |
| 2588 | |
| 2589 | va_list vargs; |
| 2590 | #ifdef HAVE_STDARG_PROTOTYPES |
| 2591 | va_start(vargs, format); |
| 2592 | #else |
| 2593 | va_start(vargs); |
| 2594 | #endif |
| 2595 | msg = PyUnicode_FromFormatV(format, vargs); |
| 2596 | va_end(vargs); |
| 2597 | |
| 2598 | if (msg == NULL) { |
| 2599 | return NULL; |
| 2600 | } |
| 2601 | |
Petr Viktorin | ffd9753 | 2020-02-11 17:46:57 +0100 | [diff] [blame] | 2602 | PyObject *e = PyObject_CallOneArg(et, msg); |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 2603 | Py_DECREF(msg); |
| 2604 | if (e == NULL) { |
| 2605 | return NULL; |
| 2606 | } |
| 2607 | |
| 2608 | if (task_call_step_soon(task, e) == -1) { |
| 2609 | Py_DECREF(e); |
| 2610 | return NULL; |
| 2611 | } |
| 2612 | |
| 2613 | Py_DECREF(e); |
| 2614 | Py_RETURN_NONE; |
| 2615 | } |
| 2616 | |
| 2617 | static PyObject * |
| 2618 | task_step_impl(TaskObj *task, PyObject *exc) |
| 2619 | { |
| 2620 | int res; |
| 2621 | int clear_exc = 0; |
| 2622 | PyObject *result = NULL; |
Serhiy Storchaka | bca4939 | 2017-09-03 08:10:14 +0300 | [diff] [blame] | 2623 | PyObject *coro; |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 2624 | PyObject *o; |
| 2625 | |
| 2626 | if (task->task_state != STATE_PENDING) { |
Yury Selivanov | 0cf16f9 | 2017-12-25 10:48:15 -0500 | [diff] [blame] | 2627 | PyErr_Format(asyncio_InvalidStateError, |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 2628 | "_step(): already done: %R %R", |
| 2629 | task, |
| 2630 | exc ? exc : Py_None); |
INADA Naoki | c411a7d | 2016-10-18 11:48:14 +0900 | [diff] [blame] | 2631 | goto fail; |
| 2632 | } |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 2633 | |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 2634 | if (task->task_must_cancel) { |
| 2635 | assert(exc != Py_None); |
| 2636 | |
| 2637 | if (exc) { |
| 2638 | /* Check if exc is a CancelledError */ |
| 2639 | res = PyObject_IsInstance(exc, asyncio_CancelledError); |
| 2640 | if (res == -1) { |
| 2641 | /* An error occurred, abort */ |
| 2642 | goto fail; |
| 2643 | } |
| 2644 | if (res == 0) { |
| 2645 | /* exc is not CancelledError; reset it to NULL */ |
| 2646 | exc = NULL; |
| 2647 | } |
| 2648 | } |
| 2649 | |
| 2650 | if (!exc) { |
| 2651 | /* exc was not a CancelledError */ |
Chris Jerdonek | 1ce5841 | 2020-05-15 16:55:50 -0700 | [diff] [blame] | 2652 | exc = create_cancelled_error(task->task_cancel_msg); |
| 2653 | |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 2654 | if (!exc) { |
| 2655 | goto fail; |
| 2656 | } |
| 2657 | clear_exc = 1; |
| 2658 | } |
| 2659 | |
| 2660 | task->task_must_cancel = 0; |
| 2661 | } |
| 2662 | |
| 2663 | Py_CLEAR(task->task_fut_waiter); |
| 2664 | |
Serhiy Storchaka | bca4939 | 2017-09-03 08:10:14 +0300 | [diff] [blame] | 2665 | coro = task->task_coro; |
| 2666 | if (coro == NULL) { |
| 2667 | PyErr_SetString(PyExc_RuntimeError, "uninitialized Task object"); |
Chris Jerdonek | d2c349b | 2020-05-08 03:54:38 -0700 | [diff] [blame] | 2668 | if (clear_exc) { |
| 2669 | /* We created 'exc' during this call */ |
| 2670 | Py_DECREF(exc); |
| 2671 | } |
Serhiy Storchaka | bca4939 | 2017-09-03 08:10:14 +0300 | [diff] [blame] | 2672 | return NULL; |
| 2673 | } |
| 2674 | |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 2675 | if (exc == NULL) { |
| 2676 | if (PyGen_CheckExact(coro) || PyCoro_CheckExact(coro)) { |
| 2677 | result = _PyGen_Send((PyGenObject*)coro, Py_None); |
| 2678 | } |
| 2679 | else { |
Jeroen Demeyer | 59ad110 | 2019-07-11 10:59:05 +0200 | [diff] [blame] | 2680 | result = _PyObject_CallMethodIdOneArg(coro, &PyId_send, Py_None); |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 2681 | } |
| 2682 | } |
| 2683 | else { |
Jeroen Demeyer | 59ad110 | 2019-07-11 10:59:05 +0200 | [diff] [blame] | 2684 | result = _PyObject_CallMethodIdOneArg(coro, &PyId_throw, exc); |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 2685 | if (clear_exc) { |
| 2686 | /* We created 'exc' during this call */ |
Serhiy Storchaka | bca4939 | 2017-09-03 08:10:14 +0300 | [diff] [blame] | 2687 | Py_DECREF(exc); |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 2688 | } |
| 2689 | } |
| 2690 | |
| 2691 | if (result == NULL) { |
| 2692 | PyObject *et, *ev, *tb; |
| 2693 | |
| 2694 | if (_PyGen_FetchStopIterationValue(&o) == 0) { |
| 2695 | /* The error is StopIteration and that means that |
| 2696 | the underlying coroutine has resolved */ |
Yury Selivanov | edad4d8 | 2019-09-25 03:32:08 -0700 | [diff] [blame] | 2697 | |
| 2698 | PyObject *res; |
INADA Naoki | 991adca | 2017-05-11 21:18:38 +0900 | [diff] [blame] | 2699 | if (task->task_must_cancel) { |
| 2700 | // Task is cancelled right before coro stops. |
INADA Naoki | 991adca | 2017-05-11 21:18:38 +0900 | [diff] [blame] | 2701 | task->task_must_cancel = 0; |
Chris Jerdonek | 1ce5841 | 2020-05-15 16:55:50 -0700 | [diff] [blame] | 2702 | res = future_cancel((FutureObj*)task, task->task_cancel_msg); |
INADA Naoki | 991adca | 2017-05-11 21:18:38 +0900 | [diff] [blame] | 2703 | } |
Yury Selivanov | edad4d8 | 2019-09-25 03:32:08 -0700 | [diff] [blame] | 2704 | else { |
| 2705 | res = future_set_result((FutureObj*)task, o); |
| 2706 | } |
| 2707 | |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 2708 | Py_DECREF(o); |
Yury Selivanov | edad4d8 | 2019-09-25 03:32:08 -0700 | [diff] [blame] | 2709 | |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 2710 | if (res == NULL) { |
| 2711 | return NULL; |
| 2712 | } |
| 2713 | Py_DECREF(res); |
| 2714 | Py_RETURN_NONE; |
| 2715 | } |
| 2716 | |
| 2717 | if (PyErr_ExceptionMatches(asyncio_CancelledError)) { |
| 2718 | /* CancelledError */ |
Chris Jerdonek | 1ce5841 | 2020-05-15 16:55:50 -0700 | [diff] [blame] | 2719 | PyErr_Fetch(&et, &ev, &tb); |
| 2720 | |
Chris Jerdonek | da742ba | 2020-05-17 22:47:31 -0700 | [diff] [blame] | 2721 | FutureObj *fut = (FutureObj*)task; |
| 2722 | _PyErr_StackItem *exc_state = &fut->fut_cancelled_exc_state; |
| 2723 | exc_state->exc_type = et; |
| 2724 | exc_state->exc_value = ev; |
| 2725 | exc_state->exc_traceback = tb; |
Chris Jerdonek | 1ce5841 | 2020-05-15 16:55:50 -0700 | [diff] [blame] | 2726 | |
Chris Jerdonek | da742ba | 2020-05-17 22:47:31 -0700 | [diff] [blame] | 2727 | return future_cancel(fut, NULL); |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 2728 | } |
| 2729 | |
| 2730 | /* Some other exception; pop it and call Task.set_exception() */ |
| 2731 | PyErr_Fetch(&et, &ev, &tb); |
INADA Naoki | 991adca | 2017-05-11 21:18:38 +0900 | [diff] [blame] | 2732 | |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 2733 | assert(et); |
| 2734 | if (!ev || !PyObject_TypeCheck(ev, (PyTypeObject *) et)) { |
| 2735 | PyErr_NormalizeException(&et, &ev, &tb); |
| 2736 | } |
Yury Selivanov | edfe886 | 2016-12-01 11:37:47 -0500 | [diff] [blame] | 2737 | if (tb != NULL) { |
| 2738 | PyException_SetTraceback(ev, tb); |
| 2739 | } |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 2740 | o = future_set_exception((FutureObj*)task, ev); |
| 2741 | if (!o) { |
| 2742 | /* An exception in Task.set_exception() */ |
Serhiy Storchaka | bca4939 | 2017-09-03 08:10:14 +0300 | [diff] [blame] | 2743 | Py_DECREF(et); |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 2744 | Py_XDECREF(tb); |
| 2745 | Py_XDECREF(ev); |
| 2746 | goto fail; |
| 2747 | } |
| 2748 | assert(o == Py_None); |
Serhiy Storchaka | bca4939 | 2017-09-03 08:10:14 +0300 | [diff] [blame] | 2749 | Py_DECREF(o); |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 2750 | |
Yury Selivanov | 431b540 | 2019-05-27 14:45:12 +0200 | [diff] [blame] | 2751 | if (PyErr_GivenExceptionMatches(et, PyExc_KeyboardInterrupt) || |
| 2752 | PyErr_GivenExceptionMatches(et, PyExc_SystemExit)) |
| 2753 | { |
| 2754 | /* We've got a KeyboardInterrupt or a SystemError; re-raise it */ |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 2755 | PyErr_Restore(et, ev, tb); |
| 2756 | goto fail; |
| 2757 | } |
| 2758 | |
Serhiy Storchaka | bca4939 | 2017-09-03 08:10:14 +0300 | [diff] [blame] | 2759 | Py_DECREF(et); |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 2760 | Py_XDECREF(tb); |
| 2761 | Py_XDECREF(ev); |
| 2762 | |
| 2763 | Py_RETURN_NONE; |
| 2764 | } |
| 2765 | |
| 2766 | if (result == (PyObject*)task) { |
| 2767 | /* We have a task that wants to await on itself */ |
| 2768 | goto self_await; |
| 2769 | } |
| 2770 | |
| 2771 | /* Check if `result` is FutureObj or TaskObj (and not a subclass) */ |
| 2772 | if (Future_CheckExact(result) || Task_CheckExact(result)) { |
| 2773 | PyObject *wrapper; |
| 2774 | PyObject *res; |
| 2775 | FutureObj *fut = (FutureObj*)result; |
| 2776 | |
| 2777 | /* Check if `result` future is attached to a different loop */ |
| 2778 | if (fut->fut_loop != task->task_loop) { |
| 2779 | goto different_loop; |
| 2780 | } |
| 2781 | |
Serhiy Storchaka | fb3e9c0 | 2018-09-21 09:11:32 +0300 | [diff] [blame] | 2782 | if (!fut->fut_blocking) { |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 2783 | goto yield_insteadof_yf; |
| 2784 | } |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 2785 | |
Serhiy Storchaka | fb3e9c0 | 2018-09-21 09:11:32 +0300 | [diff] [blame] | 2786 | fut->fut_blocking = 0; |
| 2787 | |
| 2788 | /* result.add_done_callback(task._wakeup) */ |
| 2789 | wrapper = TaskWakeupMethWrapper_new(task); |
| 2790 | if (wrapper == NULL) { |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 2791 | goto fail; |
| 2792 | } |
Serhiy Storchaka | fb3e9c0 | 2018-09-21 09:11:32 +0300 | [diff] [blame] | 2793 | res = future_add_done_callback( |
| 2794 | (FutureObj*)result, wrapper, task->task_context); |
| 2795 | Py_DECREF(wrapper); |
| 2796 | if (res == NULL) { |
| 2797 | goto fail; |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 2798 | } |
Serhiy Storchaka | fb3e9c0 | 2018-09-21 09:11:32 +0300 | [diff] [blame] | 2799 | Py_DECREF(res); |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 2800 | |
Serhiy Storchaka | fb3e9c0 | 2018-09-21 09:11:32 +0300 | [diff] [blame] | 2801 | /* task._fut_waiter = result */ |
| 2802 | task->task_fut_waiter = result; /* no incref is necessary */ |
| 2803 | |
| 2804 | if (task->task_must_cancel) { |
| 2805 | PyObject *r; |
Elvis Pranskevichus | 0c797a6 | 2018-10-03 10:30:31 -0400 | [diff] [blame] | 2806 | int is_true; |
Chris Jerdonek | 1ce5841 | 2020-05-15 16:55:50 -0700 | [diff] [blame] | 2807 | r = _PyObject_CallMethodIdOneArg(result, &PyId_cancel, |
| 2808 | task->task_cancel_msg); |
Serhiy Storchaka | fb3e9c0 | 2018-09-21 09:11:32 +0300 | [diff] [blame] | 2809 | if (r == NULL) { |
| 2810 | return NULL; |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 2811 | } |
Elvis Pranskevichus | 0c797a6 | 2018-10-03 10:30:31 -0400 | [diff] [blame] | 2812 | is_true = PyObject_IsTrue(r); |
| 2813 | Py_DECREF(r); |
| 2814 | if (is_true < 0) { |
| 2815 | return NULL; |
| 2816 | } |
| 2817 | else if (is_true) { |
Serhiy Storchaka | fb3e9c0 | 2018-09-21 09:11:32 +0300 | [diff] [blame] | 2818 | task->task_must_cancel = 0; |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 2819 | } |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 2820 | } |
Serhiy Storchaka | fb3e9c0 | 2018-09-21 09:11:32 +0300 | [diff] [blame] | 2821 | |
| 2822 | Py_RETURN_NONE; |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 2823 | } |
| 2824 | |
| 2825 | /* Check if `result` is None */ |
| 2826 | if (result == Py_None) { |
| 2827 | /* Bare yield relinquishes control for one event loop iteration. */ |
| 2828 | if (task_call_step_soon(task, NULL)) { |
| 2829 | goto fail; |
| 2830 | } |
| 2831 | return result; |
| 2832 | } |
| 2833 | |
Serhiy Storchaka | fb3e9c0 | 2018-09-21 09:11:32 +0300 | [diff] [blame] | 2834 | /* Check if `result` is a Future-compatible object */ |
| 2835 | if (_PyObject_LookupAttrId(result, &PyId__asyncio_future_blocking, &o) < 0) { |
| 2836 | goto fail; |
| 2837 | } |
| 2838 | if (o != NULL && o != Py_None) { |
| 2839 | /* `result` is a Future-compatible object */ |
| 2840 | PyObject *wrapper; |
| 2841 | PyObject *res; |
| 2842 | |
| 2843 | int blocking = PyObject_IsTrue(o); |
| 2844 | Py_DECREF(o); |
| 2845 | if (blocking < 0) { |
| 2846 | goto fail; |
| 2847 | } |
| 2848 | |
| 2849 | /* Check if `result` future is attached to a different loop */ |
| 2850 | PyObject *oloop = get_future_loop(result); |
| 2851 | if (oloop == NULL) { |
| 2852 | goto fail; |
| 2853 | } |
| 2854 | if (oloop != task->task_loop) { |
| 2855 | Py_DECREF(oloop); |
| 2856 | goto different_loop; |
| 2857 | } |
| 2858 | Py_DECREF(oloop); |
| 2859 | |
| 2860 | if (!blocking) { |
| 2861 | goto yield_insteadof_yf; |
| 2862 | } |
| 2863 | |
| 2864 | /* result._asyncio_future_blocking = False */ |
| 2865 | if (_PyObject_SetAttrId( |
| 2866 | result, &PyId__asyncio_future_blocking, Py_False) == -1) { |
| 2867 | goto fail; |
| 2868 | } |
| 2869 | |
| 2870 | wrapper = TaskWakeupMethWrapper_new(task); |
| 2871 | if (wrapper == NULL) { |
| 2872 | goto fail; |
| 2873 | } |
| 2874 | |
| 2875 | /* result.add_done_callback(task._wakeup) */ |
| 2876 | PyObject *add_cb = _PyObject_GetAttrId( |
| 2877 | result, &PyId_add_done_callback); |
| 2878 | if (add_cb == NULL) { |
| 2879 | Py_DECREF(wrapper); |
| 2880 | goto fail; |
| 2881 | } |
| 2882 | PyObject *stack[2]; |
| 2883 | stack[0] = wrapper; |
| 2884 | stack[1] = (PyObject *)task->task_context; |
Petr Viktorin | ffd9753 | 2020-02-11 17:46:57 +0100 | [diff] [blame] | 2885 | res = PyObject_Vectorcall(add_cb, stack, 1, context_kwname); |
Serhiy Storchaka | fb3e9c0 | 2018-09-21 09:11:32 +0300 | [diff] [blame] | 2886 | Py_DECREF(add_cb); |
| 2887 | Py_DECREF(wrapper); |
| 2888 | if (res == NULL) { |
| 2889 | goto fail; |
| 2890 | } |
| 2891 | Py_DECREF(res); |
| 2892 | |
| 2893 | /* task._fut_waiter = result */ |
| 2894 | task->task_fut_waiter = result; /* no incref is necessary */ |
| 2895 | |
| 2896 | if (task->task_must_cancel) { |
| 2897 | PyObject *r; |
| 2898 | int is_true; |
Chris Jerdonek | 1ce5841 | 2020-05-15 16:55:50 -0700 | [diff] [blame] | 2899 | r = _PyObject_CallMethodIdOneArg(result, &PyId_cancel, |
| 2900 | task->task_cancel_msg); |
Serhiy Storchaka | fb3e9c0 | 2018-09-21 09:11:32 +0300 | [diff] [blame] | 2901 | if (r == NULL) { |
| 2902 | return NULL; |
| 2903 | } |
| 2904 | is_true = PyObject_IsTrue(r); |
| 2905 | Py_DECREF(r); |
| 2906 | if (is_true < 0) { |
| 2907 | return NULL; |
| 2908 | } |
| 2909 | else if (is_true) { |
| 2910 | task->task_must_cancel = 0; |
| 2911 | } |
| 2912 | } |
| 2913 | |
| 2914 | Py_RETURN_NONE; |
| 2915 | } |
| 2916 | |
| 2917 | Py_XDECREF(o); |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 2918 | /* Check if `result` is a generator */ |
Serhiy Storchaka | fb3e9c0 | 2018-09-21 09:11:32 +0300 | [diff] [blame] | 2919 | res = PyObject_IsInstance(result, (PyObject*)&PyGen_Type); |
| 2920 | if (res < 0) { |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 2921 | goto fail; |
| 2922 | } |
Serhiy Storchaka | fb3e9c0 | 2018-09-21 09:11:32 +0300 | [diff] [blame] | 2923 | if (res) { |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 2924 | /* `result` is a generator */ |
Serhiy Storchaka | 6655354 | 2018-05-20 16:30:31 +0300 | [diff] [blame] | 2925 | o = task_set_error_soon( |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 2926 | task, PyExc_RuntimeError, |
| 2927 | "yield was used instead of yield from for " |
Serhiy Storchaka | 6655354 | 2018-05-20 16:30:31 +0300 | [diff] [blame] | 2928 | "generator in task %R with %R", task, result); |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 2929 | Py_DECREF(result); |
Serhiy Storchaka | 6655354 | 2018-05-20 16:30:31 +0300 | [diff] [blame] | 2930 | return o; |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 2931 | } |
| 2932 | |
| 2933 | /* The `result` is none of the above */ |
Serhiy Storchaka | 6655354 | 2018-05-20 16:30:31 +0300 | [diff] [blame] | 2934 | o = task_set_error_soon( |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 2935 | task, PyExc_RuntimeError, "Task got bad yield: %R", result); |
Serhiy Storchaka | 6655354 | 2018-05-20 16:30:31 +0300 | [diff] [blame] | 2936 | Py_DECREF(result); |
| 2937 | return o; |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 2938 | |
| 2939 | self_await: |
| 2940 | o = task_set_error_soon( |
| 2941 | task, PyExc_RuntimeError, |
| 2942 | "Task cannot await on itself: %R", task); |
| 2943 | Py_DECREF(result); |
| 2944 | return o; |
| 2945 | |
| 2946 | yield_insteadof_yf: |
| 2947 | o = task_set_error_soon( |
| 2948 | task, PyExc_RuntimeError, |
| 2949 | "yield was used instead of yield from " |
| 2950 | "in task %R with %R", |
| 2951 | task, result); |
| 2952 | Py_DECREF(result); |
| 2953 | return o; |
| 2954 | |
| 2955 | different_loop: |
| 2956 | o = task_set_error_soon( |
| 2957 | task, PyExc_RuntimeError, |
| 2958 | "Task %R got Future %R attached to a different loop", |
| 2959 | task, result); |
| 2960 | Py_DECREF(result); |
| 2961 | return o; |
| 2962 | |
| 2963 | fail: |
| 2964 | Py_XDECREF(result); |
| 2965 | return NULL; |
| 2966 | } |
| 2967 | |
| 2968 | static PyObject * |
| 2969 | task_step(TaskObj *task, PyObject *exc) |
| 2970 | { |
| 2971 | PyObject *res; |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 2972 | |
Andrew Svetlov | 44d1a59 | 2017-12-16 21:58:38 +0200 | [diff] [blame] | 2973 | if (enter_task(task->task_loop, (PyObject*)task) < 0) { |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 2974 | return NULL; |
| 2975 | } |
| 2976 | |
| 2977 | res = task_step_impl(task, exc); |
| 2978 | |
| 2979 | if (res == NULL) { |
| 2980 | PyObject *et, *ev, *tb; |
| 2981 | PyErr_Fetch(&et, &ev, &tb); |
Andrew Svetlov | 44d1a59 | 2017-12-16 21:58:38 +0200 | [diff] [blame] | 2982 | leave_task(task->task_loop, (PyObject*)task); |
Serhiy Storchaka | bca4939 | 2017-09-03 08:10:14 +0300 | [diff] [blame] | 2983 | _PyErr_ChainExceptions(et, ev, tb); |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 2984 | return NULL; |
| 2985 | } |
| 2986 | else { |
Serhiy Storchaka | fb3e9c0 | 2018-09-21 09:11:32 +0300 | [diff] [blame] | 2987 | if (leave_task(task->task_loop, (PyObject*)task) < 0) { |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 2988 | Py_DECREF(res); |
| 2989 | return NULL; |
| 2990 | } |
| 2991 | else { |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 2992 | return res; |
| 2993 | } |
| 2994 | } |
| 2995 | } |
| 2996 | |
| 2997 | static PyObject * |
| 2998 | task_wakeup(TaskObj *task, PyObject *o) |
| 2999 | { |
Serhiy Storchaka | bca4939 | 2017-09-03 08:10:14 +0300 | [diff] [blame] | 3000 | PyObject *et, *ev, *tb; |
| 3001 | PyObject *result; |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 3002 | assert(o); |
| 3003 | |
| 3004 | if (Future_CheckExact(o) || Task_CheckExact(o)) { |
| 3005 | PyObject *fut_result = NULL; |
| 3006 | int res = future_get_result((FutureObj*)o, &fut_result); |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 3007 | |
| 3008 | switch(res) { |
| 3009 | case -1: |
| 3010 | assert(fut_result == NULL); |
Serhiy Storchaka | bca4939 | 2017-09-03 08:10:14 +0300 | [diff] [blame] | 3011 | break; /* exception raised */ |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 3012 | case 0: |
| 3013 | Py_DECREF(fut_result); |
Yury Selivanov | 22feeb8 | 2018-01-24 11:31:01 -0500 | [diff] [blame] | 3014 | return task_step(task, NULL); |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 3015 | default: |
| 3016 | assert(res == 1); |
Yury Selivanov | 22feeb8 | 2018-01-24 11:31:01 -0500 | [diff] [blame] | 3017 | result = task_step(task, fut_result); |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 3018 | Py_DECREF(fut_result); |
| 3019 | return result; |
| 3020 | } |
| 3021 | } |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 3022 | else { |
Serhiy Storchaka | bca4939 | 2017-09-03 08:10:14 +0300 | [diff] [blame] | 3023 | PyObject *fut_result = PyObject_CallMethod(o, "result", NULL); |
| 3024 | if (fut_result != NULL) { |
| 3025 | Py_DECREF(fut_result); |
Yury Selivanov | 22feeb8 | 2018-01-24 11:31:01 -0500 | [diff] [blame] | 3026 | return task_step(task, NULL); |
Serhiy Storchaka | bca4939 | 2017-09-03 08:10:14 +0300 | [diff] [blame] | 3027 | } |
| 3028 | /* exception raised */ |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 3029 | } |
Serhiy Storchaka | bca4939 | 2017-09-03 08:10:14 +0300 | [diff] [blame] | 3030 | |
| 3031 | PyErr_Fetch(&et, &ev, &tb); |
Serhiy Storchaka | bca4939 | 2017-09-03 08:10:14 +0300 | [diff] [blame] | 3032 | if (!ev || !PyObject_TypeCheck(ev, (PyTypeObject *) et)) { |
| 3033 | PyErr_NormalizeException(&et, &ev, &tb); |
| 3034 | } |
| 3035 | |
Yury Selivanov | 22feeb8 | 2018-01-24 11:31:01 -0500 | [diff] [blame] | 3036 | result = task_step(task, ev); |
Serhiy Storchaka | bca4939 | 2017-09-03 08:10:14 +0300 | [diff] [blame] | 3037 | |
| 3038 | Py_DECREF(et); |
| 3039 | Py_XDECREF(tb); |
| 3040 | Py_XDECREF(ev); |
| 3041 | |
| 3042 | return result; |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 3043 | } |
| 3044 | |
| 3045 | |
Yury Selivanov | a70232f | 2017-12-13 14:49:42 -0500 | [diff] [blame] | 3046 | /*********************** Functions **************************/ |
| 3047 | |
| 3048 | |
| 3049 | /*[clinic input] |
| 3050 | _asyncio._get_running_loop |
| 3051 | |
| 3052 | Return the running event loop or None. |
| 3053 | |
| 3054 | This is a low-level function intended to be used by event loops. |
| 3055 | This function is thread-specific. |
| 3056 | |
| 3057 | [clinic start generated code]*/ |
| 3058 | |
| 3059 | static PyObject * |
| 3060 | _asyncio__get_running_loop_impl(PyObject *module) |
| 3061 | /*[clinic end generated code: output=b4390af721411a0a input=0a21627e25a4bd43]*/ |
| 3062 | { |
| 3063 | PyObject *loop; |
| 3064 | if (get_running_loop(&loop)) { |
| 3065 | return NULL; |
| 3066 | } |
| 3067 | if (loop == NULL) { |
| 3068 | /* There's no currently running event loop */ |
| 3069 | Py_RETURN_NONE; |
| 3070 | } |
| 3071 | return loop; |
| 3072 | } |
| 3073 | |
| 3074 | /*[clinic input] |
| 3075 | _asyncio._set_running_loop |
| 3076 | loop: 'O' |
| 3077 | / |
| 3078 | |
| 3079 | Set the running event loop. |
| 3080 | |
| 3081 | This is a low-level function intended to be used by event loops. |
| 3082 | This function is thread-specific. |
| 3083 | [clinic start generated code]*/ |
| 3084 | |
| 3085 | static PyObject * |
| 3086 | _asyncio__set_running_loop(PyObject *module, PyObject *loop) |
| 3087 | /*[clinic end generated code: output=ae56bf7a28ca189a input=4c9720233d606604]*/ |
| 3088 | { |
| 3089 | if (set_running_loop(loop)) { |
| 3090 | return NULL; |
| 3091 | } |
| 3092 | Py_RETURN_NONE; |
| 3093 | } |
| 3094 | |
| 3095 | /*[clinic input] |
| 3096 | _asyncio.get_event_loop |
| 3097 | |
| 3098 | Return an asyncio event loop. |
| 3099 | |
| 3100 | When called from a coroutine or a callback (e.g. scheduled with |
| 3101 | call_soon or similar API), this function will always return the |
| 3102 | running event loop. |
| 3103 | |
| 3104 | If there is no running event loop set, the function will return |
| 3105 | the result of `get_event_loop_policy().get_event_loop()` call. |
| 3106 | [clinic start generated code]*/ |
| 3107 | |
| 3108 | static PyObject * |
| 3109 | _asyncio_get_event_loop_impl(PyObject *module) |
| 3110 | /*[clinic end generated code: output=2a2d8b2f824c648b input=9364bf2916c8655d]*/ |
| 3111 | { |
| 3112 | return get_event_loop(); |
| 3113 | } |
| 3114 | |
| 3115 | /*[clinic input] |
| 3116 | _asyncio.get_running_loop |
| 3117 | |
| 3118 | Return the running event loop. Raise a RuntimeError if there is none. |
| 3119 | |
| 3120 | This function is thread-specific. |
| 3121 | [clinic start generated code]*/ |
| 3122 | |
| 3123 | static PyObject * |
| 3124 | _asyncio_get_running_loop_impl(PyObject *module) |
| 3125 | /*[clinic end generated code: output=c247b5f9e529530e input=2a3bf02ba39f173d]*/ |
| 3126 | { |
| 3127 | PyObject *loop; |
| 3128 | if (get_running_loop(&loop)) { |
| 3129 | return NULL; |
| 3130 | } |
| 3131 | if (loop == NULL) { |
| 3132 | /* There's no currently running event loop */ |
| 3133 | PyErr_SetString( |
| 3134 | PyExc_RuntimeError, "no running event loop"); |
| 3135 | } |
| 3136 | return loop; |
| 3137 | } |
| 3138 | |
Andrew Svetlov | 44d1a59 | 2017-12-16 21:58:38 +0200 | [diff] [blame] | 3139 | /*[clinic input] |
| 3140 | _asyncio._register_task |
| 3141 | |
Andrew Svetlov | 44d1a59 | 2017-12-16 21:58:38 +0200 | [diff] [blame] | 3142 | task: object |
| 3143 | |
| 3144 | Register a new task in asyncio as executed by loop. |
| 3145 | |
| 3146 | Returns None. |
| 3147 | [clinic start generated code]*/ |
| 3148 | |
| 3149 | static PyObject * |
Yury Selivanov | ca9b36c | 2017-12-23 15:04:15 -0500 | [diff] [blame] | 3150 | _asyncio__register_task_impl(PyObject *module, PyObject *task) |
| 3151 | /*[clinic end generated code: output=8672dadd69a7d4e2 input=21075aaea14dfbad]*/ |
Andrew Svetlov | 44d1a59 | 2017-12-16 21:58:38 +0200 | [diff] [blame] | 3152 | { |
Yury Selivanov | ca9b36c | 2017-12-23 15:04:15 -0500 | [diff] [blame] | 3153 | if (register_task(task) < 0) { |
Andrew Svetlov | 44d1a59 | 2017-12-16 21:58:38 +0200 | [diff] [blame] | 3154 | return NULL; |
| 3155 | } |
| 3156 | Py_RETURN_NONE; |
| 3157 | } |
| 3158 | |
| 3159 | |
| 3160 | /*[clinic input] |
| 3161 | _asyncio._unregister_task |
| 3162 | |
Andrew Svetlov | 44d1a59 | 2017-12-16 21:58:38 +0200 | [diff] [blame] | 3163 | task: object |
| 3164 | |
| 3165 | Unregister a task. |
| 3166 | |
| 3167 | Returns None. |
| 3168 | [clinic start generated code]*/ |
| 3169 | |
| 3170 | static PyObject * |
Yury Selivanov | ca9b36c | 2017-12-23 15:04:15 -0500 | [diff] [blame] | 3171 | _asyncio__unregister_task_impl(PyObject *module, PyObject *task) |
| 3172 | /*[clinic end generated code: output=6e5585706d568a46 input=28fb98c3975f7bdc]*/ |
Andrew Svetlov | 44d1a59 | 2017-12-16 21:58:38 +0200 | [diff] [blame] | 3173 | { |
Yury Selivanov | ca9b36c | 2017-12-23 15:04:15 -0500 | [diff] [blame] | 3174 | if (unregister_task(task) < 0) { |
Andrew Svetlov | 44d1a59 | 2017-12-16 21:58:38 +0200 | [diff] [blame] | 3175 | return NULL; |
| 3176 | } |
| 3177 | Py_RETURN_NONE; |
| 3178 | } |
| 3179 | |
| 3180 | |
| 3181 | /*[clinic input] |
| 3182 | _asyncio._enter_task |
| 3183 | |
| 3184 | loop: object |
| 3185 | task: object |
| 3186 | |
| 3187 | Enter into task execution or resume suspended task. |
| 3188 | |
| 3189 | Task belongs to loop. |
| 3190 | |
| 3191 | Returns None. |
| 3192 | [clinic start generated code]*/ |
| 3193 | |
| 3194 | static PyObject * |
| 3195 | _asyncio__enter_task_impl(PyObject *module, PyObject *loop, PyObject *task) |
| 3196 | /*[clinic end generated code: output=a22611c858035b73 input=de1b06dca70d8737]*/ |
| 3197 | { |
| 3198 | if (enter_task(loop, task) < 0) { |
| 3199 | return NULL; |
| 3200 | } |
| 3201 | Py_RETURN_NONE; |
| 3202 | } |
| 3203 | |
| 3204 | |
| 3205 | /*[clinic input] |
| 3206 | _asyncio._leave_task |
| 3207 | |
| 3208 | loop: object |
| 3209 | task: object |
| 3210 | |
| 3211 | Leave task execution or suspend a task. |
| 3212 | |
| 3213 | Task belongs to loop. |
| 3214 | |
| 3215 | Returns None. |
| 3216 | [clinic start generated code]*/ |
| 3217 | |
| 3218 | static PyObject * |
| 3219 | _asyncio__leave_task_impl(PyObject *module, PyObject *loop, PyObject *task) |
| 3220 | /*[clinic end generated code: output=0ebf6db4b858fb41 input=51296a46313d1ad8]*/ |
| 3221 | { |
| 3222 | if (leave_task(loop, task) < 0) { |
| 3223 | return NULL; |
| 3224 | } |
| 3225 | Py_RETURN_NONE; |
| 3226 | } |
| 3227 | |
Yury Selivanov | a70232f | 2017-12-13 14:49:42 -0500 | [diff] [blame] | 3228 | |
Yury Selivanov | 9d411c1 | 2018-01-23 15:10:03 -0500 | [diff] [blame] | 3229 | /*********************** PyRunningLoopHolder ********************/ |
| 3230 | |
| 3231 | |
| 3232 | static PyRunningLoopHolder * |
| 3233 | new_running_loop_holder(PyObject *loop) |
| 3234 | { |
| 3235 | PyRunningLoopHolder *rl = PyObject_New( |
| 3236 | PyRunningLoopHolder, &PyRunningLoopHolder_Type); |
| 3237 | if (rl == NULL) { |
| 3238 | return NULL; |
| 3239 | } |
| 3240 | |
| 3241 | #if defined(HAVE_GETPID) && !defined(MS_WINDOWS) |
| 3242 | rl->rl_pid = getpid(); |
| 3243 | #endif |
| 3244 | |
| 3245 | Py_INCREF(loop); |
| 3246 | rl->rl_loop = loop; |
| 3247 | |
| 3248 | return rl; |
| 3249 | } |
| 3250 | |
| 3251 | |
| 3252 | static void |
| 3253 | PyRunningLoopHolder_tp_dealloc(PyRunningLoopHolder *rl) |
| 3254 | { |
| 3255 | Py_CLEAR(rl->rl_loop); |
| 3256 | PyObject_Free(rl); |
| 3257 | } |
| 3258 | |
| 3259 | |
| 3260 | static PyTypeObject PyRunningLoopHolder_Type = { |
| 3261 | PyVarObject_HEAD_INIT(NULL, 0) |
| 3262 | "_RunningLoopHolder", |
| 3263 | sizeof(PyRunningLoopHolder), |
| 3264 | .tp_getattro = PyObject_GenericGetAttr, |
| 3265 | .tp_flags = Py_TPFLAGS_DEFAULT, |
| 3266 | .tp_dealloc = (destructor)PyRunningLoopHolder_tp_dealloc, |
| 3267 | }; |
| 3268 | |
| 3269 | |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 3270 | /*********************** Module **************************/ |
| 3271 | |
| 3272 | |
| 3273 | static void |
Zackery Spytz | e40ad79 | 2017-12-19 11:48:13 -0700 | [diff] [blame] | 3274 | module_free_freelists(void) |
Yury Selivanov | 1b7c11f | 2017-12-17 20:19:47 -0500 | [diff] [blame] | 3275 | { |
| 3276 | PyObject *next; |
| 3277 | PyObject *current; |
| 3278 | |
| 3279 | next = (PyObject*) fi_freelist; |
| 3280 | while (next != NULL) { |
| 3281 | assert(fi_freelist_len > 0); |
| 3282 | fi_freelist_len--; |
| 3283 | |
| 3284 | current = next; |
| 3285 | next = (PyObject*) ((futureiterobject*) current)->future; |
| 3286 | PyObject_GC_Del(current); |
| 3287 | } |
| 3288 | assert(fi_freelist_len == 0); |
| 3289 | fi_freelist = NULL; |
| 3290 | } |
| 3291 | |
| 3292 | |
| 3293 | static void |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 3294 | module_free(void *m) |
| 3295 | { |
Andrew Svetlov | 44d1a59 | 2017-12-16 21:58:38 +0200 | [diff] [blame] | 3296 | Py_CLEAR(asyncio_mod); |
Andrew Svetlov | 44d1a59 | 2017-12-16 21:58:38 +0200 | [diff] [blame] | 3297 | Py_CLEAR(traceback_extract_stack); |
| 3298 | Py_CLEAR(asyncio_future_repr_info_func); |
| 3299 | Py_CLEAR(asyncio_get_event_loop_policy); |
| 3300 | Py_CLEAR(asyncio_iscoroutine_func); |
| 3301 | Py_CLEAR(asyncio_task_get_stack_func); |
| 3302 | Py_CLEAR(asyncio_task_print_stack_func); |
| 3303 | Py_CLEAR(asyncio_task_repr_info_func); |
| 3304 | Py_CLEAR(asyncio_InvalidStateError); |
| 3305 | Py_CLEAR(asyncio_CancelledError); |
| 3306 | |
Andrew Svetlov | 44d1a59 | 2017-12-16 21:58:38 +0200 | [diff] [blame] | 3307 | Py_CLEAR(all_tasks); |
Yury Selivanov | a9d7e55 | 2017-12-19 07:18:45 -0500 | [diff] [blame] | 3308 | Py_CLEAR(current_tasks); |
| 3309 | Py_CLEAR(iscoroutine_typecache); |
Yury Selivanov | 1b7c11f | 2017-12-17 20:19:47 -0500 | [diff] [blame] | 3310 | |
Yury Selivanov | f23746a | 2018-01-22 19:11:18 -0500 | [diff] [blame] | 3311 | Py_CLEAR(context_kwname); |
| 3312 | |
Yury Selivanov | 1b7c11f | 2017-12-17 20:19:47 -0500 | [diff] [blame] | 3313 | module_free_freelists(); |
Jeffrey Quesnelle | a75e730 | 2020-04-16 22:09:45 -0400 | [diff] [blame] | 3314 | |
| 3315 | module_initialized = 0; |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 3316 | } |
| 3317 | |
| 3318 | static int |
| 3319 | module_init(void) |
| 3320 | { |
| 3321 | PyObject *module = NULL; |
Andrew Svetlov | 44d1a59 | 2017-12-16 21:58:38 +0200 | [diff] [blame] | 3322 | |
| 3323 | asyncio_mod = PyImport_ImportModule("asyncio"); |
| 3324 | if (asyncio_mod == NULL) { |
| 3325 | goto fail; |
| 3326 | } |
Ben Harper | 321def8 | 2019-10-07 12:19:58 -0400 | [diff] [blame] | 3327 | if (module_initialized != 0) { |
| 3328 | return 0; |
Andrew Svetlov | 969ae7a | 2019-12-07 13:23:21 +0200 | [diff] [blame] | 3329 | } |
Ben Harper | 321def8 | 2019-10-07 12:19:58 -0400 | [diff] [blame] | 3330 | else { |
| 3331 | module_initialized = 1; |
| 3332 | } |
Andrew Svetlov | 44d1a59 | 2017-12-16 21:58:38 +0200 | [diff] [blame] | 3333 | |
| 3334 | current_tasks = PyDict_New(); |
| 3335 | if (current_tasks == NULL) { |
| 3336 | goto fail; |
| 3337 | } |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 3338 | |
Yury Selivanov | a9d7e55 | 2017-12-19 07:18:45 -0500 | [diff] [blame] | 3339 | iscoroutine_typecache = PySet_New(NULL); |
| 3340 | if (iscoroutine_typecache == NULL) { |
| 3341 | goto fail; |
| 3342 | } |
| 3343 | |
Yury Selivanov | f23746a | 2018-01-22 19:11:18 -0500 | [diff] [blame] | 3344 | |
Serhiy Storchaka | fb3e9c0 | 2018-09-21 09:11:32 +0300 | [diff] [blame] | 3345 | context_kwname = Py_BuildValue("(s)", "context"); |
Yury Selivanov | f23746a | 2018-01-22 19:11:18 -0500 | [diff] [blame] | 3346 | if (context_kwname == NULL) { |
| 3347 | goto fail; |
| 3348 | } |
Yury Selivanov | f23746a | 2018-01-22 19:11:18 -0500 | [diff] [blame] | 3349 | |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 3350 | #define WITH_MOD(NAME) \ |
| 3351 | Py_CLEAR(module); \ |
| 3352 | module = PyImport_ImportModule(NAME); \ |
| 3353 | if (module == NULL) { \ |
Serhiy Storchaka | bca4939 | 2017-09-03 08:10:14 +0300 | [diff] [blame] | 3354 | goto fail; \ |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 3355 | } |
| 3356 | |
| 3357 | #define GET_MOD_ATTR(VAR, NAME) \ |
| 3358 | VAR = PyObject_GetAttrString(module, NAME); \ |
| 3359 | if (VAR == NULL) { \ |
| 3360 | goto fail; \ |
| 3361 | } |
| 3362 | |
| 3363 | WITH_MOD("asyncio.events") |
Yury Selivanov | a70232f | 2017-12-13 14:49:42 -0500 | [diff] [blame] | 3364 | GET_MOD_ATTR(asyncio_get_event_loop_policy, "get_event_loop_policy") |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 3365 | |
| 3366 | WITH_MOD("asyncio.base_futures") |
| 3367 | GET_MOD_ATTR(asyncio_future_repr_info_func, "_future_repr_info") |
Andrew Svetlov | 0baa72f | 2018-09-11 10:13:04 -0700 | [diff] [blame] | 3368 | |
| 3369 | WITH_MOD("asyncio.exceptions") |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 3370 | GET_MOD_ATTR(asyncio_InvalidStateError, "InvalidStateError") |
| 3371 | GET_MOD_ATTR(asyncio_CancelledError, "CancelledError") |
| 3372 | |
| 3373 | WITH_MOD("asyncio.base_tasks") |
| 3374 | GET_MOD_ATTR(asyncio_task_repr_info_func, "_task_repr_info") |
| 3375 | GET_MOD_ATTR(asyncio_task_get_stack_func, "_task_get_stack") |
| 3376 | GET_MOD_ATTR(asyncio_task_print_stack_func, "_task_print_stack") |
| 3377 | |
Andrew Svetlov | f74ef45 | 2017-12-15 07:04:38 +0200 | [diff] [blame] | 3378 | WITH_MOD("asyncio.coroutines") |
| 3379 | GET_MOD_ATTR(asyncio_iscoroutine_func, "iscoroutine") |
| 3380 | |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 3381 | WITH_MOD("traceback") |
| 3382 | GET_MOD_ATTR(traceback_extract_stack, "extract_stack") |
| 3383 | |
Yury Selivanov | ca9b36c | 2017-12-23 15:04:15 -0500 | [diff] [blame] | 3384 | PyObject *weak_set; |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 3385 | WITH_MOD("weakref") |
Yury Selivanov | ca9b36c | 2017-12-23 15:04:15 -0500 | [diff] [blame] | 3386 | GET_MOD_ATTR(weak_set, "WeakSet"); |
Victor Stinner | 2ff58a2 | 2019-06-17 14:27:23 +0200 | [diff] [blame] | 3387 | all_tasks = PyObject_CallNoArgs(weak_set); |
Yury Selivanov | ca9b36c | 2017-12-23 15:04:15 -0500 | [diff] [blame] | 3388 | Py_CLEAR(weak_set); |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 3389 | if (all_tasks == NULL) { |
INADA Naoki | c411a7d | 2016-10-18 11:48:14 +0900 | [diff] [blame] | 3390 | goto fail; |
| 3391 | } |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 3392 | |
Serhiy Storchaka | bca4939 | 2017-09-03 08:10:14 +0300 | [diff] [blame] | 3393 | Py_DECREF(module); |
INADA Naoki | c411a7d | 2016-10-18 11:48:14 +0900 | [diff] [blame] | 3394 | return 0; |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 3395 | |
INADA Naoki | c411a7d | 2016-10-18 11:48:14 +0900 | [diff] [blame] | 3396 | fail: |
INADA Naoki | c411a7d | 2016-10-18 11:48:14 +0900 | [diff] [blame] | 3397 | Py_CLEAR(module); |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 3398 | module_free(NULL); |
INADA Naoki | c411a7d | 2016-10-18 11:48:14 +0900 | [diff] [blame] | 3399 | return -1; |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 3400 | |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 3401 | #undef WITH_MOD |
| 3402 | #undef GET_MOD_ATTR |
| 3403 | } |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 3404 | |
INADA Naoki | c411a7d | 2016-10-18 11:48:14 +0900 | [diff] [blame] | 3405 | PyDoc_STRVAR(module_doc, "Accelerator module for asyncio"); |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 3406 | |
Yury Selivanov | a70232f | 2017-12-13 14:49:42 -0500 | [diff] [blame] | 3407 | static PyMethodDef asyncio_methods[] = { |
| 3408 | _ASYNCIO_GET_EVENT_LOOP_METHODDEF |
| 3409 | _ASYNCIO_GET_RUNNING_LOOP_METHODDEF |
| 3410 | _ASYNCIO__GET_RUNNING_LOOP_METHODDEF |
| 3411 | _ASYNCIO__SET_RUNNING_LOOP_METHODDEF |
Andrew Svetlov | 44d1a59 | 2017-12-16 21:58:38 +0200 | [diff] [blame] | 3412 | _ASYNCIO__REGISTER_TASK_METHODDEF |
| 3413 | _ASYNCIO__UNREGISTER_TASK_METHODDEF |
| 3414 | _ASYNCIO__ENTER_TASK_METHODDEF |
| 3415 | _ASYNCIO__LEAVE_TASK_METHODDEF |
Yury Selivanov | a70232f | 2017-12-13 14:49:42 -0500 | [diff] [blame] | 3416 | {NULL, NULL} |
| 3417 | }; |
| 3418 | |
INADA Naoki | 9f2ce25 | 2016-10-15 15:39:19 +0900 | [diff] [blame] | 3419 | static struct PyModuleDef _asynciomodule = { |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 3420 | PyModuleDef_HEAD_INIT, /* m_base */ |
INADA Naoki | 9f2ce25 | 2016-10-15 15:39:19 +0900 | [diff] [blame] | 3421 | "_asyncio", /* m_name */ |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 3422 | module_doc, /* m_doc */ |
| 3423 | -1, /* m_size */ |
Yury Selivanov | a70232f | 2017-12-13 14:49:42 -0500 | [diff] [blame] | 3424 | asyncio_methods, /* m_methods */ |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 3425 | NULL, /* m_slots */ |
| 3426 | NULL, /* m_traverse */ |
| 3427 | NULL, /* m_clear */ |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 3428 | (freefunc)module_free /* m_free */ |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 3429 | }; |
| 3430 | |
| 3431 | |
| 3432 | PyMODINIT_FUNC |
INADA Naoki | 9f2ce25 | 2016-10-15 15:39:19 +0900 | [diff] [blame] | 3433 | PyInit__asyncio(void) |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 3434 | { |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 3435 | if (module_init() < 0) { |
INADA Naoki | c411a7d | 2016-10-18 11:48:14 +0900 | [diff] [blame] | 3436 | return NULL; |
| 3437 | } |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 3438 | if (PyType_Ready(&FutureIterType) < 0) { |
| 3439 | return NULL; |
| 3440 | } |
Serhiy Storchaka | bca4939 | 2017-09-03 08:10:14 +0300 | [diff] [blame] | 3441 | if (PyType_Ready(&TaskStepMethWrapper_Type) < 0) { |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 3442 | return NULL; |
| 3443 | } |
Serhiy Storchaka | fb3e9c0 | 2018-09-21 09:11:32 +0300 | [diff] [blame] | 3444 | if (PyType_Ready(&TaskWakeupMethWrapper_Type) < 0) { |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 3445 | return NULL; |
| 3446 | } |
Yury Selivanov | 9d411c1 | 2018-01-23 15:10:03 -0500 | [diff] [blame] | 3447 | if (PyType_Ready(&PyRunningLoopHolder_Type) < 0) { |
| 3448 | return NULL; |
| 3449 | } |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 3450 | |
INADA Naoki | 9f2ce25 | 2016-10-15 15:39:19 +0900 | [diff] [blame] | 3451 | PyObject *m = PyModule_Create(&_asynciomodule); |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 3452 | if (m == NULL) { |
| 3453 | return NULL; |
| 3454 | } |
| 3455 | |
Dong-hee Na | 37fcbb6 | 2020-03-25 07:08:51 +0900 | [diff] [blame] | 3456 | /* FutureType and TaskType are made ready by PyModule_AddType() calls below. */ |
| 3457 | if (PyModule_AddType(m, &FutureType) < 0) { |
Brandt Bucher | c3f6bdc | 2019-11-16 14:26:54 -0800 | [diff] [blame] | 3458 | Py_DECREF(m); |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 3459 | return NULL; |
| 3460 | } |
| 3461 | |
Dong-hee Na | 37fcbb6 | 2020-03-25 07:08:51 +0900 | [diff] [blame] | 3462 | if (PyModule_AddType(m, &TaskType) < 0) { |
Brandt Bucher | c3f6bdc | 2019-11-16 14:26:54 -0800 | [diff] [blame] | 3463 | Py_DECREF(m); |
Yury Selivanov | a0c1ba6 | 2016-10-28 12:52:37 -0400 | [diff] [blame] | 3464 | return NULL; |
| 3465 | } |
| 3466 | |
Andrew Svetlov | 44d1a59 | 2017-12-16 21:58:38 +0200 | [diff] [blame] | 3467 | Py_INCREF(all_tasks); |
| 3468 | if (PyModule_AddObject(m, "_all_tasks", all_tasks) < 0) { |
| 3469 | Py_DECREF(all_tasks); |
Brandt Bucher | c3f6bdc | 2019-11-16 14:26:54 -0800 | [diff] [blame] | 3470 | Py_DECREF(m); |
Andrew Svetlov | 44d1a59 | 2017-12-16 21:58:38 +0200 | [diff] [blame] | 3471 | return NULL; |
| 3472 | } |
| 3473 | |
| 3474 | Py_INCREF(current_tasks); |
| 3475 | if (PyModule_AddObject(m, "_current_tasks", current_tasks) < 0) { |
| 3476 | Py_DECREF(current_tasks); |
Brandt Bucher | c3f6bdc | 2019-11-16 14:26:54 -0800 | [diff] [blame] | 3477 | Py_DECREF(m); |
Andrew Svetlov | 44d1a59 | 2017-12-16 21:58:38 +0200 | [diff] [blame] | 3478 | return NULL; |
| 3479 | } |
| 3480 | |
INADA Naoki | 9e4e38e | 2016-10-09 14:44:47 +0900 | [diff] [blame] | 3481 | return m; |
| 3482 | } |