From 7ff3a390b1931d74147183315e62bb4e6d833bb8 Mon Sep 17 00:00:00 2001 From: ThePhD Date: Wed, 13 Sep 2017 11:29:32 -0400 Subject: [PATCH] final lua_xmove fixes --- docs/source/api/reference.rst | 6 ++- docs/source/threading.rst | 2 +- examples/optional_with_iteration.cpp | 2 +- single/sol/sol.hpp | 78 +++++++++++++++++----------- sol/reference.hpp | 41 +++++++++++++-- sol/stack_core.hpp | 5 -- sol/thread.hpp | 28 +++------- 7 files changed, 99 insertions(+), 63 deletions(-) diff --git a/docs/source/api/reference.rst b/docs/source/api/reference.rst index 415f4b68..8774ad0d 100644 --- a/docs/source/api/reference.rst +++ b/docs/source/api/reference.rst @@ -35,7 +35,11 @@ members The first constructor creates a reference from the Lua stack at the specified index, saving it into the metatable registry. The second attemtps to register something that already exists in the registry. The third attempts to reference a pre-existing object and create a reference to it. These constructors are exposed on all types that derive from ``sol::reference``, meaning that you can grab tables, functions, and coroutines from the registry, stack, or from other objects easily. -Note that the last constructor have ``lua_xmove`` safety built into it. You can pin an object to a certain thread (or the main thread) by initializing it with ``sol::reference pinned(state, other_reference_object);``. This ensures that ``other_reference_object`` will exist in the state/thread of ``state``. This applies for any ``sol::reference`` derived type. +.. _lua_xmove-note:: + +.. note:: + + Note that the last constructor has ``lua_xmove`` safety built into it. You can pin an object to a certain thread (or the main thread) by initializing it with ``sol::reference pinned(state, other_reference_object);``. This ensures that ``other_reference_object`` will exist in the state/thread of ``state``. Also note that copy/move assignment operations will also use pinning semantics if it detects that the state of the object on the right is ``lua_xmove`` compatible. (But, the ``reference`` object on the left must have a valid state as well. You can have a nil ``reference`` with a valid state by using the ``sol::reference pinned(state, sol::lua_nil)`` constructor as well.) This applies for any ``sol::reference`` derived type. .. code-block:: cpp :caption: function: push referred-to element from the stack diff --git a/docs/source/threading.rst b/docs/source/threading.rst index fc18ec32..7510aa02 100644 --- a/docs/source/threading.rst +++ b/docs/source/threading.rst @@ -16,7 +16,7 @@ Lua 5.1 does not keep a reference to the main thread, therefore the user has to working with multiple Lua threads --------------------------------- -You can mitigate some of the pressure of using coroutines and threading by using the ``lua_xmove`` constructors that sol implements. Simply keep a reference to your ``sol::state_view`` or ``sol::state`` or the target ``lua_State*`` pointer, and pass it into the constructor along with the object you want to copy. +You can mitigate some of the pressure of using coroutines and threading by using the ``lua_xmove`` constructors that sol implements. Simply keep a reference to your ``sol::state_view`` or ``sol::state`` or the target ``lua_State*`` pointer, and pass it into the constructor along with the object you want to copy. Note that there is also some implicit ``lua_xmove`` checks that are done for copy and move assignment operators as well, as noted :ref:`at the reference constructor explanations`. .. code-block:: cpp :caption: transfer from state function diff --git a/examples/optional_with_iteration.cpp b/examples/optional_with_iteration.cpp index b04f911f..5f9c6162 100644 --- a/examples/optional_with_iteration.cpp +++ b/examples/optional_with_iteration.cpp @@ -6,7 +6,7 @@ #include int main(int, char**) { - std::cout << "=== optional and iteration example ===" << std::endl; + std::cout << "=== optional with iteration example ===" << std::endl; struct thing { int a = 20; diff --git a/single/sol/sol.hpp b/single/sol/sol.hpp index eec16bae..33edc974 100644 --- a/single/sol/sol.hpp +++ b/single/sol/sol.hpp @@ -20,8 +20,8 @@ // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // This file was generated with a script. -// Generated 2017-09-13 14:18:42.960702 UTC -// This header was generated with sol v2.18.2 (revision 5816c6c) +// Generated 2017-09-13 15:29:20.751295 UTC +// This header was generated with sol v2.18.2 (revision dcff5cd) // https://github.com/ThePhD/sol2 #ifndef SOL_SINGLE_INCLUDE_HPP @@ -5801,6 +5801,13 @@ namespace sol { // end of sol/stack_reference.hpp namespace sol { + namespace detail { + inline const char (&default_main_thread_name())[9] { + static const char name[9] = "sol.\xF0\x9F\x93\x8C"; + return name; + } + } // namespace detail + namespace stack { inline void remove(lua_State* L, int rawindex, int count) { if (count < 1) @@ -5895,6 +5902,25 @@ namespace sol { } } // namespace stack + inline lua_State* main_thread(lua_State* L, lua_State* backup_if_unsupported = nullptr) { +#if SOL_LUA_VERSION < 502 + if (L == nullptr) + return backup_if_unsupported; + lua_getglobal(L, detail::default_main_thread_name()); + auto pp = stack::pop_n(L, 1); + if (type_of(L, -1) == type::thread) { + return lua_tothread(L, -1); + } + return backup_if_unsupported; +#else + if (L == nullptr) + return backup_if_unsupported; + lua_rawgeti(L, LUA_REGISTRYINDEX, LUA_RIDX_MAINTHREAD); + L = lua_tothread(L, -1); + return L; +#endif // Lua 5.2+ has the main thread getter + } + namespace detail { struct global_tag { } const global_{}; @@ -6021,11 +6047,15 @@ namespace sol { } reference& operator=(reference&& r) noexcept { + if (valid()) { + deref(); + } if (r.ref == LUA_REFNIL) { + luastate = r.lua_state(); ref = LUA_REFNIL; return *this; } - if (r.ref == LUA_NOREF || lua_state() == nullptr) { + if (r.ref == LUA_NOREF) { ref = LUA_NOREF; return *this; } @@ -6035,6 +6065,7 @@ namespace sol { return *this; } + luastate = r.lua_state(); ref = r.ref; r.ref = LUA_NOREF; r.luastate = nullptr; @@ -6042,11 +6073,15 @@ namespace sol { } reference& operator=(const reference& r) noexcept { + if (valid()) { + deref(); + } if (r.ref == LUA_REFNIL) { + luastate = r.lua_state(); ref = LUA_REFNIL; return *this; } - if (r.ref == LUA_NOREF || lua_state() == nullptr) { + if (r.ref == LUA_NOREF) { ref = LUA_NOREF; return *this; } @@ -6055,7 +6090,7 @@ namespace sol { ref = luaL_ref(lua_state(), LUA_REGISTRYINDEX); return *this; } - + luastate = r.lua_state(); ref = r.copy(); return *this; } @@ -6322,11 +6357,6 @@ namespace sol { void reserve(std::basic_string& arr, std::size_t hint) { arr.reserve(hint); } - - inline const char (&default_main_thread_name())[9] { - static const char name[9] = "sol.\xF0\x9F\x93\x8C"; - return name; - } } // namespace detail namespace stack { @@ -18469,11 +18499,15 @@ namespace sol { namespace sol { struct lua_thread_state { lua_State* L; - operator lua_State*() const { + + lua_State* lua_state() const noexcept { return L; } - lua_State* operator->() const { - return L; + operator lua_State*() const noexcept { + return lua_state(); + } + lua_State* operator->() const noexcept { + return lua_state(); } }; @@ -18524,24 +18558,6 @@ namespace sol { } } // namespace stack - inline lua_State* main_thread(lua_State* L, lua_State* backup_if_unsupported = nullptr) { -#if SOL_LUA_VERSION < 502 - if (L == nullptr) - return backup_if_unsupported; - lua_getglobal(L, detail::default_main_thread_name()); - auto pp = stack::pop_n(L, 1); - if (type_of(L, -1) == type::thread) { - return lua_tothread(L, -1); - } - return backup_if_unsupported; -#else - (void)backup_if_unsupported; - lua_rawgeti(L, LUA_REGISTRYINDEX, LUA_RIDX_MAINTHREAD); - lua_thread_state s = stack::pop(L); - return s.L; -#endif // Lua 5.2+ has the main thread getter - } - class thread : public reference { public: thread() noexcept = default; diff --git a/sol/reference.hpp b/sol/reference.hpp index 9ed8e815..afd1d2f0 100644 --- a/sol/reference.hpp +++ b/sol/reference.hpp @@ -26,6 +26,13 @@ #include "stack_reference.hpp" namespace sol { + namespace detail { + inline const char (&default_main_thread_name())[9] { + static const char name[9] = "sol.\xF0\x9F\x93\x8C"; + return name; + } + } // namespace detail + namespace stack { inline void remove(lua_State* L, int rawindex, int count) { if (count < 1) @@ -120,6 +127,25 @@ namespace sol { } } // namespace stack + inline lua_State* main_thread(lua_State* L, lua_State* backup_if_unsupported = nullptr) { +#if SOL_LUA_VERSION < 502 + if (L == nullptr) + return backup_if_unsupported; + lua_getglobal(L, detail::default_main_thread_name()); + auto pp = stack::pop_n(L, 1); + if (type_of(L, -1) == type::thread) { + return lua_tothread(L, -1); + } + return backup_if_unsupported; +#else + if (L == nullptr) + return backup_if_unsupported; + lua_rawgeti(L, LUA_REGISTRYINDEX, LUA_RIDX_MAINTHREAD); + L = lua_tothread(L, -1); + return L; +#endif // Lua 5.2+ has the main thread getter + } + namespace detail { struct global_tag { } const global_{}; @@ -246,11 +272,15 @@ namespace sol { } reference& operator=(reference&& r) noexcept { + if (valid()) { + deref(); + } if (r.ref == LUA_REFNIL) { + luastate = r.lua_state(); ref = LUA_REFNIL; return *this; } - if (r.ref == LUA_NOREF || lua_state() == nullptr) { + if (r.ref == LUA_NOREF) { ref = LUA_NOREF; return *this; } @@ -260,6 +290,7 @@ namespace sol { return *this; } + luastate = r.lua_state(); ref = r.ref; r.ref = LUA_NOREF; r.luastate = nullptr; @@ -267,11 +298,15 @@ namespace sol { } reference& operator=(const reference& r) noexcept { + if (valid()) { + deref(); + } if (r.ref == LUA_REFNIL) { + luastate = r.lua_state(); ref = LUA_REFNIL; return *this; } - if (r.ref == LUA_NOREF || lua_state() == nullptr) { + if (r.ref == LUA_NOREF) { ref = LUA_NOREF; return *this; } @@ -280,7 +315,7 @@ namespace sol { ref = luaL_ref(lua_state(), LUA_REGISTRYINDEX); return *this; } - + luastate = r.lua_state(); ref = r.copy(); return *this; } diff --git a/sol/stack_core.hpp b/sol/stack_core.hpp index 8913e6a8..f291cca8 100644 --- a/sol/stack_core.hpp +++ b/sol/stack_core.hpp @@ -103,11 +103,6 @@ namespace sol { void reserve(std::basic_string& arr, std::size_t hint) { arr.reserve(hint); } - - inline const char (&default_main_thread_name())[9] { - static const char name[9] = "sol.\xF0\x9F\x93\x8C"; - return name; - } } // namespace detail namespace stack { diff --git a/sol/thread.hpp b/sol/thread.hpp index 1ee10705..9f418d5d 100644 --- a/sol/thread.hpp +++ b/sol/thread.hpp @@ -28,11 +28,15 @@ namespace sol { struct lua_thread_state { lua_State* L; - operator lua_State*() const { + + lua_State* lua_state() const noexcept { return L; } - lua_State* operator->() const { - return L; + operator lua_State*() const noexcept { + return lua_state(); + } + lua_State* operator->() const noexcept { + return lua_state(); } }; @@ -83,24 +87,6 @@ namespace sol { } } // namespace stack - inline lua_State* main_thread(lua_State* L, lua_State* backup_if_unsupported = nullptr) { -#if SOL_LUA_VERSION < 502 - if (L == nullptr) - return backup_if_unsupported; - lua_getglobal(L, detail::default_main_thread_name()); - auto pp = stack::pop_n(L, 1); - if (type_of(L, -1) == type::thread) { - return lua_tothread(L, -1); - } - return backup_if_unsupported; -#else - (void)backup_if_unsupported; - lua_rawgeti(L, LUA_REGISTRYINDEX, LUA_RIDX_MAINTHREAD); - lua_thread_state s = stack::pop(L); - return s.L; -#endif // Lua 5.2+ has the main thread getter - } - class thread : public reference { public: thread() noexcept = default;