@@ -205,6 +205,43 @@ STATIC mp_obj_t task_done(mp_obj_t self_in) {
205
205
}
206
206
STATIC MP_DEFINE_CONST_FUN_OBJ_1 (task_done_obj , task_done );
207
207
208
+ STATIC mp_obj_t task_add_done_callback (mp_obj_t self_in , mp_obj_t callback ) {
209
+ assert (mp_obj_is_callable (callback ));
210
+ mp_obj_task_t * self = MP_OBJ_TO_PTR (self_in );
211
+
212
+ if (TASK_IS_DONE (self )) {
213
+ // In CPython the callbacks are not immediately called and are instead
214
+ // called by the event loop. However, CircuitPython's event loop doesn't
215
+ // support `call_soon` to handle callback processing.
216
+ //
217
+ // Because of this, it's close enough to call the callback immediately.
218
+ mp_call_function_1 (callback , self_in );
219
+ return mp_const_none ;
220
+ }
221
+
222
+ if (self -> state != mp_const_true ) {
223
+ // Tasks SHOULD support more than one callback per CPython but to reduce
224
+ // the surface area of this change tasks can currently only support one.
225
+ mp_raise_RuntimeError (MP_ERROR_TEXT ("Tasks only support one done callback." ));
226
+ }
227
+
228
+ self -> state = callback ;
229
+ return mp_const_none ;
230
+ }
231
+ STATIC MP_DEFINE_CONST_FUN_OBJ_2 (task_add_done_callback_obj , task_add_done_callback );
232
+
233
+ STATIC mp_obj_t task_remove_done_callback (mp_obj_t self_in , mp_obj_t callback ) {
234
+ mp_obj_task_t * self = MP_OBJ_TO_PTR (self_in );
235
+
236
+ if (callback != self -> state ) {
237
+ return mp_obj_new_int (0 );
238
+ }
239
+
240
+ self -> state = mp_const_true ;
241
+ return mp_obj_new_int (1 );
242
+ }
243
+ STATIC MP_DEFINE_CONST_FUN_OBJ_2 (task_remove_done_callback_obj , task_remove_done_callback );
244
+
208
245
STATIC mp_obj_t task_get_coro (mp_obj_t self_in ) {
209
246
mp_obj_task_t * self = MP_OBJ_TO_PTR (self_in );
210
247
return MP_OBJ_FROM_PTR (self -> coro );
@@ -364,6 +401,12 @@ STATIC void task_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
364
401
} else if (attr == MP_QSTR___await__ ) {
365
402
dest [0 ] = MP_OBJ_FROM_PTR (& task_await_obj );
366
403
dest [1 ] = self_in ;
404
+ } else if (attr == MP_QSTR_add_done_callback ) {
405
+ dest [0 ] = MP_OBJ_FROM_PTR (& task_add_done_callback_obj );
406
+ dest [1 ] = self_in ;
407
+ } else if (attr == MP_QSTR_remove_done_callback ) {
408
+ dest [0 ] = MP_OBJ_FROM_PTR (& task_remove_done_callback_obj );
409
+ dest [1 ] = self_in ;
367
410
} else if (attr == MP_QSTR_get_coro ) {
368
411
dest [0 ] = MP_OBJ_FROM_PTR (& task_get_coro_obj );
369
412
dest [1 ] = self_in ;
0 commit comments