From c9aa05102552f960ddc7dd44519969dfacb2fb70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Tue, 13 Jan 2026 23:30:43 +0100 Subject: [PATCH] Add overalignment support for node_allocator, private_node_allocator and cached_node_allocator --- .../allocators/cached_node_allocator.hpp | 6 ++- .../allocators/detail/allocator_common.hpp | 40 ++++++++++++---- .../allocators/detail/node_pool.hpp | 14 ++++-- .../allocators/node_allocator.hpp | 6 ++- .../allocators/private_node_allocator.hpp | 14 +++--- test/cached_node_allocator_test.cpp | 27 ++++++++++- test/node_allocator_test.cpp | 33 +++++++++++-- test/node_pool_test.cpp | 48 +++++++++++++++---- test/node_pool_test.hpp | 10 +++- test/private_node_allocator_test.cpp | 26 +++++++++- 10 files changed, 187 insertions(+), 37 deletions(-) diff --git a/include/boost/interprocess/allocators/cached_node_allocator.hpp b/include/boost/interprocess/allocators/cached_node_allocator.hpp index 582b3ee..255dda9 100644 --- a/include/boost/interprocess/allocators/cached_node_allocator.hpp +++ b/include/boost/interprocess/allocators/cached_node_allocator.hpp @@ -56,6 +56,7 @@ class cached_node_allocator_v1 < SegmentManager , sizeof_value::value , NodesPerBlock + , alignof_value::value > , 1> { @@ -67,6 +68,7 @@ class cached_node_allocator_v1 < SegmentManager , sizeof_value::value , NodesPerBlock + , alignof_value::value > , 1> base_t; typedef uses_segment_manager uses_segment_manager_t; @@ -77,7 +79,7 @@ class cached_node_allocator_v1 typedef cached_node_allocator_v1 other; }; - + typedef typename base_t::size_type size_type; cached_node_allocator_v1(SegmentManager *segment_mngr, @@ -122,6 +124,7 @@ class cached_node_allocator < SegmentManager , sizeof_value::value , NodesPerBlock + , alignof_value::value > , 2> #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED @@ -135,6 +138,7 @@ class cached_node_allocator < SegmentManager , sizeof_value::value , NodesPerBlock + , alignof_value::value > , 2> base_t; diff --git a/include/boost/interprocess/allocators/detail/allocator_common.hpp b/include/boost/interprocess/allocators/detail/allocator_common.hpp index 87c6287..62dc6b7 100644 --- a/include/boost/interprocess/allocators/detail/allocator_common.hpp +++ b/include/boost/interprocess/allocators/detail/allocator_common.hpp @@ -62,22 +62,46 @@ struct sizeof_value template <> struct sizeof_value -{ - static const std::size_t value = sizeof(void*); -}; + : sizeof_value +{}; template <> struct sizeof_value -{ - static const std::size_t value = sizeof(void*); -}; + : sizeof_value +{}; template <> struct sizeof_value + : sizeof_value +{}; + +template +struct alignof_value { - static const std::size_t value = sizeof(void*); + static const std::size_t value = boost::container::dtl::alignment_of::value; }; +template <> +struct alignof_value +{ + static const std::size_t value = boost::container::dtl::alignment_of::value; +}; + +template <> +struct alignof_value + : alignof_value +{}; + +template <> +struct alignof_value + : alignof_value +{}; + +template <> +struct alignof_value + : alignof_value +{}; + template class uses_segment_manager { @@ -523,7 +547,7 @@ class node_pool_allocation_impl } else{ return pointer(static_cast - (pool->get_segment_manager()->allocate(count*sizeof(T)))); + (pool->get_segment_manager()->allocate_aligned(count*sizeof(T), boost::container::dtl::alignment_of::value))); } } diff --git a/include/boost/interprocess/allocators/detail/node_pool.hpp b/include/boost/interprocess/allocators/detail/node_pool.hpp index 552410a..854b694 100644 --- a/include/boost/interprocess/allocators/detail/node_pool.hpp +++ b/include/boost/interprocess/allocators/detail/node_pool.hpp @@ -42,7 +42,10 @@ namespace ipcdetail { //!a reference count but the class does not delete itself, this is //!responsibility of user classes. Node size (NodeSize) and the number of //!nodes allocated per block (NodesPerBlock) are known at compile time -template< class SegmentManager, std::size_t NodeSize, std::size_t NodesPerBlock > +template< class SegmentManager + , std::size_t NodeSize + , std::size_t NodesPerBlock + , std::size_t NodeAlign = 0> class private_node_pool //Inherit from the implementation to avoid template bloat : public boost::container::dtl:: @@ -63,9 +66,11 @@ class private_node_pool //Deprecated, use nodes_per_block static const size_type nodes_per_chunk = NodesPerBlock; + static const size_type node_alignment = NodeAlign ? NodeAlign : 1u; + //!Constructor from a segment manager. Never throws private_node_pool(segment_manager *segment_mngr) - : base_t(segment_mngr, NodeSize, NodesPerBlock) + : base_t(segment_mngr, NodeSize, NodesPerBlock, NodeAlign) {} //!Returns the segment manager. Never throws @@ -85,16 +90,17 @@ class private_node_pool template< class SegmentManager , std::size_t NodeSize , std::size_t NodesPerBlock + , std::size_t NodeAlign > class shared_node_pool : public ipcdetail::shared_pool_impl < private_node_pool - + > { typedef ipcdetail::shared_pool_impl < private_node_pool - + > base_t; public: shared_node_pool(SegmentManager *segment_mgnr) diff --git a/include/boost/interprocess/allocators/node_allocator.hpp b/include/boost/interprocess/allocators/node_allocator.hpp index 2a0ecc8..0d12d48 100644 --- a/include/boost/interprocess/allocators/node_allocator.hpp +++ b/include/boost/interprocess/allocators/node_allocator.hpp @@ -78,7 +78,11 @@ class node_allocator_base struct node_pool { typedef ipcdetail::shared_node_pool - < SegmentManager, sizeof_value::value, NodesPerBlock> type; + < SegmentManager + , sizeof_value::value + , NodesPerBlock + , alignof_value::value + > type; static type *get(void *p) { return static_cast(p); } diff --git a/include/boost/interprocess/allocators/private_node_allocator.hpp b/include/boost/interprocess/allocators/private_node_allocator.hpp index b32f91d..021cb97 100644 --- a/include/boost/interprocess/allocators/private_node_allocator.hpp +++ b/include/boost/interprocess/allocators/private_node_allocator.hpp @@ -73,9 +73,10 @@ class private_node_allocator_base typedef private_node_allocator_base < Version, T, SegmentManager, NodesPerBlock> self_t; typedef ipcdetail::private_node_pool - ::value - , NodesPerBlock + < SegmentManager + , sizeof_value::value + , NodesPerBlock + , alignof_value::value > node_pool_t; BOOST_INTERPROCESS_STATIC_ASSERT((Version <=2)); @@ -115,9 +116,10 @@ class private_node_allocator_base struct node_pool { typedef ipcdetail::private_node_pool - ::value - , NodesPerBlock + < SegmentManager + , sizeof_value::value + , NodesPerBlock + , alignof_value::value > type; static type *get(void *p) diff --git a/test/cached_node_allocator_test.cpp b/test/cached_node_allocator_test.cpp index b5c56b9..9d32152 100644 --- a/test/cached_node_allocator_test.cpp +++ b/test/cached_node_allocator_test.cpp @@ -12,14 +12,14 @@ #include #include #include -#include "print_container.hpp" -#include "dummy_test_allocator.hpp" #include "movable_int.hpp" #include "list_test.hpp" #include "vector_test.hpp" using namespace boost::interprocess; +typedef test::overaligned_copyable_int oint_t; + //Alias an integer node allocator type typedef cached_node_allocator @@ -28,16 +28,23 @@ typedef ipcdetail::cached_node_allocator_v1 cached_node_allocator_v1_t; +typedef cached_node_allocator + < oint_t, managed_shared_memory::segment_manager> shmem_onode_allocator_t; +typedef ipcdetail::cached_node_allocator_v1 + < oint_t, managed_shared_memory::segment_manager> shmem_onode_allocator_v1_t; + namespace boost { namespace interprocess { //Explicit instantiations to catch compilation errors template class cached_node_allocator; +template class cached_node_allocator; template class cached_node_allocator; namespace ipcdetail { template class ipcdetail::cached_node_allocator_v1; +template class ipcdetail::cached_node_allocator_v1; template class ipcdetail::cached_node_allocator_v1; }}} @@ -45,10 +52,14 @@ template class ipcdetail::cached_node_allocator_v1 MyShmList; typedef boost::container::list MyShmListV1; +typedef boost::container::list MyOShmList; +typedef boost::container::list MyOShmListV1; //Alias vector types typedef boost::container::vector MyShmVector; typedef boost::container::vector MyShmVectorV1; +typedef boost::container::vector MyOShmVector; +typedef boost::container::vector MyOShmVectorV1; int main () { @@ -56,9 +67,21 @@ int main () return 1; if(test::list_test()) return 1; + + if(test::list_test()) + return 1; + if(test::list_test()) + return 1; + if(test::vector_test()) return 1; if(test::vector_test()) return 1; + + if(test::vector_test()) + return 1; + if(test::vector_test()) + return 1; + return 0; } diff --git a/test/node_allocator_test.cpp b/test/node_allocator_test.cpp index c70a159..b4f163b 100644 --- a/test/node_allocator_test.cpp +++ b/test/node_allocator_test.cpp @@ -12,31 +12,37 @@ #include #include #include -#include "print_container.hpp" -#include "dummy_test_allocator.hpp" #include "movable_int.hpp" #include "list_test.hpp" #include "vector_test.hpp" using namespace boost::interprocess; +typedef test::overaligned_copyable_int oint_t; + //We will work with wide characters for shared memory objects //Alias an integer node allocator type typedef node_allocator shmem_node_allocator_t; typedef ipcdetail::node_allocator_v1 shmem_node_allocator_v1_t; +typedef node_allocator + < oint_t, managed_shared_memory::segment_manager> shmem_onode_allocator_t; +typedef ipcdetail::node_allocator_v1 + < oint_t, managed_shared_memory::segment_manager> shmem_onode_allocator_v1_t; namespace boost { namespace interprocess { //Explicit instantiations to catch compilation errors template class node_allocator; +template class node_allocator; template class node_allocator; namespace ipcdetail { template class ipcdetail::node_allocator_v1; +template class ipcdetail::node_allocator_v1; template class ipcdetail::node_allocator_v1; }}} @@ -44,20 +50,41 @@ template class ipcdetail::node_allocator_v1 MyShmList; typedef boost::container::list MyShmListV1; +typedef boost::container::list MyOShmList; +typedef boost::container::list MyOShmListV1; +typedef boost::container::vector MyOShmVector; +typedef boost::container::vector MyOShmVectorV1; //Alias vector types typedef boost::container::vector MyShmVector; typedef boost::container::vector MyShmVectorV1; int main () -{ +{/* if(test::list_test()) return 1; if(test::list_test()) return 1; + + if(test::list_test()) + return 1;*/ + if(test::list_test()) + return 1; +/* + if(test::list_test()) + return 1; + if(test::list_test()) + return 1; + if(test::vector_test()) return 1; if(test::vector_test()) return 1; + + if(test::vector_test()) + return 1;*/ + if(test::vector_test()) + return 1; + return 0; } diff --git a/test/node_pool_test.cpp b/test/node_pool_test.cpp index d4bca5f..c515be9 100644 --- a/test/node_pool_test.cpp +++ b/test/node_pool_test.cpp @@ -16,17 +16,49 @@ typedef managed_shared_memory::segment_manager segment_manager_t; int main () { - typedef ipcdetail::private_node_pool - node_pool_t; + { //Private, normal alignment, small data + typedef ipcdetail::private_node_pool + node_pool_t; - if(!test::test_all_node_pool()) - return 1; + if (!test::test_all_node_pool()) + return 1; + } + { //Private, small alignment, small data + typedef ipcdetail::private_node_pool + node_pool_t; - typedef ipcdetail::shared_node_pool - shared_node_pool_t; + if (!test::test_all_node_pool()) + return 1; + } + { //Private, normal alignment + typedef ipcdetail::private_node_pool + node_pool_t; - if(!test::test_all_node_pool()) - return 1; + if (!test::test_all_node_pool()) + return 1; + } + { //Private, overaligned + typedef ipcdetail::private_node_pool + node_pool_t; + + if (!test::test_all_node_pool()) + return 1; + } + + { //Shared, normal alignment + typedef ipcdetail::shared_node_pool + node_pool_t; + + if (!test::test_all_node_pool()) + return 1; + } + { //Shared, overaligned + typedef ipcdetail::shared_node_pool + node_pool_t; + + if (!test::test_all_node_pool()) + return 1; + } return 0; } diff --git a/test/node_pool_test.hpp b/test/node_pool_test.hpp index 52fc8ff..6532a27 100644 --- a/test/node_pool_test.hpp +++ b/test/node_pool_test.hpp @@ -42,7 +42,13 @@ bool test_node_pool::allocate_then_deallocate(NodePool &pool) //First allocate nodes for(std::size_t i = 0; i < num_alloc; ++i){ - nodes.push_back(pool.allocate_node()); + void* ptr = pool.allocate_node(); + const std::size_t al = NodePool::node_alignment; + const bool aligned = 0 == ((std::size_t)ptr & (al - 1u)); + BOOST_ASSERT(aligned); + if (!aligned) + return false; + nodes.push_back(ptr); } //Check that the free count is correct @@ -136,7 +142,7 @@ bool test_all_node_pool() typedef boost::interprocess::test::test_node_pool test_node_pool_t; shared_memory_object::remove(test::get_process_id_name()); { - managed_shared_memory shm(create_only, test::get_process_id_name(), 4*1024*sizeof(segment_manager::void_pointer)); + managed_shared_memory shm(create_only, test::get_process_id_name(), 4*1024*sizeof(segment_manager::void_pointer)); typedef deleter deleter_t; typedef unique_ptr unique_ptr_t; diff --git a/test/private_node_allocator_test.cpp b/test/private_node_allocator_test.cpp index e74756f..e7eb314 100644 --- a/test/private_node_allocator_test.cpp +++ b/test/private_node_allocator_test.cpp @@ -12,31 +12,37 @@ #include #include #include -#include "print_container.hpp" -#include "dummy_test_allocator.hpp" #include "movable_int.hpp" #include "list_test.hpp" #include "vector_test.hpp" using namespace boost::interprocess; +typedef test::overaligned_copyable_int oint_t; + //We will work with wide characters for shared memory objects //Alias an integer node allocator type typedef private_node_allocator priv_node_allocator_t; typedef ipcdetail::private_node_allocator_v1 priv_node_allocator_v1_t; +typedef private_node_allocator + < oint_t, managed_shared_memory::segment_manager> shmem_onode_allocator_t; +typedef ipcdetail::private_node_allocator_v1 + < oint_t, managed_shared_memory::segment_manager> shmem_onode_allocator_v1_t; namespace boost { namespace interprocess { //Explicit instantiations to catch compilation errors template class private_node_allocator; +template class private_node_allocator; template class private_node_allocator; namespace ipcdetail { template class ipcdetail::private_node_allocator_v1; +template class ipcdetail::private_node_allocator_v1; template class ipcdetail::private_node_allocator_v1; }}} @@ -44,10 +50,14 @@ template class ipcdetail::private_node_allocator_v1 MyShmList; typedef boost::container::list MyShmListV1; +typedef boost::container::list MyOShmList; +typedef boost::container::list MyOShmListV1; //Alias vector types typedef boost::container::vector MyShmVector; typedef boost::container::vector MyShmVectorV1; +typedef boost::container::vector MyOShmVector; +typedef boost::container::vector MyOShmVectorV1; int main () { @@ -55,9 +65,21 @@ int main () return 1; if(test::list_test(false)) return 1; + + if(test::list_test(false)) + return 1; + if(test::list_test(false)) + return 1; + if(test::vector_test()) return 1; if(test::vector_test()) return 1; + + if(test::vector_test()) + return 1; + if(test::vector_test()) + return 1; + return 0; }