Skip to content

Commit 6512eae

Browse files
committed
Allow adaptive pool based classes to support overaligned types. This change requires adding the node alignment data thorough the class inheritance and complicating a bit the logic for the adaptive pool. Overalignment value is packed inside free bits of existing bits in order to avoid breaking ABI.
1 parent 4b44909 commit 6512eae

File tree

8 files changed

+142
-33
lines changed

8 files changed

+142
-33
lines changed

include/boost/interprocess/allocators/adaptive_pool.hpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,13 @@ class adaptive_pool_base
8181
struct node_pool
8282
{
8383
typedef ipcdetail::shared_adaptive_node_pool
84-
< SegmentManager, sizeof_value<T>::value, NodesPerBlock, MaxFreeBlocks, OverheadPercent> type;
84+
< SegmentManager
85+
, sizeof_value<T>::value
86+
, NodesPerBlock
87+
, MaxFreeBlocks
88+
, OverheadPercent
89+
, alignof_value<T>::value
90+
> type;
8591

8692
static type *get(void *p)
8793
{ return static_cast<type*>(p); }

include/boost/interprocess/allocators/cached_adaptive_pool.hpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ class cached_adaptive_pool_v1
5656
, NodesPerBlock
5757
, MaxFreeBlocks
5858
, OverheadPercent
59+
, alignof_value<T>::value
5960
>
6061
, 1>
6162
{
@@ -69,6 +70,7 @@ class cached_adaptive_pool_v1
6970
, NodesPerBlock
7071
, MaxFreeBlocks
7172
, OverheadPercent
73+
, alignof_value<T>::value
7274
>
7375
, 1> base_t;
7476

@@ -146,6 +148,7 @@ class cached_adaptive_pool
146148
, NodesPerBlock
147149
, MaxFreeBlocks
148150
, OverheadPercent
151+
, alignof_value<T>::value
149152
>
150153
, 2>
151154
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
@@ -161,6 +164,7 @@ class cached_adaptive_pool
161164
, NodesPerBlock
162165
, MaxFreeBlocks
163166
, OverheadPercent
167+
, alignof_value<T>::value
164168
>
165169
, 2> base_t;
166170

include/boost/interprocess/allocators/detail/adaptive_node_pool.hpp

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ template< class SegmentManager
4646
, std::size_t NodesPerBlock
4747
, std::size_t MaxFreeBlocks
4848
, unsigned char OverheadPercent
49+
, std::size_t NodeAlign
4950
>
5051
class private_adaptive_node_pool
5152
: public boost::container::dtl::private_adaptive_node_pool_impl_rt
@@ -68,11 +69,12 @@ class private_adaptive_node_pool
6869
typedef SegmentManager segment_manager;
6970
typedef typename base_t::size_type size_type;
7071

71-
static const size_type nodes_per_block = NodesPerBlock;
72+
BOOST_STATIC_CONSTEXPR size_type nodes_per_block = NodesPerBlock;
73+
BOOST_STATIC_CONSTEXPR std::size_t node_alignment = NodeAlign != 0 ? NodeAlign : 1u;
7274

7375
//!Constructor from a segment manager. Never throws
7476
private_adaptive_node_pool(segment_manager *segment_mngr)
75-
: base_t(segment_mngr, NodeSize, NodesPerBlock, MaxFreeBlocks, OverheadPercent)
77+
: base_t(segment_mngr, NodeSize, NodesPerBlock, MaxFreeBlocks, OverheadPercent, NodeAlign)
7678
{}
7779

7880
//!Returns the segment manager. Never throws
@@ -89,16 +91,17 @@ template< class SegmentManager
8991
, std::size_t NodesPerBlock
9092
, std::size_t MaxFreeBlocks
9193
, unsigned char OverheadPercent
94+
, std::size_t NodeAlign
9295
>
9396
class shared_adaptive_node_pool
9497
: public ipcdetail::shared_pool_impl
9598
< private_adaptive_node_pool
96-
<SegmentManager, NodeSize, NodesPerBlock, MaxFreeBlocks, OverheadPercent>
99+
<SegmentManager, NodeSize, NodesPerBlock, MaxFreeBlocks, OverheadPercent, NodeAlign>
97100
>
98101
{
99102
typedef ipcdetail::shared_pool_impl
100103
< private_adaptive_node_pool
101-
<SegmentManager, NodeSize, NodesPerBlock, MaxFreeBlocks, OverheadPercent>
104+
<SegmentManager, NodeSize, NodesPerBlock, MaxFreeBlocks, OverheadPercent, NodeAlign>
102105
> base_t;
103106
public:
104107
shared_adaptive_node_pool(SegmentManager *segment_mgnr)

include/boost/interprocess/allocators/private_adaptive_pool.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ class private_adaptive_pool_base
8080
, NodesPerBlock
8181
, MaxFreeBlocks
8282
, OverheadPercent
83+
, alignof_value<T>::value
8384
> node_pool_t;
8485

8586
BOOST_INTERPROCESS_STATIC_ASSERT((Version <=2));
@@ -125,6 +126,7 @@ class private_adaptive_pool_base
125126
, NodesPerBlock
126127
, MaxFreeBlocks
127128
, OverheadPercent
129+
, alignof_value<T>::value
128130
> type;
129131

130132
static type *get(void *p)

test/adaptive_node_pool_test.cpp

Lines changed: 42 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,49 @@ typedef managed_shared_memory::segment_manager segment_manager_t;
1717

1818
int main ()
1919
{
20-
typedef ipcdetail::private_adaptive_node_pool
21-
<segment_manager_t, 4, 64, 64, 5> node_pool_t;
20+
{ //Private, normal alignment, small data
21+
typedef ipcdetail::private_adaptive_node_pool
22+
<segment_manager_t, 1u, 64, 64, 5, 0> node_pool_t;
2223

23-
if(!test::test_all_node_pool<node_pool_t>())
24-
return 1;
24+
if (!test::test_all_node_pool<node_pool_t>())
25+
return 1;
26+
}
27+
{ //Private, small alignment, small data
28+
typedef ipcdetail::private_adaptive_node_pool
29+
<segment_manager_t, 1u, 64, 64, 5, 2> node_pool_t;
30+
31+
if (!test::test_all_node_pool<node_pool_t>())
32+
return 1;
33+
}
34+
{ //Private, normal alignment
35+
typedef ipcdetail::private_adaptive_node_pool
36+
<segment_manager_t, sizeof(void*), 64, 64, 5, 0> node_pool_t;
37+
38+
if (!test::test_all_node_pool<node_pool_t>())
39+
return 1;
40+
}
41+
{ //Private, overaligned
42+
typedef ipcdetail::private_adaptive_node_pool
43+
<segment_manager_t, sizeof(void*), 64, 64, 5, sizeof(void*)*4U> node_pool_t;
44+
45+
if (!test::test_all_node_pool<node_pool_t>())
46+
return 1;
47+
}
48+
49+
{ //Shared, normal alignment
50+
typedef ipcdetail::shared_adaptive_node_pool
51+
<segment_manager_t, 4u, 64, 64, 5, 0> node_pool_t;
52+
53+
if (!test::test_all_node_pool<node_pool_t>())
54+
return 1;
55+
}
56+
{ //Shared, overaligned
57+
typedef ipcdetail::shared_adaptive_node_pool
58+
<segment_manager_t, sizeof(void*), 64, 64, 5, sizeof(void*) * 4u> node_pool_t;
59+
60+
if (!test::test_all_node_pool<node_pool_t>())
61+
return 1;
62+
}
2563

2664
return 0;
2765
}

test/adaptive_pool_test.cpp

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,14 @@
1212
#include <boost/container/list.hpp>
1313
#include <boost/container/vector.hpp>
1414
#include <boost/interprocess/allocators/adaptive_pool.hpp>
15-
#include "print_container.hpp"
16-
#include "dummy_test_allocator.hpp"
1715
#include "movable_int.hpp"
1816
#include "list_test.hpp"
1917
#include "vector_test.hpp"
2018

2119
using namespace boost::interprocess;
2220

21+
typedef test::overaligned_copyable_int oint_t;
22+
2323
//We will work with wide characters for shared memory objects
2424
//Alias an adaptive pool that allocates ints
2525
typedef adaptive_pool
@@ -28,41 +28,60 @@ typedef adaptive_pool
2828
typedef ipcdetail::adaptive_pool_v1
2929
<int, managed_shared_memory::segment_manager> shmem_node_allocator_v1_t;
3030

31+
typedef adaptive_pool
32+
< oint_t, managed_shared_memory::segment_manager> shmem_onode_allocator_t;
33+
typedef ipcdetail::adaptive_pool_v1
34+
< oint_t, managed_shared_memory::segment_manager> shmem_onode_allocator_v1_t;
35+
3136
namespace boost {
3237
namespace interprocess {
3338

3439
//Explicit instantiations to catch compilation errors
3540
template class adaptive_pool<int, managed_shared_memory::segment_manager>;
41+
template class adaptive_pool<oint_t, managed_shared_memory::segment_manager>;
3642
template class adaptive_pool<void, managed_shared_memory::segment_manager>;
3743

3844
namespace ipcdetail {
3945

4046
template class ipcdetail::adaptive_pool_v1<int, managed_shared_memory::segment_manager>;
47+
template class ipcdetail::adaptive_pool_v1<oint_t, managed_shared_memory::segment_manager>;
4148
template class ipcdetail::adaptive_pool_v1<void, managed_shared_memory::segment_manager>;
4249

4350
}}}
4451

4552
//Alias list types
4653
typedef boost::container::list<int, shmem_node_allocator_t> MyShmList;
4754
typedef boost::container::list<int, shmem_node_allocator_v1_t> MyShmListV1;
55+
typedef boost::container::list<oint_t, shmem_onode_allocator_t> MyOShmList;
56+
typedef boost::container::list<oint_t, shmem_onode_allocator_v1_t> MyOShmListV1;
4857

4958
//Alias vector types
5059
typedef boost::container::vector<int, shmem_node_allocator_t> MyShmVector;
5160
typedef boost::container::vector<int, shmem_node_allocator_v1_t> MyShmVectorV1;
61+
typedef boost::container::vector<oint_t, shmem_onode_allocator_t> MyOShmVector;
62+
typedef boost::container::vector<oint_t, shmem_onode_allocator_v1_t> MyOShmVectorV1;
5263

5364
int main ()
5465
{
5566
if(test::list_test<managed_shared_memory, MyShmList, true>())
5667
return 1;
57-
5868
if(test::list_test<managed_shared_memory, MyShmListV1, true>())
5969
return 1;
6070

61-
if(test::vector_test<managed_shared_memory, MyShmVector>())
71+
if(test::list_test<managed_shared_memory, MyOShmList, true>())
72+
return 1;
73+
if(test::list_test<managed_shared_memory, MyOShmListV1, true>())
6274
return 1;
6375

76+
if(test::vector_test<managed_shared_memory, MyShmVector>())
77+
return 1;
6478
if(test::vector_test<managed_shared_memory, MyShmVectorV1>())
6579
return 1;
6680

81+
if(test::vector_test<managed_shared_memory, MyOShmVector>())
82+
return 1;
83+
if(test::vector_test<managed_shared_memory, MyOShmVectorV1>())
84+
return 1;
85+
6786
return 0;
6887
}

test/cached_adaptive_pool_test.cpp

Lines changed: 30 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -12,59 +12,74 @@
1212
#include <boost/container/list.hpp>
1313
#include <boost/container/vector.hpp>
1414
#include <boost/interprocess/allocators/cached_adaptive_pool.hpp>
15-
#include "print_container.hpp"
16-
#include "dummy_test_allocator.hpp"
1715
#include "movable_int.hpp"
1816
#include "list_test.hpp"
1917
#include "vector_test.hpp"
2018

2119
using namespace boost::interprocess;
2220

21+
typedef test::overaligned_copyable_int oint_t;
22+
2323
//We will work with wide characters for shared memory objects
24-
//Alias an cached adaptive pool that allocates ints
24+
//Alias an integer node allocator type
2525
typedef cached_adaptive_pool
26-
<int, managed_shared_memory::segment_manager>
27-
cached_node_allocator_t;
28-
26+
<int, managed_shared_memory::segment_manager> priv_node_allocator_t;
2927
typedef ipcdetail::cached_adaptive_pool_v1
30-
<int, managed_shared_memory::segment_manager>
31-
cached_node_allocator_v1_t;
28+
<int, managed_shared_memory::segment_manager> priv_node_allocator_v1_t;
29+
typedef cached_adaptive_pool
30+
< oint_t, managed_shared_memory::segment_manager> shmem_onode_allocator_t;
31+
typedef ipcdetail::cached_adaptive_pool_v1
32+
< oint_t, managed_shared_memory::segment_manager> shmem_onode_allocator_v1_t;
3233

3334
namespace boost {
3435
namespace interprocess {
3536

3637
//Explicit instantiations to catch compilation errors
3738
template class cached_adaptive_pool<int, managed_shared_memory::segment_manager>;
39+
template class cached_adaptive_pool<oint_t, managed_shared_memory::segment_manager>;
3840
template class cached_adaptive_pool<void, managed_shared_memory::segment_manager>;
3941

4042
namespace ipcdetail {
4143

4244
template class ipcdetail::cached_adaptive_pool_v1<int, managed_shared_memory::segment_manager>;
45+
template class ipcdetail::cached_adaptive_pool_v1<oint_t, managed_shared_memory::segment_manager>;
4346
template class ipcdetail::cached_adaptive_pool_v1<void, managed_shared_memory::segment_manager>;
4447

4548
}}}
4649

4750
//Alias list types
48-
typedef boost::container::list<int, cached_node_allocator_t> MyShmList;
49-
typedef boost::container::list<int, cached_node_allocator_v1_t> MyShmListV1;
51+
typedef boost::container::list<int, priv_node_allocator_t> MyShmList;
52+
typedef boost::container::list<int, priv_node_allocator_v1_t> MyShmListV1;
53+
typedef boost::container::list<oint_t, shmem_onode_allocator_t> MyOShmList;
54+
typedef boost::container::list<oint_t, shmem_onode_allocator_v1_t> MyOShmListV1;
5055

5156
//Alias vector types
52-
typedef boost::container::vector<int, cached_node_allocator_t> MyShmVector;
53-
typedef boost::container::vector<int, cached_node_allocator_v1_t> MyShmVectorV1;
57+
typedef boost::container::vector<int, priv_node_allocator_t> MyShmVector;
58+
typedef boost::container::vector<int, priv_node_allocator_v1_t> MyShmVectorV1;
59+
typedef boost::container::vector<oint_t, shmem_onode_allocator_t> MyOShmVector;
60+
typedef boost::container::vector<oint_t, shmem_onode_allocator_v1_t> MyOShmVectorV1;
5461

5562
int main ()
5663
{
57-
if(test::list_test<managed_shared_memory, MyShmList, true>())
64+
if(test::list_test<managed_shared_memory, MyShmList, true>(false))
65+
return 1;
66+
if(test::list_test<managed_shared_memory, MyShmListV1, true>(false))
5867
return 1;
5968

60-
if(test::list_test<managed_shared_memory, MyShmListV1, true>())
69+
if(test::list_test<managed_shared_memory, MyOShmList, true>())
70+
return 1;
71+
if(test::list_test<managed_shared_memory, MyOShmListV1, true>())
6172
return 1;
6273

6374
if(test::vector_test<managed_shared_memory, MyShmVector>())
6475
return 1;
65-
6676
if(test::vector_test<managed_shared_memory, MyShmVectorV1>())
6777
return 1;
6878

79+
if(test::vector_test<managed_shared_memory, MyOShmVector>())
80+
return 1;
81+
if(test::vector_test<managed_shared_memory, MyOShmVectorV1>())
82+
return 1;
83+
6984
return 0;
7085
}

0 commit comments

Comments
 (0)