Modify experimental "allocate_many" function to take an alignment parameter.

This commit is contained in:
Ion Gaztañaga
2026-01-10 18:58:01 +01:00
parent 5069b61f65
commit aab8703240
8 changed files with 112 additions and 99 deletions

View File

@@ -3986,7 +3986,7 @@ Here is a small example showing how aligned allocation is used:
[section:managed_memory_segment_multiple_allocations Multiple allocation functions] [section:managed_memory_segment_multiple_allocations Multiple allocation functions]
[caution This feature is experimental, interface and ABI are unstable] [caution This feature is experimental, API and ABI are unstable]
If an application needs to allocate a lot of memory buffers but it needs If an application needs to allocate a lot of memory buffers but it needs
to deallocate them independently, the application is normally forced to loop to deallocate them independently, the application is normally forced to loop
@@ -6875,6 +6875,12 @@ thank them:
* Added `BOOST_HEADER_DEPRECATED` to `<boost/interprocess/containers/*.hpp> headers. They were deprecated several releases ago, but this * Added `BOOST_HEADER_DEPRECATED` to `<boost/interprocess/containers/*.hpp> headers. They were deprecated several releases ago, but this
message will annoy existing users to switch to Boost.Container headers. message will annoy existing users to switch to Boost.Container headers.
* Changed the interface of [link managed_memory_segment_advanced_features.managed_memory_segment_multiple_allocations Multiple allocation functions]
(still experimental and API/ABI unstable) to support alignment.
Added `BOOST_HEADER_DEPRECATED` to `<boost/interprocess/containers/*.hpp> headers. They were deprecated several releases ago, but this
message will annoy existing users to switch to Boost.Container headers.
* Fixed bugs: * Fixed bugs:
* [@https://github.com/boostorg/interprocess/issues/242 GitHub #242 (['"Cygwin compatibility issues"])]. * [@https://github.com/boostorg/interprocess/issues/242 GitHub #242 (['"Cygwin compatibility issues"])].
* [@https://github.com/boostorg/interprocess/issues/247 GitHub #247 (['"destruction of move-constructed map using private_adaptive_pool triggers Assertion"])]. * [@https://github.com/boostorg/interprocess/issues/247 GitHub #247 (['"destruction of move-constructed map using private_adaptive_pool triggers Assertion"])].

View File

@@ -38,9 +38,9 @@ int main()
managed_shared_memory managed_shm(create_only,test::get_process_id_name(), 65536); managed_shared_memory managed_shm(create_only,test::get_process_id_name(), 65536);
//Allocate 16 elements of 100 bytes in a single call. Non-throwing version. //Allocate 16 elements of 100 bytes with a minimal alignment of 4, in a single call. Non-throwing version.
multiallocation_chain chain; multiallocation_chain chain;
managed_shm.allocate_many(std::nothrow, 100, 16, chain); managed_shm.allocate_many(std::nothrow, 100, 16, 4u, chain);
//Check if the memory allocation was successful //Check if the memory allocation was successful
if(chain.empty()) return 1; if(chain.empty()) return 1;
@@ -68,7 +68,7 @@ int main()
for(std::size_t i = 0; i < 10; ++i) for(std::size_t i = 0; i < 10; ++i)
sizes[i] = i*3; sizes[i] = i*3;
managed_shm.allocate_many(sizes, 10, 1, chain); managed_shm.allocate_many(sizes, 10, 1, 4, chain);
managed_shm.deallocate_many(chain); managed_shm.deallocate_many(chain);
return 0; return 0;
} }

View File

@@ -307,24 +307,24 @@ class basic_managed_memory_impl
//!Allocates n_elements of elem_bytes bytes. //!Allocates n_elements of elem_bytes bytes.
//!Throws bad_alloc on failure. chain.size() is not increased on failure. //!Throws bad_alloc on failure. chain.size() is not increased on failure.
void allocate_many(size_type elem_bytes, size_type n_elements, multiallocation_chain &chain) void allocate_many(size_type elem_bytes, size_type n_elements, size_type alignment, multiallocation_chain &chain)
{ mp_header->allocate_many(elem_bytes, n_elements, chain); } { mp_header->allocate_many(elem_bytes, n_elements, alignment, chain); }
//!Allocates n_elements, each one of element_lengths[i]*sizeof_element bytes. //!Allocates n_elements, each one of element_lengths[i]*sizeof_element bytes.
//!Throws bad_alloc on failure. chain.size() is not increased on failure. //!Throws bad_alloc on failure. chain.size() is not increased on failure.
void allocate_many(const size_type *element_lengths, size_type n_elements, size_type sizeof_element, multiallocation_chain &chain) void allocate_many(const size_type *element_lengths, size_type n_elements, size_type sizeof_element, size_type alignment, multiallocation_chain &chain)
{ mp_header->allocate_many(element_lengths, n_elements, sizeof_element, chain); } { mp_header->allocate_many(element_lengths, n_elements, sizeof_element, alignment, chain); }
//!Allocates n_elements of elem_bytes bytes. //!Allocates n_elements of elem_bytes bytes.
//!Non-throwing version. chain.size() is not increased on failure. //!Non-throwing version. chain.size() is not increased on failure.
void allocate_many(const std::nothrow_t &tag, size_type elem_bytes, size_type n_elements, multiallocation_chain &chain) void allocate_many(const std::nothrow_t &tag, size_type elem_bytes, size_type n_elements, size_type alignment, multiallocation_chain &chain)
{ mp_header->allocate_many(tag, elem_bytes, n_elements, chain); } { mp_header->allocate_many(tag, elem_bytes, n_elements, alignment, chain); }
//!Allocates n_elements, each one of //!Allocates n_elements, each one of
//!element_lengths[i]*sizeof_element bytes. //!element_lengths[i]*sizeof_element bytes.
//!Non-throwing version. chain.size() is not increased on failure. //!Non-throwing version. chain.size() is not increased on failure.
void allocate_many(const std::nothrow_t &tag, const size_type *elem_sizes, size_type n_elements, size_type sizeof_element, multiallocation_chain &chain) void allocate_many(const std::nothrow_t &tag, const size_type *elem_sizes, size_type n_elements, size_type sizeof_element, size_type alignment, multiallocation_chain &chain)
{ mp_header->allocate_many(tag, elem_sizes, n_elements, sizeof_element, chain); } { mp_header->allocate_many(tag, elem_sizes, n_elements, sizeof_element, alignment, chain); }
//!Deallocates all elements contained in chain. //!Deallocates all elements contained in chain.
//!Never throws. //!Never throws.

View File

@@ -125,9 +125,9 @@ class memory_algorithm_common
{ return get_rounded_size(size, Alignment); } { return get_rounded_size(size, Alignment); }
static void allocate_many static void allocate_many
(MemoryAlgorithm *memory_algo, size_type elem_bytes, size_type n_elements, multiallocation_chain &chain) (MemoryAlgorithm *memory_algo, size_type elem_bytes, size_type n_elements, size_type alignment, multiallocation_chain &chain)
{ {
return this_type::priv_allocate_many(memory_algo, &elem_bytes, n_elements, 0, chain); return this_type::priv_allocate_many(memory_algo, &elem_bytes, n_elements, alignment, 0, chain);
} }
static void deallocate_many(MemoryAlgorithm *memory_algo, multiallocation_chain &chain) static void deallocate_many(MemoryAlgorithm *memory_algo, multiallocation_chain &chain)
@@ -235,9 +235,10 @@ class memory_algorithm_common
, const size_type *elem_sizes , const size_type *elem_sizes
, size_type n_elements , size_type n_elements
, size_type sizeof_element , size_type sizeof_element
, size_type alignment
, multiallocation_chain &chain) , multiallocation_chain &chain)
{ {
this_type::priv_allocate_many(memory_algo, elem_sizes, n_elements, sizeof_element, chain); this_type::priv_allocate_many(memory_algo, elem_sizes, n_elements, sizeof_element, alignment, chain);
} }
static void* allocate_aligned(MemoryAlgorithm * const memory_algo, const size_type nbytes, const size_type alignment) static void* allocate_aligned(MemoryAlgorithm * const memory_algo, const size_type nbytes, const size_type alignment)
@@ -487,6 +488,7 @@ class memory_algorithm_common
( MemoryAlgorithm *memory_algo ( MemoryAlgorithm *memory_algo
, const size_type *elem_sizes , const size_type *elem_sizes
, size_type n_elements , size_type n_elements
, size_type alignment
, size_type sizeof_element , size_type sizeof_element
, multiallocation_chain &chain) , multiallocation_chain &chain)
{ {
@@ -530,7 +532,7 @@ class memory_algorithm_common
size_type received_size = total_bytes; size_type received_size = total_bytes;
void *ignore_reuse = 0; void *ignore_reuse = 0;
void *ret = memory_algo->priv_allocate void *ret = memory_algo->priv_allocate
(boost::interprocess::allocate_new, min_allocation, received_size, ignore_reuse); (boost::interprocess::allocate_new, min_allocation, received_size, ignore_reuse, 1, alignment);
if(!ret){ if(!ret){
break; break;
} }

View File

@@ -157,22 +157,22 @@ class simple_seq_fit_impl
//!Multiple element allocation, same size //!Multiple element allocation, same size
//!Experimental. Dont' use //!Experimental. Dont' use
void allocate_many(size_type elem_bytes, size_type num_elements, multiallocation_chain &chain) void allocate_many(size_type elem_bytes, size_type num_elements, size_type alignment, multiallocation_chain &chain)
{ {
//----------------------- //-----------------------
boost::interprocess::scoped_lock<interprocess_mutex> guard(m_header); boost::interprocess::scoped_lock<interprocess_mutex> guard(m_header);
//----------------------- //-----------------------
algo_impl_t::allocate_many(this, elem_bytes, num_elements, chain); algo_impl_t::allocate_many(this, elem_bytes, num_elements, alignment, chain);
} }
//!Multiple element allocation, different size //!Multiple element allocation, different size
//!Experimental. Dont' use //!Experimental. Dont' use
void allocate_many(const size_type *elem_sizes, size_type n_elements, size_type sizeof_element, multiallocation_chain &chain) void allocate_many(const size_type *elem_sizes, size_type n_elements, size_type sizeof_element, size_type alignment, multiallocation_chain &chain)
{ {
//----------------------- //-----------------------
boost::interprocess::scoped_lock<interprocess_mutex> guard(m_header); boost::interprocess::scoped_lock<interprocess_mutex> guard(m_header);
//----------------------- //-----------------------
algo_impl_t::allocate_many(this, elem_sizes, n_elements, sizeof_element, chain); algo_impl_t::allocate_many(this, elem_sizes, n_elements, sizeof_element, alignment, chain);
} }
//!Multiple element deallocation //!Multiple element deallocation
@@ -229,7 +229,7 @@ class simple_seq_fit_impl
//!Real allocation algorithm with min allocation option //!Real allocation algorithm with min allocation option
void * priv_allocate(boost::interprocess::allocation_type command void * priv_allocate(boost::interprocess::allocation_type command
,size_type min_size ,size_type min_size
,size_type &prefer_in_recvd_out_size, void *&reuse_ptr, size_type alignof_object = Alignment); ,size_type &prefer_in_recvd_out_size, void *&reuse_ptr, size_type sizeof_object = 1, size_type alignof_object = Alignment);
//!Returns the number of total units that a user buffer //!Returns the number of total units that a user buffer
//!of "userbytes" bytes really occupies (including header) //!of "userbytes" bytes really occupies (including header)
@@ -635,7 +635,7 @@ simple_seq_fit_impl<MutexFamily, VoidPointer>::
template<class MutexFamily, class VoidPointer> template<class MutexFamily, class VoidPointer>
void * simple_seq_fit_impl<MutexFamily, VoidPointer>:: void * simple_seq_fit_impl<MutexFamily, VoidPointer>::
priv_allocate(boost::interprocess::allocation_type command priv_allocate(boost::interprocess::allocation_type command
,size_type limit_size, size_type &prefer_in_recvd_out_size, void *&reuse_ptr, size_type alignof_object) ,size_type limit_size, size_type &prefer_in_recvd_out_size, void *&reuse_ptr, size_type /*sizeof_object*/, size_type alignof_object)
{ {
//Backwards expansion not supported //Backwards expansion not supported
command &= ~boost::interprocess::expand_bwd; command &= ~boost::interprocess::expand_bwd;

View File

@@ -204,22 +204,22 @@ class rbtree_best_fit
//!Multiple element allocation, same size //!Multiple element allocation, same size
//!Experimental. Dont' use //!Experimental. Dont' use
void allocate_many(size_type elem_bytes, size_type num_elements, multiallocation_chain &chain) void allocate_many(size_type elem_bytes, size_type num_elements, size_type alignment, multiallocation_chain &chain)
{ {
//----------------------- //-----------------------
boost::interprocess::scoped_lock<mutex_type> guard(m_header); boost::interprocess::scoped_lock<mutex_type> guard(m_header);
//----------------------- //-----------------------
algo_impl_t::allocate_many(this, elem_bytes, num_elements, chain); algo_impl_t::allocate_many(this, elem_bytes, num_elements, alignment, chain);
} }
//!Multiple element allocation, different size //!Multiple element allocation, different size
//!Experimental. Dont' use //!Experimental. Dont' use
void allocate_many(const size_type *elem_sizes, size_type n_elements, size_type sizeof_element, multiallocation_chain &chain) void allocate_many(const size_type *elem_sizes, size_type n_elements, size_type sizeof_element, size_type alignment, multiallocation_chain &chain)
{ {
//----------------------- //-----------------------
boost::interprocess::scoped_lock<mutex_type> guard(m_header); boost::interprocess::scoped_lock<mutex_type> guard(m_header);
//----------------------- //-----------------------
algo_impl_t::allocate_many(this, elem_sizes, n_elements, sizeof_element, chain); algo_impl_t::allocate_many(this, elem_sizes, n_elements, sizeof_element, alignment, chain);
} }
//!Multiple element allocation, different size //!Multiple element allocation, different size

View File

@@ -210,10 +210,10 @@ class segment_manager_base
//Experimental. Don't use. //Experimental. Don't use.
//!Allocates n_elements of elem_bytes bytes. //!Allocates n_elements of elem_bytes bytes.
//!Throws bad_alloc on failure. chain.size() is not increased on failure. //!Throws bad_alloc on failure. chain.size() is not increased on failure.
void allocate_many(size_type elem_bytes, size_type n_elements, multiallocation_chain &chain) void allocate_many(size_type elem_bytes, size_type n_elements, size_type alignment, multiallocation_chain &chain)
{ {
size_type prev_size = chain.size(); size_type prev_size = chain.size();
MemoryAlgorithm::allocate_many(elem_bytes, n_elements, chain); MemoryAlgorithm::allocate_many(elem_bytes, n_elements, alignment, chain);
if(!elem_bytes || chain.size() == prev_size){ if(!elem_bytes || chain.size() == prev_size){
throw bad_alloc(); throw bad_alloc();
} }
@@ -222,10 +222,10 @@ class segment_manager_base
//Experimental. Don't use. //Experimental. Don't use.
//!Allocates n_elements, each one of element_lengths[i]*sizeof_element bytes. //!Allocates n_elements, each one of element_lengths[i]*sizeof_element bytes.
//!Throws bad_alloc on failure. chain.size() is not increased on failure. //!Throws bad_alloc on failure. chain.size() is not increased on failure.
void allocate_many(const size_type *element_lengths, size_type n_elements, size_type sizeof_element, multiallocation_chain &chain) void allocate_many(const size_type *element_lengths, size_type n_elements, size_type sizeof_element, size_type alignment, multiallocation_chain &chain)
{ {
size_type prev_size = chain.size(); size_type prev_size = chain.size();
MemoryAlgorithm::allocate_many(element_lengths, n_elements, sizeof_element, chain); MemoryAlgorithm::allocate_many(element_lengths, n_elements, sizeof_element, alignment, chain);
if(!sizeof_element || chain.size() == prev_size){ if(!sizeof_element || chain.size() == prev_size){
throw bad_alloc(); throw bad_alloc();
} }
@@ -234,15 +234,15 @@ class segment_manager_base
//Experimental. Don't use. //Experimental. Don't use.
//!Allocates n_elements of elem_bytes bytes. //!Allocates n_elements of elem_bytes bytes.
//!Non-throwing version. chain.size() is not increased on failure. //!Non-throwing version. chain.size() is not increased on failure.
void allocate_many(const std::nothrow_t &, size_type elem_bytes, size_type n_elements, multiallocation_chain &chain) void allocate_many(const std::nothrow_t &, size_type elem_bytes, size_type n_elements, size_type alignment, multiallocation_chain &chain)
{ MemoryAlgorithm::allocate_many(elem_bytes, n_elements, chain); } { MemoryAlgorithm::allocate_many(elem_bytes, n_elements, alignment, chain); }
//Experimental. Don't use. //Experimental. Don't use.
//!Allocates n_elements, each one of //!Allocates n_elements, each one of
//!element_lengths[i]*sizeof_element bytes. //!element_lengths[i]*sizeof_element bytes.
//!Non-throwing version. chain.size() is not increased on failure. //!Non-throwing version. chain.size() is not increased on failure.
void allocate_many(const std::nothrow_t &, const size_type *elem_sizes, size_type n_elements, size_type sizeof_element, multiallocation_chain &chain) void allocate_many(const std::nothrow_t &, const size_type *elem_sizes, size_type n_elements, size_type sizeof_element, size_type alignment, multiallocation_chain &chain)
{ MemoryAlgorithm::allocate_many(elem_sizes, n_elements, sizeof_element, chain); } { MemoryAlgorithm::allocate_many(elem_sizes, n_elements, sizeof_element, alignment, chain); }
//Experimental. Don't use. //Experimental. Don't use.
//!Deallocates all elements contained in chain. //!Deallocates all elements contained in chain.

View File

@@ -40,7 +40,7 @@ bool test_allocation(SegMngr &sm)
void *ptr = sm.allocate(i, std::nothrow); void *ptr = sm.allocate(i, std::nothrow);
if(!ptr) if(!ptr)
break; break;
std::size_t size = sm.size(ptr); std::size_t size = sm.size(ptr);
std::memset(ptr, 0, size); std::memset(ptr, 0, size);
buffers.push_back(ptr); buffers.push_back(ptr);
} }
@@ -700,72 +700,74 @@ bool test_many_equal_allocation(SegMngr &sm)
return false; return false;
typedef typename SegMngr::multiallocation_chain multiallocation_chain; typedef typename SegMngr::multiallocation_chain multiallocation_chain;
std::vector<void*> buffers; for(std::size_t al = 1; al <= SegMngr::MemAlignment*32u; al *= 2u) {
for(std::size_t i = 0; true; ++i){ std::vector<void*> buffers;
multiallocation_chain chain; for(std::size_t i = 0; true; ++i){
sm.allocate_many(std::nothrow, i+1, (i+1)*2, chain); multiallocation_chain chain;
if(chain.empty()) sm.allocate_many(std::nothrow, i+1, (i+1)*2, al, chain);
break; if(chain.empty())
break;
typename multiallocation_chain::size_type n = chain.size(); typename multiallocation_chain::size_type n = chain.size();
while(!chain.empty()){ while(!chain.empty()){
buffers.push_back(ipcdetail::to_raw_pointer(chain.pop_front())); buffers.push_back(ipcdetail::to_raw_pointer(chain.pop_front()));
}
if(n != std::size_t((i+1)*2))
return false;
} }
if(n != std::size_t((i+1)*2))
if(!sm.check_sanity())
return false; return false;
}
if(!sm.check_sanity()) switch(t){
return false; case DirectDeallocation:
{
switch(t){ for(std::size_t j = 0, max = buffers.size()
case DirectDeallocation: ;j < max
{ ;++j){
for(std::size_t j = 0, max = buffers.size() sm.deallocate(buffers[j]);
;j < max }
;++j){
sm.deallocate(buffers[j]);
} }
} break;
break; case InverseDeallocation:
case InverseDeallocation: {
{ for(std::size_t j = buffers.size()
for(std::size_t j = buffers.size() ;j--
;j-- ;){
;){ sm.deallocate(buffers[j]);
sm.deallocate(buffers[j]); }
} }
} break;
break; case MixedDeallocation:
case MixedDeallocation: {
{ for(std::size_t j = 0, max = buffers.size()
for(std::size_t j = 0, max = buffers.size() ;j < max
;j < max ;++j){
;++j){ std::size_t pos = (j%4)*(buffers.size())/4;
std::size_t pos = (j%4)*(buffers.size())/4; sm.deallocate(buffers[pos]);
sm.deallocate(buffers[pos]); buffers.erase(buffers.begin()+std::ptrdiff_t(pos));
buffers.erase(buffers.begin()+std::ptrdiff_t(pos)); }
} }
break;
default:
break;
} }
break;
default: //Deallocate the rest of the blocks
break;
//Deallocate it in non sequential order
for(std::size_t j = 0, max = buffers2.size()
;j < max
;++j){
std::size_t pos = (j%4)*(buffers2.size())/4;
sm.deallocate(buffers2[pos]);
buffers2.erase(buffers2.begin()+std::ptrdiff_t(pos));
}
bool ok = free_memory == sm.get_free_memory() &&
sm.all_memory_deallocated() && sm.check_sanity();
if(!ok) return ok;
} }
//Deallocate the rest of the blocks
//Deallocate it in non sequential order
for(std::size_t j = 0, max = buffers2.size()
;j < max
;++j){
std::size_t pos = (j%4)*(buffers2.size())/4;
sm.deallocate(buffers2[pos]);
buffers2.erase(buffers2.begin()+std::ptrdiff_t(pos));
}
bool ok = free_memory == sm.get_free_memory() &&
sm.all_memory_deallocated() && sm.check_sanity();
if(!ok) return ok;
} }
return true; return true;
} }
@@ -776,12 +778,13 @@ template<class SegMngr>
bool test_many_different_allocation(SegMngr &sm) bool test_many_different_allocation(SegMngr &sm)
{ {
typedef typename SegMngr::multiallocation_chain multiallocation_chain; typedef typename SegMngr::multiallocation_chain multiallocation_chain;
const std::size_t ArraySize = 11; const std::size_t ArraySize = 22;
typename SegMngr::size_type requested_sizes[ArraySize]; typename SegMngr::size_type requested_sizes[ArraySize];
for(std::size_t i = 0; i < ArraySize; ++i){ for(std::size_t i = 0; i < ArraySize; ++i){
requested_sizes[i] = 4*i; requested_sizes[i] = 4*i;
} }
for(std::size_t al = 1; al <= SegMngr::MemAlignment*32u; al *= 2u)
for( deallocation_type t = DirectDeallocation for( deallocation_type t = DirectDeallocation
; t != EndDeallocationType ; t != EndDeallocationType
; t = (deallocation_type)((int)t + 1)){ ; t = (deallocation_type)((int)t + 1)){
@@ -791,7 +794,9 @@ bool test_many_different_allocation(SegMngr &sm)
//Allocate buffers with extra memory //Allocate buffers with extra memory
for(std::size_t i = 0; true; ++i){ for(std::size_t i = 0; true; ++i){
void *ptr = sm.allocate(i, std::nothrow); void *ptr = al > SegMngr::MemAlignment
? sm.allocate_aligned(i, al, std::nothrow)
: sm.allocate(i, std::nothrow);
if(!ptr) if(!ptr)
break; break;
std::size_t size = sm.size(ptr); std::size_t size = sm.size(ptr);
@@ -813,7 +818,7 @@ bool test_many_different_allocation(SegMngr &sm)
std::vector<void*> buffers; std::vector<void*> buffers;
while(true){ while(true){
multiallocation_chain chain; multiallocation_chain chain;
sm.allocate_many(std::nothrow, requested_sizes, ArraySize, 1, chain); sm.allocate_many(std::nothrow, requested_sizes, ArraySize, 1, al, chain);
if(chain.empty()) if(chain.empty())
break; break;
typename multiallocation_chain::size_type n = chain.size(); typename multiallocation_chain::size_type n = chain.size();
@@ -881,8 +886,6 @@ bool test_many_different_allocation(SegMngr &sm)
template<class SegMngr> template<class SegMngr>
bool test_many_deallocation(SegMngr &sm) bool test_many_deallocation(SegMngr &sm)
{ {
typedef typename SegMngr::multiallocation_chain multiallocation_chain;
typedef typename SegMngr::multiallocation_chain multiallocation_chain; typedef typename SegMngr::multiallocation_chain multiallocation_chain;
const std::size_t ArraySize = 11; const std::size_t ArraySize = 11;
boost::container::vector<multiallocation_chain> buffers; boost::container::vector<multiallocation_chain> buffers;
@@ -892,10 +895,11 @@ bool test_many_deallocation(SegMngr &sm)
} }
typename SegMngr::size_type free_memory = sm.get_free_memory(); typename SegMngr::size_type free_memory = sm.get_free_memory();
for(std::size_t al = 1; al <= SegMngr::MemAlignment*32u; al *= 2u)
{ {
while(true){ while(true){
multiallocation_chain chain; multiallocation_chain chain;
sm.allocate_many(std::nothrow, requested_sizes, ArraySize, 1, chain); sm.allocate_many(std::nothrow, requested_sizes, ArraySize, 1, al, chain);
if(chain.empty()) if(chain.empty())
break; break;
buffers.push_back(boost::move(chain)); buffers.push_back(boost::move(chain));
@@ -909,10 +913,11 @@ bool test_many_deallocation(SegMngr &sm)
if(!ok) return ok; if(!ok) return ok;
} }
for(std::size_t al = 1; al <= SegMngr::MemAlignment*32u; al *= 2u)
{ {
for(std::size_t i = 0; true; ++i){ for(std::size_t i = 0; true; ++i){
multiallocation_chain chain; multiallocation_chain chain;
sm.allocate_many(std::nothrow, i*4, ArraySize, chain); sm.allocate_many(std::nothrow, i*4, ArraySize, al, chain);
if(chain.empty()) if(chain.empty())
break; break;
buffers.push_back(boost::move(chain)); buffers.push_back(boost::move(chain));