mirror of
https://github.com/ThePhD/sol2.git
synced 2024-03-22 13:10:44 +08:00
memory tracker and separate-definition ADL customization points, inspired by Olek and Aurailus
This commit is contained in:
parent
e8649d276b
commit
9294afc082
|
@ -36,6 +36,9 @@ if (SOL2_INTEROP_EXAMPLES OR SOL2_INTEROP_EXAMPLES_SINGLE OR SOL2_INTEROP_EXAMPL
|
|||
add_subdirectory(interop/luwra)
|
||||
endif()
|
||||
|
||||
# # In-depth customization example
|
||||
add_subdirectory(customization)
|
||||
|
||||
# # Utility assert.hpp "library"
|
||||
add_library(sol2_assert INTERFACE)
|
||||
add_library(sol2::assert ALIAS sol2_assert)
|
||||
|
|
68
examples/customization/CMakeLists.txt
Normal file
68
examples/customization/CMakeLists.txt
Normal file
|
@ -0,0 +1,68 @@
|
|||
# # # # sol3
|
||||
# The MIT License (MIT)
|
||||
#
|
||||
# Copyright (c) 2013-2019 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.
|
||||
|
||||
# # # sol3 Customization Examples
|
||||
|
||||
function (MAKE_CUSTOMIZATION_EXAMPLE example_suffix target_sol)
|
||||
set(customization_example_name customization_to_table${example_suffix})
|
||||
|
||||
add_executable(${customization_example_name} source/main.cpp source/lua_interop.cpp source/lua_zm_interop.cpp)
|
||||
set_target_properties(${customization_example_name}
|
||||
PROPERTIES
|
||||
OUTPUT_NAME "${customization_example_name}"
|
||||
EXPORT_NAME sol2::${customization_example_name})
|
||||
|
||||
if (MSVC)
|
||||
target_compile_options(${customization_example_name}
|
||||
PRIVATE /std:c++latest /EHsc "$<$<CONFIG:Debug>:/MDd>"
|
||||
"$<$<CONFIG:Release>:/MD>"
|
||||
"$<$<CONFIG:RelWithDebInfo>:/MD>"
|
||||
"$<$<CONFIG:MinSizeRel>:/MD>")
|
||||
target_compile_definitions(${customization_example_name}
|
||||
PRIVATE UNICODE _UNICODE
|
||||
_CRT_SECURE_NO_WARNINGS _CRT_SECURE_NO_DEPRECATE)
|
||||
else()
|
||||
target_compile_options(${customization_example_name}
|
||||
PRIVATE -std=c++1z
|
||||
-ftemplate-backtrace-limit=0
|
||||
-Wno-unknown-warning -Wno-unknown-warning-option
|
||||
-Wall -Wpedantic -Werror -pedantic -pedantic-errors
|
||||
-Wno-noexcept-type)
|
||||
endif()
|
||||
|
||||
target_link_libraries(${customization_example_name}
|
||||
PRIVATE Threads::Threads ${target_sol} ${LUA_LIBRARIES})
|
||||
target_include_directories(${customization_example_name}
|
||||
PRIVATE include)
|
||||
endfunction()
|
||||
|
||||
if (SOL2_EXAMPLES)
|
||||
MAKE_CUSTOMIZATION_EXAMPLE("" sol2::sol2)
|
||||
endif()
|
||||
|
||||
if (SOL2_EXAMPLES_SINGLE)
|
||||
MAKE_CUSTOMIZATION_EXAMPLE(".single" sol2::sol2_single)
|
||||
endif()
|
||||
|
||||
if (SOL2_EXAMPLES_SINGLE_GENERATED)
|
||||
MAKE_CUSTOMIZATION_EXAMPLE(".single.generated" sol2::sol2_single_generated)
|
||||
endif()
|
25
examples/customization/include/entity.hpp
Normal file
25
examples/customization/include/entity.hpp
Normal file
|
@ -0,0 +1,25 @@
|
|||
#pragma once
|
||||
|
||||
#ifndef PROGRAM_ENTITY_HPP
|
||||
#define PROGRAM_ENTITY_HPP
|
||||
|
||||
#include <zm/vec3.hpp>
|
||||
|
||||
class entity {
|
||||
private:
|
||||
zm::vec3 position_;
|
||||
|
||||
public:
|
||||
entity() {
|
||||
this->position_ = { 1, 1, 1 };
|
||||
}
|
||||
|
||||
zm::vec3 get_position() const {
|
||||
return this->position_;
|
||||
}
|
||||
void set_position(zm::vec3 v) {
|
||||
this->position_ = v;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // PROGRAM_ENTITY_HPP
|
13
examples/customization/include/lua_interop.hpp
Normal file
13
examples/customization/include/lua_interop.hpp
Normal file
|
@ -0,0 +1,13 @@
|
|||
#pragma once
|
||||
|
||||
#ifndef PROGRAM_LUA_INTEROP_HPP
|
||||
#define PROGRAM_LUA_INTEROP_HPP
|
||||
|
||||
#include <lua_zm_interop.hpp>
|
||||
|
||||
#define SOL_ALL_SAFETIES_ON 1
|
||||
#include <sol/forward.hpp>
|
||||
|
||||
void register_lua(sol::state& lua);
|
||||
|
||||
#endif // PROGRAM_LUA_INTEROP_HPP
|
19
examples/customization/include/lua_zm_interop.hpp
Normal file
19
examples/customization/include/lua_zm_interop.hpp
Normal file
|
@ -0,0 +1,19 @@
|
|||
#pragma once
|
||||
|
||||
#ifndef PROGRAM_LUA_ZM_INTEROP_HPP
|
||||
#define PROGRAM_LUA_ZM_INTEROP_HPP
|
||||
|
||||
#define SOL_ALL_SAFETIES_ON 1
|
||||
#include <sol/forward.hpp>
|
||||
|
||||
#include <zm/vec3.hpp>
|
||||
|
||||
#include <functional>
|
||||
|
||||
bool sol_lua_check(sol::types<zm::vec3>, lua_State* L, int index, std::function<sol::check_handler_type> handler, sol::stack::record& tracking);
|
||||
|
||||
zm::vec3 sol_lua_get(sol::types<zm::vec3>, lua_State* L, int index, sol::stack::record& tracking);
|
||||
|
||||
int sol_lua_push(sol::types<zm::vec3>, lua_State* L, const zm::vec3& v);
|
||||
|
||||
#endif // PROGRAM_LUA_ZM_INTEROP_HPP
|
64
examples/customization/include/zm/vec3.hpp
Normal file
64
examples/customization/include/zm/vec3.hpp
Normal file
|
@ -0,0 +1,64 @@
|
|||
#pragma once
|
||||
|
||||
#ifndef ZM_VEC3_HPP
|
||||
#define ZM_VEC3_HPP
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
namespace zm {
|
||||
|
||||
struct vec3 {
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wgnu-anonymous-struct"
|
||||
#pragma clang diagnostic ignored "-Wnested-anon-types"
|
||||
#elif defined(__GNUC__)
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wpedantic"
|
||||
#elif defined(_MSC_VER)
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4201) // nonstandard extension used : nameless struct/union
|
||||
#pragma warning(disable : 4324) // structure was padded due to alignment specifier
|
||||
#endif
|
||||
union {
|
||||
float elements[3];
|
||||
struct {
|
||||
union {
|
||||
float x, r, s;
|
||||
};
|
||||
union {
|
||||
float y, g, t;
|
||||
};
|
||||
union {
|
||||
float z, b, p;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic pop
|
||||
#elif defined(__GNUC__)
|
||||
#pragma GCC diagnostic pop
|
||||
#elif defined(_MSC_VER)
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
constexpr float* data() {
|
||||
return elements;
|
||||
}
|
||||
|
||||
constexpr const float* data() const {
|
||||
return this->elements;
|
||||
}
|
||||
|
||||
constexpr float& operator[](std::size_t i) {
|
||||
return this->elements[i];
|
||||
}
|
||||
|
||||
constexpr const float& operator[](std::size_t i) const {
|
||||
return this->elements[i];
|
||||
}
|
||||
};
|
||||
} // namespace zm
|
||||
|
||||
#endif // ZM_VEC3_HPP
|
10
examples/customization/source/lua_interop.cpp
Normal file
10
examples/customization/source/lua_interop.cpp
Normal file
|
@ -0,0 +1,10 @@
|
|||
#include <lua_interop.hpp>
|
||||
|
||||
#include <entity.hpp>
|
||||
|
||||
#define SOL_ALL_SAFETIES_ON 1
|
||||
#include <sol/sol.hpp>
|
||||
|
||||
void register_lua(sol::state& lua) {
|
||||
lua.new_usertype<entity>("entity", "position", sol::property(&entity::get_position, &entity::set_position));
|
||||
}
|
31
examples/customization/source/lua_zm_interop.cpp
Normal file
31
examples/customization/source/lua_zm_interop.cpp
Normal file
|
@ -0,0 +1,31 @@
|
|||
#include <lua_zm_interop.hpp>
|
||||
|
||||
#include <zm/vec3.hpp>
|
||||
|
||||
#define SOL_ALL_SAFETIES_ON 1
|
||||
#include <sol/sol.hpp>
|
||||
|
||||
bool sol_lua_check(sol::types<zm::vec3>, lua_State* L, int index, std::function<sol::check_handler_type> handler, sol::stack::record& tracking) {
|
||||
// use sol's method for checking
|
||||
// specifically for a table
|
||||
return sol::stack::check<sol::lua_table>(L, index, handler, tracking);
|
||||
}
|
||||
|
||||
zm::vec3 sol_lua_get(sol::types<zm::vec3>, lua_State* L, int index, sol::stack::record& tracking) {
|
||||
sol::lua_table vec3table = sol::stack::get<sol::lua_table>(L, index, tracking);
|
||||
float x = vec3table["x"];
|
||||
float y = vec3table["y"];
|
||||
float z = vec3table["z"];
|
||||
return zm::vec3{ x, y, z };
|
||||
}
|
||||
|
||||
int sol_lua_push(sol::types<zm::vec3>, lua_State* L, const zm::vec3& v) {
|
||||
// create table
|
||||
sol::state_view lua(L);
|
||||
sol::table vec3table = sol::table::create_with(L, "x", v.x, "y", v.y, "z", v.z);
|
||||
// use base sol method to
|
||||
// push the table
|
||||
int amount = sol::stack::push(L, vec3table);
|
||||
// return # of things pushed onto stack
|
||||
return amount;
|
||||
}
|
39
examples/customization/source/main.cpp
Normal file
39
examples/customization/source/main.cpp
Normal file
|
@ -0,0 +1,39 @@
|
|||
#include <lua_interop.hpp>
|
||||
#include <entity.hpp>
|
||||
|
||||
#define SOL_ALL_SAFETIES_ON 1
|
||||
#include <sol/sol.hpp>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
int main(int, char* []) {
|
||||
std::cout << "=== customization: vec3 as table ===" << std::endl;
|
||||
|
||||
sol::state lua;
|
||||
lua.open_libraries(sol::lib::base);
|
||||
|
||||
std::cout << "registering entities into Lua ..." << std::endl;
|
||||
register_lua(lua);
|
||||
std::cout << "running script ..." << std::endl;
|
||||
|
||||
const auto& script = R"lua(
|
||||
local e = entity.new()
|
||||
local pos = e.position
|
||||
print("pos type", type(pos))
|
||||
print("pos", pos.x, pos.y, pos.z)
|
||||
e.position = { x = 52, y = 5.5, z = 47.5 }
|
||||
local new_pos = e.position
|
||||
print("pos", pos.x, pos.y, pos.z)
|
||||
print("new_pos", new_pos.x, new_pos.y, new_pos.z)
|
||||
)lua";
|
||||
|
||||
sol::optional<sol::error> result = lua.safe_script(script);
|
||||
if (result.has_value()) {
|
||||
std::cerr << "Something went horribly wrong: " << result.value().what() << std::endl;
|
||||
}
|
||||
|
||||
std::cout << "finishing ..." << std::endl;
|
||||
|
||||
std::cout << std::endl;
|
||||
return 0;
|
||||
}
|
132
examples/source/allocation_limit.cpp
Normal file
132
examples/source/allocation_limit.cpp
Normal file
|
@ -0,0 +1,132 @@
|
|||
#define SOL_ALL_SAFETIES_ON 1
|
||||
#include <sol/sol.hpp>
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdlib>
|
||||
|
||||
class memory_tracker {
|
||||
public:
|
||||
// 10 MB or something?
|
||||
// idk whatever
|
||||
inline static constexpr std::size_t arbitrary_default_limit = 1024 * 1024 * 10;
|
||||
|
||||
memory_tracker() : memory_tracker(arbitrary_default_limit) {
|
||||
}
|
||||
|
||||
memory_tracker(std::size_t maximum_memory) : used(0), limit(maximum_memory), n_threads(0), n_tables(0), n_functions(0), n_userdata(0), n_strings(0) {
|
||||
}
|
||||
|
||||
std::size_t currently_used() const {
|
||||
return used;
|
||||
}
|
||||
|
||||
std::size_t memory_limit() const {
|
||||
return limit;
|
||||
}
|
||||
|
||||
static void* allocate(void* memory_tracker_ud, void* ptr, size_t object_code, size_t nsize) {
|
||||
memory_tracker& self = (*static_cast<memory_tracker*>(memory_tracker_ud));
|
||||
return self.alloc(ptr, object_code, nsize);
|
||||
}
|
||||
|
||||
private:
|
||||
void* alloc(void* ptr, size_t original_block_size_or_code, size_t new_block_size) {
|
||||
std::size_t original_block_size = original_block_size_or_code;
|
||||
if (ptr == nullptr) {
|
||||
// object code!
|
||||
sol::type object_type = static_cast<sol::type>(original_block_size_or_code);
|
||||
switch (object_type) {
|
||||
case sol::type::function:
|
||||
++n_functions;
|
||||
break;
|
||||
case sol::type::string:
|
||||
++n_strings;
|
||||
break;
|
||||
case sol::type::userdata:
|
||||
++n_userdata;
|
||||
break;
|
||||
case sol::type::table:
|
||||
++n_tables;
|
||||
break;
|
||||
case sol::type::thread:
|
||||
++n_threads;
|
||||
break;
|
||||
default:
|
||||
// not a clue, fam
|
||||
break;
|
||||
}
|
||||
// because it is an object code,
|
||||
// it tells us literally nothing about
|
||||
// the old block size,
|
||||
// so set that to 0
|
||||
original_block_size = 0;
|
||||
}
|
||||
if (new_block_size == 0) {
|
||||
// Lua expects us to act like a "free"
|
||||
// when the new block size is 0
|
||||
std::free(ptr);
|
||||
used -= original_block_size;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// did we hit the limit?
|
||||
std::size_t memory_differntial = new_block_size - original_block_size;
|
||||
std::size_t desired_use = used + memory_differntial;
|
||||
if (desired_use > limit) {
|
||||
// tell the Lua Virtual Machine
|
||||
// to toss off (by returning nullptr)
|
||||
return nullptr;
|
||||
}
|
||||
// alright now we have to expand this shit
|
||||
// guess we use C's realloc
|
||||
ptr = std::realloc(ptr, new_block_size);
|
||||
if (ptr != nullptr) {
|
||||
// alright, we successfully allocated some space
|
||||
// track it
|
||||
used = desired_use;
|
||||
}
|
||||
// even if we're null, let Lua crash and burn for us
|
||||
return ptr;
|
||||
}
|
||||
|
||||
std::size_t used;
|
||||
std::size_t limit;
|
||||
std::size_t n_threads;
|
||||
std::size_t n_tables;
|
||||
std::size_t n_functions;
|
||||
std::size_t n_userdata;
|
||||
std::size_t n_strings;
|
||||
};
|
||||
|
||||
struct my_type {
|
||||
int a = 24;
|
||||
bool b = false;
|
||||
double d = 3.5;
|
||||
};
|
||||
|
||||
#include <iostream>
|
||||
|
||||
int main() {
|
||||
|
||||
std::cout << "=== memory tracker ===" << std::endl;
|
||||
|
||||
memory_tracker box;
|
||||
std::cout << "memory at start: " << box.currently_used() << " bytes / " << box.memory_limit() << " bytes" << std::endl;
|
||||
sol::state lua(&sol::default_at_panic, &memory_tracker::allocate, &box);
|
||||
lua.open_libraries(sol::lib::base);
|
||||
|
||||
std::cout << "memory after state creation: " << box.currently_used() << " bytes / " << box.memory_limit() << " bytes" << std::endl;
|
||||
|
||||
// trigger some allocations
|
||||
lua.new_usertype<my_type>("my_type", "a", &my_type::a, "b", &my_type::b, "d", &my_type::d);
|
||||
lua["f"] = [](std::string s) { return s + " woof!"; };
|
||||
|
||||
std::cout << "memory after function and usertype setup: " << box.currently_used() << " bytes / " << box.memory_limit() << " bytes" << std::endl;
|
||||
|
||||
lua.safe_script("print(f('bark'))");
|
||||
lua.safe_script("local obj = my_type.new() print(obj.a, obj.b, obj.c) obj.b = true print(obj.a, obj.b, obj.c)");
|
||||
|
||||
std::cout << "memory at end: " << box.currently_used() << " bytes / " << box.memory_limit() << " bytes" << std::endl;
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -28,17 +28,20 @@
|
|||
|
||||
#include <utility>
|
||||
#include <type_traits>
|
||||
#include <string_view>
|
||||
|
||||
#if defined(SOL_USING_CXX_LUA) && SOL_USING_CXX_LUA
|
||||
struct lua_State;
|
||||
#else
|
||||
extern "C" {
|
||||
struct lua_State;
|
||||
struct lua_State;
|
||||
}
|
||||
#endif // C++ Mangling for Lua vs. Not
|
||||
|
||||
namespace sol {
|
||||
|
||||
enum class type;
|
||||
|
||||
class stateless_reference;
|
||||
template <bool b>
|
||||
class basic_reference;
|
||||
|
@ -235,6 +238,8 @@ namespace sol {
|
|||
class optional<T&>;
|
||||
#endif
|
||||
|
||||
using check_handler_type = int(lua_State*, int, type, type, const char*);
|
||||
|
||||
} // namespace sol
|
||||
|
||||
#define SOL_BASE_CLASSES(T, ...) \
|
||||
|
|
|
@ -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 2019-08-28 04:16:59.509251 UTC
|
||||
// This header was generated with sol (revision )
|
||||
// Generated 2019-09-01 06:26:40.948435 UTC
|
||||
// This header was generated with sol v3.0.3 (revision e8649d2)
|
||||
// https://github.com/ThePhD/sol2
|
||||
|
||||
#ifndef SOL_SINGLE_INCLUDE_FORWARD_HPP
|
||||
|
@ -250,17 +250,20 @@
|
|||
|
||||
#include <utility>
|
||||
#include <type_traits>
|
||||
#include <string_view>
|
||||
|
||||
#if defined(SOL_USING_CXX_LUA) && SOL_USING_CXX_LUA
|
||||
struct lua_State;
|
||||
#else
|
||||
extern "C" {
|
||||
struct lua_State;
|
||||
struct lua_State;
|
||||
}
|
||||
#endif // C++ Mangling for Lua vs. Not
|
||||
|
||||
namespace sol {
|
||||
|
||||
enum class type;
|
||||
|
||||
class stateless_reference;
|
||||
template <bool b>
|
||||
class basic_reference;
|
||||
|
@ -457,6 +460,8 @@ namespace sol {
|
|||
class optional<T&>;
|
||||
#endif
|
||||
|
||||
using check_handler_type = int(lua_State*, int, type, type, const char*);
|
||||
|
||||
} // namespace sol
|
||||
|
||||
#define SOL_BASE_CLASSES(T, ...) \
|
||||
|
|
|
@ -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 2019-08-28 04:16:58.879902 UTC
|
||||
// This header was generated with sol (revision )
|
||||
// Generated 2019-09-01 06:26:40.339961 UTC
|
||||
// This header was generated with sol v3.0.3 (revision e8649d2)
|
||||
// https://github.com/ThePhD/sol2
|
||||
|
||||
#ifndef SOL_SINGLE_INCLUDE_HPP
|
||||
|
@ -276,17 +276,20 @@
|
|||
|
||||
#include <utility>
|
||||
#include <type_traits>
|
||||
#include <string_view>
|
||||
|
||||
#if defined(SOL_USING_CXX_LUA) && SOL_USING_CXX_LUA
|
||||
struct lua_State;
|
||||
#else
|
||||
extern "C" {
|
||||
struct lua_State;
|
||||
struct lua_State;
|
||||
}
|
||||
#endif // C++ Mangling for Lua vs. Not
|
||||
|
||||
namespace sol {
|
||||
|
||||
enum class type;
|
||||
|
||||
class stateless_reference;
|
||||
template <bool b>
|
||||
class basic_reference;
|
||||
|
@ -483,6 +486,8 @@ namespace sol {
|
|||
class optional<T&>;
|
||||
#endif
|
||||
|
||||
using check_handler_type = int(lua_State*, int, type, type, const char*);
|
||||
|
||||
} // namespace sol
|
||||
|
||||
#define SOL_BASE_CLASSES(T, ...) \
|
||||
|
@ -1256,7 +1261,6 @@ namespace sol {
|
|||
|
||||
#include <string>
|
||||
#if defined(SOL_CXX17_FEATURES) && SOL_CXX17_FEATURES
|
||||
#include <string_view>
|
||||
#endif // C++17 features
|
||||
#include <functional>
|
||||
#if defined(SOL_USE_BOOST) && SOL_USE_BOOST
|
||||
|
|
Loading…
Reference in New Issue
Block a user