diff --git a/furvm/include/furvm/context.hpp b/furvm/include/furvm/context.hpp index e588c97..8941478 100644 --- a/furvm/include/furvm/context.hpp +++ b/furvm/include/furvm/context.hpp @@ -7,6 +7,7 @@ #include "furvm/handle.hpp" #include "furvm/module.hpp" // IWYU pragma: keep #include "furvm/thing.hpp" // IWYU pragma: keep +#include "furvm/thing_allocator.hpp" #include #include diff --git a/furvm/include/furvm/thing.hpp b/furvm/include/furvm/thing.hpp index 10d7e1f..baba740 100644 --- a/furvm/include/furvm/thing.hpp +++ b/furvm/include/furvm/thing.hpp @@ -1,7 +1,6 @@ #ifndef FURVM_THING_HPP #define FURVM_THING_HPP -#include "furlang/arena.hpp" #include "furvm/exceptions.hpp" #include "furvm/fwd.hpp" #include "furvm/module.hpp" @@ -373,104 +372,6 @@ private: allocator_type m_allocator; }; -template -class thing_allocator { - template - friend class thing_allocator; - - using dead_things = std::vector>; -public: - using value_type = T; /**< Value type. */ -public: - /** - * @brief Constructs a thing allocator. - * - * @param arena Base arena allocator. - */ - explicit thing_allocator(furlang::arena& arena) noexcept - : m_arena(&arena), m_deadThings(std::make_shared()) {} - - /** - * @brief Move constructor. - */ - template - thing_allocator(thing_allocator&& other) noexcept - : m_arena(std::move(other.m_arena)), m_deadThings(std::move(other.m_deadThings)) {} - - /** - * @brief Move constructor. - */ - template - thing_allocator& operator=(thing_allocator&& other) noexcept { - if (this == &other) return *this; - m_arena = std::move(other.m_arena); - m_deadThings = std::move(other.m_deadThings); - return *this; - } - - /** - * @brief Copy constructor. - */ - template - thing_allocator(const thing_allocator& other) noexcept - : m_arena(other.m_arena), m_deadThings(other.m_deadThings) {} - - /** - * @brief Copy constructor. - */ - template - thing_allocator& operator=(const thing_allocator& other) noexcept { - if (this == &other) return *this; - m_arena = other.m_arena; - m_deadThings = other.m_deadThings; - return *this; - } -public: - /** - * @brief Returns a free chunk of memory. - * - * @param count Count of the things that must fit inside the chunk. - * @return The chunk. - */ - [[nodiscard]] T* allocate(std::size_t count = 1) { - for (auto it = m_deadThings->begin(); it != m_deadThings->end(); ++it) { - if (it->second != count) continue; - m_deadThings->erase(it); - return it->first; - } - return m_arena->allocate(count); - } - - /** - * @brief Recycles the pointer. - */ - void deallocate(T* ptr, std::size_t count) noexcept { m_deadThings->emplace_back(ptr, count); } -public: - /** - * @brief Compares two thing allocators for equality. - * - * @return true if the two things are equal. - */ - template - bool operator==(const thing_allocator& other) const noexcept { - return m_arena == other.m_arena && m_deadThings == other.m_deadThings; - } - - /** - * @brief Compares two thing allocators for inequality. - * - * @return true if the two things are not equal. - */ - template - bool operator!=(const thing_allocator& other) const noexcept { - return m_arena != other.m_arena || m_deadThings != other.m_deadThings; - } -private: - furlang::arena* m_arena; - - std::shared_ptr m_deadThings; -}; - } // namespace furvm #endif // FURVM_THING_HPP diff --git a/furvm/include/furvm/thing_allocator.hpp b/furvm/include/furvm/thing_allocator.hpp new file mode 100644 index 0000000..cd1badb --- /dev/null +++ b/furvm/include/furvm/thing_allocator.hpp @@ -0,0 +1,110 @@ +#ifndef FURVM_THING_ALLOCATOR_HPP +#define FURVM_THING_ALLOCATOR_HPP + +#include "furlang/arena.hpp" + +#include + +namespace furvm { + +template +class thing_allocator { + template + friend class thing_allocator; + + using dead_things = std::vector>; +public: + using value_type = T; /**< Value type. */ +public: + /** + * @brief Constructs a thing allocator. + * + * @param arena Base arena allocator. + */ + explicit thing_allocator(furlang::arena& arena) noexcept + : m_arena(&arena), m_deadThings(std::make_shared()) {} + + /** + * @brief Move constructor. + */ + template + thing_allocator(thing_allocator&& other) noexcept + : m_arena(std::move(other.m_arena)), m_deadThings(std::move(other.m_deadThings)) {} + + /** + * @brief Move constructor. + */ + template + thing_allocator& operator=(thing_allocator&& other) noexcept { + if (this == &other) return *this; + m_arena = std::move(other.m_arena); + m_deadThings = std::move(other.m_deadThings); + return *this; + } + + /** + * @brief Copy constructor. + */ + template + thing_allocator(const thing_allocator& other) noexcept + : m_arena(other.m_arena), m_deadThings(other.m_deadThings) {} + + /** + * @brief Copy constructor. + */ + template + thing_allocator& operator=(const thing_allocator& other) noexcept { + if (this == &other) return *this; + m_arena = other.m_arena; + m_deadThings = other.m_deadThings; + return *this; + } +public: + /** + * @brief Returns a free chunk of memory. + * + * @param count Count of the things that must fit inside the chunk. + * @return The chunk. + */ + [[nodiscard]] T* allocate(std::size_t count = 1) { + for (auto it = m_deadThings->begin(); it != m_deadThings->end(); ++it) { + if (it->second != count) continue; + m_deadThings->erase(it); + return it->first; + } + return m_arena->allocate(count); + } + + /** + * @brief Recycles the pointer. + */ + void deallocate(T* ptr, std::size_t count) noexcept { m_deadThings->emplace_back(ptr, count); } +public: + /** + * @brief Compares two thing allocators for equality. + * + * @return true if the two things are equal. + */ + template + bool operator==(const thing_allocator& other) const noexcept { + return m_arena == other.m_arena && m_deadThings == other.m_deadThings; + } + + /** + * @brief Compares two thing allocators for inequality. + * + * @return true if the two things are not equal. + */ + template + bool operator!=(const thing_allocator& other) const noexcept { + return m_arena != other.m_arena || m_deadThings != other.m_deadThings; + } +private: + furlang::arena* m_arena; + + std::shared_ptr m_deadThings; +}; + +} // namespace furvm + +#endif // FURVM_THING_ALLOCATOR_HPP