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
AlignAfterOpenBracket: DontAlign # uses ContinuationIndentWidth for this instead
AccessModifierOffset: -5 # do not push public: or private: around
#AlignConsecutiveAssignments: true
#AlignConsecutiveDeclarations: true
#AlignConsecutiveAssignments: true # affects more than what's expected: do not use
#AlignConsecutiveDeclarations: true # affects more than what's expected: do not use
# Type Alignment
DerivePointerAlignment: false
@ -29,7 +29,6 @@ ReflowComments: true
# Macros
AlignEscapedNewlines: Left
SortIncludes: false
IndentPPDirectives: None
# Functions
@ -38,6 +37,8 @@ AlwaysBreakAfterReturnType: None
BreakConstructorInitializers: BeforeComma
ConstructorInitializerIndentWidth: 0
ConstructorInitializerAllOnOneLineOrOnePerLine: true
BinPackArguments: true
BinPackParameters: true
# Classes
BreakBeforeInheritanceComma: false
@ -66,7 +67,6 @@ AllowShortLoopsOnASingleLine: false
AllowShortCaseLabelsOnASingleLine: false
IndentCaseLabels: false
# Spaces
SpaceAfterCStyleCast: false
SpacesInCStyleCastParentheses: false
@ -81,6 +81,7 @@ MaxEmptyLinesToKeep: 1
# OCD
SortUsingDeclarations: true
SortIncludes: false
---
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>`.
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
:caption: transfer from state function
: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) {
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) {
@ -1020,7 +1020,7 @@ namespace sol {
auto& src = get_src(L);
stack::push(L, next<ip>);
stack::push<user<iter>>(L, src, deferred_traits::begin(L, src));
stack::push(L, sol::lua_nil);
stack::push(L, lua_nil);
return 3;
}

View File

@ -346,7 +346,7 @@ namespace sol {
};
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;
static int push(lua_State* L, const T& cont) {
@ -361,7 +361,7 @@ namespace sol {
};
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;
static int push(lua_State* L, T* cont) {

View File

@ -28,7 +28,8 @@
#include "thread.hpp"
namespace sol {
class coroutine : public reference {
template <typename base_t>
class basic_coroutine : public base_t {
private:
call_status stats = call_status::yielded;
@ -66,41 +67,43 @@ namespace sol {
}
public:
coroutine() noexcept = default;
coroutine(const coroutine&) noexcept = default;
coroutine(coroutine&&) noexcept = default;
coroutine& operator=(const coroutine&) noexcept = default;
coroutine& operator=(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>
coroutine(T&& r)
: reference(std::forward<T>(r)) {
using base_t::lua_state;
basic_coroutine() noexcept = default;
basic_coroutine(const basic_coroutine&) noexcept = default;
basic_coroutine(basic_coroutine&&) noexcept = default;
basic_coroutine& operator=(const basic_coroutine&) noexcept = default;
basic_coroutine& operator=(basic_coroutine&&) noexcept = default;
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)
: reference(r) {
basic_coroutine(lua_nil_t r)
: base_t(r) {
}
coroutine(const stack_reference& r) noexcept
: coroutine(r.lua_state(), r.stack_index()) {
basic_coroutine(const stack_reference& r) noexcept
: basic_coroutine(r.lua_state(), r.stack_index()) {
}
coroutine(stack_reference&& r) noexcept
: coroutine(r.lua_state(), r.stack_index()) {
basic_coroutine(stack_reference&& r) noexcept
: 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>
coroutine(lua_State* L, T&& r)
: coroutine(L, sol::ref_index(r.registry_index())) {
template <typename T, meta::enable<meta::neg<is_lua_index<meta::unqualified_t<T>>>> = meta::enabler>
basic_coroutine(lua_State* L, T&& r)
: base_t(L, std::forward<T>(r)) {
}
coroutine(lua_State* L, int index = -1)
: reference(L, index) {
basic_coroutine(lua_State* L, int index = -1)
: base_t(L, index) {
#ifdef SOL_CHECK_ARGUMENTS
constructor_handler handler{};
stack::check<coroutine>(L, index, handler);
stack::check<basic_coroutine>(lua_state(), index, handler);
#endif // Safety
}
coroutine(lua_State* L, ref_index index)
: reference(L, index) {
basic_coroutine(lua_State* L, ref_index index)
: base_t(L, index) {
#ifdef SOL_CHECK_ARGUMENTS
auto pp = stack::push_pop(*this);
constructor_handler handler{};
stack::check<coroutine>(L, -1, handler);
stack::check<basic_coroutine>(lua_state(), -1, handler);
#endif // Safety
}
@ -114,7 +117,7 @@ namespace sol {
}
bool runnable() const noexcept {
return valid()
return base_t::valid()
&& (status() == call_status::yielded);
}
@ -134,8 +137,8 @@ namespace sol {
template <typename... Ret, typename... Args>
decltype(auto) call(Args&&... args) {
push();
int pushcount = stack::multi_push(lua_state(), std::forward<Args>(args)...);
base_t::push();
int pushcount = stack::multi_push_reference(lua_state(), std::forward<Args>(args)...);
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)
: 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)) {
sol::stack_table mt(L, sol::new_table(0, 1));
mt.set(sol::meta_function::index, fallback);
stack_table mt(L, new_table(0, 1));
mt.set(meta_function::index, fallback);
this->set(metatable_key, mt);
mt.pop();
}
@ -65,7 +66,8 @@ namespace sol {
#endif // Safety
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)) {
#ifdef SOL_CHECK_ARGUMENTS
constructor_handler handler{};
@ -137,7 +139,7 @@ namespace sol {
this_environment()
: env(nullopt) {
}
this_environment(sol::environment e)
this_environment(environment e)
: env(std::move(e)) {
}
this_environment(const this_environment&) = default;
@ -194,8 +196,8 @@ namespace sol {
return this_environment();
}
sol::stack_reference f(L, -1);
sol::environment env(sol::env_key, f);
stack_reference f(L, -1);
environment env(env_key, f);
if (!env.valid()) {
lua_settop(L, pre_stack_size);
return this_environment();

View File

@ -26,11 +26,18 @@
namespace sol {
class reference;
template <bool b>
class basic_reference;
using reference = basic_reference<false>;
using main_reference = basic_reference<true>;
class stack_reference;
struct proxy_base_tag;
template <typename Super>
struct proxy_base;
template <typename Table, typename Key>
struct proxy;
template <typename T>
class usertype;
template <typename T>
@ -40,16 +47,21 @@ namespace sol {
template <bool b>
using table_core = basic_table_core<b, reference>;
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>;
template <typename T>
using basic_table = basic_table_core<false, T>;
typedef table_core<false> 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<true> stack_global_table;
template <typename base_t>
struct basic_environment;
using environment = basic_environment<reference>;
using main_environment = basic_environment<main_reference>;
using stack_environment = basic_environment<stack_reference>;
template <typename T, bool>
class basic_function;
@ -57,6 +69,8 @@ namespace sol {
class basic_protected_function;
using unsafe_function = basic_function<reference, false>;
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_safe_function = basic_protected_function<stack_reference, false, reference>;
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;
#ifdef SOL_SAFE_FUNCTIONS
using function = protected_function;
using main_function = main_protected_function;
using stack_function = stack_protected_function;
using stack_aligned_function = stack_aligned_safe_function;
#else
using function = unsafe_function;
using main_function = main_unsafe_function;
using stack_function = stack_unsafe_function;
using stack_aligned_function = stack_aligned_unsafe_function;
#endif
@ -79,25 +95,39 @@ namespace sol {
struct protected_function_result;
using safe_function_result = protected_function_result;
using unsafe_function_result = function_result;
template <typename base_t>
class basic_object;
template <typename base_t>
class basic_userdata;
template <typename base_t>
class basic_lightuserdata;
template <typename base_t>
class basic_coroutine;
template <typename base_t>
class basic_thread;
using object = basic_object<reference>;
using stack_object = basic_object<stack_reference>;
using userdata = basic_userdata<reference>;
using stack_userdata = basic_userdata<stack_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>;
class coroutine;
class thread;
using stack_thread = basic_thread<stack_reference>;
using stack_coroutine = basic_coroutine<stack_reference>;
struct variadic_args;
struct variadic_results;
struct stack_count;
struct this_state;
struct this_main_state;
struct this_environment;
template <typename T>
struct as_table_t;
template <typename T>

View File

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

View File

@ -196,12 +196,12 @@ namespace sol {
}
#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) {
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) {
stack::push(L, std::forward<Fx>(fx));
}
@ -309,10 +309,10 @@ namespace sol {
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>> {
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) {
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 {
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) {
int backpedal = stack::push(L, std::forward<T>(value));
R r = stack::get<R>(L, -backpedal);
@ -42,7 +42,7 @@ namespace sol {
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) {
int backpedal = stack::push<T>(L, std::forward<Args>(args)...);
R r = stack::get<R>(L, -backpedal);
@ -71,7 +71,7 @@ namespace sol {
basic_object(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)
: base_t(L, std::forward<T>(r)) {
}
@ -111,7 +111,7 @@ namespace sol {
}
template <typename T, typename... Args>
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>
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>
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;
int stackindex;
@ -81,11 +81,12 @@ namespace sol {
template <typename base_t, bool aligned = false, typename handler_t = reference>
class basic_protected_function : public base_t {
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) {
if (is_stack_handler::value || L == nullptr)
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());
auto pp = stack::pop_n(L, 1);
return handler_t(L, -1);
@ -96,13 +97,14 @@ namespace sol {
if (ref.lua_state() == nullptr) {
return;
}
lua_State* L = ref.lua_state();
if (!ref.valid()) {
lua_pushnil(ref.lua_state());
lua_setglobal(ref.lua_state(), detail::default_handler_name());
lua_pushnil(L);
lua_setglobal(L, detail::default_handler_name());
}
else {
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)) {
}
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(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)
: 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)) {
#ifdef SOL_CHECK_ARGUMENTS
constructor_handler handler{};
stack::check<basic_protected_function>(L, index, handler);
stack::check<basic_protected_function>(lua_state(), index, handler);
#endif // Safety
}
basic_protected_function(lua_State* L, absolute_index index)
@ -261,7 +263,7 @@ namespace sol {
: base_t(L, index), error_handler(std::move(eh)) {
#ifdef SOL_CHECK_ARGUMENTS
constructor_handler handler{};
stack::check<basic_protected_function>(L, index, handler);
stack::check<basic_protected_function>(lua_state(), index, handler);
#endif // Safety
}
basic_protected_function(lua_State* L, raw_index index)
@ -271,7 +273,7 @@ namespace sol {
: base_t(L, index), error_handler(std::move(eh)) {
#ifdef SOL_CHECK_ARGUMENTS
constructor_handler handler{};
stack::check<basic_protected_function>(L, index, handler);
stack::check<basic_protected_function>(lua_state(), index, handler);
#endif // Safety
}
basic_protected_function(lua_State* L, ref_index index)

View File

@ -77,12 +77,12 @@ namespace sol {
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) {
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) {
return set(std::forward<U>(other));
}
@ -194,11 +194,25 @@ namespace sol {
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 {
template <typename Table, typename Key>
struct pusher<proxy<Table, Key>> {
static int push(lua_State* L, const proxy<Table, Key>& p) {
sol::reference r = p;
reference r = p;
return r.push(L);
}
};

View File

@ -152,10 +152,23 @@ namespace sol {
} const global_{};
struct no_safety_tag {
} 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
class reference {
template <bool main_only = false>
class basic_reference {
private:
template <bool o_main_only>
friend class basic_reference;
lua_State* luastate = nullptr; // non-owning
int ref = LUA_NOREF;
@ -166,9 +179,58 @@ namespace sol {
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:
reference(lua_State* L, detail::global_tag) noexcept
: luastate(L) {
basic_reference(lua_State* L, detail::global_tag) noexcept
: luastate(detail::pick_main_thread<main_only>(L, L)) {
lua_pushglobaltable(lua_state());
ref = luaL_ref(lua_state(), LUA_REGISTRYINDEX);
}
@ -182,18 +244,19 @@ namespace sol {
}
public:
reference() noexcept = default;
reference(lua_nil_t) noexcept
: reference() {
basic_reference() noexcept = default;
basic_reference(lua_nil_t) noexcept
: basic_reference() {
}
reference(const stack_reference& r) noexcept
: reference(r.lua_state(), r.stack_index()) {
basic_reference(const stack_reference& r) noexcept
: basic_reference(r.lua_state(), r.stack_index()) {
}
reference(stack_reference&& r) noexcept
: reference(r.lua_state(), r.stack_index()) {
basic_reference(stack_reference&& r) noexcept
: basic_reference(r.lua_state(), r.stack_index()) {
}
reference(lua_State* L, const reference& r) noexcept
: luastate(L) {
template <bool r_main_only>
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) {
ref = LUA_REFNIL;
return;
@ -209,8 +272,10 @@ namespace sol {
}
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) {
ref = LUA_REFNIL;
return;
@ -228,8 +293,9 @@ namespace sol {
r.ref = LUA_NOREF;
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) {
ref = LUA_NOREF;
return;
@ -244,83 +310,72 @@ namespace sol {
r.push(lua_state());
ref = luaL_ref(lua_state(), LUA_REGISTRYINDEX);
}
reference(lua_State* L, int index = -1) noexcept
: luastate(L) {
basic_reference(lua_State* L, int index = -1) noexcept
: luastate(detail::pick_main_thread<main_only>(L, L)) {
lua_pushvalue(lua_state(), index);
ref = luaL_ref(lua_state(), LUA_REGISTRYINDEX);
}
reference(lua_State* L, ref_index index) noexcept
: luastate(L) {
lua_rawgeti(L, LUA_REGISTRYINDEX, index.index);
basic_reference(lua_State* L, ref_index index) noexcept
: luastate(detail::pick_main_thread<main_only>(L, L)) {
lua_rawgeti(lua_state(), LUA_REGISTRYINDEX, index.index);
ref = luaL_ref(lua_state(), LUA_REGISTRYINDEX);
}
reference(lua_State* L, lua_nil_t) noexcept
: luastate(L) {
basic_reference(lua_State* L, lua_nil_t) noexcept
: luastate(detail::pick_main_thread<main_only>(L, L)) {
}
~reference() noexcept {
~basic_reference() noexcept {
if (lua_state() == nullptr || ref == LUA_NOREF)
return;
deref();
}
reference(const reference& o) noexcept
: luastate(o.luastate), ref(o.copy()) {
basic_reference(const basic_reference& o) noexcept
: luastate(o.lua_state()), ref(o.copy()) {
}
reference(reference&& o) noexcept
: luastate(o.luastate), ref(o.ref) {
basic_reference(basic_reference&& o) noexcept
: luastate(o.lua_state()), ref(o.ref) {
o.luastate = nullptr;
o.ref = LUA_NOREF;
}
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) {
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;
}
basic_reference(const basic_reference<!main_only>& o) noexcept
: luastate(detail::pick_main_thread<main_only && !main_only>(o.lua_state(), o.lua_state())), ref(o.copy()) {
}
luastate = r.lua_state();
ref = r.ref;
r.ref = LUA_NOREF;
r.luastate = nullptr;
basic_reference(basic_reference<!main_only>&& o) noexcept
: luastate(detail::pick_main_thread<main_only && !main_only>(o.lua_state(), o.lua_state())), ref(o.ref) {
o.luastate = nullptr;
o.ref = LUA_NOREF;
}
basic_reference& operator=(basic_reference&& r) noexcept {
move_assign(std::move(r));
return *this;
}
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) {
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();
basic_reference& operator=(const basic_reference& r) noexcept {
copy_assign(r);
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 {
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 ppr = stack::push_pop(r);
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);
}
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();
}
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();
}
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();
}
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();
}
} // namespace sol

View File

@ -77,7 +77,7 @@ namespace sol {
}
auto fit = functions.find(accessorkey);
if (fit != functions.cend()) {
sol::object& func = fit->second;
object& func = fit->second;
if (is_index) {
return stack::push(L, func);
}
@ -525,7 +525,7 @@ namespace sol {
stack_reference metabehind(L, -1);
stack::set_field(L, meta_function::type, type_table, metabehind.stack_index());
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) {
stack::set_field(L, meta_function::index,
@ -560,7 +560,7 @@ namespace sol {
stack_reference metabehind(L, -1);
stack::set_field(L, meta_function::type, type_table, metabehind.stack_index());
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
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;
typedef std::array<void*, data_t_count> data_t;
data_t data{{}};
data_t data{ {} };
std::memcpy(&data[0], std::addressof(item), itemsize);
int pushcount = 0;
for (auto&& v : data) {
@ -91,7 +91,7 @@ namespace sol {
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*);
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*)) {
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>>
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)...);
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) {
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>
struct checker<this_environment, type::poly, C> {
template <typename Handler>

View File

@ -245,7 +245,7 @@ namespace sol {
template <typename T, typename... Args>
inline int multi_push(lua_State* L, T&& t, Args&&... args) {
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;
}
@ -257,7 +257,7 @@ namespace sol {
template <typename T, typename... Args>
inline int multi_push_reference(lua_State* L, T&& t, Args&&... args) {
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;
}

View File

@ -330,7 +330,7 @@ namespace stack {
};
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) {
tracking.use(1);
return T(L, index);
@ -569,7 +569,15 @@ namespace stack {
struct getter<this_state> {
static this_state get(lua_State* L, int, record& tracking) {
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>
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>
static int push(lua_State* L, Args&&... args) {
return pusher<detail::as_pointer_tag<T>>{}.push(L, std::forward<Args>(args)...);
@ -315,7 +315,7 @@ namespace stack {
};
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) {
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 <>
struct pusher<new_table> {
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()) {
set_panic(panic);
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::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()) {
set_panic(panic);
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::luajit_exception_handler(unique_base::get());
}

View File

@ -67,7 +67,7 @@ namespace sol {
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;
}
@ -377,7 +377,7 @@ namespace sol {
}
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 = {};
const char* chunknametarget = detail::make_chunk_name(code, chunkname, basechunkname);
int index = lua_gettop(L);
@ -402,7 +402,7 @@ namespace sol {
}
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);
if (luaL_loadfilex(L, filename.c_str(), to_string(mode).c_str())) {
lua_error(L);

View File

@ -73,9 +73,9 @@ namespace sol {
auto pp = stack::push_pop(*this);
stack::push(base_t::lua_state(), lua_nil);
while (lua_next(base_t::lua_state(), -2)) {
sol::object key(base_t::lua_state(), -2);
sol::object value(base_t::lua_state(), -1);
std::pair<sol::object&, sol::object&> keyvalue(key, value);
object key(base_t::lua_state(), -2);
object value(base_t::lua_state(), -1);
std::pair<object&, object&> keyvalue(key, value);
auto pn = stack::pop_n(base_t::lua_state(), 1);
fx(keyvalue);
}
@ -86,8 +86,8 @@ namespace sol {
auto pp = stack::push_pop(*this);
stack::push(base_t::lua_state(), lua_nil);
while (lua_next(base_t::lua_state(), -2)) {
sol::object key(base_t::lua_state(), -2);
sol::object value(base_t::lua_state(), -1);
object key(base_t::lua_state(), -2);
object value(base_t::lua_state(), -1);
auto pn = stack::pop_n(base_t::lua_state(), 1);
fx(key, value);
}
@ -204,13 +204,13 @@ namespace sol {
basic_table_core(stack_reference&& r)
: 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(L, std::forward<T>(r)) {
}
basic_table_core(lua_State* L, new_table nt)
: 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);
}
}
@ -454,7 +454,7 @@ namespace sol {
template <typename Fx>
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));
}

View File

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

View File

@ -491,6 +491,31 @@ namespace sol {
struct this_state {
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 {
return lua_state();
}
@ -577,7 +602,7 @@ namespace sol {
};
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",
"yielded",
"runtime",
@ -586,7 +611,7 @@ namespace sol {
"gc",
"syntax",
"file",
}};
} };
switch (c) {
case call_status::ok:
return names[0];
@ -609,13 +634,13 @@ namespace sol {
}
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",
"memory",
"gc",
"syntax",
"file",
}};
} };
switch (c) {
case load_status::ok:
return names[0];
@ -632,11 +657,11 @@ namespace sol {
}
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",
"t",
"b",
}};
} };
return names[static_cast<std::size_t>(c)];
}
@ -680,7 +705,7 @@ namespace sol {
typedef meta_function meta_method;
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",
"__newindex",
"__mode",
@ -713,7 +738,7 @@ namespace sol {
"__ipairs",
"__next",
"__type",
"__typeinfo"}};
"__typeinfo" } };
return names;
}
@ -831,7 +856,7 @@ namespace sol {
struct lua_type_of<std::nullptr_t> : std::integral_constant<type, type::lua_nil> {};
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>
struct lua_type_of<basic_table_core<b, Base>> : std::integral_constant<type, type::table> {};
@ -851,8 +876,8 @@ namespace sol {
template <typename T>
struct lua_type_of<as_table_t<T>> : std::integral_constant<type, type::table> {};
template <>
struct lua_type_of<reference> : std::integral_constant<type, type::poly> {};
template <bool b>
struct lua_type_of<basic_reference<b>> : std::integral_constant<type, type::poly> {};
template <>
struct lua_type_of<stack_reference> : std::integral_constant<type, type::poly> {};
@ -923,6 +948,9 @@ namespace sol {
template <>
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 <>
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_size<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
|| meta::is_specialization_of<std::tuple, 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>
struct is_lua_reference : std::integral_constant<bool,
std::is_base_of<reference, meta::unqualified_t<T>>::value
|| std::is_base_of<stack_reference, meta::unqualified_t<T>>::value
|| meta::is_specialization_of<proxy, 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> {};
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>
struct is_lua_primitive<T*> : std::true_type {};
@ -1052,6 +1092,8 @@ namespace sol {
template <>
struct is_transparent_argument<this_state> : std::true_type {};
template <>
struct is_transparent_argument<this_main_state> : std::true_type {};
template <>
struct is_transparent_argument<this_environment> : std::true_type {};
template <>
struct is_transparent_argument<variadic_args> : std::true_type {};
@ -1069,13 +1111,6 @@ namespace sol {
template <>
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>
struct lua_bind_traits : meta::bind_traits<Signature> {
private:

View File

@ -54,7 +54,7 @@ namespace sol {
basic_userdata(stack_reference&& r)
: 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)
: 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>
inline void make_reg_op(Regs& l, int& index, const char* name) {
lua_CFunction f = &comparsion_operator_wrap<T, Op>;
l[index] = luaL_Reg{name, f};
l[index] = luaL_Reg{ name, f };
++index;
}
@ -125,7 +125,7 @@ namespace sol {
inline void make_to_string_op(Regs& l, int& index) {
const char* name = to_string(meta_function::to_string).c_str();
lua_CFunction f = &detail::static_trampoline<&default_to_string<T>>;
l[index] = luaL_Reg{name, f};
l[index] = luaL_Reg{ name, f };
++index;
}
@ -138,7 +138,7 @@ namespace sol {
inline void make_call_op(Regs& l, int& index) {
const char* name = to_string(meta_function::call).c_str();
lua_CFunction f = &c_call<decltype(&T::operator()), &T::operator()>;
l[index] = luaL_Reg{name, f};
l[index] = luaL_Reg{ name, f };
++index;
}
@ -150,7 +150,7 @@ namespace sol {
template <typename T, typename Regs, meta::enable<meta::has_size<T>> = meta::enabler>
inline void make_length_op(Regs& l, int& index) {
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;
}
@ -162,7 +162,7 @@ namespace sol {
template <typename T, typename Regs, meta::enable<meta::neg<std::is_pointer<T>>, std::is_destructible<T>>>
void make_destructor(Regs& l, int& index) {
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;
}
@ -174,7 +174,7 @@ namespace sol {
// this won't trigger if the user performs `new_usertype` / `new_simple_usertype` and
// rigs the class up properly
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;
}
}
@ -195,7 +195,7 @@ namespace sol {
}
if (fx(meta_function::pairs)) {
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;
}
if (fx(meta_function::length)) {
@ -210,8 +210,7 @@ namespace sol {
}
} // namespace usertype_detail
namespace stack {
namespace stack_detail {
namespace stack { namespace stack_detail {
template <typename T>
struct undefined_metatable {
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::make_destructor<T>(l, index);
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);
}

View File

@ -252,10 +252,10 @@ namespace sol {
std::string& accessor = maybeaccessor.value();
auto preexistingit = functions.find(accessor);
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 {
preexistingit->second = sol::object(L, 3);
preexistingit->second = object(L, 3);
}
return;
}
@ -278,7 +278,7 @@ namespace sol {
}
else {
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);
}
};
@ -468,7 +468,7 @@ namespace sol {
case meta_function::garbage_collect:
if (destructfunc != nullptr) {
#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
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

View File

@ -281,3 +281,93 @@ co = nil
std::string s = t[1];
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");
}