mirror of
https://github.com/bytecodealliance/wasm-micro-runtime.git
synced 2025-05-11 12:11:14 +00:00
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:
parent
5c6613b2b1
commit
8d1cf46f02
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1292,6 +1292,32 @@ WASM_RUNTIME_API_EXTERN bool
|
|||
wasm_externref_obj2ref(wasm_module_inst_t module_inst,
|
||||
void *extern_obj, uint32_t *p_externref_idx);
|
||||
|
||||
/**
|
||||
* Delete external object registered by `wasm_externref_obj2ref`.
|
||||
*
|
||||
* @param module_inst the WASM module instance that the extern object
|
||||
* belongs to
|
||||
* @param extern_obj the external object to be deleted
|
||||
*
|
||||
* @return true if success, false otherwise
|
||||
*/
|
||||
WASM_RUNTIME_API_EXTERN bool
|
||||
wasm_externref_objdel(wasm_module_inst_t module_inst, void *extern_obj);
|
||||
|
||||
/**
|
||||
* Set cleanup callback to release external object.
|
||||
*
|
||||
* @param module_inst the WASM module instance that the extern object
|
||||
* belongs to
|
||||
* @param extern_obj the external object to which to set the `extern_obj_cleanup` cleanup callback.
|
||||
* @param extern_obj_cleanup a callback to release `extern_obj`
|
||||
*
|
||||
* @return true if success, false otherwise
|
||||
*/
|
||||
WASM_RUNTIME_API_EXTERN bool
|
||||
wasm_externref_set_cleanup(wasm_module_inst_t module_inst, void *extern_obj,
|
||||
void (*extern_obj_cleanup)(void *));
|
||||
|
||||
/**
|
||||
* Retrieve the external object from an internal externref index
|
||||
*
|
||||
|
|
Loading…
Reference in New Issue
Block a user