diff options
author | Stanislaw Halik <sthalik@misaki.pl> | 2023-03-19 18:20:49 +0100 |
---|---|---|
committer | Stanislaw Halik <sthalik@misaki.pl> | 2023-03-19 18:28:21 +0100 |
commit | bfbbfc325f081d9523f56accc267167c82ffa495 (patch) | |
tree | f03202dde3c3eb771878cc4b56cb2a57f02981c1 /src | |
parent | 00c86f570f2081e51d7bed617a33a4269f00eb4c (diff) |
src/rtree: add simple object pool impl
Diffstat (limited to 'src')
-rw-r--r-- | src/RTree.cpp | 61 | ||||
-rw-r--r-- | src/RTree.h | 13 | ||||
-rw-r--r-- | src/RTree.hpp | 28 |
3 files changed, 90 insertions, 12 deletions
diff --git a/src/RTree.cpp b/src/RTree.cpp index 81677922..bee4641c 100644 --- a/src/RTree.cpp +++ b/src/RTree.cpp @@ -1,3 +1,64 @@ +#define RTREE_NO_EXTERN_TEMPLATE_POOL #include "RTree.hpp" +//#define RTREE_POOL_DEBUG + +#ifdef RTREE_POOL_DEBUG +#include <cstdio> +#include <Corrade/Containers/StringView.h> +#include <Corrade/Utility/Debug.h> +#endif + +namespace floormat::detail { + +template<typename T> rtree_pool<T>::rtree_pool() +{ + free_list.reserve(128); +} + +template<typename T> rtree_pool<T>::~rtree_pool() +{ + for (auto* ptr : free_list) + ::operator delete(ptr); + free_list.clear(); + free_list.shrink_to_fit(); +} + +template<typename T> T* rtree_pool<T>::construct() +{ + if (free_list.empty()) + { +#ifdef RTREE_POOL_DEBUG + static unsigned i = 0; Debug{} << "rtree-pool: fresh"_s << ++i; std::fflush(stdout); +#endif + return new T; + } + else + { + auto* ret = free_list.back(); + free_list.pop_back(); + new (ret) T(); +#ifdef RTREE_POOL_DEBUG + static unsigned i = 0; Debug{} << "rtree-pool: reused"_s << ++i; std::fflush(stdout); +#endif + return ret; + } +} + +template<typename T> void rtree_pool<T>::free(T* ptr) +{ + ptr->~T(); + free_list.push_back(ptr); +} + +using my_rtree = RTree<uint64_t, float, 2, float>; + +template<> std::vector<my_rtree::Node*> rtree_pool<my_rtree::Node>::free_list = {}; // NOLINT +template<> std::vector<my_rtree::ListNode*> rtree_pool<my_rtree::ListNode>::free_list = {}; // NOLINT + +template struct floormat::detail::rtree_pool<my_rtree::Node>; +template struct floormat::detail::rtree_pool<my_rtree::ListNode>; + +} // namespace floormat::detail + template class RTree<floormat::uint64_t, float, 2, float>; diff --git a/src/RTree.h b/src/RTree.h index 9ef66f34..1a30a735 100644 --- a/src/RTree.h +++ b/src/RTree.h @@ -17,15 +17,16 @@ // RTree.h // -#define RTREE_DONT_USE_MEMPOOLS // This version does not contain a fixed memory allocator, fill in lines with EXAMPLE to implement one. +//#define RTREE_DONT_USE_MEMPOOLS // This version does not contain a fixed memory allocator, fill in lines with EXAMPLE to implement one. #define RTREE_USE_SPHERICAL_VOLUME // Better split classification, may be slower on some systems +namespace floormat::detail { template<typename T> struct rtree_pool; } + #ifdef RTREE_STDIO // Fwd decl class RTFileStream; // File I/O helper class, look below for implementation and notes. #endif - /// \class RTree /// Implementation of RTree, a multidimensional bounding rectangle tree. /// Example usage: For a 3-dimensional tree use RTree<Object*, float, 3> myTree; @@ -47,11 +48,10 @@ template<class DATATYPE, class ELEMTYPE, int NUMDIMS, class RTree { -protected: +public: struct Node; // Fwd decl. Used by other internal structs and iterator - -public: + struct ListNode; // These constant must be declared after Branch and before Node struct // Stuck up here for MSVC 6 compiler. NSVC .NET 2003 is much happier. @@ -184,8 +184,6 @@ public: ELEMTYPE m_max[NUMDIMS]; ///< Max dimensions of bounding box }; -protected: - /// May be data or may be another subtree /// The parents level determines this. /// If the parents level is 0, then this is data @@ -214,6 +212,7 @@ protected: Node* m_node; ///< Node }; +protected: /// Variables for finding a split partition struct PartitionVars { diff --git a/src/RTree.hpp b/src/RTree.hpp index da60a76f..45cbb378 100644 --- a/src/RTree.hpp +++ b/src/RTree.hpp @@ -32,6 +32,24 @@ #define Max std::max #endif //Max +namespace floormat::detail { +template<typename T> struct rtree_pool final +{ + rtree_pool(); + ~rtree_pool(); + static T* construct(); + static void free(T* pool); + +private: + static std::vector<T*> free_list; // NOLINT +}; + +#ifndef RTREE_NO_EXTERN_TEMPLATE_POOL +extern template struct rtree_pool<RTree<std::uint64_t, float, 2, float>::Node>; +extern template struct rtree_pool<RTree<std::uint64_t, float, 2, float>::ListNode>; +#endif +} // namespace floormat::detail + #ifdef RTREE_STDIO // Because there is not stream support, this is a quick and dirty file I/O helper. // Users will likely replace its usage with a Stream implementation from their favorite API. @@ -508,7 +526,7 @@ void RTREE_QUAL::RemoveAll() RTREE_TEMPLATE void RTREE_QUAL::Reset() { -#ifdef RTREE_DONT_USE_MEMPOOLS +#if defined RTREE_DONT_USE_MEMPOOLS || 1 // Delete all existing nodes RemoveAllRec(m_root); #else // RTREE_DONT_USE_MEMPOOLS @@ -542,7 +560,7 @@ typename RTREE_QUAL::Node* RTREE_QUAL::AllocNode() #ifdef RTREE_DONT_USE_MEMPOOLS newNode = new Node; #else // RTREE_DONT_USE_MEMPOOLS - // EXAMPLE + newNode = floormat::detail::rtree_pool<Node>::construct(); #endif // RTREE_DONT_USE_MEMPOOLS InitNode(newNode); return newNode; @@ -557,7 +575,7 @@ void RTREE_QUAL::FreeNode(Node* a_node) #ifdef RTREE_DONT_USE_MEMPOOLS delete a_node; #else // RTREE_DONT_USE_MEMPOOLS - // EXAMPLE + floormat::detail::rtree_pool<Node>::free(a_node); #endif // RTREE_DONT_USE_MEMPOOLS } @@ -570,7 +588,7 @@ typename RTREE_QUAL::ListNode* RTREE_QUAL::AllocListNode() #ifdef RTREE_DONT_USE_MEMPOOLS return new ListNode; #else // RTREE_DONT_USE_MEMPOOLS - // EXAMPLE + return floormat::detail::rtree_pool<ListNode>::construct(); #endif // RTREE_DONT_USE_MEMPOOLS } @@ -581,7 +599,7 @@ void RTREE_QUAL::FreeListNode(ListNode* a_listNode) #ifdef RTREE_DONT_USE_MEMPOOLS delete a_listNode; #else // RTREE_DONT_USE_MEMPOOLS - // EXAMPLE + floormat::detail::rtree_pool<ListNode>::free(a_listNode); #endif // RTREE_DONT_USE_MEMPOOLS } |