From ec2c81fc569f8935c6ef1c466cb0781b427404cf Mon Sep 17 00:00:00 2001 From: CHatingPython Date: Thu, 18 Jun 2026 23:58:37 +0200 Subject: [PATCH] refactor(furvm): improve the handle system Absolute slop Refs: #12 --- furlang/include/furlang/arena.hpp | 51 ++++- furvm/include/furvm/context.hpp | 152 +++++-------- furvm/include/furvm/detail/handle.hpp | 24 ++ furvm/include/furvm/executor.hpp | 15 +- furvm/include/furvm/fwd.hpp | 46 ++-- furvm/include/furvm/handle.hpp | 315 ++++++++++++++++++-------- furvm/include/furvm/module.hpp | 83 +++---- furvm/include/furvm/thing.hpp | 213 +++++++++++++---- furvm/src/context.cpp | 10 +- furvm/src/executor.cpp | 69 +++--- furvm/src/main.cpp | 3 +- furvm/src/serializer.cpp | 49 ++-- furvm/src/thing.cpp | 228 ------------------- 13 files changed, 641 insertions(+), 617 deletions(-) create mode 100644 furvm/include/furvm/detail/handle.hpp delete mode 100644 furvm/src/thing.cpp diff --git a/furlang/include/furlang/arena.hpp b/furlang/include/furlang/arena.hpp index ef87d97..58dce98 100644 --- a/furlang/include/furlang/arena.hpp +++ b/furlang/include/furlang/arena.hpp @@ -106,6 +106,55 @@ private: region* m_tail = nullptr; }; +template +class arena_allocator { + template + friend class arena_allocator; +public: + using value_type = T; +public: + explicit arena_allocator(arena& arena) noexcept + : m_arena(&arena) {} + + template + arena_allocator(const arena_allocator& other) noexcept + : m_arena(other.m_arena) {} + + template + arena_allocator& operator=(const arena_allocator& other) noexcept { + if (this == &other) return *this; + m_arena = other.m_arena; + return *this; + } + + template + arena_allocator(arena_allocator&& other) noexcept + : m_arena(std::move(other.m_arena)) {} + + template + arena_allocator& operator=(arena_allocator&& other) noexcept { + if (this == &other) return *this; + m_arena = std::move(other.m_arena); + return *this; + } +public: + [[nodiscard]] T* allocate(std::size_t count = 1) { return m_arena->allocate(count); } + + void deallocate(T* ptr, std::size_t count) noexcept {} +public: + template + bool operator==(const arena_allocator& other) const noexcept { + return m_arena == other.m_arena; + } + + template + bool operator!=(const arena_allocator& other) const noexcept { + return m_arena != other.m_arena; + } +private: + arena* m_arena; +}; + } // namespace furlang -#endif // FURLANG_ARENA_HPP \ No newline at end of file +#endif // FURLANG_ARENA_HPP diff --git a/furvm/include/furvm/context.hpp b/furvm/include/furvm/context.hpp index f2e9298..e1203dd 100644 --- a/furvm/include/furvm/context.hpp +++ b/furvm/include/furvm/context.hpp @@ -4,24 +4,18 @@ #include "furlang/arena.hpp" #include "furvm/executor.hpp" #include "furvm/fwd.hpp" -#include "furvm/module.hpp" -#include "furvm/thing.hpp" +#include "furvm/handle.hpp" +#include "furvm/module.hpp" // IWYU pragma: keep +#include "furvm/thing.hpp" // IWYU pragma: keep -#include -#include -#include -#include -#include -#include +#include #include -#include namespace furvm { class context { public: friend class executor; - friend class thing; public: context(); ~context() = default; @@ -39,105 +33,77 @@ public: context(const context&) = delete; context& operator=(const context&) = delete; public: - /** - * @brief Emplaces a new module in this context. - * - * @param args Arguments to forward to module's constructor. - * @return A handle to the module. - */ - template >> - mod_h emplace_module(Args&&... args) { - mod_p mod = std::make_shared(std::forward(args)...); - std::string name = mod->name(); - return { name, m_modules[name] = std::move(mod) }; + template + auto emplace_module(Args&&... args) { + return m_modules.emplace(std::forward(args)...); } - /** - * @brief Erases a module from this context. - * - * @param name Name of the module to erase. - * @return A shared pointer to the erased module. - */ - template - mod_p erase_module(Name&& name) { - return std::move(m_modules.erase(std::forward(name))->second); + template + auto module_at(Args&&... args) { + return m_modules.at(std::forward(args)...); } - /** - * @brief Returns a module of this context. - * - * @param name Name of the module. - * @return The module. - */ - template - constexpr mod_p& module_at(Name&& name) { - return m_modules.at(std::forward(name)); + template + auto module_at(Args&&... args) const { + return m_modules.at(std::forward(args)...); } - /** - * @brief Returns a module of this context. - * - * @param name Name of the module. - * @return The module. - */ - template - constexpr const mod_p& module_at(Name&& name) const { - return m_modules.at(std::forward(name)); + template + auto erase_module(Args&&... args) { + return m_modules.erase(std::forward(args)...); } - - /** - * @brief Returns how many does this context have modules. - * - * @return The module count. - */ - constexpr size_t module_count() const { return m_modules.size(); } public: - template >> - executor_h emplace_executor(Args&&... args) { - executor executor(std::forward(args)...); - executor_id id = m_executors.size(); - m_executors.emplace_back(std::move(executor)); - return { id, m_executors[id] }; + template + auto emplace_executor(Args&&... args) { + return m_executors.emplace_back(std::forward(args)...); + } + + template + auto executor_at(Args&&... args) { + return m_executors.at(std::forward(args)...); + } + + template + auto executor_at(Args&&... args) const { + return m_executors.at(std::forward(args)...); + } + + template + auto erase_executor(Args&&... args) { + return m_executors.erase(std::forward(args)...); + } +public: + template + auto emplace_thing(Args&&... args) { + return m_things.emplace_back(std::forward(args)...); + } + + template + auto thing_at(Args&&... args) { + return m_things.at(std::forward(args)...); + } + + template + auto thing_at(Args&&... args) const { + return m_things.at(std::forward(args)...); + } + + template + auto erase_thing(Args&&... args) { + return m_things.erase(std::forward(args)...); } public: /** * @brief Removes unreferenced things from the thing list. */ void collect(); -public: - thing_h emplace_thing(thing_t type) { - thing_id id = m_things.size(); - if (!m_deadThings.empty()) { - id = m_deadThings.front(); - m_deadThings.pop(); - } - - size_t size = thing_type_size(type); - void* data = nullptr; - for (auto it = m_deadThingData.begin(); it != m_deadThingData.end(); ++it) { - thing_t curType{}; - std::memcpy(&curType, static_cast(*it) - sizeof(curType), sizeof(curType)); - if (thing_type_size(curType) != size) continue; - data = *it; - m_deadThingData.erase(it); - break; - } - if (data == nullptr) data = m_thingArena.allocate(sizeof(thing_t) + size); - memcpy(data, &type, sizeof(type)); - data = static_cast(data) + sizeof(type); - - thing_p thing = std::make_shared(type, data); - return { id, m_things.emplace_back(std::move(thing)) }; - } private: - std::unordered_map m_modules; + handle_container m_modules; + handle_container m_things; + handle_container m_executors; - std::vector m_things; - std::vector m_executors; - - std::queue m_deadThings; - std::vector m_deadThingData; - furlang::arena m_thingArena; + furlang::arena m_thingArena; + thing_allocator m_thingAllocator; }; } // namespace furvm diff --git a/furvm/include/furvm/detail/handle.hpp b/furvm/include/furvm/detail/handle.hpp new file mode 100644 index 0000000..e426c33 --- /dev/null +++ b/furvm/include/furvm/detail/handle.hpp @@ -0,0 +1,24 @@ +#ifndef FURVM_DETAIL_HANDLE_HPP +#define FURVM_DETAIL_HANDLE_HPP + +#include + +namespace furvm { +namespace detail { + +template +struct header_has_refcount : std::false_type {}; + +template +struct header_has_refcount().acquire()), + decltype(std::declval().release()), + decltype(std::declval().reference_count())>> : std::true_type {}; + +template +static constexpr auto header_has_refcount_v = header_has_refcount
::value; + +} // namespace detail +} // namespace furvm + +#endif // FURVM_DETAIL_HANDLE_HPP diff --git a/furvm/include/furvm/executor.hpp b/furvm/include/furvm/executor.hpp index b550789..ae60589 100644 --- a/furvm/include/furvm/executor.hpp +++ b/furvm/include/furvm/executor.hpp @@ -2,8 +2,11 @@ #define FURVM_EXECUTOR_HPP #include "furvm/fwd.hpp" +#include "furvm/module.hpp" // IWYU pragma: keep +#include "furvm/thing.hpp" // IWYU pragma: keep #include +#include #include namespace furvm { @@ -99,19 +102,17 @@ public: */ frame frame() const; public: - /** - * @brief Pushes a thing onto the stack. - * - * @param thing The thing to push. - */ - void push_thing(const thing_h& thing); + template + void push_thing(HandleFwd&& handle) { + m_stack.emplace(std::forward(handle)); + } /** * @brief Pushes a thing onto the stack. * * @param thing The thing to push. */ - void push_thing(thing_h&& thing); + thing_h push_thing(class thing<>&& thing); /** * @brief Pops a thing from the stack. diff --git a/furvm/include/furvm/fwd.hpp b/furvm/include/furvm/fwd.hpp index d947449..6c4c822 100644 --- a/furvm/include/furvm/fwd.hpp +++ b/furvm/include/furvm/fwd.hpp @@ -1,8 +1,6 @@ #ifndef FURVM_FWD_HPP #define FURVM_FWD_HPP -#include "furvm/handle.hpp" - #include // IWYU pragma: export #include // IWYU pragma: export #include @@ -25,6 +23,24 @@ using byte = std::uint8_t; */ using bytecode_pos = std::uint64_t; +/** + * @brief Handle header with reference count. + */ +template +class refcount_header; + +/** + * @brief Generic handle header. + */ +template +class generic_header; + +/** + * @brief Handle. + */ +template +class handle; + // constant.hpp /** @@ -76,11 +92,6 @@ enum class function_t : std::uint8_t; */ class function; -/** - * @brief An alias to a function shared pointer. - */ -using function_p = std::shared_ptr; - /** * @brief Furvm function's index. */ @@ -89,7 +100,7 @@ using function_id = std::uint16_t; /** * @brief A handle to a furvm function. */ -using function_h = handle; +using function_h = handle>; // module.hpp @@ -114,7 +125,7 @@ using mod_id = std::string; /** * @brief A handle to a furvm module. */ -using mod_h = handle; +using mod_h = handle>; // thing.hpp @@ -130,28 +141,27 @@ enum class thing_t : std::uint8_t; */ class bad_thing_access; +template +class thing_allocator; + /** * @class thing * @brief Furvm thing. * * A stack element. Think of it like of a value in C++ or I guess a class in java. */ +template