emscripten-core / emscripten-core/emscripten
RFE: shortcomings and design flaws in/around addFunction() and removeFunction()
- Dominant language
- C++
- Stars
- 27.6k
- Forks
- 3.6k
- Avg merge
- 1d 1h
- Merged PRs (30d)
- 105
Description
```
emcc (Emscripten gcc/clang-like replacement + linker emulating GNU ld) 3.1.13 (531257621816c200bc7c3be53129494afd029aec)
```
Background: i'm currently implementing a framework which allows mostly-transparent mapping of C structs into JS, such that both JS and C share the same view of the object and changes made to struct members in one environment are visible in the other.
Where i'm currently stumbling is handling of pointer-to-function members. They can be mapped as opaque pointers, but my end goal here is to allow a JS function to be assigned to such a member and register that function with WASM using Emscripten's `addFunction()`.
That doesn't pose a particular technical problem but implementing it has exposed shortcomings of the `addFunction()`/`removeFunction()` constellation:
1) Given just a pointer (integer) value, it would be exceptionally useful for me (in this particular use case) to be able to say "give me the registered function, if any, for this pointer."
2) Similarly, it's not possible for client code to ask "is there are registration for this Function already?" and get the pointer to that binding.
3) `addFunction()` silently recycles functions, so it's not possible for a caller to know whether it's safe for them to call `removeFunction()`. If they call `removeFunction()` they may remove a mapping which they inherited via `addFunction()`'s recycling. If they don't call `removeFunction()` they are leaking. In order for a call to `removeFunction()` to be safe, `addFunction()` must stop recycling functions or it must explicitly support multiple registrations of any given function, e.g. by adding a reference count to such bindings, such that `removeFunction()` reduces the reference count and only unregisters the function when the count is 0.
The biggest issue is (3), as it reduces the utility of add/removeFunction to only very basic cases. As soon as two code paths call `addFunction()` for the same function, using `removeFunction()` becomes illegal for _both_ of them. In the sqlite3 WASM binding this case has come up when creating user-defined SQL-bound functions in JS. Two DB handles may register the same SQL-bound function, but neither is permitted to call `removeFunction()` because doing so would break the other DB handle if that SQL function is ever called. We have to work around that by creating a dummy wrapper function for each instance of such functions, then pass the dummy to `addFunction()` so that each dummy wrapper becomes a distinct instance in the function table.
My request, then, is that the function registration/unregistration APIs be fleshed out to make them suitable for more than trivial use cases.
Contributor guide
Assessment
This issue has not been assessed yet.