Implement wasm_externref_objdel and wasm_externref_set_cleanup (#2455)
## Context Some native libraries may want to explicitly delete an externref object without waiting for the module instance to be deleted. In addition, it may want to add a cleanup function. ## Proposed Changes Implement: * `wasm_externref_objdel` to explicitly delete an externeref'd object. * `wasm_externref_set_cleanup` to set a cleanup function that is called when the externref'd object is deleted.
This commit is contained in:
@ -4681,6 +4681,8 @@ typedef struct ExternRefMapNode {
|
||||
bool retained;
|
||||
/* Whether it is marked by runtime */
|
||||
bool marked;
|
||||
/* cleanup function called when the externref is freed */
|
||||
void (*cleanup)(void *);
|
||||
} ExternRefMapNode;
|
||||
|
||||
static uint32
|
||||
@ -4743,6 +4745,81 @@ lookup_extobj_callback(void *key, void *value, void *user_data)
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
delete_externref(void *key, ExternRefMapNode *node)
|
||||
{
|
||||
bh_hash_map_remove(externref_map, key, NULL, NULL);
|
||||
if (node->cleanup) {
|
||||
(*node->cleanup)(node->extern_obj);
|
||||
}
|
||||
wasm_runtime_free(node);
|
||||
}
|
||||
|
||||
static void
|
||||
delete_extobj_callback(void *key, void *value, void *user_data)
|
||||
{
|
||||
ExternRefMapNode *node = (ExternRefMapNode *)value;
|
||||
LookupExtObj_UserData *lookup_user_data =
|
||||
(LookupExtObj_UserData *)user_data;
|
||||
|
||||
if (node->extern_obj == lookup_user_data->node.extern_obj
|
||||
&& node->module_inst == lookup_user_data->node.module_inst) {
|
||||
lookup_user_data->found = true;
|
||||
delete_externref(key, node);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
wasm_externref_objdel(WASMModuleInstanceCommon *module_inst, void *extern_obj)
|
||||
{
|
||||
LookupExtObj_UserData lookup_user_data = { 0 };
|
||||
bool ok = false;
|
||||
|
||||
/* in a wrapper, extern_obj could be any value */
|
||||
lookup_user_data.node.extern_obj = extern_obj;
|
||||
lookup_user_data.node.module_inst = module_inst;
|
||||
lookup_user_data.found = false;
|
||||
|
||||
os_mutex_lock(&externref_lock);
|
||||
/* Lookup hashmap firstly */
|
||||
bh_hash_map_traverse(externref_map, delete_extobj_callback,
|
||||
(void *)&lookup_user_data);
|
||||
if (lookup_user_data.found) {
|
||||
ok = true;
|
||||
}
|
||||
os_mutex_unlock(&externref_lock);
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
bool
|
||||
wasm_externref_set_cleanup(WASMModuleInstanceCommon *module_inst,
|
||||
void *extern_obj, void (*extern_obj_cleanup)(void *))
|
||||
{
|
||||
|
||||
LookupExtObj_UserData lookup_user_data = { 0 };
|
||||
bool ok = false;
|
||||
|
||||
/* in a wrapper, extern_obj could be any value */
|
||||
lookup_user_data.node.extern_obj = extern_obj;
|
||||
lookup_user_data.node.module_inst = module_inst;
|
||||
lookup_user_data.found = false;
|
||||
|
||||
os_mutex_lock(&externref_lock);
|
||||
/* Lookup hashmap firstly */
|
||||
bh_hash_map_traverse(externref_map, lookup_extobj_callback,
|
||||
(void *)&lookup_user_data);
|
||||
if (lookup_user_data.found) {
|
||||
void *key = (void *)(uintptr_t)lookup_user_data.externref_idx;
|
||||
ExternRefMapNode *node = bh_hash_map_find(externref_map, key);
|
||||
node->cleanup = extern_obj_cleanup;
|
||||
ok = true;
|
||||
}
|
||||
os_mutex_unlock(&externref_lock);
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
bool
|
||||
wasm_externref_obj2ref(WASMModuleInstanceCommon *module_inst, void *extern_obj,
|
||||
uint32 *p_externref_idx)
|
||||
@ -4792,6 +4869,7 @@ wasm_externref_obj2ref(WASMModuleInstanceCommon *module_inst, void *extern_obj,
|
||||
memset(node, 0, sizeof(ExternRefMapNode));
|
||||
node->extern_obj = extern_obj;
|
||||
node->module_inst = module_inst;
|
||||
node->cleanup = NULL;
|
||||
|
||||
externref_idx = externref_global_id;
|
||||
|
||||
@ -4842,8 +4920,7 @@ reclaim_extobj_callback(void *key, void *value, void *user_data)
|
||||
|
||||
if (node->module_inst == module_inst) {
|
||||
if (!node->marked && !node->retained) {
|
||||
bh_hash_map_remove(externref_map, key, NULL, NULL);
|
||||
wasm_runtime_free(value);
|
||||
delete_externref(key, node);
|
||||
}
|
||||
else {
|
||||
node->marked = false;
|
||||
@ -4958,8 +5035,7 @@ cleanup_extobj_callback(void *key, void *value, void *user_data)
|
||||
(WASMModuleInstanceCommon *)user_data;
|
||||
|
||||
if (node->module_inst == module_inst) {
|
||||
bh_hash_map_remove(externref_map, key, NULL, NULL);
|
||||
wasm_runtime_free(value);
|
||||
delete_externref(key, node);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user