refactor(furvm): improve the handle system

Absolute slop

Refs: #12
This commit is contained in:
2026-06-18 23:58:37 +02:00
parent e9b38e95a2
commit ec2c81fc56
13 changed files with 641 additions and 617 deletions
+59 -93
View File
@@ -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 <cstring>
#include <memory>
#include <queue>
#include <string>
#include <type_traits>
#include <unordered_map>
#include <cstddef>
#include <utility>
#include <vector>
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 <typename... Args, typename = std::enable_if_t<std::is_constructible_v<mod, Args...>>>
mod_h emplace_module(Args&&... args) {
mod_p mod = std::make_shared<class mod>(std::forward<Args>(args)...);
std::string name = mod->name();
return { name, m_modules[name] = std::move(mod) };
template <typename... Args>
auto emplace_module(Args&&... args) {
return m_modules.emplace(std::forward<Args>(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 <typename Name>
mod_p erase_module(Name&& name) {
return std::move(m_modules.erase(std::forward<Name>(name))->second);
template <typename... Args>
auto module_at(Args&&... args) {
return m_modules.at(std::forward<Args>(args)...);
}
/**
* @brief Returns a module of this context.
*
* @param name Name of the module.
* @return The module.
*/
template <typename Name>
constexpr mod_p& module_at(Name&& name) {
return m_modules.at(std::forward<Name>(name));
template <typename... Args>
auto module_at(Args&&... args) const {
return m_modules.at(std::forward<Args>(args)...);
}
/**
* @brief Returns a module of this context.
*
* @param name Name of the module.
* @return The module.
*/
template <typename Name>
constexpr const mod_p& module_at(Name&& name) const {
return m_modules.at(std::forward<Name>(name));
template <typename... Args>
auto erase_module(Args&&... args) {
return m_modules.erase(std::forward<Args>(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 <typename... Args, typename = std::enable_if_t<std::is_constructible_v<executor, Args...>>>
executor_h emplace_executor(Args&&... args) {
executor executor(std::forward<Args>(args)...);
executor_id id = m_executors.size();
m_executors.emplace_back(std::move(executor));
return { id, m_executors[id] };
template <typename... Args>
auto emplace_executor(Args&&... args) {
return m_executors.emplace_back(std::forward<Args>(args)...);
}
template <typename... Args>
auto executor_at(Args&&... args) {
return m_executors.at(std::forward<Args>(args)...);
}
template <typename... Args>
auto executor_at(Args&&... args) const {
return m_executors.at(std::forward<Args>(args)...);
}
template <typename... Args>
auto erase_executor(Args&&... args) {
return m_executors.erase(std::forward<Args>(args)...);
}
public:
template <typename... Args>
auto emplace_thing(Args&&... args) {
return m_things.emplace_back(std::forward<Args>(args)...);
}
template <typename... Args>
auto thing_at(Args&&... args) {
return m_things.at(std::forward<Args>(args)...);
}
template <typename... Args>
auto thing_at(Args&&... args) const {
return m_things.at(std::forward<Args>(args)...);
}
template <typename... Args>
auto erase_thing(Args&&... args) {
return m_things.erase(std::forward<Args>(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<char*>(*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<char>(sizeof(thing_t) + size);
memcpy(data, &type, sizeof(type));
data = static_cast<char*>(data) + sizeof(type);
thing_p thing = std::make_shared<class thing>(type, data);
return { id, m_things.emplace_back(std::move(thing)) };
}
private:
std::unordered_map<std::string, mod_p> m_modules;
handle_container<mod_h> m_modules;
handle_container<thing_h> m_things;
handle_container<executor_h> m_executors;
std::vector<thing_p> m_things;
std::vector<executor> m_executors;
std::queue<thing_id> m_deadThings;
std::vector<void*> m_deadThingData;
furlang::arena m_thingArena;
furlang::arena m_thingArena;
thing_allocator<std::byte> m_thingAllocator;
};
} // namespace furvm