31
31
32
32
#if MICROPY_PY_UASYNCIO
33
33
34
+ #define TASK_STATE_RUNNING_NOT_WAITED_ON (mp_const_true)
35
+ #define TASK_STATE_DONE_NOT_WAITED_ON (mp_const_none)
36
+ #define TASK_STATE_DONE_WAS_WAITED_ON (mp_const_false)
37
+
38
+ #define TASK_IS_DONE (task ) ( \
39
+ (task)->state == TASK_STATE_DONE_NOT_WAITED_ON \
40
+ || (task)->state == TASK_STATE_DONE_WAS_WAITED_ON)
41
+
34
42
typedef struct _mp_obj_task_t {
35
43
mp_pairheap_t pairheap ;
36
44
mp_obj_t coro ;
37
45
mp_obj_t data ;
38
- mp_obj_t waiting ;
39
-
46
+ mp_obj_t state ;
40
47
mp_obj_t ph_key ;
41
48
} mp_obj_task_t ;
42
49
@@ -146,9 +153,6 @@ STATIC const mp_obj_type_t task_queue_type = {
146
153
/******************************************************************************/
147
154
// Task class
148
155
149
- // For efficiency, the task object is stored to the coro entry when the task is done.
150
- #define TASK_IS_DONE (task ) ((task)->coro == MP_OBJ_FROM_PTR(task))
151
-
152
156
// This is the core uasyncio context with cur_task, _task_queue and CancelledError.
153
157
STATIC mp_obj_t uasyncio_context = MP_OBJ_NULL ;
154
158
@@ -159,7 +163,7 @@ STATIC mp_obj_t task_make_new(const mp_obj_type_t *type, size_t n_args, const mp
159
163
mp_pairheap_init_node (task_lt , & self -> pairheap );
160
164
self -> coro = args [0 ];
161
165
self -> data = mp_const_none ;
162
- self -> waiting = mp_const_none ;
166
+ self -> state = TASK_STATE_RUNNING_NOT_WAITED_ON ;
163
167
self -> ph_key = MP_OBJ_NEW_SMALL_INT (0 );
164
168
if (n_args == 2 ) {
165
169
uasyncio_context = args [1 ];
@@ -218,24 +222,6 @@ STATIC mp_obj_t task_cancel(mp_obj_t self_in) {
218
222
}
219
223
STATIC MP_DEFINE_CONST_FUN_OBJ_1 (task_cancel_obj , task_cancel );
220
224
221
- STATIC mp_obj_t task_throw (mp_obj_t self_in , mp_obj_t value_in ) {
222
- // This task raised an exception which was uncaught; handle that now.
223
- mp_obj_task_t * self = MP_OBJ_TO_PTR (self_in );
224
- // Set the data because it was cleared by the main scheduling loop.
225
- self -> data = value_in ;
226
- if (self -> waiting == mp_const_none ) {
227
- // Nothing await'ed on the task so call the exception handler.
228
- mp_obj_t _exc_context = mp_obj_dict_get (uasyncio_context , MP_OBJ_NEW_QSTR (MP_QSTR__exc_context ));
229
- mp_obj_dict_store (_exc_context , MP_OBJ_NEW_QSTR (MP_QSTR_exception ), value_in );
230
- mp_obj_dict_store (_exc_context , MP_OBJ_NEW_QSTR (MP_QSTR_future ), self_in );
231
- mp_obj_t Loop = mp_obj_dict_get (uasyncio_context , MP_OBJ_NEW_QSTR (MP_QSTR_Loop ));
232
- mp_obj_t call_exception_handler = mp_load_attr (Loop , MP_QSTR_call_exception_handler );
233
- mp_call_function_1 (call_exception_handler , _exc_context );
234
- }
235
- return mp_const_none ;
236
- }
237
- STATIC MP_DEFINE_CONST_FUN_OBJ_2 (task_throw_obj , task_throw );
238
-
239
225
STATIC void task_attr (mp_obj_t self_in , qstr attr , mp_obj_t * dest ) {
240
226
mp_obj_task_t * self = MP_OBJ_TO_PTR (self_in );
241
227
if (dest [0 ] == MP_OBJ_NULL ) {
@@ -244,32 +230,24 @@ STATIC void task_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
244
230
dest [0 ] = self -> coro ;
245
231
} else if (attr == MP_QSTR_data ) {
246
232
dest [0 ] = self -> data ;
247
- } else if (attr == MP_QSTR_waiting ) {
248
- if (self -> waiting != mp_const_none && self -> waiting != mp_const_false ) {
249
- dest [0 ] = self -> waiting ;
250
- }
233
+ } else if (attr == MP_QSTR_state ) {
234
+ dest [0 ] = self -> state ;
251
235
} else if (attr == MP_QSTR_done ) {
252
236
dest [0 ] = MP_OBJ_FROM_PTR (& task_done_obj );
253
237
dest [1 ] = self_in ;
254
238
} else if (attr == MP_QSTR_cancel ) {
255
239
dest [0 ] = MP_OBJ_FROM_PTR (& task_cancel_obj );
256
240
dest [1 ] = self_in ;
257
- } else if (attr == MP_QSTR_throw ) {
258
- dest [0 ] = MP_OBJ_FROM_PTR (& task_throw_obj );
259
- dest [1 ] = self_in ;
260
241
} else if (attr == MP_QSTR_ph_key ) {
261
242
dest [0 ] = self -> ph_key ;
262
243
}
263
244
} else if (dest [1 ] != MP_OBJ_NULL ) {
264
245
// Store
265
- if (attr == MP_QSTR_coro ) {
266
- self -> coro = dest [1 ];
267
- dest [0 ] = MP_OBJ_NULL ;
268
- } else if (attr == MP_QSTR_data ) {
246
+ if (attr == MP_QSTR_data ) {
269
247
self -> data = dest [1 ];
270
248
dest [0 ] = MP_OBJ_NULL ;
271
- } else if (attr == MP_QSTR_waiting ) {
272
- self -> waiting = dest [1 ];
249
+ } else if (attr == MP_QSTR_state ) {
250
+ self -> state = dest [1 ];
273
251
dest [0 ] = MP_OBJ_NULL ;
274
252
}
275
253
}
@@ -278,15 +256,12 @@ STATIC void task_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
278
256
STATIC mp_obj_t task_getiter (mp_obj_t self_in , mp_obj_iter_buf_t * iter_buf ) {
279
257
(void )iter_buf ;
280
258
mp_obj_task_t * self = MP_OBJ_TO_PTR (self_in );
281
- if (self -> waiting == mp_const_none ) {
282
- // The is the first access of the "waiting" entry.
283
- if (TASK_IS_DONE (self )) {
284
- // Signal that the completed-task has been await'ed on.
285
- self -> waiting = mp_const_false ;
286
- } else {
287
- // Lazily allocate the waiting queue.
288
- self -> waiting = task_queue_make_new (& task_queue_type , 0 , 0 , NULL );
289
- }
259
+ if (TASK_IS_DONE (self )) {
260
+ // Signal that the completed-task has been await'ed on.
261
+ self -> state = TASK_STATE_DONE_WAS_WAITED_ON ;
262
+ } else if (self -> state == TASK_STATE_RUNNING_NOT_WAITED_ON ) {
263
+ // Allocate the waiting queue.
264
+ self -> state = task_queue_make_new (& task_queue_type , 0 , 0 , NULL );
290
265
}
291
266
return self_in ;
292
267
}
@@ -299,7 +274,7 @@ STATIC mp_obj_t task_iternext(mp_obj_t self_in) {
299
274
} else {
300
275
// Put calling task on waiting queue.
301
276
mp_obj_t cur_task = mp_obj_dict_get (uasyncio_context , MP_OBJ_NEW_QSTR (MP_QSTR_cur_task ));
302
- mp_obj_t args [2 ] = { self -> waiting , cur_task };
277
+ mp_obj_t args [2 ] = { self -> state , cur_task };
303
278
task_queue_push_sorted (2 , args );
304
279
// Set calling task's data to this task that it waits on, to double-link it.
305
280
((mp_obj_task_t * )MP_OBJ_TO_PTR (cur_task ))-> data = self_in ;
0 commit comments