Skip to content

Commit 0bd99fd

Browse files
committed
py/modatexit: Switch to using list.
Signed-off-by: Andrew Leech <[email protected]>
1 parent f80c6c7 commit 0bd99fd

File tree

1 file changed

+19
-38
lines changed

1 file changed

+19
-38
lines changed

py/modatexit.c

Lines changed: 19 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -34,45 +34,26 @@
3434

3535
#if MICROPY_PY_ATEXIT
3636

37-
typedef struct _m_atexit_node_t {
38-
struct _m_atexit_node_t *prev;
39-
struct _m_atexit_node_t *next;
40-
mp_obj_t fn;
41-
} m_atexit_node_t;
42-
43-
// atexit.register(function): Functions are called LIFO when soft-reset / exit is called.
4437
mp_obj_t mp_atexit_register(mp_obj_t function) {
4538
if (!mp_obj_is_callable(function)) {
4639
mp_raise_ValueError(MP_ERROR_TEXT("function not callable"));
4740
}
48-
m_atexit_node_t *node = m_malloc(sizeof(m_atexit_node_t));
49-
if (MP_STATE_VM(atexit) != NULL) {
50-
MP_STATE_VM(atexit)->prev = node;
41+
if (MP_STATE_VM(atexit) == NULL) {
42+
MP_STATE_VM(atexit) = mp_obj_new_list(0, mp_const_none);
5143
}
52-
node->fn = function;
53-
node->prev = NULL;
54-
node->next = MP_STATE_VM(atexit);
55-
MP_STATE_VM(atexit) = node;
44+
mp_obj_list_append(MP_STATE_VM(atexit), function);
5645
// return the passed in function so this can be used as a decorator
5746
return function;
5847
}
5948
static MP_DEFINE_CONST_FUN_OBJ_1(mp_atexit_register_obj, mp_atexit_register);
6049

6150
#if MICROPY_PY_ATEXIT_UNREGISTER
6251
mp_obj_t mp_atexit_unregister(mp_obj_t function) {
63-
m_atexit_node_t *node = MP_STATE_VM(atexit);
64-
while (node != NULL) {
65-
if (mp_obj_equal(node->fn, function)) {
66-
if (node->next != NULL) {
67-
node->next->prev = node->prev;
68-
}
69-
if (node->prev != NULL) {
70-
node->prev->next = node->next;
71-
} else {
72-
MP_STATE_VM(atexit) = node->next;
73-
}
52+
nlr_buf_t nlr;
53+
if (nlr_push(&nlr) == 0) {
54+
while (MP_STATE_VM(atexit) != NULL) {
55+
mp_obj_list_remove(MP_STATE_VM(atexit), function);
7456
}
75-
node = node->next;
7657
}
7758
return mp_const_none;
7859
}
@@ -86,30 +67,30 @@ static const mp_rom_map_elem_t mp_module_atexit_globals_table[] = {
8667
{ MP_ROM_QSTR(MP_QSTR_unregister), MP_ROM_PTR(&mp_atexit_unregister_obj) },
8768
#endif
8869
};
89-
9070
static MP_DEFINE_CONST_DICT(mp_module_atexit_globals, mp_module_atexit_globals_table);
9171

9272
const mp_obj_module_t mp_module_atexit = {
9373
.base = { &mp_type_module },
9474
.globals = (mp_obj_dict_t *)&mp_module_atexit_globals,
9575
};
9676

97-
MP_REGISTER_ROOT_POINTER(struct _m_atexit_node_t *atexit);
77+
MP_REGISTER_ROOT_POINTER(mp_obj_list_t * atexit);
9878
MP_REGISTER_MODULE(MP_QSTR_atexit, mp_module_atexit);
9979

10080
int mp_atexit_execute(void) {
10181
int exit_code = 0;
102-
// This function is intended to be run by a port during its soft-reset / exit.
103-
// walk down linked list last in / first out and execute each function.
104-
// Beware, the sys.settrace function should be disabled before running sys.atexit.
105-
while (MP_STATE_VM(atexit) != NULL) {
106-
nlr_buf_t nlr;
107-
if (nlr_push(&nlr) == 0) {
108-
mp_call_function_0(MP_STATE_VM(atexit)->fn);
109-
} else {
110-
exit_code = pyexec_handle_uncaught_exception(nlr.ret_val);
82+
if (MP_STATE_VM(atexit) != NULL) {
83+
mp_obj_list_t *list = MP_STATE_VM(atexit);
84+
for (size_t i = 0; i < list->len; i++) {
85+
mp_obj_t function = list->items[i];
86+
87+
nlr_buf_t nlr;
88+
if (nlr_push(&nlr) == 0) {
89+
mp_call_function_0(function);
90+
} else {
91+
exit_code = pyexec_handle_uncaught_exception(nlr.ret_val);
92+
}
11193
}
112-
MP_STATE_VM(atexit) = MP_STATE_VM(atexit)->next;
11394
}
11495
return exit_code;
11596
}

0 commit comments

Comments
 (0)