mirror of
https://github.com/boostorg/interprocess.git
synced 2026-01-19 04:12:13 +00:00
Modify experimental "allocate_many" function to take an alignment parameter.
This commit is contained in:
@@ -3986,7 +3986,7 @@ Here is a small example showing how aligned allocation is used:
|
||||
|
||||
[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
|
||||
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
|
||||
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:
|
||||
* [@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"])].
|
||||
|
||||
@@ -38,9 +38,9 @@ int main()
|
||||
|
||||
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;
|
||||
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
|
||||
if(chain.empty()) return 1;
|
||||
@@ -68,7 +68,7 @@ int main()
|
||||
for(std::size_t i = 0; i < 10; ++i)
|
||||
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);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -307,24 +307,24 @@ class basic_managed_memory_impl
|
||||
|
||||
//!Allocates n_elements of elem_bytes bytes.
|
||||
//!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)
|
||||
{ mp_header->allocate_many(elem_bytes, n_elements, 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, alignment, chain); }
|
||||
|
||||
//!Allocates n_elements, each one of element_lengths[i]*sizeof_element bytes.
|
||||
//!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)
|
||||
{ mp_header->allocate_many(element_lengths, n_elements, sizeof_element, 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, alignment, chain); }
|
||||
|
||||
//!Allocates n_elements of elem_bytes bytes.
|
||||
//!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)
|
||||
{ mp_header->allocate_many(tag, elem_bytes, n_elements, 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, alignment, chain); }
|
||||
|
||||
//!Allocates n_elements, each one of
|
||||
//!element_lengths[i]*sizeof_element bytes.
|
||||
//!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)
|
||||
{ mp_header->allocate_many(tag, elem_sizes, n_elements, sizeof_element, 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, alignment, chain); }
|
||||
|
||||
//!Deallocates all elements contained in chain.
|
||||
//!Never throws.
|
||||
|
||||
@@ -125,9 +125,9 @@ class memory_algorithm_common
|
||||
{ return get_rounded_size(size, Alignment); }
|
||||
|
||||
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)
|
||||
@@ -235,9 +235,10 @@ class memory_algorithm_common
|
||||
, const size_type *elem_sizes
|
||||
, size_type n_elements
|
||||
, size_type sizeof_element
|
||||
, size_type alignment
|
||||
, 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)
|
||||
@@ -487,6 +488,7 @@ class memory_algorithm_common
|
||||
( MemoryAlgorithm *memory_algo
|
||||
, const size_type *elem_sizes
|
||||
, size_type n_elements
|
||||
, size_type alignment
|
||||
, size_type sizeof_element
|
||||
, multiallocation_chain &chain)
|
||||
{
|
||||
@@ -530,7 +532,7 @@ class memory_algorithm_common
|
||||
size_type received_size = total_bytes;
|
||||
void *ignore_reuse = 0;
|
||||
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){
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -157,22 +157,22 @@ class simple_seq_fit_impl
|
||||
|
||||
//!Multiple element allocation, same size
|
||||
//!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);
|
||||
//-----------------------
|
||||
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
|
||||
//!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);
|
||||
//-----------------------
|
||||
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
|
||||
@@ -229,7 +229,7 @@ class simple_seq_fit_impl
|
||||
//!Real allocation algorithm with min allocation option
|
||||
void * priv_allocate(boost::interprocess::allocation_type command
|
||||
,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
|
||||
//!of "userbytes" bytes really occupies (including header)
|
||||
@@ -635,7 +635,7 @@ simple_seq_fit_impl<MutexFamily, VoidPointer>::
|
||||
template<class MutexFamily, class VoidPointer>
|
||||
void * simple_seq_fit_impl<MutexFamily, VoidPointer>::
|
||||
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
|
||||
command &= ~boost::interprocess::expand_bwd;
|
||||
|
||||
@@ -204,22 +204,22 @@ class rbtree_best_fit
|
||||
|
||||
//!Multiple element allocation, same size
|
||||
//!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);
|
||||
//-----------------------
|
||||
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
|
||||
//!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);
|
||||
//-----------------------
|
||||
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
|
||||
|
||||
@@ -210,10 +210,10 @@ class segment_manager_base
|
||||
//Experimental. Don't use.
|
||||
//!Allocates n_elements of elem_bytes bytes.
|
||||
//!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();
|
||||
MemoryAlgorithm::allocate_many(elem_bytes, n_elements, chain);
|
||||
MemoryAlgorithm::allocate_many(elem_bytes, n_elements, alignment, chain);
|
||||
if(!elem_bytes || chain.size() == prev_size){
|
||||
throw bad_alloc();
|
||||
}
|
||||
@@ -222,10 +222,10 @@ class segment_manager_base
|
||||
//Experimental. Don't use.
|
||||
//!Allocates n_elements, each one of element_lengths[i]*sizeof_element bytes.
|
||||
//!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();
|
||||
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){
|
||||
throw bad_alloc();
|
||||
}
|
||||
@@ -234,15 +234,15 @@ class segment_manager_base
|
||||
//Experimental. Don't use.
|
||||
//!Allocates n_elements of elem_bytes bytes.
|
||||
//!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)
|
||||
{ MemoryAlgorithm::allocate_many(elem_bytes, n_elements, 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, alignment, chain); }
|
||||
|
||||
//Experimental. Don't use.
|
||||
//!Allocates n_elements, each one of
|
||||
//!element_lengths[i]*sizeof_element bytes.
|
||||
//!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)
|
||||
{ MemoryAlgorithm::allocate_many(elem_sizes, n_elements, sizeof_element, 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, alignment, chain); }
|
||||
|
||||
//Experimental. Don't use.
|
||||
//!Deallocates all elements contained in chain.
|
||||
|
||||
@@ -700,10 +700,11 @@ bool test_many_equal_allocation(SegMngr &sm)
|
||||
return false;
|
||||
|
||||
typedef typename SegMngr::multiallocation_chain multiallocation_chain;
|
||||
for(std::size_t al = 1; al <= SegMngr::MemAlignment*32u; al *= 2u) {
|
||||
std::vector<void*> buffers;
|
||||
for(std::size_t i = 0; true; ++i){
|
||||
multiallocation_chain chain;
|
||||
sm.allocate_many(std::nothrow, i+1, (i+1)*2, chain);
|
||||
sm.allocate_many(std::nothrow, i+1, (i+1)*2, al, chain);
|
||||
if(chain.empty())
|
||||
break;
|
||||
|
||||
@@ -767,6 +768,7 @@ bool test_many_equal_allocation(SegMngr &sm)
|
||||
sm.all_memory_deallocated() && sm.check_sanity();
|
||||
if(!ok) return ok;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -776,12 +778,13 @@ template<class SegMngr>
|
||||
bool test_many_different_allocation(SegMngr &sm)
|
||||
{
|
||||
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];
|
||||
for(std::size_t i = 0; i < ArraySize; ++i){
|
||||
requested_sizes[i] = 4*i;
|
||||
}
|
||||
|
||||
for(std::size_t al = 1; al <= SegMngr::MemAlignment*32u; al *= 2u)
|
||||
for( deallocation_type t = DirectDeallocation
|
||||
; t != EndDeallocationType
|
||||
; t = (deallocation_type)((int)t + 1)){
|
||||
@@ -791,7 +794,9 @@ bool test_many_different_allocation(SegMngr &sm)
|
||||
|
||||
//Allocate buffers with extra memory
|
||||
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)
|
||||
break;
|
||||
std::size_t size = sm.size(ptr);
|
||||
@@ -813,7 +818,7 @@ bool test_many_different_allocation(SegMngr &sm)
|
||||
std::vector<void*> buffers;
|
||||
while(true){
|
||||
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())
|
||||
break;
|
||||
typename multiallocation_chain::size_type n = chain.size();
|
||||
@@ -881,8 +886,6 @@ bool test_many_different_allocation(SegMngr &sm)
|
||||
template<class SegMngr>
|
||||
bool test_many_deallocation(SegMngr &sm)
|
||||
{
|
||||
typedef typename SegMngr::multiallocation_chain multiallocation_chain;
|
||||
|
||||
typedef typename SegMngr::multiallocation_chain multiallocation_chain;
|
||||
const std::size_t ArraySize = 11;
|
||||
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();
|
||||
|
||||
for(std::size_t al = 1; al <= SegMngr::MemAlignment*32u; al *= 2u)
|
||||
{
|
||||
while(true){
|
||||
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())
|
||||
break;
|
||||
buffers.push_back(boost::move(chain));
|
||||
@@ -909,10 +913,11 @@ bool test_many_deallocation(SegMngr &sm)
|
||||
if(!ok) return ok;
|
||||
}
|
||||
|
||||
for(std::size_t al = 1; al <= SegMngr::MemAlignment*32u; al *= 2u)
|
||||
{
|
||||
for(std::size_t i = 0; true; ++i){
|
||||
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())
|
||||
break;
|
||||
buffers.push_back(boost::move(chain));
|
||||
|
||||
Reference in New Issue
Block a user