@@ -35,7 +35,7 @@ struct HNode
35
35
struct HNode * next ;
36
36
term key ;
37
37
term entry ;
38
- Heap * heap ;
38
+ Heap heap ;
39
39
};
40
40
41
41
static uint32_t hash_term (term t , GlobalContext * global );
@@ -53,14 +53,26 @@ struct EtsHashTable *ets_hashtable_new()
53
53
return htable ;
54
54
}
55
55
56
+ static void ets_hashtable_free_node (struct HNode * node , GlobalContext * global )
57
+ {
58
+ memory_destroy_heap (& node -> heap , global );
59
+ free (node );
60
+ }
61
+
62
+ void ets_hashtable_free_node_array (struct HNode * * allocated , size_t size , GlobalContext * global )
63
+ {
64
+ for (size_t i = 0 ; i < size ; ++ i ) {
65
+ ets_hashtable_free_node (allocated [i ], global );
66
+ }
67
+ }
68
+
56
69
void ets_hashtable_destroy (struct EtsHashTable * hash_table , GlobalContext * global )
57
70
{
58
71
for (size_t i = 0 ; i < hash_table -> capacity ; ++ i ) {
59
72
struct HNode * node = hash_table -> buckets [i ];
60
- while (node != 0 ) {
61
- memory_destroy_heap (node -> heap , global );
73
+ while (node != NULL ) {
62
74
struct HNode * next_node = node -> next ;
63
- free (node );
75
+ ets_hashtable_free_node (node , global );
64
76
node = next_node ;
65
77
}
66
78
}
@@ -82,8 +94,33 @@ static void print_info(struct EtsHashTable *hash_table)
82
94
}
83
95
#endif
84
96
85
- EtsHashtableErrorCode ets_hashtable_insert ( struct EtsHashTable * hash_table , term key , term entry , EtsHashtableOptions opts , Heap * heap , GlobalContext * global )
97
+ struct HNode * ets_hashtable_new_node ( term entry , int keypos )
86
98
{
99
+
100
+ struct HNode * new_node = malloc (sizeof (struct HNode ));
101
+ if (IS_NULL_PTR (new_node )) {
102
+ return NULL ;
103
+ }
104
+
105
+ size_t size = (size_t ) memory_estimate_usage (entry );
106
+ if (memory_init_heap (& new_node -> heap , size ) != MEMORY_GC_OK ) {
107
+ free (new_node );
108
+ return NULL ;
109
+ }
110
+
111
+ term new_entry = memory_copy_term_tree (& new_node -> heap , entry );
112
+ term key = term_get_tuple_element (new_entry , keypos );
113
+
114
+ new_node -> next = NULL ;
115
+ new_node -> key = key ;
116
+ new_node -> entry = new_entry ;
117
+
118
+ return new_node ;
119
+ }
120
+
121
+ EtsHashtableErrorCode ets_hashtable_insert (struct EtsHashTable * hash_table , struct HNode * new_node , EtsHashtableOptions opts , GlobalContext * global )
122
+ {
123
+ term key = new_node -> key ;
87
124
uint32_t hash = hash_term (key , global );
88
125
uint32_t index = hash % hash_table -> capacity ;
89
126
@@ -94,38 +131,30 @@ EtsHashtableErrorCode ets_hashtable_insert(struct EtsHashTable *hash_table, term
94
131
#endif
95
132
96
133
struct HNode * node = hash_table -> buckets [index ];
97
- if (node ) {
98
- while (1 ) {
99
- if (term_compare (key , node -> key , TermCompareExact , global ) == TermEquals ) {
100
- if (opts & EtsHashtableAllowOverwrite ) {
101
- node -> entry = entry ;
102
- memory_destroy_heap (node -> heap , global );
103
- node -> heap = heap ;
104
- return EtsHashtableOk ;
134
+ struct HNode * last_node = NULL ;
135
+ while (node ) {
136
+ if (term_compare (key , node -> key , TermCompareExact , global ) == TermEquals ) {
137
+ if (opts & EtsHashtableAllowOverwrite ) {
138
+ if (IS_NULL_PTR (last_node )) {
139
+ new_node -> next = node -> next ;
140
+ hash_table -> buckets [index ] = new_node ;
105
141
} else {
106
- return EtsHashtableFailure ;
142
+ last_node -> next = new_node ;
143
+ new_node -> next = node -> next ;
107
144
}
108
- }
109
-
110
- if (node -> next ) {
111
- node = node -> next ;
145
+ ets_hashtable_free_node (node , global );
146
+ return EtsHashtableOk ;
112
147
} else {
113
- break ;
148
+ ets_hashtable_free_node (new_node , global );
149
+ return EtsHashtableFailure ;
114
150
}
115
151
}
152
+ last_node = node ;
153
+ node = node -> next ;
116
154
}
117
155
118
- struct HNode * new_node = malloc (sizeof (struct HNode ));
119
- if (IS_NULL_PTR (new_node )) {
120
- return EtsHashtableError ;
121
- }
122
- new_node -> next = NULL ;
123
- new_node -> key = key ;
124
- new_node -> entry = entry ;
125
- new_node -> heap = heap ;
126
-
127
- if (node ) {
128
- node -> next = new_node ;
156
+ if (last_node ) {
157
+ last_node -> next = new_node ;
129
158
} else {
130
159
hash_table -> buckets [index ] = new_node ;
131
160
}
@@ -165,7 +194,7 @@ bool ets_hashtable_remove(struct EtsHashTable *hash_table, term key, size_t keyp
165
194
term key_to_compare = term_get_tuple_element (node -> entry , keypos );
166
195
if (term_compare (key , key_to_compare , TermCompareExact , global ) == TermEquals ) {
167
196
168
- memory_destroy_heap (node -> heap , global );
197
+ memory_destroy_heap (& node -> heap , global );
169
198
struct HNode * next_node = node -> next ;
170
199
free (node );
171
200
0 commit comments