Add overalignment support for node_allocator, private_node_allocator and cached_node_allocator

This commit is contained in:
Ion Gaztañaga
2026-01-13 23:30:43 +01:00
parent fb5ba06d6c
commit c9aa051025
10 changed files with 187 additions and 37 deletions

View File

@@ -56,6 +56,7 @@ class cached_node_allocator_v1
< SegmentManager
, sizeof_value<T>::value
, NodesPerBlock
, alignof_value<T>::value
>
, 1>
{
@@ -67,6 +68,7 @@ class cached_node_allocator_v1
< SegmentManager
, sizeof_value<T>::value
, NodesPerBlock
, alignof_value<T>::value
>
, 1> base_t;
typedef uses_segment_manager<SegmentManager> uses_segment_manager_t;
@@ -77,7 +79,7 @@ class cached_node_allocator_v1
typedef cached_node_allocator_v1
<T2, SegmentManager, NodesPerBlock> 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<T>::value
, NodesPerBlock
, alignof_value<T>::value
>
, 2>
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
@@ -135,6 +138,7 @@ class cached_node_allocator
< SegmentManager
, sizeof_value<T>::value
, NodesPerBlock
, alignof_value<T>::value
>
, 2> base_t;

View File

@@ -62,22 +62,46 @@ struct sizeof_value<void>
template <>
struct sizeof_value<const void>
{
static const std::size_t value = sizeof(void*);
};
: sizeof_value<void>
{};
template <>
struct sizeof_value<volatile void>
{
static const std::size_t value = sizeof(void*);
};
: sizeof_value<void>
{};
template <>
struct sizeof_value<const volatile void>
: sizeof_value<void>
{};
template <class T>
struct alignof_value
{
static const std::size_t value = sizeof(void*);
static const std::size_t value = boost::container::dtl::alignment_of<T>::value;
};
template <>
struct alignof_value<void>
{
static const std::size_t value = boost::container::dtl::alignment_of<void*>::value;
};
template <>
struct alignof_value<const void>
: alignof_value<void>
{};
template <>
struct alignof_value<volatile void>
: alignof_value<void>
{};
template <>
struct alignof_value<const volatile void>
: alignof_value<void>
{};
template<class SegmentManager>
class uses_segment_manager
{
@@ -523,7 +547,7 @@ class node_pool_allocation_impl
}
else{
return pointer(static_cast<value_type*>
(pool->get_segment_manager()->allocate(count*sizeof(T))));
(pool->get_segment_manager()->allocate_aligned(count*sizeof(T), boost::container::dtl::alignment_of<T>::value)));
}
}

View File

@@ -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
<SegmentManager, NodeSize, NodesPerBlock>
<SegmentManager, NodeSize, NodesPerBlock, NodeAlign>
>
{
typedef ipcdetail::shared_pool_impl
< private_node_pool
<SegmentManager, NodeSize, NodesPerBlock>
<SegmentManager, NodeSize, NodesPerBlock, NodeAlign>
> base_t;
public:
shared_node_pool(SegmentManager *segment_mgnr)

View File

@@ -78,7 +78,11 @@ class node_allocator_base
struct node_pool
{
typedef ipcdetail::shared_node_pool
< SegmentManager, sizeof_value<T>::value, NodesPerBlock> type;
< SegmentManager
, sizeof_value<T>::value
, NodesPerBlock
, alignof_value<T>::value
> type;
static type *get(void *p)
{ return static_cast<type*>(p); }

View File

@@ -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
<SegmentManager
, sizeof_value<T>::value
, NodesPerBlock
< SegmentManager
, sizeof_value<T>::value
, NodesPerBlock
, alignof_value<T>::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
<SegmentManager
, sizeof_value<T>::value
, NodesPerBlock
< SegmentManager
, sizeof_value<T>::value
, NodesPerBlock
, alignof_value<T>::value
> type;
static type *get(void *p)

View File

@@ -12,14 +12,14 @@
#include <boost/container/list.hpp>
#include <boost/container/vector.hpp>
#include <boost/interprocess/allocators/cached_node_allocator.hpp>
#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
<int, managed_shared_memory::segment_manager>
@@ -28,16 +28,23 @@ typedef ipcdetail::cached_node_allocator_v1
<int, managed_shared_memory::segment_manager>
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<int, managed_shared_memory::segment_manager>;
template class cached_node_allocator<oint_t, managed_shared_memory::segment_manager>;
template class cached_node_allocator<void, managed_shared_memory::segment_manager>;
namespace ipcdetail {
template class ipcdetail::cached_node_allocator_v1<int, managed_shared_memory::segment_manager>;
template class ipcdetail::cached_node_allocator_v1<oint_t, managed_shared_memory::segment_manager>;
template class ipcdetail::cached_node_allocator_v1<void, managed_shared_memory::segment_manager>;
}}}
@@ -45,10 +52,14 @@ template class ipcdetail::cached_node_allocator_v1<void, managed_shared_memory::
//Alias list types
typedef boost::container::list<int, cached_node_allocator_t> MyShmList;
typedef boost::container::list<int, cached_node_allocator_v1_t> MyShmListV1;
typedef boost::container::list<oint_t, shmem_onode_allocator_t> MyOShmList;
typedef boost::container::list<oint_t, shmem_onode_allocator_v1_t> MyOShmListV1;
//Alias vector types
typedef boost::container::vector<int, cached_node_allocator_t> MyShmVector;
typedef boost::container::vector<int, cached_node_allocator_v1_t> MyShmVectorV1;
typedef boost::container::vector<oint_t, shmem_onode_allocator_t> MyOShmVector;
typedef boost::container::vector<oint_t, shmem_onode_allocator_v1_t> MyOShmVectorV1;
int main ()
{
@@ -56,9 +67,21 @@ int main ()
return 1;
if(test::list_test<managed_shared_memory, MyShmListV1, true>())
return 1;
if(test::list_test<managed_shared_memory, MyOShmList, true>())
return 1;
if(test::list_test<managed_shared_memory, MyOShmListV1, true>())
return 1;
if(test::vector_test<managed_shared_memory, MyShmVector>())
return 1;
if(test::vector_test<managed_shared_memory, MyShmVectorV1>())
return 1;
if(test::vector_test<managed_shared_memory, MyOShmVector>())
return 1;
if(test::vector_test<managed_shared_memory, MyOShmVectorV1>())
return 1;
return 0;
}

View File

@@ -12,31 +12,37 @@
#include <boost/container/list.hpp>
#include <boost/container/vector.hpp>
#include <boost/interprocess/allocators/node_allocator.hpp>
#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
<int, managed_shared_memory::segment_manager> shmem_node_allocator_t;
typedef ipcdetail::node_allocator_v1
<int, managed_shared_memory::segment_manager> 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<int, managed_shared_memory::segment_manager>;
template class node_allocator<oint_t, managed_shared_memory::segment_manager>;
template class node_allocator<void, managed_shared_memory::segment_manager>;
namespace ipcdetail {
template class ipcdetail::node_allocator_v1<int, managed_shared_memory::segment_manager>;
template class ipcdetail::node_allocator_v1<oint_t, managed_shared_memory::segment_manager>;
template class ipcdetail::node_allocator_v1<void, managed_shared_memory::segment_manager>;
}}}
@@ -44,20 +50,41 @@ template class ipcdetail::node_allocator_v1<void, managed_shared_memory::segment
//Alias list types
typedef boost::container::list<int, shmem_node_allocator_t> MyShmList;
typedef boost::container::list<int, shmem_node_allocator_v1_t> MyShmListV1;
typedef boost::container::list<oint_t, shmem_onode_allocator_t> MyOShmList;
typedef boost::container::list<oint_t, shmem_onode_allocator_v1_t> MyOShmListV1;
typedef boost::container::vector<oint_t, shmem_onode_allocator_t> MyOShmVector;
typedef boost::container::vector<oint_t, shmem_onode_allocator_v1_t> MyOShmVectorV1;
//Alias vector types
typedef boost::container::vector<int, shmem_node_allocator_t> MyShmVector;
typedef boost::container::vector<int, shmem_node_allocator_v1_t> MyShmVectorV1;
int main ()
{
{/*
if(test::list_test<managed_shared_memory, MyShmList, true>())
return 1;
if(test::list_test<managed_shared_memory, MyShmListV1, true>())
return 1;
if(test::list_test<managed_shared_memory, MyOShmList, true>())
return 1;*/
if(test::list_test<managed_shared_memory, MyOShmListV1, true>())
return 1;
/*
if(test::list_test<managed_shared_memory, MyShmList, true>())
return 1;
if(test::list_test<managed_shared_memory, MyShmListV1, true>())
return 1;
if(test::vector_test<managed_shared_memory, MyShmVector>())
return 1;
if(test::vector_test<managed_shared_memory, MyShmVectorV1>())
return 1;
if(test::vector_test<managed_shared_memory, MyOShmVector>())
return 1;*/
if(test::vector_test<managed_shared_memory, MyOShmVectorV1>())
return 1;
return 0;
}

View File

@@ -16,17 +16,49 @@ typedef managed_shared_memory::segment_manager segment_manager_t;
int main ()
{
typedef ipcdetail::private_node_pool
<segment_manager_t, 4, 64> node_pool_t;
{ //Private, normal alignment, small data
typedef ipcdetail::private_node_pool
<segment_manager_t, 1u, 64, 0> node_pool_t;
if(!test::test_all_node_pool<node_pool_t>())
return 1;
if (!test::test_all_node_pool<node_pool_t>())
return 1;
}
{ //Private, small alignment, small data
typedef ipcdetail::private_node_pool
<segment_manager_t, 1u, 64, 2u> node_pool_t;
typedef ipcdetail::shared_node_pool
<segment_manager_t, 4, 64> shared_node_pool_t;
if (!test::test_all_node_pool<node_pool_t>())
return 1;
}
{ //Private, normal alignment
typedef ipcdetail::private_node_pool
<segment_manager_t, sizeof(void*), 64, 0> node_pool_t;
if(!test::test_all_node_pool<shared_node_pool_t>())
return 1;
if (!test::test_all_node_pool<node_pool_t>())
return 1;
}
{ //Private, overaligned
typedef ipcdetail::private_node_pool
<segment_manager_t, sizeof(void*), 64, sizeof(void*)*4U> node_pool_t;
if (!test::test_all_node_pool<node_pool_t>())
return 1;
}
{ //Shared, normal alignment
typedef ipcdetail::shared_node_pool
<segment_manager_t, 4, 64, 0> node_pool_t;
if (!test::test_all_node_pool<node_pool_t>())
return 1;
}
{ //Shared, overaligned
typedef ipcdetail::shared_node_pool
<segment_manager_t, sizeof(void*), 64, sizeof(void*)*4u> node_pool_t;
if (!test::test_all_node_pool<node_pool_t>())
return 1;
}
return 0;
}

View File

@@ -42,7 +42,13 @@ bool test_node_pool<NodePool>::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<node_pool_t> 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<node_pool_t, segment_manager> deleter_t;
typedef unique_ptr<node_pool_t, deleter_t> unique_ptr_t;

View File

@@ -12,31 +12,37 @@
#include <boost/container/list.hpp>
#include <boost/container/vector.hpp>
#include <boost/interprocess/allocators/private_node_allocator.hpp>
#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
<int, managed_shared_memory::segment_manager> priv_node_allocator_t;
typedef ipcdetail::private_node_allocator_v1
<int, managed_shared_memory::segment_manager> 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<int, managed_shared_memory::segment_manager>;
template class private_node_allocator<oint_t, managed_shared_memory::segment_manager>;
template class private_node_allocator<void, managed_shared_memory::segment_manager>;
namespace ipcdetail {
template class ipcdetail::private_node_allocator_v1<int, managed_shared_memory::segment_manager>;
template class ipcdetail::private_node_allocator_v1<oint_t, managed_shared_memory::segment_manager>;
template class ipcdetail::private_node_allocator_v1<void, managed_shared_memory::segment_manager>;
}}}
@@ -44,10 +50,14 @@ template class ipcdetail::private_node_allocator_v1<void, managed_shared_memory:
//Alias list types
typedef boost::container::list<int, priv_node_allocator_t> MyShmList;
typedef boost::container::list<int, priv_node_allocator_v1_t> MyShmListV1;
typedef boost::container::list<oint_t, shmem_onode_allocator_t> MyOShmList;
typedef boost::container::list<oint_t, shmem_onode_allocator_v1_t> MyOShmListV1;
//Alias vector types
typedef boost::container::vector<int, priv_node_allocator_t> MyShmVector;
typedef boost::container::vector<int, priv_node_allocator_v1_t> MyShmVectorV1;
typedef boost::container::vector<oint_t, shmem_onode_allocator_t> MyOShmVector;
typedef boost::container::vector<oint_t, shmem_onode_allocator_v1_t> MyOShmVectorV1;
int main ()
{
@@ -55,9 +65,21 @@ int main ()
return 1;
if(test::list_test<managed_shared_memory, MyShmListV1, true>(false))
return 1;
if(test::list_test<managed_shared_memory, MyOShmList, true>(false))
return 1;
if(test::list_test<managed_shared_memory, MyOShmListV1, true>(false))
return 1;
if(test::vector_test<managed_shared_memory, MyShmVector>())
return 1;
if(test::vector_test<managed_shared_memory, MyShmVectorV1>())
return 1;
if(test::vector_test<managed_shared_memory, MyOShmVector>())
return 1;
if(test::vector_test<managed_shared_memory, MyOShmVectorV1>())
return 1;
return 0;
}