diff --git a/furvm/include/furvm/fwd.hpp b/furvm/include/furvm/fwd.hpp index 6c4c822..a0d9c1b 100644 --- a/furvm/include/furvm/fwd.hpp +++ b/furvm/include/furvm/fwd.hpp @@ -36,11 +36,22 @@ template class generic_header; /** - * @brief Handle. + * @brief Generic furvm object handle. + * + * @tparam Value Type of the handle's value. + * @tparam Header Type of the handle's header. */ template class handle; +/** + * @brief Container for the handles. + * + * @tparam Handle Type of the container's handle. + */ +template +class handle_container; + // constant.hpp /** diff --git a/furvm/include/furvm/handle.hpp b/furvm/include/furvm/handle.hpp index 097d978..68662e4 100644 --- a/furvm/include/furvm/handle.hpp +++ b/furvm/include/furvm/handle.hpp @@ -14,30 +14,52 @@ namespace furvm { -template -class handle_container; - // TODO: Implement generational indexes template class refcount_header { public: - using id_type = Id; - using refcount_type = std::uint32_t; + using id_type = Id; /**< Id type. */ + using refcount_type = std::uint32_t; /**< Reference count type. */ public: + /** + * @brief Constructs a reference counting header. + * + * @param id Identifier of the handle's value. + * @param refCount Handle's reference count. + * @param onRelease Callback function. + */ template refcount_header(IdFwd&& id, refcount_type refCount, Func&& onRelease) : m_id(std::forward(id)), m_refCount(refCount), m_onRelease(std::forward(onRelease)) {} public: + /** + * @brief Returns the header's reference count. + * + * @return The reference count. + */ refcount_type reference_count() const { return m_refCount; } + /** + * @brief Increments the header's reference count. + */ void acquire() { ++m_refCount; } + /** + * @brief Decrements the header's reference count. + * + * If the reference count reaches 0, the onRelease callback passed in the constructor will be called. + */ void release() { --m_refCount; if (m_refCount == 0) m_onRelease(m_id); } public: + /** + * @brief Returns the header's identifier. + * + * @return The identifier. + */ id_type id() const { return m_id; } private: id_type m_id; @@ -48,11 +70,19 @@ private: template class generic_header { public: - using id_type = Id; + using id_type = Id; /**< Id type. */ public: + /** + * @brief Constructs a generic header. + * + * @param id Identifier of the handle. + */ generic_header(id_type id) : m_id(id) {} public: + /** + * @brief Returns the header's identifier. + */ id_type id() const { return m_id; } private: id_type m_id; @@ -61,18 +91,23 @@ private: template > class handle { public: - using value_type = Value; - using reference = Value&; - using const_reference = const Value&; - using pointer = Value*; - using const_pointer = const Value*; + using value_type = Value; /** Value type. */ + using reference = Value&; /** Reference type. */ + using const_reference = const Value&; /** Constant reference type. */ + using pointer = Value*; /** Pointer type. */ + using const_pointer = const Value*; /** Constant pointer type. */ public: - using id_type = typename Header::id_type; + using id_type = typename Header::id_type; /** Id type of the header. */ public: - using pair_type = std::pair; + using pair_type = std::pair; /** Type of a header-value pair. */ public: handle() = default; + /** + * @brief Constructs a handle. + * + * @param value A pointer to the header-value pair. + */ handle(pair_type* value) : m_value(value) { if constexpr (detail::header_has_refcount_v
) { @@ -80,6 +115,9 @@ public: } } + /** + * @brief Destructs a handle. + */ ~handle() { if constexpr (detail::header_has_refcount_v
) { if (m_value != nullptr) m_value->first.release(); @@ -87,11 +125,17 @@ public: m_value = nullptr; } + /** + * @brief Move constructor. + */ handle(handle&& other) noexcept : m_value(other.m_value) { other.m_value = nullptr; } + /** + * @brief Move constructor. + */ handle& operator=(handle&& other) noexcept { if (this == &other) return *this; m_value = other.m_value; @@ -99,11 +143,17 @@ public: return *this; } + /** + * @brief Copy constructor. + */ handle(const handle& other) : m_value(other.m_value) { m_value->first.acquire(); } + /** + * @brief Copy constructor. + */ handle& operator=(const handle& other) { if (this == &other) return *this; m_value = other.m_value; @@ -111,22 +161,70 @@ public: return *this; } public: + /** + * @brief Returns an identifier of the handle's header. + * + * @return The header's identifier. + */ id_type id() const { return m_value->first.id(); } + /** + * @brief Returns whether the handle is empty. + * + * @return true if the handle is empty. + */ bool empty() const { return m_value == nullptr; } + /** + * @brief Returns the handle's header reference count. + * + * @return The reference count. + */ template ReferenceCount reference_count() const { return m_value->first.reference_count(); } - pointer operator->() { return &m_value->second; } + /** + * @brief Returns a pointer to the handle's value. + * + * @return The value pointer. + */ + pointer operator->() { return &m_value->second; } + + /** + * @brief Returns a pointer to the handle's value. + * + * @return The value pointer. + */ const_pointer operator->() const { return &m_value->second; } - reference operator*() { return m_value->second; } + /** + * @brief Returns a reference to the handle's value. + * + * @return The value reference. + */ + reference operator*() { return m_value->second; } + + /** + * @brief Returns a reference to the handle's value. + * + * @return The value reference. + */ const_reference operator*() const { return m_value->second; } - reference value() { return m_value->second; } + /** + * @brief Returns a reference to the handle's value. + * + * @return The value reference. + */ + reference value() { return m_value->second; } + + /** + * @brief Returns a reference to the handle's value. + * + * @return The value reference. + */ const_reference value() const { return m_value->second; } private: pair_type* m_value = nullptr; @@ -135,12 +233,12 @@ private: template class handle_container>> { private: - using pair_type = typename Handle::pair_type; + using pair_type = typename Handle::pair_type; /**< Handle's pair type. */ public: - using value_type = std::remove_cv_t>; - using const_value = std::add_const_t; + using value_type = std::remove_cv_t>; /**< Handle type. */ + using const_value = std::add_const_t; /**< Constant handle type. */ - using id_type = typename Handle::id_type; + using id_type = typename Handle::id_type; /**< Handle's header identifier type. */ public: handle_container() = default; ~handle_container() = default; @@ -151,6 +249,13 @@ public: handle_container(const handle_container&) = delete; handle_container& operator=(const handle_container&) = delete; public: + /** + * @brief Emplaces a new value. + * + * @param id Identifier of the emplaced value. + * @param args Arguments passed to the Handle's value type constructor. + * @return A handle to the emplaced value. + */ template >> @@ -164,16 +269,33 @@ public: return { pair }; } + /** + * @brief Returns a handle to the container's value. + * + * @param id Idenfifier of the value. + * @return The value. + */ template value_type at(IdFwd&& id) { return { m_pairs.at(std::forward(id)) }; } + /** + * @brief Returns a handle to the container's value. + * + * @param id Idenfifier of the value. + * @return The value. + */ template const_value at(IdFwd&& id) const { return { m_pairs.at(std::forward(id)) }; } + /** + * @brief Erases a value from the container. + * + * @param id Identifier of the value. + */ template void erase(IdFwd&& id) { auto it = m_pairs.find(std::forward(id)); @@ -188,12 +310,12 @@ private: template class handle_container>> { private: - using pair_type = typename Handle::pair_type; + using pair_type = typename Handle::pair_type; /**< Handle's pair type. */ public: - using value_type = std::remove_cv_t>; - using const_value = std::add_const_t; + using value_type = std::remove_cv_t>; /**< Handle type. */ + using const_value = std::add_const_t; /**< Constant handle type. */ - using id_type = typename Handle::id_type; + using id_type = typename Handle::id_type; /**< Handle's header identifier type. */ public: handle_container() = default; ~handle_container() = default; @@ -204,6 +326,13 @@ public: handle_container(const handle_container&) = delete; handle_container& operator=(const handle_container&) = delete; public: + /** + * @brief Emplaces a new value. + * + * @param id Identifier of the emplaced value. + * @param args Arguments passed to the Handle's value type constructor. + * @return A handle to the emplaced value. + */ template >> value_type emplace(id_type id, Args&&... args) { @@ -221,15 +350,41 @@ public: return { newPair }; } + /** + * @brief Emplaces a new value. + * + * Emplaces a new value with an automatically-assigned identifier. + * + * @param args Arguments passed to the Handle's value type constructor. + * @return A handle to the emplaced value. + */ template >> value_type emplace_back(Args&&... args) { return emplace(static_cast(m_pairs.size()), std::forward(args)...); } - value_type at(id_type id) { return { m_pairs.at(id) }; } + /** + * @brief Returns a handle to a value. + * + * @param id Identifier of the value. + * @return The value. + */ + value_type at(id_type id) { return { m_pairs.at(id) }; } + + /** + * @brief Returns a handle to a value. + * + * @param id Identifier of the value. + * @return The value. + */ const_value at(id_type id) const { return { m_pairs.at(id) }; } + /** + * @brief Erases a value from the container. + * + * @param id Identifier of the value. + */ void erase(id_type id) { if (id >= m_pairs.size()) return; delete m_pairs[id];