34
34
35
35
#if MICROPY_PY_ATEXIT
36
36
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.
44
37
mp_obj_t mp_atexit_register (mp_obj_t function ) {
45
38
if (!mp_obj_is_callable (function )) {
46
39
mp_raise_ValueError (MP_ERROR_TEXT ("function not callable" ));
47
40
}
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 );
51
43
}
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 );
56
45
// return the passed in function so this can be used as a decorator
57
46
return function ;
58
47
}
59
48
static MP_DEFINE_CONST_FUN_OBJ_1 (mp_atexit_register_obj , mp_atexit_register ) ;
60
49
61
50
#if MICROPY_PY_ATEXIT_UNREGISTER
62
51
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 );
74
56
}
75
- node = node -> next ;
76
57
}
77
58
return mp_const_none ;
78
59
}
@@ -86,30 +67,30 @@ static const mp_rom_map_elem_t mp_module_atexit_globals_table[] = {
86
67
{ MP_ROM_QSTR (MP_QSTR_unregister ), MP_ROM_PTR (& mp_atexit_unregister_obj ) },
87
68
#endif
88
69
};
89
-
90
70
static MP_DEFINE_CONST_DICT (mp_module_atexit_globals , mp_module_atexit_globals_table ) ;
91
71
92
72
const mp_obj_module_t mp_module_atexit = {
93
73
.base = { & mp_type_module },
94
74
.globals = (mp_obj_dict_t * )& mp_module_atexit_globals ,
95
75
};
96
76
97
- MP_REGISTER_ROOT_POINTER (struct _m_atexit_node_t * atexit );
77
+ MP_REGISTER_ROOT_POINTER (mp_obj_list_t * atexit );
98
78
MP_REGISTER_MODULE (MP_QSTR_atexit , mp_module_atexit );
99
79
100
80
int mp_atexit_execute (void ) {
101
81
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
+ }
111
93
}
112
- MP_STATE_VM (atexit ) = MP_STATE_VM (atexit )-> next ;
113
94
}
114
95
return exit_code ;
115
96
}
0 commit comments