improve gc and call handling, o boi

This commit is contained in:
ThePhD 2019-03-28 23:18:59 -04:00
parent b7050de53b
commit 55ebe1b76a
No known key found for this signature in database
GPG Key ID: 1509DB1C0F702BFA
2 changed files with 31 additions and 15 deletions

View File

@ -672,26 +672,16 @@ namespace sol {
template <typename T, typename Fx, bool is_index, bool is_variable, bool checked, int boost, bool clean_stack, typename C> template <typename T, typename Fx, bool is_index, bool is_variable, bool checked, int boost, bool clean_stack, typename C>
struct lua_call_wrapper<T, destructor_wrapper<Fx>, is_index, is_variable, checked, boost, clean_stack, C> { struct lua_call_wrapper<T, destructor_wrapper<Fx>, is_index, is_variable, checked, boost, clean_stack, C> {
typedef destructor_wrapper<Fx> F;
static int call(lua_State* L, const F& f) { template <typename F>
static int call(lua_State* L, F&& f) {
if constexpr (std::is_void_v<Fx>) { if constexpr (std::is_void_v<Fx>) {
return detail::usertype_alloc_destruct<T>(L); return detail::usertype_alloc_destruct<T>(L);
} }
else { else {
if constexpr (std::is_void_v<T>) { using uFx = meta::unqualified_t<Fx>;
using bt = meta::bind_traits<meta::unqualified_t<decltype(f.fx)>>; lua_call_wrapper<T, uFx, is_index, is_variable, checked, boost, clean_stack> lcw{};
using arg0_t = typename bt::template arg_at<0>; return lcw.call(L, std::forward<F>(f).fx);
decltype(auto) obj = stack::get<arg0_t>(L, -1);
f.fx(detail::implicit_wrapper<std::remove_reference_t<decltype(obj)>>(obj));
return 0;
}
else {
T& obj = stack::get<T>(L, -1);
f.fx(detail::implicit_wrapper<T>(obj));
return 0;
}
} }
} }
}; };

View File

@ -595,3 +595,29 @@ TEST_CASE("gc/alignment", "test that allocation is always on aligned boundaries,
lobj.check_alignment(); lobj.check_alignment();
} }
} }
TEST_CASE("gc/multi-argument destructors", "make sure transparent arguments come along for the ride") {
static int transparent_foos_destroyed = 0;
struct transparent_foo {
~transparent_foo() {
++transparent_foos_destroyed;
}
};
lua_State* lua_state = nullptr;
lua_State* call_state = nullptr;
auto call_des = [&call_state](transparent_foo* f, sol::this_state s) {
call_state = s;
return f->~transparent_foo();
};
{
sol::state lua;
lua_state = lua;
lua.new_usertype<transparent_foo>("foo", sol::meta_function::garbage_collect, sol::destructor(std::move(call_des)));
lua.script("foo.new()");
}
REQUIRE(transparent_foos_destroyed == 1);
REQUIRE(call_state == lua_state);
}