mirror of
https://github.com/boostorg/container.git
synced 2026-01-19 04:02:17 +00:00
- Modify dlmalloc_allocation_command to use alignment info, this requires modifying the dlmalloc_ext wrapper library.
- Replace all dlmalloc_malloc uses with dlmalloc_allocation_command to support overaligned types in array allocations.
This commit is contained in:
@@ -14,6 +14,7 @@
|
||||
|
||||
#include <boost/container/detail/dlmalloc.hpp>
|
||||
#include <boost/container/throw_exception.hpp>
|
||||
#include <boost/container/detail/type_traits.hpp>
|
||||
|
||||
#define BOOST_INTERPROCESS_VECTOR_ALLOC_STATS
|
||||
|
||||
@@ -71,7 +72,7 @@ void allocation_timing_test(std::size_t num_iterations, std::size_t num_elements
|
||||
if(min > max)
|
||||
max = min;
|
||||
ret = dlmalloc_allocation_command
|
||||
( m_mode, sizeof(POD)
|
||||
(m_mode, sizeof(POD), dtl::alignment_of<POD>::value
|
||||
, min, max, &received_size, addr);
|
||||
if(!ret.first){
|
||||
throw_runtime_error("!ret.first)");
|
||||
|
||||
@@ -169,7 +169,7 @@ class adaptive_pool
|
||||
return pointer(static_cast<T*>(singleton_t::instance().allocate_node()));
|
||||
}
|
||||
else{
|
||||
return static_cast<pointer>(dlmalloc_malloc(count*sizeof(T)));
|
||||
return static_cast<pointer>(dlmalloc_memalign(count*sizeof(T), dtl::alignment_of<T>::value));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -346,7 +346,8 @@ class adaptive_pool
|
||||
std::size_t r_size;
|
||||
{
|
||||
void* reuse_ptr_void = reuse_ptr;
|
||||
ret = dlmalloc_allocation_command(command, sizeof(T), l_size, p_size, &r_size, reuse_ptr_void);
|
||||
ret = dlmalloc_allocation_command( command, sizeof(T), dtl::alignment_of<T>::value
|
||||
, l_size, p_size, &r_size, reuse_ptr_void);
|
||||
reuse_ptr = ret.second ? static_cast<T*>(reuse_ptr_void) : 0;
|
||||
}
|
||||
prefer_in_recvd_out_size = r_size/sizeof(T);
|
||||
@@ -470,7 +471,7 @@ class private_adaptive_pool
|
||||
return pointer(static_cast<T*>(m_pool.allocate_node()));
|
||||
}
|
||||
else{
|
||||
return static_cast<pointer>(dlmalloc_malloc(count*sizeof(T)));
|
||||
return static_cast<pointer>(dlmalloc_memalign(count*sizeof(T), dtl::alignment_of<T>::value));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -600,7 +601,8 @@ class private_adaptive_pool
|
||||
std::size_t r_size;
|
||||
{
|
||||
void* reuse_ptr_void = reuse_ptr;
|
||||
ret = dlmalloc_allocation_command(command, sizeof(T), l_size, p_size, &r_size, reuse_ptr_void);
|
||||
ret = dlmalloc_allocation_command( command, sizeof(T), dtl::alignment_of<T>::value
|
||||
, l_size, p_size, &r_size, reuse_ptr_void);
|
||||
reuse_ptr = ret.second ? static_cast<T*>(reuse_ptr_void) : 0;
|
||||
}
|
||||
prefer_in_recvd_out_size = r_size/sizeof(T);
|
||||
|
||||
@@ -184,7 +184,7 @@ class allocator
|
||||
(void)hint;
|
||||
if(count > size_type(-1)/(2u*sizeof(T)))
|
||||
boost::container::throw_bad_alloc();
|
||||
void *ret = dlmalloc_malloc(count*sizeof(T));
|
||||
void *ret = dlmalloc_memalign(count*sizeof(T), dtl::alignment_of<T>::value);
|
||||
if(!ret)
|
||||
boost::container::throw_bad_alloc();
|
||||
return static_cast<pointer>(ret);
|
||||
@@ -359,7 +359,8 @@ class allocator
|
||||
std::size_t r_size;
|
||||
{
|
||||
void* reuse_ptr_void = reuse_ptr;
|
||||
ret = dlmalloc_allocation_command(command, sizeof(T), l_size, p_size, &r_size, reuse_ptr_void);
|
||||
ret = dlmalloc_allocation_command( command, sizeof(T), dtl::alignment_of<T>::value
|
||||
, l_size, p_size, &r_size, reuse_ptr_void);
|
||||
reuse_ptr = ret.second ? static_cast<T*>(reuse_ptr_void) : 0;
|
||||
}
|
||||
prefer_in_recvd_out_size = r_size/sizeof(T);
|
||||
|
||||
@@ -284,6 +284,7 @@ int boost_cont_malloc_check(void);
|
||||
boost_cont_command_ret_t boost_cont_allocation_command
|
||||
( allocation_type command
|
||||
, size_t sizeof_object
|
||||
, size_t alignof_object
|
||||
, size_t limit_objects
|
||||
, size_t preferred_objects
|
||||
, size_t *received_objects
|
||||
|
||||
@@ -75,6 +75,7 @@ BOOST_CONTAINER_DECL int dlmalloc_malloc_check();
|
||||
BOOST_CONTAINER_DECL boost_cont_command_ret_t dlmalloc_allocation_command
|
||||
( allocation_type command
|
||||
, size_t sizeof_object
|
||||
, size_t alignof_object
|
||||
, size_t limit_objects
|
||||
, size_t preferred_objects
|
||||
, size_t *received_objects
|
||||
|
||||
@@ -156,7 +156,7 @@ class node_allocator
|
||||
return pointer(static_cast<T*>(singleton_t::instance().allocate_node()));
|
||||
}
|
||||
else{
|
||||
void *ret = dlmalloc_malloc(count*sizeof(T));
|
||||
void *ret = dlmalloc_memalign(count*sizeof(T), dtl::alignment_of<T>::value);
|
||||
if(BOOST_UNLIKELY(!ret))
|
||||
boost::container::throw_bad_alloc();
|
||||
return static_cast<pointer>(ret);
|
||||
@@ -338,7 +338,8 @@ class node_allocator
|
||||
std::size_t r_size;
|
||||
{
|
||||
void* reuse_ptr_void = reuse;
|
||||
ret = dlmalloc_allocation_command(command, sizeof(T), l_size, p_size, &r_size, reuse_ptr_void);
|
||||
ret = dlmalloc_allocation_command( command, sizeof(T), dtl::alignment_of<T>::value
|
||||
, l_size, p_size, &r_size, reuse_ptr_void);
|
||||
reuse = static_cast<T*>(reuse_ptr_void);
|
||||
}
|
||||
prefer_in_recvd_out_size = r_size/sizeof(T);
|
||||
|
||||
@@ -79,12 +79,13 @@ BOOST_CONTAINER_DECL int dlmalloc_malloc_check()
|
||||
BOOST_CONTAINER_DECL boost_cont_command_ret_t dlmalloc_allocation_command
|
||||
( allocation_type command
|
||||
, size_t sizeof_object
|
||||
, size_t alignof_object
|
||||
, size_t limit_objects
|
||||
, size_t preferred_objects
|
||||
, size_t *received_objects
|
||||
, void *reuse_ptr
|
||||
)
|
||||
{ return boost_cont_allocation_command(command, sizeof_object, limit_objects, preferred_objects, received_objects, reuse_ptr); }
|
||||
{ return boost_cont_allocation_command(command, sizeof_object, alignof_object, limit_objects, preferred_objects, received_objects, reuse_ptr); }
|
||||
|
||||
BOOST_CONTAINER_DECL void *dlmalloc_sync_create()
|
||||
{ return boost_cont_sync_create(); }
|
||||
|
||||
@@ -1174,7 +1174,7 @@ void* boost_cont_malloc(size_t bytes)
|
||||
size_t received_bytes;
|
||||
ensure_initialization();
|
||||
return boost_cont_allocation_command
|
||||
(BOOST_CONTAINER_ALLOCATE_NEW, 1, bytes, bytes, &received_bytes, 0).first;
|
||||
(BOOST_CONTAINER_ALLOCATE_NEW, 1, 1, bytes, bytes, &received_bytes, 0).first;
|
||||
}
|
||||
|
||||
void boost_cont_free(void* mem)
|
||||
@@ -1341,7 +1341,7 @@ void* boost_cont_alloc
|
||||
{
|
||||
//ensure_initialization provided by boost_cont_allocation_command
|
||||
return boost_cont_allocation_command
|
||||
(BOOST_CONTAINER_ALLOCATE_NEW, 1, minbytes, preferred_bytes, received_bytes, 0).first;
|
||||
(BOOST_CONTAINER_ALLOCATE_NEW, 1, 1, minbytes, preferred_bytes, received_bytes, 0).first;
|
||||
}
|
||||
|
||||
void boost_cont_multidealloc(boost_cont_memchain *pchain)
|
||||
@@ -1373,7 +1373,7 @@ int boost_cont_malloc_check(void)
|
||||
|
||||
|
||||
boost_cont_command_ret_t boost_cont_allocation_command
|
||||
(allocation_type command, size_t sizeof_object, size_t limit_size
|
||||
(allocation_type command, size_t sizeof_object, size_t alignof_object, size_t limit_size
|
||||
, size_t preferred_size, size_t *received_size, void *reuse_ptr)
|
||||
{
|
||||
boost_cont_command_ret_t ret = { 0, 0 };
|
||||
@@ -1416,12 +1416,15 @@ boost_cont_command_ret_t boost_cont_allocation_command
|
||||
}
|
||||
|
||||
if(command & BOOST_CONTAINER_ALLOCATE_NEW){
|
||||
void *addr = mspace_malloc_lockless(ms, preferred_size);
|
||||
if(!addr) addr = mspace_malloc_lockless(ms, limit_size);
|
||||
disable_lock(ms);
|
||||
void *addr = mspace_memalign(ms, alignof_object, preferred_size);
|
||||
if(!addr) addr = mspace_memalign(ms, alignof_object, limit_size);
|
||||
if(addr){
|
||||
s_allocated_memory += chunksize(mem2chunk(addr));
|
||||
*received_size = DL_SIZE_IMPL(addr);
|
||||
}
|
||||
enable_lock(ms);
|
||||
|
||||
ret.first = addr;
|
||||
ret.second = 0;
|
||||
if(addr){
|
||||
|
||||
@@ -112,12 +112,12 @@ bool test_allocation_shrink()
|
||||
; ++i){
|
||||
std::size_t try_received_size = 0;
|
||||
void* try_result = dlmalloc_allocation_command
|
||||
( BOOST_CONTAINER_TRY_SHRINK_IN_PLACE, 1, i*2
|
||||
( BOOST_CONTAINER_TRY_SHRINK_IN_PLACE, 1, 1, i*2
|
||||
, i, &try_received_size, (char*)buffers[i]).first;
|
||||
|
||||
std::size_t received_size = 0;
|
||||
void* result = dlmalloc_allocation_command
|
||||
( BOOST_CONTAINER_SHRINK_IN_PLACE, 1, i*2
|
||||
( BOOST_CONTAINER_SHRINK_IN_PLACE, 1, 1, i*2
|
||||
, i, &received_size, (char*)buffers[i]).first;
|
||||
|
||||
if(result != try_result)
|
||||
@@ -174,7 +174,7 @@ bool test_allocation_expand()
|
||||
std::size_t preferred_size = i*2;
|
||||
preferred_size = min_size > preferred_size ? min_size : preferred_size;
|
||||
while(dlmalloc_allocation_command
|
||||
( BOOST_CONTAINER_EXPAND_FWD, 1, min_size
|
||||
( BOOST_CONTAINER_EXPAND_FWD, 1, 1, min_size
|
||||
, preferred_size, &received_size, (char*)buffers[i]).first){
|
||||
//Check received size is bigger than minimum
|
||||
if(received_size < min_size){
|
||||
@@ -211,10 +211,10 @@ bool test_allocation_shrink_and_expand()
|
||||
for(std::size_t i = 0; i != NumIt; ++i){
|
||||
std::size_t received_size = 0;
|
||||
void *ptr = dlmalloc_allocation_command
|
||||
(BOOST_CONTAINER_ALLOCATE_NEW, 1u, i, i*2u, &received_size, 0).first;
|
||||
(BOOST_CONTAINER_ALLOCATE_NEW, 1u, 1u, i, i*2u, &received_size, 0).first;
|
||||
if(!ptr){
|
||||
ptr = dlmalloc_allocation_command
|
||||
( BOOST_CONTAINER_ALLOCATE_NEW, 1u, 1u, i*2, &received_size, 0).first;
|
||||
( BOOST_CONTAINER_ALLOCATE_NEW, 1u, 1u, 1u, i*2, &received_size, 0).first;
|
||||
if(!ptr)
|
||||
break;
|
||||
}
|
||||
@@ -230,7 +230,7 @@ bool test_allocation_shrink_and_expand()
|
||||
bool size_reduced_flag;
|
||||
if(true == (size_reduced_flag = !!
|
||||
dlmalloc_allocation_command
|
||||
( BOOST_CONTAINER_SHRINK_IN_PLACE, 1, received_sizes[i]
|
||||
( BOOST_CONTAINER_SHRINK_IN_PLACE, 1, 1, received_sizes[i]
|
||||
, i, &received_size, (char*)buffers[i]).first)){
|
||||
if(received_size > std::size_t(received_sizes[i])){
|
||||
return false;
|
||||
@@ -250,7 +250,7 @@ bool test_allocation_shrink_and_expand()
|
||||
std::size_t received_size = 0;
|
||||
std::size_t request_size = received_sizes[i];
|
||||
if(dlmalloc_allocation_command
|
||||
( BOOST_CONTAINER_EXPAND_FWD, 1, request_size
|
||||
( BOOST_CONTAINER_EXPAND_FWD, 1, 1, request_size
|
||||
, request_size, &received_size, (char*)buffers[i]).first){
|
||||
if(received_size != request_size){
|
||||
return false;
|
||||
@@ -314,7 +314,7 @@ bool test_allocation_deallocation_expand()
|
||||
preferred_size = min_size > preferred_size ? min_size : preferred_size;
|
||||
|
||||
while(dlmalloc_allocation_command
|
||||
( BOOST_CONTAINER_EXPAND_FWD, 1, min_size
|
||||
( BOOST_CONTAINER_EXPAND_FWD, 1, 1, min_size
|
||||
, preferred_size, &received_size, (char*)buffers[i]).first){
|
||||
//Check received size is bigger than minimum
|
||||
if(received_size < min_size){
|
||||
@@ -383,7 +383,7 @@ bool test_allocation_with_reuse()
|
||||
std::size_t min_size = (received_size/sizeof_object + 1u)*sizeof_object;
|
||||
std::size_t prf_size = (received_size/sizeof_object + (i+1u)*2u)*sizeof_object;
|
||||
dlmalloc_command_ret_t ret = dlmalloc_allocation_command
|
||||
( BOOST_CONTAINER_EXPAND_BWD, sizeof_object, min_size
|
||||
( BOOST_CONTAINER_EXPAND_BWD, sizeof_object, 1u, min_size
|
||||
, prf_size, &received_size, (char*)ptr);
|
||||
//If we have memory, this must be a buffer reuse
|
||||
if(!ret.first)
|
||||
|
||||
@@ -112,10 +112,9 @@ struct GetAllocatorCont
|
||||
template<class ValueType>
|
||||
struct apply
|
||||
{
|
||||
typedef vector< ValueType
|
||||
, typename allocator_traits<VoidAllocator>
|
||||
::template portable_rebind_alloc<ValueType>::type
|
||||
> type;
|
||||
typedef typename allocator_traits<VoidAllocator>
|
||||
::template portable_rebind_alloc<ValueType>::type rebound_allocator_type;
|
||||
typedef vector< ValueType, rebound_allocator_type> type;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -127,6 +126,7 @@ int test_cont_variants()
|
||||
typedef typename GetAllocatorCont<VoidAllocator>::template apply<test::movable_and_copyable_int>::type MyCopyMoveCont;
|
||||
typedef typename GetAllocatorCont<VoidAllocator>::template apply<test::copyable_int>::type MyCopyCont;
|
||||
typedef typename GetAllocatorCont<VoidAllocator>::template apply<test::moveconstruct_int>::type MyMoveConstructCont;
|
||||
typedef typename GetAllocatorCont<VoidAllocator>::template apply<test::overaligned_copyable_int>::type MyOverAlignCont;
|
||||
|
||||
if (test::vector_test<MyCont>())
|
||||
return 1;
|
||||
@@ -138,7 +138,11 @@ int test_cont_variants()
|
||||
return 1;
|
||||
if (test::vector_test<MyMoveConstructCont>())
|
||||
return 1;
|
||||
|
||||
#if !defined(__cpp_aligned_new) //old std::allocators don't support overaligned types
|
||||
BOOST_IF_CONSTEXPR(!dtl::is_same<typename MyCont::allocator_type, std::allocator<int> >::value)
|
||||
#endif
|
||||
if (test::vector_test<MyOverAlignCont>())
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -276,6 +280,11 @@ int main()
|
||||
std::cerr << "test_cont_variants< allocator<void> > failed" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
// boost::container::new_allocator
|
||||
if(test_cont_variants< new_allocator<void> >()){
|
||||
std::cerr << "test_cont_variants< allocator<void> > failed" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
{ //Test enum container
|
||||
typedef vector<Test, std::allocator<Test> > MyEnumCont;
|
||||
|
||||
Reference in New Issue
Block a user