Skip to content

Commit 55017f4

Browse files
committed
Fixes #247
Fix move semantics for cache-containing allocators
1 parent ded9a06 commit 55017f4

File tree

8 files changed

+170
-1
lines changed

8 files changed

+170
-1
lines changed

doc/interprocess.qbk

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6783,6 +6783,13 @@ thank them:
67836783

67846784
[section:release_notes Release Notes]
67856785

6786+
[section:release_notes_boost_1_91_00 Boost 1.91 Release]
6787+
6788+
* Fixed bugs:
6789+
* [@https://github.com/boostorg/interprocess/issues/247 GitHub #247 (['"destruction of move-constructed map using private_adaptive_pool triggers Assertion"])].
6790+
6791+
[endsect]
6792+
67866793
[section:release_notes_boost_1_90_00 Boost 1.90 Release]
67876794

67886795
* Minor documentation fixes

include/boost/interprocess/allocators/cached_adaptive_pool.hpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ class cached_adaptive_pool_v1
5959
>
6060
, 1>
6161
{
62+
BOOST_COPYABLE_AND_MOVABLE_ALT(cached_adaptive_pool_v1)
6263
public:
6364
typedef ipcdetail::cached_allocator_impl
6465
< T
@@ -91,6 +92,14 @@ class cached_adaptive_pool_v1
9192
<T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> &other)
9293
: base_t(other)
9394
{}
95+
96+
cached_adaptive_pool_v1(const cached_adaptive_pool_v1 &other)
97+
: base_t(other)
98+
{}
99+
100+
cached_adaptive_pool_v1(BOOST_RV_REF(cached_adaptive_pool_v1) other)
101+
: base_t(BOOST_MOVE_BASE(base_t, other))
102+
{}
94103
};
95104

96105
} //namespace ipcdetail{
@@ -148,6 +157,7 @@ class cached_adaptive_pool
148157
>
149158
, 2> base_t;
150159

160+
BOOST_COPYABLE_AND_MOVABLE_ALT(cached_adaptive_pool)
151161
public:
152162
typedef boost::interprocess::version_type<cached_adaptive_pool, 2> version;
153163

@@ -169,6 +179,14 @@ class cached_adaptive_pool
169179
: base_t(other)
170180
{}
171181

182+
cached_adaptive_pool(const cached_adaptive_pool &other)
183+
: base_t(other)
184+
{}
185+
186+
cached_adaptive_pool(BOOST_RV_REF(cached_adaptive_pool) other)
187+
: base_t(BOOST_MOVE_BASE(base_t, other))
188+
{}
189+
172190
#else
173191
public:
174192
typedef implementation_defined::segment_manager segment_manager;
@@ -212,6 +230,10 @@ class cached_adaptive_pool
212230
//!count of the associated node pool. Never throws
213231
cached_adaptive_pool(const cached_adaptive_pool &other);
214232

233+
//!Move constructor from other. Increments the reference
234+
//!count of the associated node pool and captures the cache. Never throws
235+
cached_adaptive_pool(cached_adaptive_pool &&other);
236+
215237
//!Copy constructor from related cached_adaptive_pool. If not present, constructs
216238
//!a node pool. Increments the reference count of the associated node pool.
217239
//!Can throw boost::interprocess::bad_alloc

include/boost/interprocess/allocators/cached_node_allocator.hpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ class cached_node_allocator_v1
5656
>
5757
, 1>
5858
{
59+
BOOST_COPYABLE_AND_MOVABLE_ALT(cached_node_allocator_v1)
5960
public:
6061
typedef ipcdetail::cached_allocator_impl
6162
< T
@@ -86,6 +87,14 @@ class cached_node_allocator_v1
8687
<T2, SegmentManager, NodesPerBlock> &other)
8788
: base_t(other)
8889
{}
90+
91+
cached_node_allocator_v1(const cached_node_allocator_v1 &other)
92+
: base_t(other)
93+
{}
94+
95+
cached_node_allocator_v1(BOOST_RV_REF(cached_node_allocator_v1) other)
96+
: base_t(BOOST_MOVE_BASE(base_t, other))
97+
{}
8998
};
9099

91100
} //namespace ipcdetail{
@@ -120,6 +129,8 @@ class cached_node_allocator
120129
>
121130
, 2> base_t;
122131

132+
BOOST_COPYABLE_AND_MOVABLE_ALT(cached_node_allocator)
133+
123134
public:
124135
typedef boost::interprocess::version_type<cached_node_allocator, 2> version;
125136
typedef typename base_t::size_type size_type;
@@ -141,6 +152,14 @@ class cached_node_allocator
141152
: base_t(other)
142153
{}
143154

155+
cached_node_allocator(const cached_node_allocator & other)
156+
: base_t(other)
157+
{}
158+
159+
cached_node_allocator(BOOST_RV_REF(cached_node_allocator) other)
160+
: base_t(BOOST_MOVE_BASE(base_t, other))
161+
{}
162+
144163
#else
145164
public:
146165
typedef implementation_defined::segment_manager segment_manager;
@@ -184,6 +203,10 @@ class cached_node_allocator
184203
//!count of the associated node pool. Never throws
185204
cached_node_allocator(const cached_node_allocator &other);
186205

206+
//!Move constructor from other. Increments the reference
207+
//!count of the associated node pool and captures the cache. Never throws
208+
cached_node_allocator(cached_node_allocator &&other);
209+
187210
//!Copy constructor from related cached_node_allocator. If not present, constructs
188211
//!a node pool. Increments the reference count of the associated node pool.
189212
//!Can throw boost::interprocess::bad_alloc

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

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,21 +162,34 @@ class cache_impl
162162
multiallocation_chain m_cached_nodes;
163163
size_type m_max_cached_nodes;
164164

165+
BOOST_COPYABLE_AND_MOVABLE_ALT(cache_impl)
166+
165167
public:
166168
typedef typename NodePool::segment_manager segment_manager;
167169

168170
cache_impl(segment_manager *segment_mngr, size_type max_cached_nodes)
169171
: mp_node_pool(get_or_create_node_pool<NodePool>(segment_mngr))
172+
, m_cached_nodes()
170173
, m_max_cached_nodes(max_cached_nodes)
171174
{}
172175

173176
cache_impl(const cache_impl &other)
174177
: mp_node_pool(other.get_node_pool())
178+
, m_cached_nodes()
175179
, m_max_cached_nodes(other.get_max_cached_nodes())
176180
{
177181
mp_node_pool->inc_ref_count();
178182
}
179183

184+
cache_impl(BOOST_RV_REF(cache_impl) other)
185+
: mp_node_pool(BOOST_MOVE_TO_LV(other).get_node_pool())
186+
, m_cached_nodes()
187+
, m_max_cached_nodes(BOOST_MOVE_TO_LV(other).get_max_cached_nodes())
188+
{
189+
mp_node_pool->inc_ref_count();
190+
m_cached_nodes.swap(BOOST_MOVE_TO_LV(other).m_cached_nodes);
191+
}
192+
180193
~cache_impl()
181194
{
182195
this->deallocate_all_cached_nodes();
@@ -565,6 +578,8 @@ class cached_allocator_impl
565578
typedef typename base_t::multiallocation_chain multiallocation_chain;
566579
typedef typename base_t::value_type value_type;
567580

581+
BOOST_COPYABLE_AND_MOVABLE_ALT(cached_allocator_impl)
582+
568583
public:
569584
static const std::size_t DEFAULT_MAX_CACHED_NODES = 64;
570585

@@ -576,6 +591,10 @@ class cached_allocator_impl
576591
: m_cache(other.m_cache)
577592
{}
578593

594+
cached_allocator_impl(BOOST_RV_REF(cached_allocator_impl) other)
595+
: m_cache(boost::move(BOOST_MOVE_TO_LV(other).m_cache))
596+
{}
597+
579598
//!Copy constructor from related cached_adaptive_pool_base. If not present, constructs
580599
//!a node pool. Increments the reference count of the associated node pool.
581600
//!Can throw boost::interprocess::bad_alloc

include/boost/interprocess/allocators/private_adaptive_pool.hpp

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,9 @@ class private_adaptive_pool_base
129129
};
130130

131131
private:
132+
133+
BOOST_COPYABLE_AND_MOVABLE_ALT(private_adaptive_pool_base)
134+
132135
//!Not assignable from related private_adaptive_pool_base
133136
template<unsigned int Version2, class T2, class MemoryAlgorithm2, std::size_t N2, std::size_t F2, unsigned char OP2>
134137
private_adaptive_pool_base& operator=
@@ -149,7 +152,14 @@ class private_adaptive_pool_base
149152
: m_node_pool(other.get_segment_manager())
150153
{}
151154

152-
//!Copy constructor from related private_adaptive_pool_base. Never throws.
155+
//!Copy constructor from other private_adaptive_pool_base. Never throws
156+
private_adaptive_pool_base(BOOST_RV_REF(private_adaptive_pool_base) other)
157+
: m_node_pool(other.get_segment_manager())
158+
{
159+
m_node_pool.swap(BOOST_MOVE_TO_LV(other).m_node_pool);
160+
}
161+
162+
//!Move constructor from related private_adaptive_pool_base. Never throws.
153163
template<class T2>
154164
private_adaptive_pool_base
155165
(const private_adaptive_pool_base
@@ -208,6 +218,7 @@ class private_adaptive_pool_v1
208218
, OverheadPercent
209219
>
210220
{
221+
BOOST_COPYABLE_AND_MOVABLE_ALT(private_adaptive_pool_v1)
211222
public:
212223
typedef ipcdetail::private_adaptive_pool_base
213224
< 1, T, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> base_t;
@@ -227,6 +238,14 @@ class private_adaptive_pool_v1
227238
(const private_adaptive_pool_v1<T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> &other)
228239
: base_t(other)
229240
{}
241+
242+
private_adaptive_pool_v1(const private_adaptive_pool_v1 &other)
243+
: base_t(other)
244+
{}
245+
246+
private_adaptive_pool_v1(BOOST_RV_REF(private_adaptive_pool_v1) other)
247+
: base_t(BOOST_MOVE_BASE(base_t, other))
248+
{}
230249
};
231250

232251
} //namespace ipcdetail {
@@ -268,6 +287,8 @@ class private_adaptive_pool
268287
#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
269288
typedef ipcdetail::private_adaptive_pool_base
270289
< 2, T, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> base_t;
290+
291+
BOOST_COPYABLE_AND_MOVABLE_ALT(private_adaptive_pool)
271292
public:
272293
typedef boost::interprocess::version_type<private_adaptive_pool, 2> version;
273294

@@ -288,6 +309,14 @@ class private_adaptive_pool
288309
: base_t(other)
289310
{}
290311

312+
private_adaptive_pool(const private_adaptive_pool &other)
313+
: base_t(other)
314+
{}
315+
316+
private_adaptive_pool(BOOST_RV_REF(private_adaptive_pool) other)
317+
: base_t(BOOST_MOVE_BASE(base_t, other))
318+
{}
319+
291320
#else
292321
public:
293322
typedef implementation_defined::segment_manager segment_manager;
@@ -332,6 +361,10 @@ class private_adaptive_pool
332361
//!count of the associated node pool. Never throws
333362
private_adaptive_pool(const private_adaptive_pool &other);
334363

364+
//!Move constructor from other. Increments the reference
365+
//!count of the associated node pool and captures the cache. Never throws
366+
private_adaptive_pool(private_adaptive_pool &&other);
367+
335368
//!Copy constructor from related private_adaptive_pool. If not present, constructs
336369
//!a node pool. Increments the reference count of the associated node pool.
337370
//!Can throw boost::interprocess::bad_alloc

include/boost/interprocess/allocators/private_node_allocator.hpp

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ class private_node_allocator_base
5959
, SegmentManager
6060
>
6161
{
62+
BOOST_COPYABLE_AND_MOVABLE_ALT(private_node_allocator_base)
6263
public:
6364
//Segment manager
6465
typedef SegmentManager segment_manager;
@@ -141,6 +142,13 @@ class private_node_allocator_base
141142
: m_node_pool(other.get_segment_manager())
142143
{}
143144

145+
//!Move constructor from other private_node_allocator_base. Never throws
146+
private_node_allocator_base(BOOST_RV_REF(private_node_allocator_base) other)
147+
: m_node_pool(other.get_segment_manager())
148+
{
149+
m_node_pool.swap(BOOST_MOVE_TO_LV(other).m_node_pool);
150+
}
151+
144152
//!Copy constructor from related private_node_allocator_base. Never throws.
145153
template<class T2>
146154
private_node_allocator_base
@@ -196,6 +204,7 @@ class private_node_allocator_v1
196204
, NodesPerBlock
197205
>
198206
{
207+
BOOST_COPYABLE_AND_MOVABLE_ALT(private_node_allocator_v1)
199208
public:
200209
typedef ipcdetail::private_node_allocator_base
201210
< 1, T, SegmentManager, NodesPerBlock> base_t;
@@ -215,6 +224,14 @@ class private_node_allocator_v1
215224
(const private_node_allocator_v1<T2, SegmentManager, NodesPerBlock> &other)
216225
: base_t(other)
217226
{}
227+
228+
private_node_allocator_v1(const private_node_allocator_v1 &other)
229+
: base_t(other)
230+
{}
231+
232+
private_node_allocator_v1(BOOST_RV_REF(private_node_allocator_v1) other)
233+
: base_t(BOOST_MOVE_BASE(base_t, other))
234+
{}
218235
};
219236

220237
} //namespace ipcdetail {
@@ -245,6 +262,8 @@ class private_node_allocator
245262
#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
246263
typedef ipcdetail::private_node_allocator_base
247264
< 2, T, SegmentManager, NodesPerBlock> base_t;
265+
266+
BOOST_COPYABLE_AND_MOVABLE_ALT(private_node_allocator)
248267
public:
249268
typedef boost::interprocess::version_type<private_node_allocator, 2> version;
250269

@@ -265,6 +284,14 @@ class private_node_allocator
265284
: base_t(other)
266285
{}
267286

287+
private_node_allocator(const private_node_allocator &other)
288+
: base_t(other)
289+
{}
290+
291+
private_node_allocator(BOOST_RV_REF(private_node_allocator) other)
292+
: base_t(BOOST_MOVE_BASE(base_t, other))
293+
{}
294+
268295
#else
269296
public:
270297
typedef implementation_defined::segment_manager segment_manager;
@@ -309,6 +336,10 @@ class private_node_allocator
309336
//!count of the associated node pool. Never throws
310337
private_node_allocator(const private_node_allocator &other);
311338

339+
//!Move constructor from other. Increments the reference
340+
//!count of the associated node pool and captures the cache. Never throws
341+
private_node_allocator(private_node_allocator &&other);
342+
312343
//!Copy constructor from related private_node_allocator. If not present, constructs
313344
//!a node pool. Increments the reference count of the associated node pool.
314345
//!Can throw boost::interprocess::bad_alloc

test/adaptive_node_pool_test.cpp

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,32 @@ int main ()
2525

2626
return 0;
2727
}
28+
/*
29+
30+
#include <boost/interprocess/allocators/private_adaptive_pool.hpp>
31+
#include <boost/interprocess/containers/map.hpp>
32+
#include <boost/interprocess/managed_heap_memory.hpp>
33+
#include <cstdint>
34+
35+
typedef boost::interprocess::managed_heap_memory::segment_manager
36+
segment_manager_t;
37+
38+
typedef boost::interprocess::map<
39+
uint32_t, uint32_t, std::less<uint32_t>,
40+
boost::interprocess::private_adaptive_pool<
41+
std::pair<const uint32_t, uint32_t>, segment_manager_t>>
42+
mymap_t;
43+
44+
int main() {
45+
boost::interprocess::managed_heap_memory heap_mem(1u << 20);
46+
47+
{
48+
mymap_t bbmap(heap_mem.get_segment_manager());
49+
50+
bbmap.emplace(1, 2);
51+
52+
mymap_t bbmap2(boost::move(bbmap));
53+
} // <= CRASHES HERE
54+
55+
return 0;
56+
}*/

test/list_test.hpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,11 @@ int list_test (bool copied_allocators_equal = true)
135135
stdlist->pop_front();
136136
if(!CheckEqualContainers(shmlist, stdlist)) return 1;
137137

138+
{
139+
MyShmList m(boost::move(*shmlist));
140+
*shmlist = boost::move(m);
141+
}
142+
138143
{
139144
IntType aux_vect[50];
140145
for(int i = 0; i < 50; ++i){

0 commit comments

Comments
 (0)