final lua_xmove fixes

This commit is contained in:
ThePhD 2017-09-13 11:29:32 -04:00
parent dcff5cdaa0
commit 7ff3a390b1
7 changed files with 99 additions and 63 deletions

View File

@ -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

View File

@ -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<lua_xmove-note>`.
.. code-block:: cpp
:caption: transfer from state function

View File

@ -6,7 +6,7 @@
#include <iostream>
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;

View File

@ -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<T, Tr, Al>& 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<lua_thread_state>(L);
return s.L;
#endif // Lua 5.2+ has the main thread getter
}
class thread : public reference {
public:
thread() noexcept = default;

View File

@ -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;
}

View File

@ -103,11 +103,6 @@ namespace sol {
void reserve(std::basic_string<T, Tr, Al>& 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 {

View File

@ -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<lua_thread_state>(L);
return s.L;
#endif // Lua 5.2+ has the main thread getter
}
class thread : public reference {
public:
thread() noexcept = default;