Make sure resolve works and provide some protection against deleting the handler that originates from a specific sol::state. sol::state_view users will be left out in the dark, though.

This commit is contained in:
ThePhD 2016-12-26 13:50:08 -05:00
parent 3aa42c5db8
commit 26b85c8136
4 changed files with 297 additions and 253 deletions

View File

@ -5,15 +5,21 @@ getting good final product out of sol2
For individiauls who use :doc:`usertypes<api/usertype>` a lot, they can find their compilation times increase. This is due to C++11 and C++14 not having very good facilities for handling template parameters and variadic template parameters. There are a few things in cutting-edge C++17 and C++Next that sol can use, but the problem is many people cannot work with the latest and greatest: therefore, we have to use older techniques that result in a fair amount of redundant function specializations that can be subject to the pickiness of the compiler's inlining and other such techniques.
what to do
----------
Here are some notes on achieving better compile-times without sacrificing too much performance:
* When you bind lots of usertypes, put them all in a *single* translation unit (one C++ file) so that it is not recompiled multiple times over, only to be discarded later by the linker.
- Remember that the usertype binding ends up being serialized into the Lua state, so you never need them to appear in a header and cause that same compilation overhead for every compiled unit in your project.
* For extremely large usertypes, consider using :doc:`simple_usertype<api/simple_usertype>`.
- It performs much more work at runtime rather than compile-time, and should still give comparative performance (but it loses out in some cases for variable bindings or when you bind all functions to a usertype).
* If you are developing a shared library, restrict your overall surface area by specifically and explicitly marking functions as visible and exported and letting everything else as hidden or invisible by default
* If you are developing a shared library, restrict your overall surface area by specifically and explicitly marking functions as visible and exported and leaving everything else as hidden or invisible by default
next steps
----------
The next step for Sol from a developer standpoint is to formally make the library a C++17 one. This would mean using Fold Expressions and several other things which will reduce compilation time drastically. Unfortunately, that means also boosting compiler requirements. While most wouldn't care, others are very slow to upgrade: finding the balance is difficult, and often we have to opt for backwards compatibility and fixes for bad / older compilers (of which there are many in the codebase already).
Hopefully, as things progress, we move things forward.

View File

@ -20,8 +20,8 @@
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// This file was generated with a script.
// Generated 2016-12-16 10:31:09.106965 UTC
// This header was generated with sol v2.15.5 (revision 87f8456)
// Generated 2016-12-26 18:50:00.916890 UTC
// This header was generated with sol v2.15.5 (revision 3aa42c5)
// https://github.com/ThePhD/sol2
#ifndef SOL_SINGLE_INCLUDE_HPP
@ -8531,9 +8531,10 @@ namespace sol {
// beginning of sol/resolve.hpp
namespace sol {
// Clang has distinct problems with constexpr arguments,
// so don't use the constexpr versions inside of clang.
#ifndef __clang__
// constexpr is fine for not-clang
namespace detail {
template<typename R, typename... Args, typename F, typename = std::result_of_t<meta::unqualified_t<F>(Args...)>>
inline constexpr auto resolve_i(types<R(Args...)>, F&&)->R(meta::unqualified_t<F>::*)(Args...) {
@ -8600,6 +8601,10 @@ namespace sol {
return detail::resolve_i(types<Sig...>(), std::forward<F>(f));
}
#else
// Clang has distinct problems with constexpr arguments,
// so don't use the constexpr versions inside of clang.
namespace detail {
template<typename R, typename... Args, typename F, typename = std::result_of_t<meta::unqualified_t<F>(Args...)>>
inline auto resolve_i(types<R(Args...)>, F&&)->R(meta::unqualified_t<F>::*)(Args...) {
@ -8665,7 +8670,9 @@ namespace sol {
inline auto resolve(F&& f) -> decltype(detail::resolve_i(types<Sig...>(), std::forward<F>(f))) {
return detail::resolve_i(types<Sig...>(), std::forward<F>(f));
}
#endif
} // sol
// end of sol/resolve.hpp
@ -12829,7 +12836,19 @@ namespace sol {
stack::luajit_exception_handler(unique_base::get());
}
state(const state&) = delete;
state(state&&) = default;
state& operator=(const state&) = delete;
state& operator=(state&&) = default;
using state_view::get;
~state() {
auto& handler = protected_function::get_default_handler();
if (handler.lua_state() == this->lua_state()) {
protected_function::set_default_handler(reference());
}
}
};
} // sol

View File

@ -1,166 +1,173 @@
// The MIT License (MIT)
// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#ifndef SOL_RESOLVE_HPP
#define SOL_RESOLVE_HPP
#include "traits.hpp"
#include "tuple.hpp"
namespace sol {
// Clang has distinct problems with constexpr arguments,
// so don't use the constexpr versions inside of clang.
#ifndef __clang__
namespace detail {
template<typename R, typename... Args, typename F, typename = std::result_of_t<meta::unqualified_t<F>(Args...)>>
inline constexpr auto resolve_i(types<R(Args...)>, F&&)->R(meta::unqualified_t<F>::*)(Args...) {
using Sig = R(Args...);
typedef meta::unqualified_t<F> Fu;
return static_cast<Sig Fu::*>(&Fu::operator());
}
template<typename F, typename U = meta::unqualified_t<F>>
inline constexpr auto resolve_f(std::true_type, F&& f)
-> decltype(resolve_i(types<meta::function_signature_t<decltype(&U::operator())>>(), std::forward<F>(f))) {
return resolve_i(types<meta::function_signature_t<decltype(&U::operator())>>(), std::forward<F>(f));
}
template<typename F>
inline constexpr void resolve_f(std::false_type, F&&) {
static_assert(meta::has_deducible_signature<F>::value,
"Cannot use no-template-parameter call with an overloaded functor: specify the signature");
}
template<typename F, typename U = meta::unqualified_t<F>>
inline constexpr auto resolve_i(types<>, F&& f) -> decltype(resolve_f(meta::has_deducible_signature<U>(), std::forward<F>(f))) {
return resolve_f(meta::has_deducible_signature<U> {}, std::forward<F>(f));
}
template<typename... Args, typename F, typename R = std::result_of_t<F&(Args...)>>
inline constexpr auto resolve_i(types<Args...>, F&& f) -> decltype(resolve_i(types<R(Args...)>(), std::forward<F>(f))) {
return resolve_i(types<R(Args...)>(), std::forward<F>(f));
}
template<typename Sig, typename C>
inline constexpr Sig C::* resolve_v(std::false_type, Sig C::* mem_func_ptr) {
return mem_func_ptr;
}
template<typename Sig, typename C>
inline constexpr Sig C::* resolve_v(std::true_type, Sig C::* mem_variable_ptr) {
return mem_variable_ptr;
}
} // detail
template<typename... Args, typename R>
inline constexpr auto resolve(R fun_ptr(Args...))->R(*)(Args...) {
return fun_ptr;
}
template<typename Sig>
inline constexpr Sig* resolve(Sig* fun_ptr) {
return fun_ptr;
}
template<typename... Args, typename R, typename C>
inline constexpr auto resolve(R(C::*mem_ptr)(Args...))->R(C::*)(Args...) {
return mem_ptr;
}
template<typename Sig, typename C>
inline constexpr Sig C::* resolve(Sig C::* mem_ptr) {
return detail::resolve_v(std::is_member_object_pointer<Sig C::*>(), mem_ptr);
}
template<typename... Sig, typename F, meta::disable<std::is_function<meta::unqualified_t<F>>> = meta::enabler>
inline constexpr auto resolve(F&& f) -> decltype(detail::resolve_i(types<Sig...>(), std::forward<F>(f))) {
return detail::resolve_i(types<Sig...>(), std::forward<F>(f));
}
#else
namespace detail {
template<typename R, typename... Args, typename F, typename = std::result_of_t<meta::unqualified_t<F>(Args...)>>
inline auto resolve_i(types<R(Args...)>, F&&)->R(meta::unqualified_t<F>::*)(Args...) {
using Sig = R(Args...);
typedef meta::unqualified_t<F> Fu;
return static_cast<Sig Fu::*>(&Fu::operator());
}
template<typename F, typename U = meta::unqualified_t<F>>
inline auto resolve_f(std::true_type, F&& f)
-> decltype(resolve_i(types<meta::function_signature_t<decltype(&U::operator())>>(), std::forward<F>(f))) {
return resolve_i(types<meta::function_signature_t<decltype(&U::operator())>>(), std::forward<F>(f));
}
template<typename F>
inline void resolve_f(std::false_type, F&&) {
static_assert(meta::has_deducible_signature<F>::value,
"Cannot use no-template-parameter call with an overloaded functor: specify the signature");
}
template<typename F, typename U = meta::unqualified_t<F>>
inline auto resolve_i(types<>, F&& f) -> decltype(resolve_f(meta::has_deducible_signature<U>(), std::forward<F>(f))) {
return resolve_f(meta::has_deducible_signature<U> {}, std::forward<F>(f));
}
template<typename... Args, typename F, typename R = std::result_of_t<F&(Args...)>>
inline auto resolve_i(types<Args...>, F&& f) -> decltype(resolve_i(types<R(Args...)>(), std::forward<F>(f))) {
return resolve_i(types<R(Args...)>(), std::forward<F>(f));
}
template<typename Sig, typename C>
inline Sig C::* resolve_v(std::false_type, Sig C::* mem_func_ptr) {
return mem_func_ptr;
}
template<typename Sig, typename C>
inline Sig C::* resolve_v(std::true_type, Sig C::* mem_variable_ptr) {
return mem_variable_ptr;
}
} // detail
template<typename... Args, typename R>
inline auto resolve(R fun_ptr(Args...))->R(*)(Args...) {
return fun_ptr;
}
template<typename Sig>
inline Sig* resolve(Sig* fun_ptr) {
return fun_ptr;
}
template<typename... Args, typename R, typename C>
inline auto resolve(R(C::*mem_ptr)(Args...))->R(C::*)(Args...) {
return mem_ptr;
}
template<typename Sig, typename C>
inline Sig C::* resolve(Sig C::* mem_ptr) {
return detail::resolve_v(std::is_member_object_pointer<Sig C::*>(), mem_ptr);
}
template<typename... Sig, typename F>
inline auto resolve(F&& f) -> decltype(detail::resolve_i(types<Sig...>(), std::forward<F>(f))) {
return detail::resolve_i(types<Sig...>(), std::forward<F>(f));
}
#endif
} // sol
#endif // SOL_RESOLVE_HPP
// The MIT License (MIT)
// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#ifndef SOL_RESOLVE_HPP
#define SOL_RESOLVE_HPP
#include "traits.hpp"
#include "tuple.hpp"
namespace sol {
#ifndef __clang__
// constexpr is fine for not-clang
namespace detail {
template<typename R, typename... Args, typename F, typename = std::result_of_t<meta::unqualified_t<F>(Args...)>>
inline constexpr auto resolve_i(types<R(Args...)>, F&&)->R(meta::unqualified_t<F>::*)(Args...) {
using Sig = R(Args...);
typedef meta::unqualified_t<F> Fu;
return static_cast<Sig Fu::*>(&Fu::operator());
}
template<typename F, typename U = meta::unqualified_t<F>>
inline constexpr auto resolve_f(std::true_type, F&& f)
-> decltype(resolve_i(types<meta::function_signature_t<decltype(&U::operator())>>(), std::forward<F>(f))) {
return resolve_i(types<meta::function_signature_t<decltype(&U::operator())>>(), std::forward<F>(f));
}
template<typename F>
inline constexpr void resolve_f(std::false_type, F&&) {
static_assert(meta::has_deducible_signature<F>::value,
"Cannot use no-template-parameter call with an overloaded functor: specify the signature");
}
template<typename F, typename U = meta::unqualified_t<F>>
inline constexpr auto resolve_i(types<>, F&& f) -> decltype(resolve_f(meta::has_deducible_signature<U>(), std::forward<F>(f))) {
return resolve_f(meta::has_deducible_signature<U> {}, std::forward<F>(f));
}
template<typename... Args, typename F, typename R = std::result_of_t<F&(Args...)>>
inline constexpr auto resolve_i(types<Args...>, F&& f) -> decltype(resolve_i(types<R(Args...)>(), std::forward<F>(f))) {
return resolve_i(types<R(Args...)>(), std::forward<F>(f));
}
template<typename Sig, typename C>
inline constexpr Sig C::* resolve_v(std::false_type, Sig C::* mem_func_ptr) {
return mem_func_ptr;
}
template<typename Sig, typename C>
inline constexpr Sig C::* resolve_v(std::true_type, Sig C::* mem_variable_ptr) {
return mem_variable_ptr;
}
} // detail
template<typename... Args, typename R>
inline constexpr auto resolve(R fun_ptr(Args...))->R(*)(Args...) {
return fun_ptr;
}
template<typename Sig>
inline constexpr Sig* resolve(Sig* fun_ptr) {
return fun_ptr;
}
template<typename... Args, typename R, typename C>
inline constexpr auto resolve(R(C::*mem_ptr)(Args...))->R(C::*)(Args...) {
return mem_ptr;
}
template<typename Sig, typename C>
inline constexpr Sig C::* resolve(Sig C::* mem_ptr) {
return detail::resolve_v(std::is_member_object_pointer<Sig C::*>(), mem_ptr);
}
template<typename... Sig, typename F, meta::disable<std::is_function<meta::unqualified_t<F>>> = meta::enabler>
inline constexpr auto resolve(F&& f) -> decltype(detail::resolve_i(types<Sig...>(), std::forward<F>(f))) {
return detail::resolve_i(types<Sig...>(), std::forward<F>(f));
}
#else
// Clang has distinct problems with constexpr arguments,
// so don't use the constexpr versions inside of clang.
namespace detail {
template<typename R, typename... Args, typename F, typename = std::result_of_t<meta::unqualified_t<F>(Args...)>>
inline auto resolve_i(types<R(Args...)>, F&&)->R(meta::unqualified_t<F>::*)(Args...) {
using Sig = R(Args...);
typedef meta::unqualified_t<F> Fu;
return static_cast<Sig Fu::*>(&Fu::operator());
}
template<typename F, typename U = meta::unqualified_t<F>>
inline auto resolve_f(std::true_type, F&& f)
-> decltype(resolve_i(types<meta::function_signature_t<decltype(&U::operator())>>(), std::forward<F>(f))) {
return resolve_i(types<meta::function_signature_t<decltype(&U::operator())>>(), std::forward<F>(f));
}
template<typename F>
inline void resolve_f(std::false_type, F&&) {
static_assert(meta::has_deducible_signature<F>::value,
"Cannot use no-template-parameter call with an overloaded functor: specify the signature");
}
template<typename F, typename U = meta::unqualified_t<F>>
inline auto resolve_i(types<>, F&& f) -> decltype(resolve_f(meta::has_deducible_signature<U>(), std::forward<F>(f))) {
return resolve_f(meta::has_deducible_signature<U> {}, std::forward<F>(f));
}
template<typename... Args, typename F, typename R = std::result_of_t<F&(Args...)>>
inline auto resolve_i(types<Args...>, F&& f) -> decltype(resolve_i(types<R(Args...)>(), std::forward<F>(f))) {
return resolve_i(types<R(Args...)>(), std::forward<F>(f));
}
template<typename Sig, typename C>
inline Sig C::* resolve_v(std::false_type, Sig C::* mem_func_ptr) {
return mem_func_ptr;
}
template<typename Sig, typename C>
inline Sig C::* resolve_v(std::true_type, Sig C::* mem_variable_ptr) {
return mem_variable_ptr;
}
} // detail
template<typename... Args, typename R>
inline auto resolve(R fun_ptr(Args...))->R(*)(Args...) {
return fun_ptr;
}
template<typename Sig>
inline Sig* resolve(Sig* fun_ptr) {
return fun_ptr;
}
template<typename... Args, typename R, typename C>
inline auto resolve(R(C::*mem_ptr)(Args...))->R(C::*)(Args...) {
return mem_ptr;
}
template<typename Sig, typename C>
inline Sig C::* resolve(Sig C::* mem_ptr) {
return detail::resolve_v(std::is_member_object_pointer<Sig C::*>(), mem_ptr);
}
template<typename... Sig, typename F>
inline auto resolve(F&& f) -> decltype(detail::resolve_i(types<Sig...>(), std::forward<F>(f))) {
return detail::resolve_i(types<Sig...>(), std::forward<F>(f));
}
#endif
} // sol
#endif // SOL_RESOLVE_HPP

View File

@ -1,82 +1,94 @@
// The MIT License (MIT)
// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#ifndef SOL_STATE_HPP
#define SOL_STATE_HPP
#include "state_view.hpp"
namespace sol {
inline int default_at_panic(lua_State* L) {
#ifdef SOL_NO_EXCEPTIONS
(void)L;
return -1;
#else
const char* message = lua_tostring(L, -1);
if (message) {
std::string err = message;
lua_pop(L, 1);
throw error(err);
}
throw error(std::string("An unexpected error occurred and forced the lua state to call atpanic"));
#endif
}
inline int default_error_handler(lua_State*L) {
using namespace sol;
std::string msg = "An unknown error has triggered the default error handler";
optional<string_detail::string_shim> maybetopmsg = stack::check_get<string_detail::string_shim>(L, 1);
if (maybetopmsg) {
const string_detail::string_shim& topmsg = maybetopmsg.value();
msg.assign(topmsg.c_str(), topmsg.size());
}
luaL_traceback(L, L, msg.c_str(), 1);
optional<string_detail::string_shim> maybetraceback = stack::check_get<string_detail::string_shim>(L, -1);
if (maybetraceback) {
const string_detail::string_shim& traceback = maybetraceback.value();
msg.assign(traceback.c_str(), traceback.size());
}
return stack::push(L, msg);
}
class state : private std::unique_ptr<lua_State, void(*)(lua_State*)>, public state_view {
private:
typedef std::unique_ptr<lua_State, void(*)(lua_State*)> unique_base;
public:
state(lua_CFunction panic = default_at_panic) : unique_base(luaL_newstate(), lua_close),
state_view(unique_base::get()) {
set_panic(panic);
stack::luajit_exception_handler(unique_base::get());
}
state(lua_CFunction panic, lua_Alloc alfunc, void* alpointer = nullptr) : unique_base(lua_newstate(alfunc, alpointer), lua_close),
state_view(unique_base::get()) {
set_panic(panic);
sol::protected_function::set_default_handler(sol::object(lua_state(), in_place, default_error_handler));
stack::luajit_exception_handler(unique_base::get());
}
using state_view::get;
};
} // sol
#endif // SOL_STATE_HPP
// The MIT License (MIT)
// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#ifndef SOL_STATE_HPP
#define SOL_STATE_HPP
#include "state_view.hpp"
namespace sol {
inline int default_at_panic(lua_State* L) {
#ifdef SOL_NO_EXCEPTIONS
(void)L;
return -1;
#else
const char* message = lua_tostring(L, -1);
if (message) {
std::string err = message;
lua_pop(L, 1);
throw error(err);
}
throw error(std::string("An unexpected error occurred and forced the lua state to call atpanic"));
#endif
}
inline int default_error_handler(lua_State*L) {
using namespace sol;
std::string msg = "An unknown error has triggered the default error handler";
optional<string_detail::string_shim> maybetopmsg = stack::check_get<string_detail::string_shim>(L, 1);
if (maybetopmsg) {
const string_detail::string_shim& topmsg = maybetopmsg.value();
msg.assign(topmsg.c_str(), topmsg.size());
}
luaL_traceback(L, L, msg.c_str(), 1);
optional<string_detail::string_shim> maybetraceback = stack::check_get<string_detail::string_shim>(L, -1);
if (maybetraceback) {
const string_detail::string_shim& traceback = maybetraceback.value();
msg.assign(traceback.c_str(), traceback.size());
}
return stack::push(L, msg);
}
class state : private std::unique_ptr<lua_State, void(*)(lua_State*)>, public state_view {
private:
typedef std::unique_ptr<lua_State, void(*)(lua_State*)> unique_base;
public:
state(lua_CFunction panic = default_at_panic) : unique_base(luaL_newstate(), lua_close),
state_view(unique_base::get()) {
set_panic(panic);
stack::luajit_exception_handler(unique_base::get());
}
state(lua_CFunction panic, lua_Alloc alfunc, void* alpointer = nullptr) : unique_base(lua_newstate(alfunc, alpointer), lua_close),
state_view(unique_base::get()) {
set_panic(panic);
sol::protected_function::set_default_handler(sol::object(lua_state(), in_place, default_error_handler));
stack::luajit_exception_handler(unique_base::get());
}
state(const state&) = delete;
state(state&&) = default;
state& operator=(const state&) = delete;
state& operator=(state&&) = default;
using state_view::get;
~state() {
auto& handler = protected_function::get_default_handler();
if (handler.lua_state() == this->lua_state()) {
protected_function::set_default_handler(reference());
}
}
};
} // sol
#endif // SOL_STATE_HPP