Skip to content

Commit 186ab5c

Browse files
andrewleechpi-anl
authored andcommitted
py/modatexit: Switch to using list.
Signed-off-by: Andrew Leech <[email protected]>
1 parent 3a95259 commit 186ab5c

File tree

1 file changed

+20
-38
lines changed

1 file changed

+20
-38
lines changed

py/modatexit.c

Lines changed: 20 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -34,45 +34,27 @@
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, NULL);
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_OBJ_FROM_PTR(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+
// ValueError is thrown when function is no longer in the list
54+
if (nlr_push(&nlr) == 0) {
55+
while (MP_STATE_VM(atexit) != NULL) {
56+
mp_obj_list_remove(MP_OBJ_FROM_PTR(MP_STATE_VM(atexit)), function);
7457
}
75-
node = node->next;
7658
}
7759
return mp_const_none;
7860
}
@@ -86,30 +68,30 @@ static const mp_rom_map_elem_t mp_module_atexit_globals_table[] = {
8668
{ MP_ROM_QSTR(MP_QSTR_unregister), MP_ROM_PTR(&mp_atexit_unregister_obj) },
8769
#endif
8870
};
89-
9071
static MP_DEFINE_CONST_DICT(mp_module_atexit_globals, mp_module_atexit_globals_table);
9172

9273
const mp_obj_module_t mp_module_atexit = {
9374
.base = { &mp_type_module },
9475
.globals = (mp_obj_dict_t *)&mp_module_atexit_globals,
9576
};
9677

97-
MP_REGISTER_ROOT_POINTER(struct _m_atexit_node_t *atexit);
78+
MP_REGISTER_ROOT_POINTER(mp_obj_list_t * atexit);
9879
MP_REGISTER_MODULE(MP_QSTR_atexit, mp_module_atexit);
9980

10081
int mp_atexit_execute(void) {
10182
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);
83+
if (MP_STATE_VM(atexit) != NULL) {
84+
mp_obj_list_t *list = MP_STATE_VM(atexit);
85+
for (size_t i = 0; i < list->len; i++) {
86+
mp_obj_t function = list->items[i];
87+
88+
nlr_buf_t nlr;
89+
if (nlr_push(&nlr) == 0) {
90+
mp_call_function_0(function);
91+
} else {
92+
exit_code = pyexec_handle_uncaught_exception(nlr.ret_val);
93+
}
11194
}
112-
MP_STATE_VM(atexit) = MP_STATE_VM(atexit)->next;
11395
}
11496
return exit_code;
11597
}

0 commit comments

Comments
 (0)