mirror of
https://github.com/bytecodealliance/wasm-micro-runtime.git
synced 2025-05-13 13:11:25 +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;
|
bool retained;
|
||||||
/* Whether it is marked by runtime */
|
/* Whether it is marked by runtime */
|
||||||
bool marked;
|
bool marked;
|
||||||
|
/* cleanup function called when the externref is freed */
|
||||||
|
void (*cleanup)(void *);
|
||||||
} ExternRefMapNode;
|
} ExternRefMapNode;
|
||||||
|
|
||||||
static uint32
|
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
|
bool
|
||||||
wasm_externref_obj2ref(WASMModuleInstanceCommon *module_inst, void *extern_obj,
|
wasm_externref_obj2ref(WASMModuleInstanceCommon *module_inst, void *extern_obj,
|
||||||
uint32 *p_externref_idx)
|
uint32 *p_externref_idx)
|
||||||
|
@ -4792,6 +4869,7 @@ wasm_externref_obj2ref(WASMModuleInstanceCommon *module_inst, void *extern_obj,
|
||||||
memset(node, 0, sizeof(ExternRefMapNode));
|
memset(node, 0, sizeof(ExternRefMapNode));
|
||||||
node->extern_obj = extern_obj;
|
node->extern_obj = extern_obj;
|
||||||
node->module_inst = module_inst;
|
node->module_inst = module_inst;
|
||||||
|
node->cleanup = NULL;
|
||||||
|
|
||||||
externref_idx = externref_global_id;
|
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->module_inst == module_inst) {
|
||||||
if (!node->marked && !node->retained) {
|
if (!node->marked && !node->retained) {
|
||||||
bh_hash_map_remove(externref_map, key, NULL, NULL);
|
delete_externref(key, node);
|
||||||
wasm_runtime_free(value);
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
node->marked = false;
|
node->marked = false;
|
||||||
|
@ -4958,8 +5035,7 @@ cleanup_extobj_callback(void *key, void *value, void *user_data)
|
||||||
(WASMModuleInstanceCommon *)user_data;
|
(WASMModuleInstanceCommon *)user_data;
|
||||||
|
|
||||||
if (node->module_inst == module_inst) {
|
if (node->module_inst == module_inst) {
|
||||||
bh_hash_map_remove(externref_map, key, NULL, NULL);
|
delete_externref(key, node);
|
||||||
wasm_runtime_free(value);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1292,6 +1292,32 @@ WASM_RUNTIME_API_EXTERN bool
|
||||||
wasm_externref_obj2ref(wasm_module_inst_t module_inst,
|
wasm_externref_obj2ref(wasm_module_inst_t module_inst,
|
||||||
void *extern_obj, uint32_t *p_externref_idx);
|
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
|
* Retrieve the external object from an internal externref index
|
||||||
*
|
*
|
||||||
|
|
Loading…
Reference in New Issue
Block a user