#ifdef _MSC_VER
#pragma warning (disable:4702)
#endif
#include <vector>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <boost/container/detail/dlmalloc.hpp>
namespace boost { namespace container { namespace test {
static const std::size_t NumIt = 200;
enum deallocation_type { DirectDeallocation, InverseDeallocation, MixedDeallocation, EndDeallocationType };
bool test_allocation()
{
if(!dlmalloc_all_deallocated())
return false;
dlmalloc_malloc_check();
for( deallocation_type t = DirectDeallocation
; t != EndDeallocationType
; t = (deallocation_type)((int)t + 1)){
std::vector<void*> buffers;
for(std::size_t i = 0; i != NumIt; ++i){
void *ptr = dlmalloc_malloc(i);
if(!ptr)
break;
buffers.push_back(ptr);
}
switch(t){
case DirectDeallocation:
{
for(std::size_t j = 0, max = buffers.size()
;j < max
;++j){
dlmalloc_free(buffers[j]);
}
}
break;
case InverseDeallocation:
{
for(std::size_t j = buffers.size()
;j--
;){
dlmalloc_free(buffers[j]);
}
}
break;
case MixedDeallocation:
{
for(std::size_t j = 0, max = buffers.size()
;j < max
;++j){
std::size_t pos = (j%4)*(buffers.size())/4;
dlmalloc_free(buffers[pos]);
buffers.erase(buffers.begin()+(std::ptrdiff_t)pos);
}
}
break;
default:
break;
}
if(!dlmalloc_all_deallocated())
return false;
}
dlmalloc_malloc_check();
return 0 != dlmalloc_all_deallocated();
}
bool test_allocation_shrink()
{
dlmalloc_malloc_check();
std::vector<void*> buffers;
for(std::size_t i = 0; i != NumIt; ++i){
void *ptr = dlmalloc_malloc(i*2u);
if(!ptr)
break;
buffers.push_back(ptr);
}
for(std::size_t i = 0, max = buffers.size()
;i < max
; ++i){
std::size_t try_received_size = 0;
void* try_result = dlmalloc_allocation_command
( BOOST_CONTAINER_TRY_SHRINK_IN_PLACE, 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
, i, &received_size, (char*)buffers[i]).first;
if(result != try_result)
return false;
if(received_size != try_received_size)
return false;
if(result){
if(received_size > std::size_t(i*2)){
return false;
}
if(received_size < std::size_t(i)){
return false;
}
}
}
for(std::size_t j = 0, max = buffers.size()
;j < max
;++j){
std::size_t pos = (j%4u)*(buffers.size())/4u;
dlmalloc_free(buffers[pos]);
buffers.erase(buffers.begin()+(std::ptrdiff_t)pos);
}
dlmalloc_malloc_check();
return 0 != dlmalloc_all_deallocated();}
bool test_allocation_expand()
{
dlmalloc_malloc_check();
std::vector<void*> buffers;
for(std::size_t i = 0; i != NumIt; ++i){
void *ptr = dlmalloc_malloc(i);
if(!ptr)
break;
buffers.push_back(ptr);
}
for(std::size_t i = 0, max = buffers.size()
;i < max
;++i){
std::size_t received_size = 0;
std::size_t min_size = i+1;
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
, preferred_size, &received_size, (char*)buffers[i]).first){
if(received_size < min_size){
return false;
}
min_size = received_size+1;
preferred_size = min_size*2;
}
}
for(std::size_t j = 0, max = buffers.size()
;j < max
;++j){
std::size_t pos = (j%4u)*(buffers.size())/4u;
dlmalloc_free(buffers[pos]);
buffers.erase(buffers.begin()+(std::ptrdiff_t)pos);
}
dlmalloc_malloc_check();
return 0 != dlmalloc_all_deallocated();}
bool test_allocation_shrink_and_expand()
{
std::vector<void*> buffers;
std::vector<std::size_t> received_sizes;
std::vector<bool> size_reduced;
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;
if(!ptr){
ptr = dlmalloc_allocation_command
( BOOST_CONTAINER_ALLOCATE_NEW, 1u, 1u, i*2, &received_size, 0).first;
if(!ptr)
break;
}
buffers.push_back(ptr);
received_sizes.push_back(received_size);
}
for(std::size_t i = 0, max = buffers.size()
; i < max
; ++i){
std::size_t received_size = 0;
bool size_reduced_flag;
if(true == (size_reduced_flag = !!
dlmalloc_allocation_command
( BOOST_CONTAINER_SHRINK_IN_PLACE, 1, received_sizes[i]
, i, &received_size, (char*)buffers[i]).first)){
if(received_size > std::size_t(received_sizes[i])){
return false;
}
if(received_size < std::size_t(i)){
return false;
}
}
size_reduced.push_back(size_reduced_flag);
}
for(std::size_t i = 0, max = buffers.size()
;i < max
;++i){
if(!size_reduced[i]) continue;
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
, request_size, &received_size, (char*)buffers[i]).first){
if(received_size != request_size){
return false;
}
}
else{
return false;
}
}
for(std::size_t j = 0, max = buffers.size()
;j < max
;++j){
std::size_t pos = (j%4u)*(buffers.size())/4u;
dlmalloc_free(buffers[pos]);
buffers.erase(buffers.begin()+(std::ptrdiff_t)pos);
}
return 0 != dlmalloc_all_deallocated();}
bool test_allocation_deallocation_expand()
{
dlmalloc_malloc_check();
std::vector<void*> buffers;
for(std::size_t i = 0; i != NumIt; ++i){
void *ptr = dlmalloc_malloc(i);
if(!ptr)
break;
buffers.push_back(ptr);
}
for(std::size_t i = 0, max = buffers.size()
;i < max
;++i){
if(i%2){
dlmalloc_free(buffers[i]);
buffers[i] = 0;
}
}
for(std::size_t i = 0, max = buffers.size()
;i < max
;++i){
if(buffers[i]){
std::size_t received_size = 0;
std::size_t min_size = i+1;
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
, preferred_size, &received_size, (char*)buffers[i]).first){
if(received_size < min_size){
return false;
}
min_size = received_size+1;
preferred_size = min_size*2;
}
}
}
buffers.erase(std::remove(buffers.begin(), buffers.end(), (void*)0)
,buffers.end());
for(std::size_t j = 0, max = buffers.size()
;j < max
;++j){
std::size_t pos = (j%4u)*(buffers.size())/4u;
dlmalloc_free(buffers[pos]);
buffers.erase(buffers.begin()+(std::ptrdiff_t)pos);
}
dlmalloc_malloc_check();
return 0 != dlmalloc_all_deallocated();}
bool test_allocation_with_reuse()
{
dlmalloc_malloc_check();
for(std::size_t sizeof_object = 1; sizeof_object < 20; ++sizeof_object){
std::vector<void*> buffers;
for(std::size_t i = 0; i != NumIt; ++i){
void *ptr = dlmalloc_malloc(i*sizeof_object);
if(!ptr)
break;
buffers.push_back(ptr);
}
for(std::size_t i = 0, max = buffers.size() - 1
;i < max
;++i){
dlmalloc_free(buffers[i]);
}
void *ptr = buffers.back();
buffers.clear();
std::size_t received_size = 0;
for(std::size_t i = 0; i != NumIt; ++i){
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
, prf_size, &received_size, (char*)ptr);
if(!ret.first)
break;
if(!ret.second)
return false;
if(received_size < min_size)
return false;
ptr = ret.first;
}
dlmalloc_free(ptr);
dlmalloc_malloc_check();
if(!dlmalloc_all_deallocated())
return false;
}
return true;
}
bool test_aligned_allocation()
{
dlmalloc_malloc_check();
for(std::size_t i = 1u; i != (1u << (sizeof(int)/2u)); i <<= 1u){
for(std::size_t j = 1u; j != 512u; j <<= 1){
void *ptr = dlmalloc_memalign(i-1, j);
if(!ptr){
return false;
}
if(((std::size_t)ptr & (j - 1)) != 0)
return false;
dlmalloc_free(ptr);
}
}
dlmalloc_malloc_check();
return 0 != dlmalloc_all_deallocated();}
bool test_continuous_aligned_allocation()
{
dlmalloc_malloc_check();
std::vector<void*> buffers;
bool continue_loop = true;
std::size_t MaxAlign = 4096;
std::size_t MaxSize = 4096;
for(std::size_t i = 1; i < MaxSize; i <<= 1){
for(std::size_t j = 1; j < MaxAlign; j <<= 1){
for(std::size_t k = 0; k != NumIt; ++k){
void *ptr = dlmalloc_memalign(i-1, j);
buffers.push_back(ptr);
if(!ptr){
continue_loop = false;
break;
}
if(((std::size_t)ptr & (j - 1)) != 0)
return false;
}
for(std::size_t k = buffers.size(); k--;){
dlmalloc_free(buffers[k]);
}
buffers.clear();
if(!continue_loop)
break;
}
}
dlmalloc_malloc_check();
return 0 != dlmalloc_all_deallocated();}
bool test_many_equal_allocation()
{
dlmalloc_malloc_check();
for( deallocation_type t = DirectDeallocation
; t != EndDeallocationType
; t = (deallocation_type)((int)t + 1)){
std::vector<void*> buffers2;
for(std::size_t i = 0; i != NumIt; ++i){
void *ptr = dlmalloc_malloc(i);
if(!ptr)
break;
buffers2.push_back(ptr);
}
for(std::size_t i = 0, max = buffers2.size()
;i < max
;++i){
if(i%2){
dlmalloc_free(buffers2[i]);
buffers2[i] = 0;
}
}
std::vector<void*> buffers;
for(std::size_t i = 0; i != NumIt/10; ++i){
dlmalloc_memchain chain;
BOOST_CONTAINER_MEMCHAIN_INIT(&chain);
dlmalloc_multialloc_nodes((i+1)*2, i+1, BOOST_CONTAINER_DL_MULTIALLOC_DEFAULT_CONTIGUOUS, &chain);
dlmalloc_memchain_it it = BOOST_CONTAINER_MEMCHAIN_BEGIN_IT(&chain);
if(BOOST_CONTAINER_MEMCHAIN_IS_END_IT(chain, it))
break;
std::size_t n = 0;
for(; !BOOST_CONTAINER_MEMCHAIN_IS_END_IT(chain, it); ++n){
buffers.push_back(BOOST_CONTAINER_MEMIT_ADDR(it));
BOOST_CONTAINER_MEMIT_NEXT(it);
}
if(n != std::size_t((i+1)*2))
return false;
}
switch(t){
case DirectDeallocation:
{
for(std::size_t j = 0, max = buffers.size()
;j < max
;++j){
dlmalloc_free(buffers[j]);
}
}
break;
case InverseDeallocation:
{
for(std::size_t j = buffers.size()
;j--
;){
dlmalloc_free(buffers[j]);
}
}
break;
case MixedDeallocation:
{
for(std::size_t j = 0, max = buffers.size()
;j < max
;++j){
std::size_t pos = (j%4u)*(buffers.size())/4u;
dlmalloc_free(buffers[pos]);
buffers.erase(buffers.begin()+(std::ptrdiff_t)pos);
}
}
break;
default:
break;
}
for(std::size_t j = 0, max = buffers2.size()
;j < max
;++j){
std::size_t pos = (j%4u)*(buffers2.size())/4u;
dlmalloc_free(buffers2[pos]);
buffers2.erase(buffers2.begin()+(std::ptrdiff_t)pos);
}
}
dlmalloc_malloc_check();
return 0 != dlmalloc_all_deallocated();
}
bool test_many_different_allocation()
{
dlmalloc_malloc_check();
const std::size_t ArraySize = 11;
std::size_t requested_sizes[ArraySize];
for(std::size_t i = 0; i < ArraySize; ++i){
requested_sizes[i] = 4*i;
}
for( deallocation_type t = DirectDeallocation
; t != EndDeallocationType
; t = (deallocation_type)((int)t + 1)){
std::vector<void*> buffers2;
for(std::size_t i = 0; i != NumIt; ++i){
void *ptr = dlmalloc_malloc(i);
if(!ptr)
break;
buffers2.push_back(ptr);
}
for(std::size_t i = 0, max = buffers2.size()
;i < max
;++i){
if(i%2){
dlmalloc_free(buffers2[i]);
buffers2[i] = 0;
}
}
std::vector<void*> buffers;
for(std::size_t i = 0; i != NumIt; ++i){
dlmalloc_memchain chain;
BOOST_CONTAINER_MEMCHAIN_INIT(&chain);
dlmalloc_multialloc_arrays(ArraySize, requested_sizes, 1, BOOST_CONTAINER_DL_MULTIALLOC_DEFAULT_CONTIGUOUS, &chain);
dlmalloc_memchain_it it = BOOST_CONTAINER_MEMCHAIN_BEGIN_IT(&chain);
if(BOOST_CONTAINER_MEMCHAIN_IS_END_IT(chain, it))
break;
std::size_t n = 0;
for(; !BOOST_CONTAINER_MEMCHAIN_IS_END_IT(chain, it); ++n){
buffers.push_back(BOOST_CONTAINER_MEMIT_ADDR(it));
BOOST_CONTAINER_MEMIT_NEXT(it);
}
if(n != ArraySize)
return false;
}
switch(t){
case DirectDeallocation:
{
for(std::size_t j = 0, max = buffers.size()
;j < max
;++j){
dlmalloc_free(buffers[j]);
}
}
break;
case InverseDeallocation:
{
for(std::size_t j = buffers.size()
;j--
;){
dlmalloc_free(buffers[j]);
}
}
break;
case MixedDeallocation:
{
for(std::size_t j = 0, max = buffers.size()
;j < max
;++j){
std::size_t pos = (j%4)*(buffers.size())/4;
dlmalloc_free(buffers[pos]);
buffers.erase(buffers.begin()+(std::ptrdiff_t)pos);
}
}
break;
default:
break;
}
for(std::size_t j = 0, max = buffers2.size()
;j < max
;++j){
std::size_t pos = (j%4u)*(buffers2.size())/4u;
dlmalloc_free(buffers2[pos]);
buffers2.erase(buffers2.begin()+(std::ptrdiff_t)pos);
}
}
dlmalloc_malloc_check();
return 0 != dlmalloc_all_deallocated();
}
bool test_many_deallocation()
{
const std::size_t ArraySize = 11;
std::vector<dlmalloc_memchain> buffers;
std::size_t requested_sizes[ArraySize];
for(std::size_t i = 0; i < ArraySize; ++i){
requested_sizes[i] = 4*i;
}
for(std::size_t i = 0; i != NumIt; ++i){
dlmalloc_memchain chain;
BOOST_CONTAINER_MEMCHAIN_INIT(&chain);
dlmalloc_multialloc_arrays(ArraySize, requested_sizes, 1, BOOST_CONTAINER_DL_MULTIALLOC_DEFAULT_CONTIGUOUS, &chain);
dlmalloc_memchain_it it = BOOST_CONTAINER_MEMCHAIN_BEGIN_IT(&chain);
if(BOOST_CONTAINER_MEMCHAIN_IS_END_IT(chain, it))
return false;
buffers.push_back(chain);
}
for(std::size_t i = 0; i != NumIt; ++i){
dlmalloc_multidealloc(&buffers[i]);
}
buffers.clear();
dlmalloc_malloc_check();
if(!dlmalloc_all_deallocated())
return false;
for(std::size_t i = 0; i != NumIt; ++i){
dlmalloc_memchain chain;
BOOST_CONTAINER_MEMCHAIN_INIT(&chain);
dlmalloc_multialloc_nodes(ArraySize, i*4+1, BOOST_CONTAINER_DL_MULTIALLOC_DEFAULT_CONTIGUOUS, &chain);
dlmalloc_memchain_it it = BOOST_CONTAINER_MEMCHAIN_BEGIN_IT(&chain);
if(BOOST_CONTAINER_MEMCHAIN_IS_END_IT(chain, it))
return false;
buffers.push_back(chain);
}
for(std::size_t i = 0; i != NumIt; ++i){
dlmalloc_multidealloc(&buffers[i]);
}
buffers.clear();
dlmalloc_malloc_check();
if(!dlmalloc_all_deallocated())
return false;
return true;
}
bool test_all_allocation()
{
std::cout << "Starting test_allocation"
<< std::endl;
if(!test_allocation()){
std::cout << "test_allocation_direct_deallocation failed"
<< std::endl;
return false;
}
std::cout << "Starting test_many_equal_allocation"
<< std::endl;
if(!test_many_equal_allocation()){
std::cout << "test_many_equal_allocation failed"
<< std::endl;
return false;
}
std::cout << "Starting test_many_different_allocation"
<< std::endl;
if(!test_many_different_allocation()){
std::cout << "test_many_different_allocation failed"
<< std::endl;
return false;
}
std::cout << "Starting test_allocation_shrink"
<< std::endl;
if(!test_allocation_shrink()){
std::cout << "test_allocation_shrink failed"
<< std::endl;
return false;
}
if(!test_allocation_shrink_and_expand()){
std::cout << "test_allocation_shrink_and_expand failed"
<< std::endl;
return false;
}
std::cout << "Starting test_allocation_expand"
<< std::endl;
if(!test_allocation_expand()){
std::cout << "test_allocation_expand failed"
<< std::endl;
return false;
}
std::cout << "Starting test_allocation_deallocation_expand"
<< std::endl;
if(!test_allocation_deallocation_expand()){
std::cout << "test_allocation_deallocation_expand failed"
<< std::endl;
return false;
}
std::cout << "Starting test_allocation_with_reuse"
<< std::endl;
if(!test_allocation_with_reuse()){
std::cout << "test_allocation_with_reuse failed"
<< std::endl;
return false;
}
std::cout << "Starting test_aligned_allocation"
<< std::endl;
if(!test_aligned_allocation()){
std::cout << "test_aligned_allocation failed"
<< std::endl;
return false;
}
std::cout << "Starting test_continuous_aligned_allocation"
<< std::endl;
if(!test_continuous_aligned_allocation()){
std::cout << "test_continuous_aligned_allocation failed"
<< std::endl;
return false;
}
if(!test_many_deallocation()){
std::cout << "test_many_deallocation failed"
<< std::endl;
return false;
}
return 0 != dlmalloc_all_deallocated();
}
}}}
int main()
{
if(!boost::container::test::test_all_allocation())
return 1;
return 0;
}