implement main_reference as per @eliasdaler's suggestions

This commit is contained in:
ThePhD 2017-09-14 00:35:40 -04:00
parent 72143a494b
commit 8d828ac47b
29 changed files with 997 additions and 498 deletions

View File

@ -14,8 +14,8 @@ FixNamespaceComments: true
ColumnLimit: 0 ColumnLimit: 0
AlignAfterOpenBracket: DontAlign # uses ContinuationIndentWidth for this instead AlignAfterOpenBracket: DontAlign # uses ContinuationIndentWidth for this instead
AccessModifierOffset: -5 # do not push public: or private: around AccessModifierOffset: -5 # do not push public: or private: around
#AlignConsecutiveAssignments: true #AlignConsecutiveAssignments: true # affects more than what's expected: do not use
#AlignConsecutiveDeclarations: true #AlignConsecutiveDeclarations: true # affects more than what's expected: do not use
# Type Alignment # Type Alignment
DerivePointerAlignment: false DerivePointerAlignment: false
@ -29,7 +29,6 @@ ReflowComments: true
# Macros # Macros
AlignEscapedNewlines: Left AlignEscapedNewlines: Left
SortIncludes: false
IndentPPDirectives: None IndentPPDirectives: None
# Functions # Functions
@ -38,6 +37,8 @@ AlwaysBreakAfterReturnType: None
BreakConstructorInitializers: BeforeComma BreakConstructorInitializers: BeforeComma
ConstructorInitializerIndentWidth: 0 ConstructorInitializerIndentWidth: 0
ConstructorInitializerAllOnOneLineOrOnePerLine: true ConstructorInitializerAllOnOneLineOrOnePerLine: true
BinPackArguments: true
BinPackParameters: true
# Classes # Classes
BreakBeforeInheritanceComma: false BreakBeforeInheritanceComma: false
@ -66,7 +67,6 @@ AllowShortLoopsOnASingleLine: false
AllowShortCaseLabelsOnASingleLine: false AllowShortCaseLabelsOnASingleLine: false
IndentCaseLabels: false IndentCaseLabels: false
# Spaces # Spaces
SpaceAfterCStyleCast: false SpaceAfterCStyleCast: false
SpacesInCStyleCastParentheses: false SpacesInCStyleCastParentheses: false
@ -81,6 +81,7 @@ MaxEmptyLinesToKeep: 1
# OCD # OCD
SortUsingDeclarations: true SortUsingDeclarations: true
SortIncludes: false
--- ---
Language: Cpp Language: Cpp

View File

@ -18,6 +18,8 @@ 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. 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>`. 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>`.
Furthermore, for every single ``sol::reference`` derived type, there exists a version prefixed with the word ``main_``, such as ``sol::main_table``, ``sol::main_function``, ``sol::main_object`` and similar. These classes, on construction, assignment and other operations, forcibly obtain the ``lua_State*`` associated with the main thread, if possible. Using these classes will allow your code to be immune when a wrapped coroutine or a lua thread is set to ``nil`` and then garbage-collected.
.. code-block:: cpp .. code-block:: cpp
:caption: transfer from state function :caption: transfer from state function
:name: state-transfer :name: state-transfer

File diff suppressed because it is too large Load Diff

View File

@ -760,7 +760,7 @@ namespace sol {
} }
static void add_insert_after(std::false_type, lua_State* L, T&, stack_object) { static void add_insert_after(std::false_type, lua_State* L, T&, stack_object) {
luaL_error(L, "cannot call 'add' on type '%s': no suitable insert/push_back C++ functions", sol::detail::demangle<T>().data()); luaL_error(L, "cannot call 'add' on type '%s': no suitable insert/push_back C++ functions", detail::demangle<T>().data());
} }
static void add_insert_after(std::true_type, lua_State*, T& self, stack_object value, iterator& at) { static void add_insert_after(std::true_type, lua_State*, T& self, stack_object value, iterator& at) {
@ -1020,7 +1020,7 @@ namespace sol {
auto& src = get_src(L); auto& src = get_src(L);
stack::push(L, next<ip>); stack::push(L, next<ip>);
stack::push<user<iter>>(L, src, deferred_traits::begin(L, src)); stack::push<user<iter>>(L, src, deferred_traits::begin(L, src));
stack::push(L, sol::lua_nil); stack::push(L, lua_nil);
return 3; return 3;
} }

View File

@ -346,7 +346,7 @@ namespace sol {
}; };
template <typename T> template <typename T>
struct pusher<T, std::enable_if_t<meta::all<is_container<meta::unqualified_t<T>>, meta::neg<meta::any<std::is_base_of<reference, meta::unqualified_t<T>>, std::is_base_of<stack_reference, meta::unqualified_t<T>>>>>::value>> { struct pusher<T, std::enable_if_t<meta::all<is_container<meta::unqualified_t<T>>, meta::neg<is_lua_reference<meta::unqualified_t<T>>>>::value>> {
typedef meta::unqualified_t<T> C; typedef meta::unqualified_t<T> C;
static int push(lua_State* L, const T& cont) { static int push(lua_State* L, const T& cont) {
@ -361,7 +361,7 @@ namespace sol {
}; };
template <typename T> template <typename T>
struct pusher<T*, std::enable_if_t<meta::all<is_container<meta::unqualified_t<T>>, meta::neg<meta::any<std::is_base_of<reference, meta::unqualified_t<T>>, std::is_base_of<stack_reference, meta::unqualified_t<T>>>>>::value>> { struct pusher<T*, std::enable_if_t<meta::all<is_container<meta::unqualified_t<T>>, meta::neg<is_lua_reference<meta::unqualified_t<T>>>>::value>> {
typedef std::add_pointer_t<meta::unqualified_t<std::remove_pointer_t<T>>> C; typedef std::add_pointer_t<meta::unqualified_t<std::remove_pointer_t<T>>> C;
static int push(lua_State* L, T* cont) { static int push(lua_State* L, T* cont) {

View File

@ -28,7 +28,8 @@
#include "thread.hpp" #include "thread.hpp"
namespace sol { namespace sol {
class coroutine : public reference { template <typename base_t>
class basic_coroutine : public base_t {
private: private:
call_status stats = call_status::yielded; call_status stats = call_status::yielded;
@ -66,41 +67,43 @@ namespace sol {
} }
public: public:
coroutine() noexcept = default; using base_t::lua_state;
coroutine(const coroutine&) noexcept = default;
coroutine(coroutine&&) noexcept = default; basic_coroutine() noexcept = default;
coroutine& operator=(const coroutine&) noexcept = default; basic_coroutine(const basic_coroutine&) noexcept = default;
coroutine& operator=(coroutine&&) noexcept = default; basic_coroutine(basic_coroutine&&) noexcept = default;
template <typename T, meta::enable<meta::neg<std::is_same<meta::unqualified_t<T>, coroutine>>, std::is_base_of<reference, meta::unqualified_t<T>>> = meta::enabler> basic_coroutine& operator=(const basic_coroutine&) noexcept = default;
coroutine(T&& r) basic_coroutine& operator=(basic_coroutine&&) noexcept = default;
: reference(std::forward<T>(r)) { template <typename T, meta::enable<meta::neg<std::is_same<meta::unqualified_t<T>, basic_coroutine>>, is_lua_reference<meta::unqualified_t<T>>> = meta::enabler>
basic_coroutine(T&& r)
: base_t(std::forward<T>(r)) {
} }
coroutine(lua_nil_t r) basic_coroutine(lua_nil_t r)
: reference(r) { : base_t(r) {
} }
coroutine(const stack_reference& r) noexcept basic_coroutine(const stack_reference& r) noexcept
: coroutine(r.lua_state(), r.stack_index()) { : basic_coroutine(r.lua_state(), r.stack_index()) {
} }
coroutine(stack_reference&& r) noexcept basic_coroutine(stack_reference&& r) noexcept
: coroutine(r.lua_state(), r.stack_index()) { : basic_coroutine(r.lua_state(), r.stack_index()) {
} }
template <typename T, meta::enable<meta::neg<std::is_integral<meta::unqualified_t<T>>>, meta::neg<std::is_same<T, ref_index>>> = meta::enabler> template <typename T, meta::enable<meta::neg<is_lua_index<meta::unqualified_t<T>>>> = meta::enabler>
coroutine(lua_State* L, T&& r) basic_coroutine(lua_State* L, T&& r)
: coroutine(L, sol::ref_index(r.registry_index())) { : base_t(L, std::forward<T>(r)) {
} }
coroutine(lua_State* L, int index = -1) basic_coroutine(lua_State* L, int index = -1)
: reference(L, index) { : base_t(L, index) {
#ifdef SOL_CHECK_ARGUMENTS #ifdef SOL_CHECK_ARGUMENTS
constructor_handler handler{}; constructor_handler handler{};
stack::check<coroutine>(L, index, handler); stack::check<basic_coroutine>(lua_state(), index, handler);
#endif // Safety #endif // Safety
} }
coroutine(lua_State* L, ref_index index) basic_coroutine(lua_State* L, ref_index index)
: reference(L, index) { : base_t(L, index) {
#ifdef SOL_CHECK_ARGUMENTS #ifdef SOL_CHECK_ARGUMENTS
auto pp = stack::push_pop(*this); auto pp = stack::push_pop(*this);
constructor_handler handler{}; constructor_handler handler{};
stack::check<coroutine>(L, -1, handler); stack::check<basic_coroutine>(lua_state(), -1, handler);
#endif // Safety #endif // Safety
} }
@ -114,7 +117,7 @@ namespace sol {
} }
bool runnable() const noexcept { bool runnable() const noexcept {
return valid() return base_t::valid()
&& (status() == call_status::yielded); && (status() == call_status::yielded);
} }
@ -134,8 +137,8 @@ namespace sol {
template <typename... Ret, typename... Args> template <typename... Ret, typename... Args>
decltype(auto) call(Args&&... args) { decltype(auto) call(Args&&... args) {
push(); base_t::push();
int pushcount = stack::multi_push(lua_state(), std::forward<Args>(args)...); int pushcount = stack::multi_push_reference(lua_state(), std::forward<Args>(args)...);
return invoke(types<Ret...>(), std::make_index_sequence<sizeof...(Ret)>(), pushcount); return invoke(types<Ret...>(), std::make_index_sequence<sizeof...(Ret)>(), pushcount);
} }
}; };

View File

@ -49,10 +49,11 @@ namespace sol {
basic_environment(lua_State* L, new_table nt) basic_environment(lua_State* L, new_table nt)
: base_t(L, std::move(nt)) { : base_t(L, std::move(nt)) {
} }
basic_environment(lua_State* L, new_table t, const reference& fallback) template <bool b>
basic_environment(lua_State* L, new_table t, const basic_reference<b>& fallback)
: basic_environment(L, std::move(t)) { : basic_environment(L, std::move(t)) {
sol::stack_table mt(L, sol::new_table(0, 1)); stack_table mt(L, new_table(0, 1));
mt.set(sol::meta_function::index, fallback); mt.set(meta_function::index, fallback);
this->set(metatable_key, mt); this->set(metatable_key, mt);
mt.pop(); mt.pop();
} }
@ -65,7 +66,8 @@ namespace sol {
#endif // Safety #endif // Safety
lua_pop(this->lua_state(), 2); lua_pop(this->lua_state(), 2);
} }
basic_environment(env_t, const reference& extraction_target) template <bool b>
basic_environment(env_t, const basic_reference<b>& extraction_target)
: base_t(detail::no_safety, extraction_target.lua_state(), (stack::push_environment_of(extraction_target), -1)) { : base_t(detail::no_safety, extraction_target.lua_state(), (stack::push_environment_of(extraction_target), -1)) {
#ifdef SOL_CHECK_ARGUMENTS #ifdef SOL_CHECK_ARGUMENTS
constructor_handler handler{}; constructor_handler handler{};
@ -137,7 +139,7 @@ namespace sol {
this_environment() this_environment()
: env(nullopt) { : env(nullopt) {
} }
this_environment(sol::environment e) this_environment(environment e)
: env(std::move(e)) { : env(std::move(e)) {
} }
this_environment(const this_environment&) = default; this_environment(const this_environment&) = default;
@ -194,8 +196,8 @@ namespace sol {
return this_environment(); return this_environment();
} }
sol::stack_reference f(L, -1); stack_reference f(L, -1);
sol::environment env(sol::env_key, f); environment env(env_key, f);
if (!env.valid()) { if (!env.valid()) {
lua_settop(L, pre_stack_size); lua_settop(L, pre_stack_size);
return this_environment(); return this_environment();

View File

@ -26,11 +26,18 @@
namespace sol { namespace sol {
class reference; template <bool b>
class basic_reference;
using reference = basic_reference<false>;
using main_reference = basic_reference<true>;
class stack_reference; class stack_reference;
struct proxy_base_tag; struct proxy_base_tag;
template <typename Super>
struct proxy_base;
template <typename Table, typename Key> template <typename Table, typename Key>
struct proxy; struct proxy;
template <typename T> template <typename T>
class usertype; class usertype;
template <typename T> template <typename T>
@ -40,16 +47,21 @@ namespace sol {
template <bool b> template <bool b>
using table_core = basic_table_core<b, reference>; using table_core = basic_table_core<b, reference>;
template <bool b> template <bool b>
using main_table_core = basic_table_core<b, main_reference>;
template <bool b>
using stack_table_core = basic_table_core<b, stack_reference>; using stack_table_core = basic_table_core<b, stack_reference>;
template <typename T> template <typename T>
using basic_table = basic_table_core<false, T>; using basic_table = basic_table_core<false, T>;
typedef table_core<false> table; typedef table_core<false> table;
typedef table_core<true> global_table; typedef table_core<true> global_table;
typedef main_table_core<false> main_table;
typedef main_table_core<true> main_global_table;
typedef stack_table_core<false> stack_table; typedef stack_table_core<false> stack_table;
typedef stack_table_core<true> stack_global_table; typedef stack_table_core<true> stack_global_table;
template <typename base_t> template <typename base_t>
struct basic_environment; struct basic_environment;
using environment = basic_environment<reference>; using environment = basic_environment<reference>;
using main_environment = basic_environment<main_reference>;
using stack_environment = basic_environment<stack_reference>; using stack_environment = basic_environment<stack_reference>;
template <typename T, bool> template <typename T, bool>
class basic_function; class basic_function;
@ -57,6 +69,8 @@ namespace sol {
class basic_protected_function; class basic_protected_function;
using unsafe_function = basic_function<reference, false>; using unsafe_function = basic_function<reference, false>;
using safe_function = basic_protected_function<reference, false, reference>; using safe_function = basic_protected_function<reference, false, reference>;
using main_unsafe_function = basic_function<main_reference, false>;
using main_safe_function = basic_protected_function<main_reference, false, reference>;
using stack_unsafe_function = basic_function<stack_reference, false>; using stack_unsafe_function = basic_function<stack_reference, false>;
using stack_safe_function = basic_protected_function<stack_reference, false, reference>; using stack_safe_function = basic_protected_function<stack_reference, false, reference>;
using stack_aligned_unsafe_function = basic_function<stack_reference, true>; using stack_aligned_unsafe_function = basic_function<stack_reference, true>;
@ -66,10 +80,12 @@ namespace sol {
using stack_aligned_protected_function = stack_aligned_safe_function; using stack_aligned_protected_function = stack_aligned_safe_function;
#ifdef SOL_SAFE_FUNCTIONS #ifdef SOL_SAFE_FUNCTIONS
using function = protected_function; using function = protected_function;
using main_function = main_protected_function;
using stack_function = stack_protected_function; using stack_function = stack_protected_function;
using stack_aligned_function = stack_aligned_safe_function; using stack_aligned_function = stack_aligned_safe_function;
#else #else
using function = unsafe_function; using function = unsafe_function;
using main_function = main_unsafe_function;
using stack_function = stack_unsafe_function; using stack_function = stack_unsafe_function;
using stack_aligned_function = stack_aligned_unsafe_function; using stack_aligned_function = stack_aligned_unsafe_function;
#endif #endif
@ -79,25 +95,39 @@ namespace sol {
struct protected_function_result; struct protected_function_result;
using safe_function_result = protected_function_result; using safe_function_result = protected_function_result;
using unsafe_function_result = function_result; using unsafe_function_result = function_result;
template <typename base_t> template <typename base_t>
class basic_object; class basic_object;
template <typename base_t> template <typename base_t>
class basic_userdata; class basic_userdata;
template <typename base_t> template <typename base_t>
class basic_lightuserdata; class basic_lightuserdata;
template <typename base_t>
class basic_coroutine;
template <typename base_t>
class basic_thread;
using object = basic_object<reference>; using object = basic_object<reference>;
using stack_object = basic_object<stack_reference>;
using userdata = basic_userdata<reference>; using userdata = basic_userdata<reference>;
using stack_userdata = basic_userdata<stack_reference>;
using lightuserdata = basic_lightuserdata<reference>; using lightuserdata = basic_lightuserdata<reference>;
using thread = basic_thread<reference>;
using coroutine = basic_coroutine<reference>;
using main_object = basic_object<main_reference>;
using main_userdata = basic_userdata<main_reference>;
using main_lightuserdata = basic_lightuserdata<main_reference>;
using stack_object = basic_object<stack_reference>;
using stack_userdata = basic_userdata<stack_reference>;
using stack_lightuserdata = basic_lightuserdata<stack_reference>; using stack_lightuserdata = basic_lightuserdata<stack_reference>;
class coroutine; using stack_thread = basic_thread<stack_reference>;
class thread; using stack_coroutine = basic_coroutine<stack_reference>;
struct variadic_args; struct variadic_args;
struct variadic_results; struct variadic_results;
struct stack_count; struct stack_count;
struct this_state; struct this_state;
struct this_main_state;
struct this_environment; struct this_environment;
template <typename T> template <typename T>
struct as_table_t; struct as_table_t;
template <typename T> template <typename T>

View File

@ -77,8 +77,8 @@ namespace sol {
template <typename... Args, typename... Ret> template <typename... Args, typename... Ret>
static std::function<Signature> get_std_func(types<Ret...>, types<Args...>, lua_State* L, int index) { static std::function<Signature> get_std_func(types<Ret...>, types<Args...>, lua_State* L, int index) {
sol::function f(L, index); unsafe_function f(L, index);
auto fx = [ f, L, index ](Args && ... args) -> meta::return_type_t<Ret...> { auto fx = [ f = std::move(f), L, index ](Args && ... args) -> meta::return_type_t<Ret...> {
return f.call<Ret...>(std::forward<Args>(args)...); return f.call<Ret...>(std::forward<Args>(args)...);
}; };
return std::move(fx); return std::move(fx);
@ -86,8 +86,8 @@ namespace sol {
template <typename... FxArgs> template <typename... FxArgs>
static std::function<Signature> get_std_func(types<void>, types<FxArgs...>, lua_State* L, int index) { static std::function<Signature> get_std_func(types<void>, types<FxArgs...>, lua_State* L, int index) {
sol::function f(L, index); unsafe_function f(L, index);
auto fx = [f, L, index](FxArgs&&... args) -> void { auto fx = [f = std::move(f), L, index](FxArgs&&... args) -> void {
f(std::forward<FxArgs>(args)...); f(std::forward<FxArgs>(args)...);
}; };
return std::move(fx); return std::move(fx);

View File

@ -196,12 +196,12 @@ namespace sol {
} }
#endif // noexcept function type #endif // noexcept function type
template <typename Fx, typename... Args, meta::disable<meta::any<std::is_base_of<reference, meta::unqualified_t<Fx>>, std::is_base_of<stack_reference, meta::unqualified_t<Fx>>>> = meta::enabler> template <typename Fx, typename... Args, meta::disable<is_lua_reference<meta::unqualified_t<Fx>>> = meta::enabler>
static void select(lua_State* L, Fx&& fx, Args&&... args) { static void select(lua_State* L, Fx&& fx, Args&&... args) {
select_function(std::is_function<std::remove_pointer_t<meta::unqualified_t<Fx>>>(), L, std::forward<Fx>(fx), std::forward<Args>(args)...); select_function(std::is_function<std::remove_pointer_t<meta::unqualified_t<Fx>>>(), L, std::forward<Fx>(fx), std::forward<Args>(args)...);
} }
template <typename Fx, meta::enable<meta::any<std::is_base_of<reference, meta::unqualified_t<Fx>>, std::is_base_of<stack_reference, meta::unqualified_t<Fx>>>> = meta::enabler> template <typename Fx, meta::enable<is_lua_reference<meta::unqualified_t<Fx>>> = meta::enabler>
static void select(lua_State* L, Fx&& fx) { static void select(lua_State* L, Fx&& fx) {
stack::push(L, std::forward<Fx>(fx)); stack::push(L, std::forward<Fx>(fx));
} }
@ -309,10 +309,10 @@ namespace sol {
template <typename F, typename G> template <typename F, typename G>
struct pusher<property_wrapper<F, G>, std::enable_if_t<!std::is_void<F>::value && !std::is_void<G>::value>> { struct pusher<property_wrapper<F, G>, std::enable_if_t<!std::is_void<F>::value && !std::is_void<G>::value>> {
static int push(lua_State* L, property_wrapper<F, G>&& pw) { static int push(lua_State* L, property_wrapper<F, G>&& pw) {
return stack::push(L, sol::overload(std::move(pw.read), std::move(pw.write))); return stack::push(L, overload(std::move(pw.read), std::move(pw.write)));
} }
static int push(lua_State* L, const property_wrapper<F, G>& pw) { static int push(lua_State* L, const property_wrapper<F, G>& pw) {
return stack::push(L, sol::overload(pw.read, pw.write)); return stack::push(L, overload(pw.read, pw.write));
} }
}; };

View File

@ -32,7 +32,7 @@
namespace sol { namespace sol {
template <typename R = reference, bool should_pop = !std::is_base_of<stack_reference, R>::value, typename T> template <typename R = reference, bool should_pop = !is_stack_based<R>::value, typename T>
R make_reference(lua_State* L, T&& value) { R make_reference(lua_State* L, T&& value) {
int backpedal = stack::push(L, std::forward<T>(value)); int backpedal = stack::push(L, std::forward<T>(value));
R r = stack::get<R>(L, -backpedal); R r = stack::get<R>(L, -backpedal);
@ -42,7 +42,7 @@ namespace sol {
return r; return r;
} }
template <typename T, typename R = reference, bool should_pop = !std::is_base_of<stack_reference, R>::value, typename... Args> template <typename T, typename R = reference, bool should_pop = !is_stack_based<R>::value, typename... Args>
R make_reference(lua_State* L, Args&&... args) { R make_reference(lua_State* L, Args&&... args) {
int backpedal = stack::push<T>(L, std::forward<Args>(args)...); int backpedal = stack::push<T>(L, std::forward<Args>(args)...);
R r = stack::get<R>(L, -backpedal); R r = stack::get<R>(L, -backpedal);
@ -71,7 +71,7 @@ namespace sol {
basic_object(T&& r) basic_object(T&& r)
: base_t(std::forward<T>(r)) { : base_t(std::forward<T>(r)) {
} }
template <typename T, meta::enable_any<std::is_base_of<reference, meta::unqualified_t<T>>, std::is_base_of<stack_reference, meta::unqualified_t<T>>> = meta::enabler> template <typename T, meta::enable<is_lua_reference<meta::unqualified_t<T>>> = meta::enabler>
basic_object(lua_State* L, T&& r) basic_object(lua_State* L, T&& r)
: base_t(L, std::forward<T>(r)) { : base_t(L, std::forward<T>(r)) {
} }
@ -111,7 +111,7 @@ namespace sol {
} }
template <typename T, typename... Args> template <typename T, typename... Args>
basic_object(lua_State* L, in_place_type_t<T>, Args&&... args) noexcept basic_object(lua_State* L, in_place_type_t<T>, Args&&... args) noexcept
: basic_object(std::integral_constant<bool, !std::is_base_of<stack_reference, base_t>::value>(), L, -stack::push<T>(L, std::forward<Args>(args)...)) { : basic_object(std::integral_constant<bool, !is_stack_based<base_t>::value>(), L, -stack::push<T>(L, std::forward<Args>(args)...)) {
} }
template <typename T, typename... Args> template <typename T, typename... Args>
basic_object(lua_State* L, in_place_t, T&& arg, Args&&... args) noexcept basic_object(lua_State* L, in_place_t, T&& arg, Args&&... args) noexcept

View File

@ -38,7 +38,7 @@ namespace sol {
template <bool b, typename target_t = reference> template <bool b, typename target_t = reference>
struct protected_handler { struct protected_handler {
typedef std::is_base_of<stack_reference, target_t> is_stack; typedef is_stack_based<target_t> is_stack;
const target_t& target; const target_t& target;
int stackindex; int stackindex;
@ -81,11 +81,12 @@ namespace sol {
template <typename base_t, bool aligned = false, typename handler_t = reference> template <typename base_t, bool aligned = false, typename handler_t = reference>
class basic_protected_function : public base_t { class basic_protected_function : public base_t {
public: public:
typedef std::is_base_of<stack_reference, handler_t> is_stack_handler; typedef is_stack_based<handler_t> is_stack_handler;
static handler_t get_default_handler(lua_State* L) { static handler_t get_default_handler(lua_State* L) {
if (is_stack_handler::value || L == nullptr) if (is_stack_handler::value || L == nullptr)
return handler_t(L, lua_nil); return handler_t(L, lua_nil);
L = is_main_threaded<base_t>::value ? main_thread(L, L) : L;
lua_getglobal(L, detail::default_handler_name()); lua_getglobal(L, detail::default_handler_name());
auto pp = stack::pop_n(L, 1); auto pp = stack::pop_n(L, 1);
return handler_t(L, -1); return handler_t(L, -1);
@ -96,13 +97,14 @@ namespace sol {
if (ref.lua_state() == nullptr) { if (ref.lua_state() == nullptr) {
return; return;
} }
lua_State* L = ref.lua_state();
if (!ref.valid()) { if (!ref.valid()) {
lua_pushnil(ref.lua_state()); lua_pushnil(L);
lua_setglobal(ref.lua_state(), detail::default_handler_name()); lua_setglobal(L, detail::default_handler_name());
} }
else { else {
ref.push(); ref.push();
lua_setglobal(ref.lua_state(), detail::default_handler_name()); lua_setglobal(L, detail::default_handler_name());
} }
} }
@ -235,11 +237,11 @@ namespace sol {
: basic_protected_function(detail::force_cast<base_t>(p), std::forward<Handler>(eh)) { : basic_protected_function(detail::force_cast<base_t>(p), std::forward<Handler>(eh)) {
} }
template <typename T, meta::enable<std::is_base_of<reference, meta::unqualified_t<T>>, std::is_base_of<stack_reference, meta::unqualified_t<T>>> = meta::enabler> template <typename T, meta::enable<is_lua_reference<meta::unqualified_t<T>>> = meta::enabler>
basic_protected_function(lua_State* L, T&& r) basic_protected_function(lua_State* L, T&& r)
: basic_protected_function(L, std::forward<T>(r), get_default_handler(L)) { : basic_protected_function(L, std::forward<T>(r), get_default_handler(L)) {
} }
template <typename T, meta::enable_any<std::is_base_of<reference, meta::unqualified_t<T>>, std::is_base_of<stack_reference, meta::unqualified_t<T>>> = meta::enabler> template <typename T, meta::enable<is_lua_reference<meta::unqualified_t<T>>> = meta::enabler>
basic_protected_function(lua_State* L, T&& r, handler_t eh) basic_protected_function(lua_State* L, T&& r, handler_t eh)
: base_t(L, std::forward<T>(r)), error_handler(std::move(eh)) { : base_t(L, std::forward<T>(r)), error_handler(std::move(eh)) {
} }
@ -251,7 +253,7 @@ namespace sol {
: base_t(L, index), error_handler(std::move(eh)) { : base_t(L, index), error_handler(std::move(eh)) {
#ifdef SOL_CHECK_ARGUMENTS #ifdef SOL_CHECK_ARGUMENTS
constructor_handler handler{}; constructor_handler handler{};
stack::check<basic_protected_function>(L, index, handler); stack::check<basic_protected_function>(lua_state(), index, handler);
#endif // Safety #endif // Safety
} }
basic_protected_function(lua_State* L, absolute_index index) basic_protected_function(lua_State* L, absolute_index index)
@ -261,7 +263,7 @@ namespace sol {
: base_t(L, index), error_handler(std::move(eh)) { : base_t(L, index), error_handler(std::move(eh)) {
#ifdef SOL_CHECK_ARGUMENTS #ifdef SOL_CHECK_ARGUMENTS
constructor_handler handler{}; constructor_handler handler{};
stack::check<basic_protected_function>(L, index, handler); stack::check<basic_protected_function>(lua_state(), index, handler);
#endif // Safety #endif // Safety
} }
basic_protected_function(lua_State* L, raw_index index) basic_protected_function(lua_State* L, raw_index index)
@ -271,7 +273,7 @@ namespace sol {
: base_t(L, index), error_handler(std::move(eh)) { : base_t(L, index), error_handler(std::move(eh)) {
#ifdef SOL_CHECK_ARGUMENTS #ifdef SOL_CHECK_ARGUMENTS
constructor_handler handler{}; constructor_handler handler{};
stack::check<basic_protected_function>(L, index, handler); stack::check<basic_protected_function>(lua_state(), index, handler);
#endif // Safety #endif // Safety
} }
basic_protected_function(lua_State* L, ref_index index) basic_protected_function(lua_State* L, ref_index index)

View File

@ -77,12 +77,12 @@ namespace sol {
return *this; return *this;
} }
template <typename U, meta::enable<meta::neg<is_lua_reference<meta::unwrap_unqualified_t<U>>>, meta::is_callable<meta::unwrap_unqualified_t<U>>> = meta::enabler> template <typename U, meta::enable<meta::neg<is_lua_reference_or_proxy<meta::unwrap_unqualified_t<U>>>, meta::is_callable<meta::unwrap_unqualified_t<U>>> = meta::enabler>
proxy& operator=(U&& other) { proxy& operator=(U&& other) {
return set_function(std::forward<U>(other)); return set_function(std::forward<U>(other));
} }
template <typename U, meta::disable<meta::neg<is_lua_reference<meta::unwrap_unqualified_t<U>>>, meta::is_callable<meta::unwrap_unqualified_t<U>>> = meta::enabler> template <typename U, meta::disable<meta::neg<is_lua_reference_or_proxy<meta::unwrap_unqualified_t<U>>>, meta::is_callable<meta::unwrap_unqualified_t<U>>> = meta::enabler>
proxy& operator=(U&& other) { proxy& operator=(U&& other) {
return set(std::forward<U>(other)); return set(std::forward<U>(other));
} }
@ -194,11 +194,25 @@ namespace sol {
return right.valid(); return right.valid();
} }
template <bool b>
template <typename Super>
basic_reference<b>& basic_reference<b>::operator=(proxy_base<Super>&& r) {
*this = r.template operator basic_reference<b>();
return *this;
}
template <bool b>
template <typename Super>
basic_reference<b>& basic_reference<b>::operator=(const proxy_base<Super>& r) {
*this = r.template operator basic_reference<b>();
return *this;
}
namespace stack { namespace stack {
template <typename Table, typename Key> template <typename Table, typename Key>
struct pusher<proxy<Table, Key>> { struct pusher<proxy<Table, Key>> {
static int push(lua_State* L, const proxy<Table, Key>& p) { static int push(lua_State* L, const proxy<Table, Key>& p) {
sol::reference r = p; reference r = p;
return r.push(L); return r.push(L);
} }
}; };

View File

@ -152,10 +152,23 @@ namespace sol {
} const global_{}; } const global_{};
struct no_safety_tag { struct no_safety_tag {
} const no_safety{}; } const no_safety{};
template <bool b>
inline lua_State* pick_main_thread(lua_State* L, lua_State* backup_if_unsupported = nullptr) {
(void)L;
(void)backup_if_unsupported;
if (b) {
return main_thread(L, backup_if_unsupported);
}
return L;
}
} // namespace detail } // namespace detail
class reference { template <bool main_only = false>
class basic_reference {
private: private:
template <bool o_main_only>
friend class basic_reference;
lua_State* luastate = nullptr; // non-owning lua_State* luastate = nullptr; // non-owning
int ref = LUA_NOREF; int ref = LUA_NOREF;
@ -166,9 +179,58 @@ namespace sol {
return luaL_ref(lua_state(), LUA_REGISTRYINDEX); return luaL_ref(lua_state(), LUA_REGISTRYINDEX);
} }
template <bool r_main_only>
void copy_assign(const basic_reference<r_main_only>& r) {
if (valid()) {
deref();
}
if (r.ref == LUA_REFNIL) {
luastate = detail::pick_main_thread < main_only && !r_main_only >(r.lua_state(), r.lua_state());
ref = LUA_REFNIL;
return;
}
if (r.ref == LUA_NOREF) {
ref = LUA_NOREF;
return;
}
if (detail::xmovable(lua_state(), r.lua_state())) {
r.push(lua_state());
ref = luaL_ref(lua_state(), LUA_REGISTRYINDEX);
return;
}
luastate = detail::pick_main_thread < main_only && !r_main_only >(r.lua_state(), r.lua_state());
ref = r.copy();
}
template <bool r_main_only>
void move_assign(basic_reference<r_main_only>&& r) {
if (valid()) {
deref();
}
if (r.ref == LUA_REFNIL) {
luastate = detail::pick_main_thread<main_only && !r_main_only>(r.lua_state(), r.lua_state());
ref = LUA_REFNIL;
return;
}
if (r.ref == LUA_NOREF) {
ref = LUA_NOREF;
return;
}
if (detail::xmovable(lua_state(), r.lua_state())) {
r.push(lua_state());
ref = luaL_ref(lua_state(), LUA_REGISTRYINDEX);
return;
}
luastate = detail::pick_main_thread < main_only && !r_main_only >(r.lua_state(), r.lua_state());
ref = r.ref;
r.ref = LUA_NOREF;
r.luastate = nullptr;
}
protected: protected:
reference(lua_State* L, detail::global_tag) noexcept basic_reference(lua_State* L, detail::global_tag) noexcept
: luastate(L) { : luastate(detail::pick_main_thread<main_only>(L, L)) {
lua_pushglobaltable(lua_state()); lua_pushglobaltable(lua_state());
ref = luaL_ref(lua_state(), LUA_REGISTRYINDEX); ref = luaL_ref(lua_state(), LUA_REGISTRYINDEX);
} }
@ -182,18 +244,19 @@ namespace sol {
} }
public: public:
reference() noexcept = default; basic_reference() noexcept = default;
reference(lua_nil_t) noexcept basic_reference(lua_nil_t) noexcept
: reference() { : basic_reference() {
} }
reference(const stack_reference& r) noexcept basic_reference(const stack_reference& r) noexcept
: reference(r.lua_state(), r.stack_index()) { : basic_reference(r.lua_state(), r.stack_index()) {
} }
reference(stack_reference&& r) noexcept basic_reference(stack_reference&& r) noexcept
: reference(r.lua_state(), r.stack_index()) { : basic_reference(r.lua_state(), r.stack_index()) {
} }
reference(lua_State* L, const reference& r) noexcept template <bool r_main_only>
: luastate(L) { basic_reference(lua_State* L, const basic_reference<r_main_only>& r) noexcept
: luastate(detail::pick_main_thread<main_only>(L, L)) {
if (r.ref == LUA_REFNIL) { if (r.ref == LUA_REFNIL) {
ref = LUA_REFNIL; ref = LUA_REFNIL;
return; return;
@ -209,8 +272,10 @@ namespace sol {
} }
ref = r.copy(); ref = r.copy();
} }
reference(lua_State* L, reference&& r) noexcept
: luastate(L) { template <bool r_main_only>
basic_reference(lua_State* L, basic_reference<r_main_only>&& r) noexcept
: luastate(detail::pick_main_thread<main_only>(L, L)) {
if (r.ref == LUA_REFNIL) { if (r.ref == LUA_REFNIL) {
ref = LUA_REFNIL; ref = LUA_REFNIL;
return; return;
@ -228,8 +293,9 @@ namespace sol {
r.ref = LUA_NOREF; r.ref = LUA_NOREF;
r.luastate = nullptr; r.luastate = nullptr;
} }
reference(lua_State* L, const stack_reference& r) noexcept
: luastate(L) { basic_reference(lua_State* L, const stack_reference& r) noexcept
: luastate(detail::pick_main_thread<main_only>(L, L)) {
if (lua_state() == nullptr || r.lua_state() == nullptr || r.get_type() == type::none) { if (lua_state() == nullptr || r.lua_state() == nullptr || r.get_type() == type::none) {
ref = LUA_NOREF; ref = LUA_NOREF;
return; return;
@ -244,83 +310,72 @@ namespace sol {
r.push(lua_state()); r.push(lua_state());
ref = luaL_ref(lua_state(), LUA_REGISTRYINDEX); ref = luaL_ref(lua_state(), LUA_REGISTRYINDEX);
} }
reference(lua_State* L, int index = -1) noexcept basic_reference(lua_State* L, int index = -1) noexcept
: luastate(L) { : luastate(detail::pick_main_thread<main_only>(L, L)) {
lua_pushvalue(lua_state(), index); lua_pushvalue(lua_state(), index);
ref = luaL_ref(lua_state(), LUA_REGISTRYINDEX); ref = luaL_ref(lua_state(), LUA_REGISTRYINDEX);
} }
reference(lua_State* L, ref_index index) noexcept basic_reference(lua_State* L, ref_index index) noexcept
: luastate(L) { : luastate(detail::pick_main_thread<main_only>(L, L)) {
lua_rawgeti(L, LUA_REGISTRYINDEX, index.index); lua_rawgeti(lua_state(), LUA_REGISTRYINDEX, index.index);
ref = luaL_ref(lua_state(), LUA_REGISTRYINDEX); ref = luaL_ref(lua_state(), LUA_REGISTRYINDEX);
} }
reference(lua_State* L, lua_nil_t) noexcept basic_reference(lua_State* L, lua_nil_t) noexcept
: luastate(L) { : luastate(detail::pick_main_thread<main_only>(L, L)) {
} }
~reference() noexcept { ~basic_reference() noexcept {
if (lua_state() == nullptr || ref == LUA_NOREF)
return;
deref(); deref();
} }
reference(const reference& o) noexcept basic_reference(const basic_reference& o) noexcept
: luastate(o.luastate), ref(o.copy()) { : luastate(o.lua_state()), ref(o.copy()) {
} }
reference(reference&& o) noexcept basic_reference(basic_reference&& o) noexcept
: luastate(o.luastate), ref(o.ref) { : luastate(o.lua_state()), ref(o.ref) {
o.luastate = nullptr; o.luastate = nullptr;
o.ref = LUA_NOREF; o.ref = LUA_NOREF;
} }
reference& operator=(reference&& r) noexcept { basic_reference(const basic_reference<!main_only>& o) noexcept
if (valid()) { : luastate(detail::pick_main_thread<main_only && !main_only>(o.lua_state(), o.lua_state())), ref(o.copy()) {
deref(); }
}
if (r.ref == LUA_REFNIL) {
luastate = r.lua_state();
ref = LUA_REFNIL;
return *this;
}
if (r.ref == LUA_NOREF) {
ref = LUA_NOREF;
return *this;
}
if (detail::xmovable(lua_state(), r.lua_state())) {
r.push(lua_state());
ref = luaL_ref(lua_state(), LUA_REGISTRYINDEX);
return *this;
}
luastate = r.lua_state(); basic_reference(basic_reference<!main_only>&& o) noexcept
ref = r.ref; : luastate(detail::pick_main_thread<main_only && !main_only>(o.lua_state(), o.lua_state())), ref(o.ref) {
r.ref = LUA_NOREF; o.luastate = nullptr;
r.luastate = nullptr; o.ref = LUA_NOREF;
}
basic_reference& operator=(basic_reference&& r) noexcept {
move_assign(std::move(r));
return *this; return *this;
} }
reference& operator=(const reference& r) noexcept { basic_reference& operator=(const basic_reference& r) noexcept {
if (valid()) { copy_assign(r);
deref();
}
if (r.ref == LUA_REFNIL) {
luastate = r.lua_state();
ref = LUA_REFNIL;
return *this;
}
if (r.ref == LUA_NOREF) {
ref = LUA_NOREF;
return *this;
}
if (detail::xmovable(lua_state(), r.lua_state())) {
r.push(lua_state());
ref = luaL_ref(lua_state(), LUA_REGISTRYINDEX);
return *this;
}
luastate = r.lua_state();
ref = r.copy();
return *this; return *this;
} }
basic_reference& operator=(basic_reference<!main_only>&& r) noexcept {
move_assign(std::move(r));
return *this;
}
basic_reference& operator=(const basic_reference<!main_only>& r) noexcept {
copy_assign(r);
return *this;
}
template <typename Super>
basic_reference& operator=(proxy_base<Super>&& r);
template <typename Super>
basic_reference& operator=(const proxy_base<Super>& r);
int push() const noexcept { int push() const noexcept {
return push(lua_state()); return push(lua_state());
} }
@ -368,29 +423,35 @@ namespace sol {
} }
}; };
inline bool operator==(const reference& l, const reference& r) { template <bool lb, bool rb>
inline bool operator==(const basic_reference<lb>& l, const basic_reference<rb>& r) {
auto ppl = stack::push_pop(l); auto ppl = stack::push_pop(l);
auto ppr = stack::push_pop(r); auto ppr = stack::push_pop(r);
return lua_compare(l.lua_state(), -1, -2, LUA_OPEQ) == 1; return lua_compare(l.lua_state(), -1, -2, LUA_OPEQ) == 1;
} }
inline bool operator!=(const reference& l, const reference& r) { template <bool lb, bool rb>
inline bool operator!=(const basic_reference<lb>& l, const basic_reference<rb>& r) {
return !operator==(l, r); return !operator==(l, r);
} }
inline bool operator==(const reference& lhs, const lua_nil_t&) { template <bool lb>
inline bool operator==(const basic_reference<lb>& lhs, const lua_nil_t&) {
return !lhs.valid(); return !lhs.valid();
} }
inline bool operator==(const lua_nil_t&, const reference& rhs) { template <bool rb>
inline bool operator==(const lua_nil_t&, const basic_reference<rb>& rhs) {
return !rhs.valid(); return !rhs.valid();
} }
inline bool operator!=(const reference& lhs, const lua_nil_t&) { template <bool lb>
inline bool operator!=(const basic_reference<lb>& lhs, const lua_nil_t&) {
return lhs.valid(); return lhs.valid();
} }
inline bool operator!=(const lua_nil_t&, const reference& rhs) { template <bool rb>
inline bool operator!=(const lua_nil_t&, const basic_reference<rb>& rhs) {
return rhs.valid(); return rhs.valid();
} }
} // namespace sol } // namespace sol

View File

@ -77,7 +77,7 @@ namespace sol {
} }
auto fit = functions.find(accessorkey); auto fit = functions.find(accessorkey);
if (fit != functions.cend()) { if (fit != functions.cend()) {
sol::object& func = fit->second; object& func = fit->second;
if (is_index) { if (is_index) {
return stack::push(L, func); return stack::push(L, func);
} }
@ -525,7 +525,7 @@ namespace sol {
stack_reference metabehind(L, -1); stack_reference metabehind(L, -1);
stack::set_field(L, meta_function::type, type_table, metabehind.stack_index()); stack::set_field(L, meta_function::type, type_table, metabehind.stack_index());
if (umx.callconstructfunc.valid()) { if (umx.callconstructfunc.valid()) {
stack::set_field(L, sol::meta_function::call_function, umx.callconstructfunc, metabehind.stack_index()); stack::set_field(L, meta_function::call_function, umx.callconstructfunc, metabehind.stack_index());
} }
if (umx.secondarymeta) { if (umx.secondarymeta) {
stack::set_field(L, meta_function::index, stack::set_field(L, meta_function::index,
@ -560,7 +560,7 @@ namespace sol {
stack_reference metabehind(L, -1); stack_reference metabehind(L, -1);
stack::set_field(L, meta_function::type, type_table, metabehind.stack_index()); stack::set_field(L, meta_function::type, type_table, metabehind.stack_index());
if (umx.callconstructfunc.valid()) { if (umx.callconstructfunc.valid()) {
stack::set_field(L, sol::meta_function::call_function, umx.callconstructfunc, metabehind.stack_index()); stack::set_field(L, meta_function::call_function, umx.callconstructfunc, metabehind.stack_index());
} }
// use indexing function // use indexing function
stack::set_field(L, meta_function::index, stack::set_field(L, meta_function::index,

View File

@ -78,7 +78,7 @@ namespace sol {
const static std::size_t data_t_count = (sizeof(TValue) + voidsizem1) / voidsize; const static std::size_t data_t_count = (sizeof(TValue) + voidsizem1) / voidsize;
typedef std::array<void*, data_t_count> data_t; typedef std::array<void*, data_t_count> data_t;
data_t data{{}}; data_t data{ {} };
std::memcpy(&data[0], std::addressof(item), itemsize); std::memcpy(&data[0], std::addressof(item), itemsize);
int pushcount = 0; int pushcount = 0;
for (auto&& v : data) { for (auto&& v : data) {
@ -91,7 +91,7 @@ namespace sol {
inline std::pair<T, int> get_as_upvalues(lua_State* L, int index = 2) { inline std::pair<T, int> get_as_upvalues(lua_State* L, int index = 2) {
const static std::size_t data_t_count = (sizeof(T) + (sizeof(void*) - 1)) / sizeof(void*); const static std::size_t data_t_count = (sizeof(T) + (sizeof(void*) - 1)) / sizeof(void*);
typedef std::array<void*, data_t_count> data_t; typedef std::array<void*, data_t_count> data_t;
data_t voiddata{{}}; data_t voiddata{ {} };
for (std::size_t i = 0, d = 0; d < sizeof(T); ++i, d += sizeof(void*)) { for (std::size_t i = 0, d = 0; d < sizeof(T); ++i, d += sizeof(void*)) {
voiddata[i] = get<lightuserdata_value>(L, upvalue_index(index++)); voiddata[i] = get<lightuserdata_value>(L, upvalue_index(index++));
} }
@ -185,7 +185,12 @@ namespace sol {
template <bool check_args = stack_detail::default_check_arguments, bool clean_stack = true, typename Ret0, typename... Ret, typename... Args, typename Fx, typename... FxArgs, typename = std::enable_if_t<meta::neg<std::is_void<Ret0>>::value>> template <bool check_args = stack_detail::default_check_arguments, bool clean_stack = true, typename Ret0, typename... Ret, typename... Args, typename Fx, typename... FxArgs, typename = std::enable_if_t<meta::neg<std::is_void<Ret0>>::value>>
inline int call_into_lua(types<Ret0, Ret...>, types<Args...> ta, lua_State* L, int start, Fx&& fx, FxArgs&&... fxargs) { inline int call_into_lua(types<Ret0, Ret...>, types<Args...> ta, lua_State* L, int start, Fx&& fx, FxArgs&&... fxargs) {
decltype(auto) r = call<check_args>(types<meta::return_type_t<Ret0, Ret...>>(), ta, L, start, std::forward<Fx>(fx), std::forward<FxArgs>(fxargs)...); decltype(auto) r = call<check_args>(types<meta::return_type_t<Ret0, Ret...>>(), ta, L, start, std::forward<Fx>(fx), std::forward<FxArgs>(fxargs)...);
typedef is_stack_based<meta::unqualified_t<decltype(r)>> is_stack; typedef meta::unqualified_t<decltype(r)> R;
typedef meta::any<is_stack_based<R>,
std::is_same<R, absolute_index>,
std::is_same<R, ref_index>,
std::is_same<R, raw_index>>
is_stack;
if (clean_stack && !is_stack::value) { if (clean_stack && !is_stack::value) {
lua_settop(L, 0); lua_settop(L, 0);
} }

View File

@ -184,6 +184,15 @@ namespace stack {
} }
}; };
template <typename C>
struct checker<this_main_state, type::poly, C> {
template <typename Handler>
static bool check(lua_State*, int, Handler&&, record& tracking) {
tracking.use(0);
return true;
}
};
template <typename C> template <typename C>
struct checker<this_environment, type::poly, C> { struct checker<this_environment, type::poly, C> {
template <typename Handler> template <typename Handler>

View File

@ -245,7 +245,7 @@ namespace sol {
template <typename T, typename... Args> template <typename T, typename... Args>
inline int multi_push(lua_State* L, T&& t, Args&&... args) { inline int multi_push(lua_State* L, T&& t, Args&&... args) {
int pushcount = push(L, std::forward<T>(t)); int pushcount = push(L, std::forward<T>(t));
void(sol::detail::swallow{(pushcount += sol::stack::push(L, std::forward<Args>(args)), 0)...}); void(detail::swallow{(pushcount += stack::push(L, std::forward<Args>(args)), 0)...});
return pushcount; return pushcount;
} }
@ -257,7 +257,7 @@ namespace sol {
template <typename T, typename... Args> template <typename T, typename... Args>
inline int multi_push_reference(lua_State* L, T&& t, Args&&... args) { inline int multi_push_reference(lua_State* L, T&& t, Args&&... args) {
int pushcount = push_reference(L, std::forward<T>(t)); int pushcount = push_reference(L, std::forward<T>(t));
void(sol::detail::swallow{(pushcount += sol::stack::push_reference(L, std::forward<Args>(args)), 0)...}); void(detail::swallow{(pushcount += stack::push_reference(L, std::forward<Args>(args)), 0)...});
return pushcount; return pushcount;
} }

View File

@ -330,7 +330,7 @@ namespace stack {
}; };
template <typename T> template <typename T>
struct getter<T, std::enable_if_t<std::is_base_of<reference, T>::value || std::is_base_of<stack_reference, T>::value>> { struct getter<T, std::enable_if_t<is_lua_reference<T>::value>> {
static T get(lua_State* L, int index, record& tracking) { static T get(lua_State* L, int index, record& tracking) {
tracking.use(1); tracking.use(1);
return T(L, index); return T(L, index);
@ -569,7 +569,15 @@ namespace stack {
struct getter<this_state> { struct getter<this_state> {
static this_state get(lua_State* L, int, record& tracking) { static this_state get(lua_State* L, int, record& tracking) {
tracking.use(0); tracking.use(0);
return this_state{L}; return this_state( L );
}
};
template <>
struct getter<this_main_state> {
static this_main_state get(lua_State* L, int, record& tracking) {
tracking.use(0);
return this_main_state( main_thread(L, L) );
} }
}; };

View File

@ -137,7 +137,7 @@ namespace stack {
}; };
template <typename T> template <typename T>
struct pusher<T*, meta::disable_if_t<meta::any<is_container<meta::unqualified_t<T>>, std::is_function<meta::unqualified_t<T>>, std::is_base_of<reference, meta::unqualified_t<T>>, std::is_base_of<stack_reference, meta::unqualified_t<T>>>::value>> { struct pusher<T*, meta::disable_if_t<meta::any<is_container<meta::unqualified_t<T>>, std::is_function<meta::unqualified_t<T>>, is_lua_reference<meta::unqualified_t<T>>>::value>> {
template <typename... Args> template <typename... Args>
static int push(lua_State* L, Args&&... args) { static int push(lua_State* L, Args&&... args) {
return pusher<detail::as_pointer_tag<T>>{}.push(L, std::forward<Args>(args)...); return pusher<detail::as_pointer_tag<T>>{}.push(L, std::forward<Args>(args)...);
@ -315,7 +315,7 @@ namespace stack {
}; };
template <typename T> template <typename T>
struct pusher<T, std::enable_if_t<std::is_base_of<reference, T>::value || std::is_base_of<stack_reference, T>::value>> { struct pusher<T, std::enable_if_t<is_lua_reference<T>::value>> {
static int push(lua_State* L, const T& ref) { static int push(lua_State* L, const T& ref) {
return ref.push(L); return ref.push(L);
} }
@ -852,6 +852,13 @@ namespace stack {
} }
}; };
template <>
struct pusher<this_main_state> {
static int push(lua_State*, const this_main_state&) {
return 0;
}
};
template <> template <>
struct pusher<new_table> { struct pusher<new_table> {
static int push(lua_State* L, const new_table& nt) { static int push(lua_State* L, const new_table& nt) {

View File

@ -72,7 +72,7 @@ namespace sol {
: unique_base(luaL_newstate(), lua_close), state_view(unique_base::get()) { : unique_base(luaL_newstate(), lua_close), state_view(unique_base::get()) {
set_panic(panic); set_panic(panic);
lua_CFunction f = c_call<decltype(&detail::default_traceback_error_handler), &detail::default_traceback_error_handler>; lua_CFunction f = c_call<decltype(&detail::default_traceback_error_handler), &detail::default_traceback_error_handler>;
protected_function::set_default_handler(sol::object(lua_state(), in_place, f)); protected_function::set_default_handler(object(lua_state(), in_place, f));
stack::register_main_thread(unique_base::get()); stack::register_main_thread(unique_base::get());
stack::luajit_exception_handler(unique_base::get()); stack::luajit_exception_handler(unique_base::get());
} }
@ -81,7 +81,7 @@ namespace sol {
: unique_base(lua_newstate(alfunc, alpointer), lua_close), state_view(unique_base::get()) { : unique_base(lua_newstate(alfunc, alpointer), lua_close), state_view(unique_base::get()) {
set_panic(panic); set_panic(panic);
lua_CFunction f = c_call<decltype(&detail::default_traceback_error_handler), &detail::default_traceback_error_handler>; lua_CFunction f = c_call<decltype(&detail::default_traceback_error_handler), &detail::default_traceback_error_handler>;
protected_function::set_default_handler(sol::object(lua_state(), in_place, f)); protected_function::set_default_handler(object(lua_state(), in_place, f));
stack::register_main_thread(unique_base::get()); stack::register_main_thread(unique_base::get());
stack::luajit_exception_handler(unique_base::get()); stack::luajit_exception_handler(unique_base::get());
} }

View File

@ -67,7 +67,7 @@ namespace sol {
return kb; return kb;
} }
inline protected_function_result script_pass_on_error(lua_State*, sol::protected_function_result result) { inline protected_function_result script_pass_on_error(lua_State*, protected_function_result result) {
return result; return result;
} }
@ -377,7 +377,7 @@ namespace sol {
} }
template <typename E> template <typename E>
function_result unsafe_script(const string_view& code, const sol::basic_environment<E>& env, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) { function_result unsafe_script(const string_view& code, const basic_environment<E>& env, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) {
detail::typical_chunk_name_t basechunkname = {}; detail::typical_chunk_name_t basechunkname = {};
const char* chunknametarget = detail::make_chunk_name(code, chunkname, basechunkname); const char* chunknametarget = detail::make_chunk_name(code, chunkname, basechunkname);
int index = lua_gettop(L); int index = lua_gettop(L);
@ -402,7 +402,7 @@ namespace sol {
} }
template <typename E> template <typename E>
function_result unsafe_script_file(const std::string& filename, const sol::basic_environment<E>& env, load_mode mode = load_mode::any) { function_result unsafe_script_file(const std::string& filename, const basic_environment<E>& env, load_mode mode = load_mode::any) {
int index = lua_gettop(L); int index = lua_gettop(L);
if (luaL_loadfilex(L, filename.c_str(), to_string(mode).c_str())) { if (luaL_loadfilex(L, filename.c_str(), to_string(mode).c_str())) {
lua_error(L); lua_error(L);

View File

@ -73,9 +73,9 @@ namespace sol {
auto pp = stack::push_pop(*this); auto pp = stack::push_pop(*this);
stack::push(base_t::lua_state(), lua_nil); stack::push(base_t::lua_state(), lua_nil);
while (lua_next(base_t::lua_state(), -2)) { while (lua_next(base_t::lua_state(), -2)) {
sol::object key(base_t::lua_state(), -2); object key(base_t::lua_state(), -2);
sol::object value(base_t::lua_state(), -1); object value(base_t::lua_state(), -1);
std::pair<sol::object&, sol::object&> keyvalue(key, value); std::pair<object&, object&> keyvalue(key, value);
auto pn = stack::pop_n(base_t::lua_state(), 1); auto pn = stack::pop_n(base_t::lua_state(), 1);
fx(keyvalue); fx(keyvalue);
} }
@ -86,8 +86,8 @@ namespace sol {
auto pp = stack::push_pop(*this); auto pp = stack::push_pop(*this);
stack::push(base_t::lua_state(), lua_nil); stack::push(base_t::lua_state(), lua_nil);
while (lua_next(base_t::lua_state(), -2)) { while (lua_next(base_t::lua_state(), -2)) {
sol::object key(base_t::lua_state(), -2); object key(base_t::lua_state(), -2);
sol::object value(base_t::lua_state(), -1); object value(base_t::lua_state(), -1);
auto pn = stack::pop_n(base_t::lua_state(), 1); auto pn = stack::pop_n(base_t::lua_state(), 1);
fx(key, value); fx(key, value);
} }
@ -204,13 +204,13 @@ namespace sol {
basic_table_core(stack_reference&& r) basic_table_core(stack_reference&& r)
: basic_table_core(r.lua_state(), r.stack_index()) { : basic_table_core(r.lua_state(), r.stack_index()) {
} }
template <typename T, meta::enable_any<std::is_base_of<reference, meta::unqualified_t<T>>, std::is_base_of<stack_reference, meta::unqualified_t<T>>> = meta::enabler> template <typename T, meta::enable_any<is_lua_reference<meta::unqualified_t<T>>> = meta::enabler>
basic_table_core(lua_State* L, T&& r) basic_table_core(lua_State* L, T&& r)
: basic_table_core(L, std::forward<T>(r)) { : basic_table_core(L, std::forward<T>(r)) {
} }
basic_table_core(lua_State* L, new_table nt) basic_table_core(lua_State* L, new_table nt)
: base_t(L, (lua_createtable(L, nt.sequence_hint, nt.map_hint), -1)) { : base_t(L, (lua_createtable(L, nt.sequence_hint, nt.map_hint), -1)) {
if (!std::is_base_of<stack_reference, base_type>::value) { if (!is_stack_based<meta::unqualified_t<base_type>>::value) {
lua_pop(L, 1); lua_pop(L, 1);
} }
} }
@ -454,7 +454,7 @@ namespace sol {
template <typename Fx> template <typename Fx>
void for_each(Fx&& fx) const { void for_each(Fx&& fx) const {
typedef meta::is_invokable<Fx(std::pair<sol::object, sol::object>)> is_paired; typedef meta::is_invokable<Fx(std::pair<object, object>)> is_paired;
for_each(is_paired(), std::forward<Fx>(fx)); for_each(is_paired(), std::forward<Fx>(fx));
} }

View File

@ -29,6 +29,10 @@ namespace sol {
struct lua_thread_state { struct lua_thread_state {
lua_State* L; lua_State* L;
lua_thread_state(lua_State* Ls)
: L(Ls) {
}
lua_State* lua_state() const noexcept { lua_State* lua_state() const noexcept {
return L; return L;
} }
@ -53,7 +57,7 @@ namespace sol {
struct getter<lua_thread_state> { struct getter<lua_thread_state> {
lua_thread_state get(lua_State* L, int index, record& tracking) { lua_thread_state get(lua_State* L, int index, record& tracking) {
tracking.use(1); tracking.use(1);
lua_thread_state lts{lua_tothread(L, index)}; lua_thread_state lts( lua_tothread(L, index) );
return lts; return lts;
} }
}; };
@ -62,8 +66,8 @@ namespace sol {
struct check_getter<lua_thread_state> { struct check_getter<lua_thread_state> {
template <typename Handler> template <typename Handler>
optional<lua_thread_state> get(lua_State* L, int index, Handler&& handler, record& tracking) { optional<lua_thread_state> get(lua_State* L, int index, Handler&& handler, record& tracking) {
lua_thread_state lts{lua_tothread(L, index)}; lua_thread_state lts( lua_tothread(L, index) );
if (lts.L == nullptr) { if (lts.lua_state() == nullptr) {
handler(L, index, type::thread, type_of(L, index), "value is not a valid thread type"); handler(L, index, type::thread, type_of(L, index), "value is not a valid thread type");
return nullopt; return nullopt;
} }
@ -87,50 +91,59 @@ namespace sol {
} }
} // namespace stack } // namespace stack
class thread : public reference { template <typename base_t>
class basic_thread : public base_t {
public: public:
thread() noexcept = default; using base_t::lua_state;
thread(const thread&) = default;
thread(thread&&) = default; basic_thread() noexcept = default;
template <typename T, meta::enable<meta::neg<std::is_same<meta::unqualified_t<T>, thread>>, std::is_base_of<reference, meta::unqualified_t<T>>> = meta::enabler> basic_thread(const basic_thread&) = default;
thread(T&& r) basic_thread(basic_thread&&) = default;
: reference(std::forward<T>(r)) { template <typename T, meta::enable<meta::neg<std::is_same<meta::unqualified_t<T>, basic_thread>>, std::is_base_of<base_t, meta::unqualified_t<T>>> = meta::enabler>
basic_thread(T&& r)
: base_t(std::forward<T>(r)) {
} }
thread(const stack_reference& r) basic_thread(const stack_reference& r)
: thread(r.lua_state(), r.stack_index()){}; : basic_thread(r.lua_state(), r.stack_index()){};
thread(stack_reference&& r) basic_thread(stack_reference&& r)
: thread(r.lua_state(), r.stack_index()){}; : basic_thread(r.lua_state(), r.stack_index()){};
thread& operator=(const thread&) = default; basic_thread& operator=(const basic_thread&) = default;
thread& operator=(thread&&) = default; basic_thread& operator=(basic_thread&&) = default;
template <typename T, meta::enable<meta::neg<std::is_integral<meta::unqualified_t<T>>>, meta::neg<std::is_same<T, ref_index>>> = meta::enabler> template <typename T, meta::enable<meta::neg<is_lua_index<meta::unqualified_t<T>>>> = meta::enabler>
thread(lua_State* L, T&& r) basic_thread(lua_State* L, T&& r)
: thread(L, sol::ref_index(r.registry_index())) { : basic_thread(L, std::forward<T>(r)) {
} }
thread(lua_State* L, int index = -1) basic_thread(lua_State* L, int index = -1)
: reference(L, index) { : base_t(L, index) {
#ifdef SOL_CHECK_ARGUMENTS
type_assert(L, index, type::thread);
#endif // Safety
}
thread(lua_State* L, ref_index index)
: reference(L, index) {
#ifdef SOL_CHECK_ARGUMENTS #ifdef SOL_CHECK_ARGUMENTS
auto pp = stack::push_pop(*this); auto pp = stack::push_pop(*this);
type_assert(L, -1, type::thread); constructor_handler handler{};
stack::check<basic_thread>(lua_state(), -1, handler);
#endif // Safety #endif // Safety
} }
thread(lua_State* L, lua_State* actualthread) basic_thread(lua_State* L, ref_index index)
: thread(L, lua_thread_state{actualthread}) { : base_t(L, index) {
}
thread(lua_State* L, sol::this_state actualthread)
: thread(L, lua_thread_state{actualthread.L}) {
}
thread(lua_State* L, lua_thread_state actualthread)
: reference(L, -stack::push(L, actualthread)) {
#ifdef SOL_CHECK_ARGUMENTS #ifdef SOL_CHECK_ARGUMENTS
type_assert(L, -1, type::thread); auto pp = stack::push_pop(*this);
constructor_handler handler{};
stack::check<basic_thread>(lua_state(), -1, handler);
#endif // Safety #endif // Safety
lua_pop(L, 1); }
basic_thread(lua_State* L, lua_State* actualthread)
: basic_thread(L, lua_thread_state{ actualthread }) {
}
basic_thread(lua_State* L, this_state actualthread)
: basic_thread(L, lua_thread_state{ actualthread.L }) {
}
basic_thread(lua_State* L, lua_thread_state actualthread)
: base_t(L, -stack::push(L, actualthread)) {
#ifdef SOL_CHECK_ARGUMENTS
constructor_handler handler{};
stack::check<basic_thread>(lua_state(), -1, handler);
#endif // Safety
if (!is_stack_based<base_t>::value) {
lua_pop(lua_state(), 1);
}
} }
state_view state() const { state_view state() const {
@ -153,23 +166,28 @@ namespace sol {
lua_State* lthread = thread_state(); lua_State* lthread = thread_state();
thread_status lstat = static_cast<thread_status>(lua_status(lthread)); thread_status lstat = static_cast<thread_status>(lua_status(lthread));
if (lstat != thread_status::ok && lua_gettop(lthread) == 0) { if (lstat != thread_status::ok && lua_gettop(lthread) == 0) {
// No thing on the thread's stack means its dead // No thing on the basic_thread's stack means its dead
return thread_status::dead; return thread_status::dead;
} }
return lstat; return lstat;
} }
thread create() { basic_thread create() {
return create(lua_state()); return create(lua_state());
} }
static thread create(lua_State* L) { static basic_thread create(lua_State* L) {
lua_newthread(L); lua_newthread(L);
thread result(L); basic_thread result(L);
lua_pop(L, 1); if (!is_stack_based<base_t>::value) {
lua_pop(L, 1);
}
return result; return result;
} }
}; };
typedef basic_thread<reference> thread;
typedef basic_thread<stack_reference> stack_thread;
} // namespace sol } // namespace sol
#endif // SOL_THREAD_HPP #endif // SOL_THREAD_HPP

View File

@ -491,6 +491,31 @@ namespace sol {
struct this_state { struct this_state {
lua_State* L; lua_State* L;
this_state(lua_State* Ls)
: L(Ls) {
}
operator lua_State*() const noexcept {
return lua_state();
}
lua_State* operator->() const noexcept {
return lua_state();
}
lua_State* lua_state() const noexcept {
return L;
}
};
struct this_main_state {
lua_State* L;
this_main_state(lua_State* Ls)
: L(Ls) {
}
operator lua_State*() const noexcept { operator lua_State*() const noexcept {
return lua_state(); return lua_state();
} }
@ -577,7 +602,7 @@ namespace sol {
}; };
inline const std::string& to_string(call_status c) { inline const std::string& to_string(call_status c) {
static const std::array<std::string, 8> names{{ static const std::array<std::string, 8> names{ {
"ok", "ok",
"yielded", "yielded",
"runtime", "runtime",
@ -586,7 +611,7 @@ namespace sol {
"gc", "gc",
"syntax", "syntax",
"file", "file",
}}; } };
switch (c) { switch (c) {
case call_status::ok: case call_status::ok:
return names[0]; return names[0];
@ -609,13 +634,13 @@ namespace sol {
} }
inline const std::string& to_string(load_status c) { inline const std::string& to_string(load_status c) {
static const std::array<std::string, 8> names{{ static const std::array<std::string, 8> names{ {
"ok", "ok",
"memory", "memory",
"gc", "gc",
"syntax", "syntax",
"file", "file",
}}; } };
switch (c) { switch (c) {
case load_status::ok: case load_status::ok:
return names[0]; return names[0];
@ -632,11 +657,11 @@ namespace sol {
} }
inline const std::string& to_string(load_mode c) { inline const std::string& to_string(load_mode c) {
static const std::array<std::string, 3> names{{ static const std::array<std::string, 3> names{ {
"bt", "bt",
"t", "t",
"b", "b",
}}; } };
return names[static_cast<std::size_t>(c)]; return names[static_cast<std::size_t>(c)];
} }
@ -680,7 +705,7 @@ namespace sol {
typedef meta_function meta_method; typedef meta_function meta_method;
inline const std::array<std::string, 32>& meta_function_names() { inline const std::array<std::string, 32>& meta_function_names() {
static const std::array<std::string, 32> names = {{"new", static const std::array<std::string, 32> names = { { "new",
"__index", "__index",
"__newindex", "__newindex",
"__mode", "__mode",
@ -713,7 +738,7 @@ namespace sol {
"__ipairs", "__ipairs",
"__next", "__next",
"__type", "__type",
"__typeinfo"}}; "__typeinfo" } };
return names; return names;
} }
@ -831,7 +856,7 @@ namespace sol {
struct lua_type_of<std::nullptr_t> : std::integral_constant<type, type::lua_nil> {}; struct lua_type_of<std::nullptr_t> : std::integral_constant<type, type::lua_nil> {};
template <> template <>
struct lua_type_of<sol::error> : std::integral_constant<type, type::string> {}; struct lua_type_of<error> : std::integral_constant<type, type::string> {};
template <bool b, typename Base> template <bool b, typename Base>
struct lua_type_of<basic_table_core<b, Base>> : std::integral_constant<type, type::table> {}; struct lua_type_of<basic_table_core<b, Base>> : std::integral_constant<type, type::table> {};
@ -851,8 +876,8 @@ namespace sol {
template <typename T> template <typename T>
struct lua_type_of<as_table_t<T>> : std::integral_constant<type, type::table> {}; struct lua_type_of<as_table_t<T>> : std::integral_constant<type, type::table> {};
template <> template <bool b>
struct lua_type_of<reference> : std::integral_constant<type, type::poly> {}; struct lua_type_of<basic_reference<b>> : std::integral_constant<type, type::poly> {};
template <> template <>
struct lua_type_of<stack_reference> : std::integral_constant<type, type::poly> {}; struct lua_type_of<stack_reference> : std::integral_constant<type, type::poly> {};
@ -923,6 +948,9 @@ namespace sol {
template <> template <>
struct lua_type_of<this_state> : std::integral_constant<type, type::poly> {}; struct lua_type_of<this_state> : std::integral_constant<type, type::poly> {};
template <>
struct lua_type_of<this_main_state> : std::integral_constant<type, type::poly> {};
template <> template <>
struct lua_type_of<this_environment> : std::integral_constant<type, type::poly> {}; struct lua_type_of<this_environment> : std::integral_constant<type, type::poly> {};
@ -1009,6 +1037,7 @@ namespace sol {
&& detail::has_internal_marker<lua_type_of<meta::unqualified_t<T>>>::value && detail::has_internal_marker<lua_type_of<meta::unqualified_t<T>>>::value
&& !detail::has_internal_marker<lua_size<meta::unqualified_t<T>>>::value) && !detail::has_internal_marker<lua_size<meta::unqualified_t<T>>>::value)
|| std::is_base_of<reference, meta::unqualified_t<T>>::value || std::is_base_of<reference, meta::unqualified_t<T>>::value
|| std::is_base_of<main_reference, meta::unqualified_t<T>>::value
|| std::is_base_of<stack_reference, meta::unqualified_t<T>>::value || std::is_base_of<stack_reference, meta::unqualified_t<T>>::value
|| meta::is_specialization_of<std::tuple, meta::unqualified_t<T>>::value || meta::is_specialization_of<std::tuple, meta::unqualified_t<T>>::value
|| meta::is_specialization_of<std::pair, meta::unqualified_t<T>>::value> {}; || meta::is_specialization_of<std::pair, meta::unqualified_t<T>>::value> {};
@ -1016,8 +1045,19 @@ namespace sol {
template <typename T> template <typename T>
struct is_lua_reference : std::integral_constant<bool, struct is_lua_reference : std::integral_constant<bool,
std::is_base_of<reference, meta::unqualified_t<T>>::value std::is_base_of<reference, meta::unqualified_t<T>>::value
|| std::is_base_of<stack_reference, meta::unqualified_t<T>>::value || std::is_base_of<main_reference, meta::unqualified_t<T>>::value
|| meta::is_specialization_of<proxy, meta::unqualified_t<T>>::value> {}; || std::is_base_of<stack_reference, meta::unqualified_t<T>>::value> {};
template <typename T>
struct is_lua_reference_or_proxy : std::integral_constant<bool,
is_lua_reference<meta::unqualified_t<T>>::value
|| meta::is_specialization_of<proxy, meta::unqualified_t<T>>::value> {};
template <typename T>
struct is_main_threaded : std::is_base_of<main_reference, T> {};
template <typename T>
struct is_stack_based : std::is_base_of<stack_reference, T> {};
template <typename T> template <typename T>
struct is_lua_primitive<T*> : std::true_type {}; struct is_lua_primitive<T*> : std::true_type {};
@ -1052,6 +1092,8 @@ namespace sol {
template <> template <>
struct is_transparent_argument<this_state> : std::true_type {}; struct is_transparent_argument<this_state> : std::true_type {};
template <> template <>
struct is_transparent_argument<this_main_state> : std::true_type {};
template <>
struct is_transparent_argument<this_environment> : std::true_type {}; struct is_transparent_argument<this_environment> : std::true_type {};
template <> template <>
struct is_transparent_argument<variadic_args> : std::true_type {}; struct is_transparent_argument<variadic_args> : std::true_type {};
@ -1069,13 +1111,6 @@ namespace sol {
template <> template <>
struct is_lua_index<upvalue_index> : std::true_type {}; struct is_lua_index<upvalue_index> : std::true_type {};
template <typename T>
struct is_stack_based : std::is_base_of<stack_reference, T> {};
template <>
struct is_stack_based<raw_index> : std::true_type {};
template <>
struct is_stack_based<absolute_index> : std::true_type {};
template <typename Signature> template <typename Signature>
struct lua_bind_traits : meta::bind_traits<Signature> { struct lua_bind_traits : meta::bind_traits<Signature> {
private: private:

View File

@ -54,7 +54,7 @@ namespace sol {
basic_userdata(stack_reference&& r) basic_userdata(stack_reference&& r)
: basic_userdata(r.lua_state(), r.stack_index()) { : basic_userdata(r.lua_state(), r.stack_index()) {
} }
template <typename T, meta::enable_any<std::is_base_of<reference, meta::unqualified_t<T>>, std::is_base_of<stack_reference, meta::unqualified_t<T>>> = meta::enabler> template <typename T, meta::enable<is_lua_reference<meta::unqualified_t<T>>> = meta::enabler>
basic_userdata(lua_State* L, T&& r) basic_userdata(lua_State* L, T&& r)
: base_t(L, std::forward<T>(r)) { : base_t(L, std::forward<T>(r)) {
} }

View File

@ -112,7 +112,7 @@ namespace sol {
template <typename T, typename Op, typename Supports, typename Regs, meta::enable<Supports> = meta::enabler> template <typename T, typename Op, typename Supports, typename Regs, meta::enable<Supports> = meta::enabler>
inline void make_reg_op(Regs& l, int& index, const char* name) { inline void make_reg_op(Regs& l, int& index, const char* name) {
lua_CFunction f = &comparsion_operator_wrap<T, Op>; lua_CFunction f = &comparsion_operator_wrap<T, Op>;
l[index] = luaL_Reg{name, f}; l[index] = luaL_Reg{ name, f };
++index; ++index;
} }
@ -125,7 +125,7 @@ namespace sol {
inline void make_to_string_op(Regs& l, int& index) { inline void make_to_string_op(Regs& l, int& index) {
const char* name = to_string(meta_function::to_string).c_str(); const char* name = to_string(meta_function::to_string).c_str();
lua_CFunction f = &detail::static_trampoline<&default_to_string<T>>; lua_CFunction f = &detail::static_trampoline<&default_to_string<T>>;
l[index] = luaL_Reg{name, f}; l[index] = luaL_Reg{ name, f };
++index; ++index;
} }
@ -138,7 +138,7 @@ namespace sol {
inline void make_call_op(Regs& l, int& index) { inline void make_call_op(Regs& l, int& index) {
const char* name = to_string(meta_function::call).c_str(); const char* name = to_string(meta_function::call).c_str();
lua_CFunction f = &c_call<decltype(&T::operator()), &T::operator()>; lua_CFunction f = &c_call<decltype(&T::operator()), &T::operator()>;
l[index] = luaL_Reg{name, f}; l[index] = luaL_Reg{ name, f };
++index; ++index;
} }
@ -150,7 +150,7 @@ namespace sol {
template <typename T, typename Regs, meta::enable<meta::has_size<T>> = meta::enabler> template <typename T, typename Regs, meta::enable<meta::has_size<T>> = meta::enabler>
inline void make_length_op(Regs& l, int& index) { inline void make_length_op(Regs& l, int& index) {
const char* name = to_string(meta_function::length).c_str(); const char* name = to_string(meta_function::length).c_str();
l[index] = luaL_Reg{name, &c_call<decltype(&T::size), &T::size>}; l[index] = luaL_Reg{ name, &c_call<decltype(&T::size), &T::size> };
++index; ++index;
} }
@ -162,7 +162,7 @@ namespace sol {
template <typename T, typename Regs, meta::enable<meta::neg<std::is_pointer<T>>, std::is_destructible<T>>> template <typename T, typename Regs, meta::enable<meta::neg<std::is_pointer<T>>, std::is_destructible<T>>>
void make_destructor(Regs& l, int& index) { void make_destructor(Regs& l, int& index) {
const char* name = to_string(meta_function::garbage_collect).c_str(); const char* name = to_string(meta_function::garbage_collect).c_str();
l[index] = luaL_Reg{name, is_unique_usertype<T>::value ? &detail::unique_destruct<T> : &detail::usertype_alloc_destruct<T>}; l[index] = luaL_Reg{ name, is_unique_usertype<T>::value ? &detail::unique_destruct<T> : &detail::usertype_alloc_destruct<T> };
++index; ++index;
} }
@ -174,7 +174,7 @@ namespace sol {
// this won't trigger if the user performs `new_usertype` / `new_simple_usertype` and // this won't trigger if the user performs `new_usertype` / `new_simple_usertype` and
// rigs the class up properly // rigs the class up properly
const char* name = to_string(meta_function::garbage_collect).c_str(); const char* name = to_string(meta_function::garbage_collect).c_str();
l[index] = luaL_Reg{name, &detail::cannot_destruct<T>}; l[index] = luaL_Reg{ name, &detail::cannot_destruct<T> };
++index; ++index;
} }
} }
@ -195,7 +195,7 @@ namespace sol {
} }
if (fx(meta_function::pairs)) { if (fx(meta_function::pairs)) {
const char* name = to_string(meta_function::pairs).c_str(); const char* name = to_string(meta_function::pairs).c_str();
l[index] = luaL_Reg{name, container_usertype_metatable<as_container_t<T>>::pairs_call}; l[index] = luaL_Reg{ name, container_usertype_metatable<as_container_t<T>>::pairs_call };
++index; ++index;
} }
if (fx(meta_function::length)) { if (fx(meta_function::length)) {
@ -210,8 +210,7 @@ namespace sol {
} }
} // namespace usertype_detail } // namespace usertype_detail
namespace stack { namespace stack { namespace stack_detail {
namespace stack_detail {
template <typename T> template <typename T>
struct undefined_metatable { struct undefined_metatable {
typedef meta::all<meta::neg<std::is_pointer<T>>, std::is_destructible<T>> is_destructible; typedef meta::all<meta::neg<std::is_pointer<T>>, std::is_destructible<T>> is_destructible;
@ -231,6 +230,16 @@ namespace sol {
usertype_detail::insert_default_registrations<P>(l, index, fx); usertype_detail::insert_default_registrations<P>(l, index, fx);
usertype_detail::make_destructor<T>(l, index); usertype_detail::make_destructor<T>(l, index);
luaL_setfuncs(L, l, 0); luaL_setfuncs(L, l, 0);
// __type table
lua_createtable(L, 0, 2);
const std::string& name = detail::demangle<T>();
lua_pushlstring(L, name.c_str(), name.size());
lua_setfield(L, -2, "name");
lua_CFunction is_func = &usertype_detail::is_check<T>;
lua_pushcclosure(L, is_func, 0);
lua_setfield(L, -2, "is");
lua_setfield(L, -2, to_string(meta_function::type).c_str());
} }
lua_setmetatable(L, -2); lua_setmetatable(L, -2);
} }

View File

@ -252,10 +252,10 @@ namespace sol {
std::string& accessor = maybeaccessor.value(); std::string& accessor = maybeaccessor.value();
auto preexistingit = functions.find(accessor); auto preexistingit = functions.find(accessor);
if (preexistingit == functions.cend()) { if (preexistingit == functions.cend()) {
functions.emplace_hint(preexistingit, std::move(accessor), sol::object(L, 3)); functions.emplace_hint(preexistingit, std::move(accessor), object(L, 3));
} }
else { else {
preexistingit->second = sol::object(L, 3); preexistingit->second = object(L, 3);
} }
return; return;
} }
@ -278,7 +278,7 @@ namespace sol {
} }
else { else {
target = preexistingit->second.runtime_target; target = preexistingit->second.runtime_target;
runtime[target] = sol::object(L, 3); runtime[target] = object(L, 3);
preexistingit->second = call_information(&runtime_object_call, &runtime_new_index, target); preexistingit->second = call_information(&runtime_object_call, &runtime_new_index, target);
} }
}; };
@ -468,7 +468,7 @@ namespace sol {
case meta_function::garbage_collect: case meta_function::garbage_collect:
if (destructfunc != nullptr) { if (destructfunc != nullptr) {
#ifdef SOL_NO_EXCEPTIONS #ifdef SOL_NO_EXCEPTIONS
throw sol::error("sol: 2 separate garbage_collect functions were set on this type. Please specify only 1 sol::meta_function::gc type AND wrap the function in a sol::destruct call, as shown by the documentation and examples"); throw error("sol: 2 separate garbage_collect functions were set on this type. Please specify only 1 sol::meta_function::gc type AND wrap the function in a sol::destruct call, as shown by the documentation and examples");
#else #else
assert(false && "sol: 2 separate garbage_collect functions were set on this type. Please specify only 1 sol::meta_function::gc type AND wrap the function in a sol::destruct call, as shown by the documentation and examples"); assert(false && "sol: 2 separate garbage_collect functions were set on this type. Please specify only 1 sol::meta_function::gc type AND wrap the function in a sol::destruct call, as shown by the documentation and examples");
#endif #endif

View File

@ -281,3 +281,93 @@ co = nil
std::string s = t[1]; std::string s = t[1];
REQUIRE(s == "SOME_TABLE"); REQUIRE(s == "SOME_TABLE");
} }
TEST_CASE("coroutines/main transfer", "check that copy and move assignment constructors using main-forced types work") {
const std::string code = R"(
-- main thread - L1
-- co - L2
-- co2 - L3
x = co_test.new("x")
local co = coroutine.wrap(
function()
local t = co_test.new("t")
local co2 = coroutine.wrap(
function()
local t2 = { "SOME_TABLE" }
t:copy_store(t2) -- t2 = [L3], t.obj = [L2]
end
)
co2()
co2 = nil
collectgarbage() -- t2 ref in t remains valid!
x:store(t:get()) -- t.obj = [L2], x.obj = [L1]
end
)
co()
co = nil
collectgarbage()
)";
struct co_test_implicit {
std::string identifier;
sol::main_reference obj;
co_test_implicit(sol::this_state L, std::string id) : identifier(id), obj(L, sol::lua_nil) {
}
void store(sol::table ref) {
// main_reference does the state shift implicitly
obj = std::move(ref);
lua_State* Lmain = sol::main_thread(ref.lua_state());
REQUIRE(obj.lua_state() == Lmain);
}
void copy_store(sol::table ref) {
// main_reference does the state shift implicitly
obj = ref;
lua_State* Lmain = sol::main_thread(ref.lua_state());
REQUIRE(obj.lua_state() == Lmain);
}
sol::reference get() {
return obj;
}
~co_test_implicit() {
}
};
sol::state lua;
lua.open_libraries(sol::lib::coroutine, sol::lib::base);
lua.new_usertype<co_test_implicit>("co_test",
sol::constructors<co_test_implicit(sol::this_state, std::string)>(),
"store", &co_test_implicit::store,
"copy_store", &co_test_implicit::copy_store,
"get", &co_test_implicit::get
);
auto r = lua.safe_script(code);
REQUIRE(r.valid());
co_test_implicit& ct = lua["x"];
lua_State* Lmain1 = lua.lua_state();
lua_State* Lmain2 = sol::main_thread(lua);
lua_State* Lmain3 = ct.get().lua_state();
REQUIRE(Lmain1 == Lmain2);
REQUIRE(Lmain1 == Lmain3);
sol::table t = ct.get();
REQUIRE(t.size() == 1);
std::string s = t[1];
REQUIRE(s == "SOME_TABLE");
}