@@ -191,6 +191,43 @@ STATIC mp_obj_t task_done(mp_obj_t self_in) {
191
191
}
192
192
STATIC MP_DEFINE_CONST_FUN_OBJ_1 (task_done_obj , task_done );
193
193
194
+ STATIC mp_obj_t task_add_done_callback (mp_obj_t self_in , mp_obj_t callback ) {
195
+ assert (mp_obj_is_callable (callback ));
196
+ mp_obj_task_t * self = MP_OBJ_TO_PTR (self_in );
197
+
198
+ if (TASK_IS_DONE (self )) {
199
+ // In CPython the callbacks are not immediately called and are instead
200
+ // called by the event loop. However, CircuitPython's event loop doesn't
201
+ // support `call_soon` to handle callback processing.
202
+ //
203
+ // Because of this, it's close enough to call the callback immediately.
204
+ mp_call_function_1 (callback , self_in );
205
+ return mp_const_none ;
206
+ }
207
+
208
+ if (self -> state != mp_const_true ) {
209
+ // Tasks SHOULD support more than one callback per CPython but to reduce
210
+ // the surface area of this change tasks can currently only support one.
211
+ mp_raise_RuntimeError (MP_ERROR_TEXT ("Tasks only support one done callback." ));
212
+ }
213
+
214
+ self -> state = callback ;
215
+ return mp_const_none ;
216
+ }
217
+ STATIC MP_DEFINE_CONST_FUN_OBJ_2 (task_add_done_callback_obj , task_add_done_callback );
218
+
219
+ STATIC mp_obj_t task_remove_done_callback (mp_obj_t self_in , mp_obj_t callback ) {
220
+ mp_obj_task_t * self = MP_OBJ_TO_PTR (self_in );
221
+
222
+ if (callback != self -> state ) {
223
+ return mp_obj_new_int (0 );
224
+ }
225
+
226
+ self -> state = mp_const_true ;
227
+ return mp_obj_new_int (1 );
228
+ }
229
+ STATIC MP_DEFINE_CONST_FUN_OBJ_2 (task_remove_done_callback_obj , task_remove_done_callback );
230
+
194
231
STATIC mp_obj_t task_get_coro (mp_obj_t self_in ) {
195
232
mp_obj_task_t * self = MP_OBJ_TO_PTR (self_in );
196
233
return MP_OBJ_FROM_PTR (self -> coro );
@@ -350,6 +387,12 @@ STATIC void task_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
350
387
} else if (attr == MP_QSTR___await__ ) {
351
388
dest [0 ] = MP_OBJ_FROM_PTR (& task_await_obj );
352
389
dest [1 ] = self_in ;
390
+ } else if (attr == MP_QSTR_add_done_callback ) {
391
+ dest [0 ] = MP_OBJ_FROM_PTR (& task_add_done_callback_obj );
392
+ dest [1 ] = self_in ;
393
+ } else if (attr == MP_QSTR_remove_done_callback ) {
394
+ dest [0 ] = MP_OBJ_FROM_PTR (& task_remove_done_callback_obj );
395
+ dest [1 ] = self_in ;
353
396
} else if (attr == MP_QSTR_get_coro ) {
354
397
dest [0 ] = MP_OBJ_FROM_PTR (& task_get_coro_obj );
355
398
dest [1 ] = self_in ;
0 commit comments