You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
(Please forgive me for the wall of text. It is an interesting read, I promise.)
I am currently investigating into using this crate in a multithreaded manner. In order to do so, I need to override the Lua definitions for the lua_lock() and lua_unlock() macros, which brought up the larger question of how these macros can be overridden. Since Lua is meant to be customizable for many different uses, I think this is an important discussion to have and something we should try to solve.
The main issue as to why this is not easy is because Lua is compiled before this crate, and not with it. C and Rust can't be mixed, so this isn't something we can solve to my knowledge.
I see three options currently, though I'd love to see if anyone else has better ideas than these admittedly poor options:
Add the ability to include custom C code during the compilation process by modifying Lua's Makefile (which we can now do, thanks to Bundle Lua rather than download it #59). This would be a feature added to the build script.
Don't allow consumers of the crate to override macros, and use a combination of C and Rust to pick-and-choose how we want to handle specific macros. For example, write hardcoded implementations of lua_lock() and lua_unlock() and make thread safety a non-optional feature.
Use function pointers and stubbing to override definitions at runtime. This would have a small runtime overhead.
Personally, (1) does not sound desirable at all, even if it can be done. I don't feel like writing any C code in a Rust application that depends on lua.
(2) is not desirable either, especially for the locking case. Locking incurs a notable runtime overhead that we do not want to force on users in a single-threaded application. Since this is compile-time, it might be near-impossible to be able to turn thread-safety off.
(3) isn't pretty, but it kind of works and isn't as much of a runtime cost as (2) could be for some users. Calling all overridable functions would have an additional branch instruction checking for NULL before making a jump to an implementation.
Here's some of the ugliness of (3) so that you can assess if it is worth it...
Adding externs for values that are overridable in lua-source/overrides.h (we must choose what overrides we want to support):
#[macro_use]externcrate lua;fnmain(){lua_override!(LUA_LOCK_STUB, lock);lua_override!(LUA_UNLOCK_STUB, unlock);letmut state = lua::State::new();
state.do_string("print('hi')");}fnlock(state:*mutlua_State){println!("lua_lock called");}fnunlock(state:*mutlua_State){println!("lua_unlock called");}
This prints "hi" between a whole lot of "lua_lock called" and "lua_unlock called". If this approach is desirable, as it looks decent to the consumer, then I can open a PR with a tidier implementation.
Are any of these good ideas? How do we want to handle macro overrides?
(Please forgive me for the wall of text. It is an interesting read, I promise.)
I am currently investigating into using this crate in a multithreaded manner. In order to do so, I need to override the Lua definitions for the
lua_lock()andlua_unlock()macros, which brought up the larger question of how these macros can be overridden. Since Lua is meant to be customizable for many different uses, I think this is an important discussion to have and something we should try to solve.The main issue as to why this is not easy is because Lua is compiled before this crate, and not with it. C and Rust can't be mixed, so this isn't something we can solve to my knowledge.
I see three options currently, though I'd love to see if anyone else has better ideas than these admittedly poor options:
lua_lock()andlua_unlock()and make thread safety a non-optional feature.Personally, (1) does not sound desirable at all, even if it can be done. I don't feel like writing any C code in a Rust application that depends on lua.
(2) is not desirable either, especially for the locking case. Locking incurs a notable runtime overhead that we do not want to force on users in a single-threaded application. Since this is compile-time, it might be near-impossible to be able to turn thread-safety off.
(3) isn't pretty, but it kind of works and isn't as much of a runtime cost as (2) could be for some users. Calling all overridable functions would have an additional branch instruction checking for NULL before making a jump to an implementation.
Here's some of the ugliness of (3) so that you can assess if it is worth it...
Adding externs for values that are overridable in
lua-source/overrides.h(we must choose what overrides we want to support):Define references for the above symbols initialized to null (
lua-source/overrides.c):Back to Rust, we define a macro that consumers of the crate can use to set these overridable function pointers:
This indeed works! A usage example:
This prints "hi" between a whole lot of "lua_lock called" and "lua_unlock called". If this approach is desirable, as it looks decent to the consumer, then I can open a PR with a tidier implementation.
Are any of these good ideas? How do we want to handle macro overrides?