yield fix for sol3

This commit is contained in:
ThePhD 2019-01-26 03:09:37 -05:00
parent 56fd896bed
commit 4f35e330e8
No known key found for this signature in database
GPG Key ID: 1509DB1C0F702BFA
3 changed files with 64 additions and 71 deletions

View File

@ -740,13 +740,23 @@ namespace sol {
struct lua_call_wrapper<T, function_arguments<Sig, P>, is_index, is_variable, checked, boost, clean_stack, C> { struct lua_call_wrapper<T, function_arguments<Sig, P>, is_index, is_variable, checked, boost, clean_stack, C> {
template <typename F> template <typename F>
static int call(lua_State* L, F&& f) { static int call(lua_State* L, F&& f) {
return lua_call_wrapper<T, meta::unqualified_t<P>, is_index, is_variable, checked, boost, clean_stack> {}.call(L, std::get<0>(f.arguments)); return lua_call_wrapper<T, meta::unqualified_t<P>, is_index, is_variable, checked, boost, clean_stack>{}.call(L, std::get<0>(f.arguments));
} }
}; };
template <typename T, bool is_index, bool is_variable, int boost = 0, bool checked = detail::default_safe_function_calls, bool clean_stack = true, typename Fx, typename... Args> template <typename T, bool is_index, bool is_variable, int boost = 0, bool checked = detail::default_safe_function_calls, bool clean_stack = true, typename Fx, typename... Args>
inline int call_wrapped(lua_State* L, Fx&& fx, Args&&... args) { inline int call_wrapped(lua_State* L, Fx&& fx, Args&&... args) {
return lua_call_wrapper<T, meta::unqualified_t<Fx>, is_index, is_variable, checked, boost, clean_stack> {}.call(L, std::forward<Fx>(fx), std::forward<Args>(args)...); using uFx = meta::unqualified_t<Fx>;
if constexpr(meta::is_specialization_of_v<uFx, yielding_t>) {
using real_fx = meta::unqualified_t<decltype(std::forward<Fx>(fx).func)>;
int nr = lua_call_wrapper<T, real_fx, is_index, is_variable, checked, boost, clean_stack>{}.call(
L, std::forward<Fx>(fx).func, std::forward<Args>(args)...);
return lua_yield(L, nr);
}
else {
return lua_call_wrapper<T, uFx, is_index, is_variable, checked, boost, clean_stack>{}.call(
L, std::forward<Fx>(fx), std::forward<Args>(args)...);
}
} }
template <typename T, bool is_index, bool is_variable, typename F, int start = 1, bool checked = detail::default_safe_function_calls, bool clean_stack = true> template <typename T, bool is_index, bool is_variable, typename F, int start = 1, bool checked = detail::default_safe_function_calls, bool clean_stack = true>

View File

@ -43,26 +43,21 @@ namespace sol {
namespace stack { namespace stack {
template <typename... Sigs> template <typename... Sigs>
struct unqualified_pusher<function_sig<Sigs...>> { struct unqualified_pusher<function_sig<Sigs...>> {
template <bool is_yielding, typename... Sig, typename Fx, typename... Args>
static void select_convertible(std::false_type, types<Sig...>, lua_State* L, Fx&& fx, Args&&... args) {
typedef std::remove_pointer_t<std::decay_t<Fx>> clean_fx;
typedef function_detail::functor_function<clean_fx, is_yielding, true> F;
set_fx<false, F>(L, std::forward<Fx>(fx), std::forward<Args>(args)...);
}
template <bool is_yielding, typename R, typename... A, typename Fx, typename... Args>
static void select_convertible(std::true_type, types<R(A...)>, lua_State* L, Fx&& fx, Args&&... args) {
using fx_ptr_t = R (*)(A...);
fx_ptr_t fxptr = detail::unwrap(std::forward<Fx>(fx));
select_function<is_yielding>(std::true_type(), L, fxptr, std::forward<Args>(args)...);
}
template <bool is_yielding, typename R, typename... A, typename Fx, typename... Args> template <bool is_yielding, typename R, typename... A, typename Fx, typename... Args>
static void select_convertible(types<R(A...)> t, lua_State* L, Fx&& fx, Args&&... args) { static void select_convertible(types<R(A...)> t, lua_State* L, Fx&& fx, Args&&... args) {
typedef std::decay_t<meta::unwrap_unqualified_t<Fx>> raw_fx_t; typedef std::decay_t<meta::unwrap_unqualified_t<Fx>> raw_fx_t;
typedef R (*fx_ptr_t)(A...); typedef R (*fx_ptr_t)(A...);
typedef std::is_convertible<raw_fx_t, fx_ptr_t> is_convertible; constexpr bool is_convertible = std::is_convertible_v<raw_fx_t, fx_ptr_t>;
select_convertible<is_yielding>(is_convertible(), t, L, std::forward<Fx>(fx), std::forward<Args>(args)...); if constexpr (is_convertible) {
using fx_ptr_t = R (*)(A...);
fx_ptr_t fxptr = detail::unwrap(std::forward<Fx>(fx));
select_function<is_yielding>(std::true_type(), L, fxptr, std::forward<Args>(args)...);
}
else {
typedef std::remove_pointer_t<std::decay_t<Fx>> clean_fx;
typedef function_detail::functor_function<clean_fx, is_yielding, true> F;
set_fx<false, F>(L, std::forward<Fx>(fx), std::forward<Args>(args)...);
}
} }
template <bool is_yielding, typename Fx, typename... Args> template <bool is_yielding, typename Fx, typename... Args>
@ -71,27 +66,6 @@ namespace sol {
select_convertible<is_yielding>(types<Sig>(), L, std::forward<Fx>(fx), std::forward<Args>(args)...); select_convertible<is_yielding>(types<Sig>(), L, std::forward<Fx>(fx), std::forward<Args>(args)...);
} }
template <bool is_yielding, typename Fx, typename T, typename... Args>
static void select_reference_member_variable(std::false_type, lua_State* L, Fx&& fx, T&& obj, Args&&... args) {
typedef std::remove_pointer_t<std::decay_t<Fx>> clean_fx;
typedef function_detail::member_variable<meta::unwrap_unqualified_t<T>, clean_fx, is_yielding> F;
set_fx<false, F>(L, std::forward<Fx>(fx), std::forward<T>(obj), std::forward<Args>(args)...);
}
template <bool is_yielding, typename Fx, typename T, typename... Args>
static void select_reference_member_variable(std::true_type, lua_State* L, Fx&& fx, T&& obj, Args&&... args) {
typedef std::decay_t<Fx> dFx;
dFx memfxptr(std::forward<Fx>(fx));
auto userptr = detail::ptr(std::forward<T>(obj), std::forward<Args>(args)...);
lua_CFunction freefunc = &function_detail::upvalue_member_variable<std::decay_t<decltype(*userptr)>, meta::unqualified_t<Fx>, is_yielding>::call;
int upvalues = 0;
upvalues += stack::push(L, nullptr);
upvalues += stack::stack_detail::push_as_upvalues(L, memfxptr);
upvalues += stack::push(L, static_cast<void const*>(userptr));
stack::push(L, c_closure(freefunc, upvalues));
}
template <bool is_yielding, typename Fx, typename... Args> template <bool is_yielding, typename Fx, typename... Args>
static void select_member_variable(std::false_type, lua_State* L, Fx&& fx, Args&&... args) { static void select_member_variable(std::false_type, lua_State* L, Fx&& fx, Args&&... args) {
select_convertible<is_yielding>(types<Sigs...>(), L, std::forward<Fx>(fx), std::forward<Args>(args)...); select_convertible<is_yielding>(types<Sigs...>(), L, std::forward<Fx>(fx), std::forward<Args>(args)...);
@ -99,8 +73,25 @@ namespace sol {
template <bool is_yielding, typename Fx, typename T, typename... Args, meta::disable<meta::is_specialization_of<meta::unqualified_t<T>, function_detail::class_indicator>> = meta::enabler> template <bool is_yielding, typename Fx, typename T, typename... Args, meta::disable<meta::is_specialization_of<meta::unqualified_t<T>, function_detail::class_indicator>> = meta::enabler>
static void select_member_variable(std::true_type, lua_State* L, Fx&& fx, T&& obj, Args&&... args) { static void select_member_variable(std::true_type, lua_State* L, Fx&& fx, T&& obj, Args&&... args) {
typedef meta::boolean<meta::is_specialization_of<meta::unqualified_t<T>, std::reference_wrapper>::value || std::is_pointer<T>::value> is_reference; constexpr bool is_reference = meta::is_specialization_of_v<meta::unqualified_t<T>, std::reference_wrapper> || std::is_pointer_v<T>;
select_reference_member_variable<is_yielding>(is_reference(), L, std::forward<Fx>(fx), std::forward<T>(obj), std::forward<Args>(args)...); if constexpr(is_reference) {
typedef std::decay_t<Fx> dFx;
dFx memfxptr(std::forward<Fx>(fx));
auto userptr = detail::ptr(std::forward<T>(obj), std::forward<Args>(args)...);
lua_CFunction freefunc
= &function_detail::upvalue_member_variable<std::decay_t<decltype(*userptr)>, meta::unqualified_t<Fx>, is_yielding>::call;
int upvalues = 0;
upvalues += stack::push(L, nullptr);
upvalues += stack::stack_detail::push_as_upvalues(L, memfxptr);
upvalues += stack::push(L, static_cast<void const*>(userptr));
stack::push(L, c_closure(freefunc, upvalues));
}
else {
using clean_fx = std::remove_pointer_t<std::decay_t<Fx>>;
using F = function_detail::member_variable<meta::unwrap_unqualified_t<T>, clean_fx, is_yielding>;
set_fx<false, F>(L, std::forward<Fx>(fx), std::forward<T>(obj), std::forward<Args>(args)...);
}
} }
template <bool is_yielding, typename Fx, typename C> template <bool is_yielding, typename Fx, typename C>
@ -230,17 +221,20 @@ namespace sol {
stack::push(L, c_closure(freefunc, upvalues)); stack::push(L, c_closure(freefunc, upvalues));
} }
template <typename Arg0, typename... Args, meta::disable<std::is_same<detail::yield_tag_t, meta::unqualified_t<Arg0>>> = meta::enabler> template <typename Arg0, typename... Args>
static int push(lua_State* L, Arg0&& arg0, Args&&... args) { static int push(lua_State* L, Arg0&& arg0, Args&&... args) {
// Set will always place one thing (function) on the stack if constexpr(std::is_same_v<meta::unqualified_t<Arg0>, detail::yield_tag_t>) {
select<true>(L, std::forward<Args>(args)...);
}
else {
select<false>(L, std::forward<Arg0>(arg0), std::forward<Args>(args)...); select<false>(L, std::forward<Arg0>(arg0), std::forward<Args>(args)...);
}
return 1; return 1;
} }
template <typename... Args> template <typename... Args>
static int push(lua_State* L, detail::yield_tag_t, Args&&... args) { static int push(lua_State* L, detail::yield_tag_t, Args&&... args) {
// Set will always place one thing (function) on the stack // Set will always place one thing (function) on the stack
select<true>(L, std::forward<Args>(args)...);
return 1; return 1;
} }
}; };
@ -258,7 +252,7 @@ namespace sol {
static int push(lua_State* L, yielding_t<T>&& f, Args&&... args) { static int push(lua_State* L, yielding_t<T>&& f, Args&&... args) {
unqualified_pusher<function_sig<>> p{}; unqualified_pusher<function_sig<>> p{};
(void)p; (void)p;
return p.push(L, detail::yield_tag, f.func, std::forward<Args>(args)...); return p.push(L, detail::yield_tag, std::move(f.func), std::forward<Args>(args)...);
} }
}; };

View File

@ -140,11 +140,8 @@ namespace sol {
template <bool B> template <bool B>
using boolean = std::integral_constant<bool, B>; using boolean = std::integral_constant<bool, B>;
template <typename T> template <bool B>
using invoke_t = typename T::type; constexpr inline bool boolean_v = boolean<B>::value;
template <typename T>
using invoke_v = boolean<T::value>;
template <typename T> template <typename T>
using neg = boolean<!T::value>; using neg = boolean<!T::value>;
@ -518,29 +515,21 @@ namespace sol {
struct is_matched_lookup_impl<T, true> : std::is_same<typename T::key_type, typename T::value_type> {}; struct is_matched_lookup_impl<T, true> : std::is_same<typename T::key_type, typename T::value_type> {};
} // namespace meta_detail } // namespace meta_detail
#if defined(_MSC_VER) && _MSC_VER <= 1910
template <typename T, typename U = T> template <typename T, typename U = T>
using supports_op_less = decltype(meta_detail::supports_op_less_test(std::ref(std::declval<T&>()), std::ref(std::declval<U&>()))); struct supports_op_less : decltype(meta_detail::supports_op_less_test(std::declval<T&>(), std::declval<U&>())) {};
template <typename T, typename U = T>
using supports_op_equal = decltype(meta_detail::supports_op_equal_test(std::ref(std::declval<T&>()), std::ref(std::declval<U&>())));
template <typename T, typename U = T>
using supports_op_less_equal = decltype(meta_detail::supports_op_less_equal_test(std::ref(std::declval<T&>()), std::ref(std::declval<U&>())));
template <typename T, typename U = std::ostream>
using supports_ostream_op = decltype(meta_detail::supports_ostream_op(std::ref(std::declval<T&>()), std::ref(std::declval<U&>())));
template <typename T> template <typename T>
using supports_adl_to_string = decltype(meta_detail::supports_adl_to_string(std::ref(std::declval<T&>()))); struct supports_op_less<void, T> : std::false_type {};
#else
template <typename T, typename U = T>
using supports_op_less = decltype(meta_detail::supports_op_less_test(std::declval<T&>(), std::declval<U&>()));
template <typename T, typename U = T>
using supports_op_equal = decltype(meta_detail::supports_op_equal_test(std::declval<T&>(), std::declval<U&>()));
template <typename T, typename U = T>
using supports_op_less_equal = decltype(meta_detail::supports_op_less_equal_test(std::declval<T&>(), std::declval<U&>()));
template <typename T, typename U = std::ostream>
using supports_ostream_op = decltype(meta_detail::supports_ostream_op(std::declval<T&>(), std::declval<U&>()));
template <typename T> template <typename T>
using supports_adl_to_string = decltype(meta_detail::supports_adl_to_string(std::declval<T&>())); struct supports_op_less<T, void> : std::false_type {};
#endif template <typename T, typename U = T>
struct supports_op_equal : decltype(meta_detail::supports_op_equal_test(std::declval<T&>(), std::declval<U&>())) {};
template <typename T, typename U = T>
struct supports_op_less_equal : decltype(meta_detail::supports_op_less_equal_test(std::declval<T&>(), std::declval<U&>())) {};
template <typename T, typename U = std::ostream>
struct supports_ostream_op : decltype(meta_detail::supports_ostream_op(std::declval<T&>(), std::declval<U&>())) {};
template <typename T>
struct supports_adl_to_string : decltype(meta_detail::supports_adl_to_string(std::declval<T&>())) {};
template <typename T> template <typename T>
using supports_to_string_member = meta::boolean<meta_detail::has_to_string_test<T>::value>; using supports_to_string_member = meta::boolean<meta_detail::has_to_string_test<T>::value>;