summaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorStanislaw Halik <sthalik@misaki.pl>2023-03-19 18:20:49 +0100
committerStanislaw Halik <sthalik@misaki.pl>2023-03-19 18:28:21 +0100
commitbfbbfc325f081d9523f56accc267167c82ffa495 (patch)
treef03202dde3c3eb771878cc4b56cb2a57f02981c1 /src
parent00c86f570f2081e51d7bed617a33a4269f00eb4c (diff)
src/rtree: add simple object pool impl
Diffstat (limited to 'src')
-rw-r--r--src/RTree.cpp61
-rw-r--r--src/RTree.h13
-rw-r--r--src/RTree.hpp28
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
}