Add Polymorphic Memory Resource utilities and rework the separately compiled library:

- Dlmalloc's based C function are boost_cont_xxx no longer exported, but wrapped into C++ linkage dlmalloc_xxx functions to effectively reuse Boost's dynamic library and autolink machinery instead of rewriting machinery to compile the C source file.
- Refactored scoped_allocator_adaptor's construct logic as it was shared with polymorphic allocator's one. Moved common logic to detail/dispatch_uses_allocator.hpp. Refactored also scoped_allocator_adaptor test utilities to be reused with polymorphic_allocator tests.
This commit is contained in:
Ion Gaztañaga
2015-09-07 19:16:46 +02:00
parent 77100c0bfc
commit 33d2f0f7af
110 changed files with 10143 additions and 1160 deletions
+6
View File
@@ -11,6 +11,12 @@
# Boost Software License, Version 1.0. (See accompanying file
# LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
project
: requirements
<link>shared:<define>BOOST_CONTAINER_DYN_LINK=1
<toolset>gcc-cygwin:<link>static
;
# this rule enumerates through all the sources and invokes
# the run rule for each source, the result is a list of all
# the run rules, which we can pass on to the test_suite rule:
+23 -23
View File
@@ -8,7 +8,7 @@
//
//////////////////////////////////////////////////////////////////////////////
#include <boost/container/detail/alloc_lib_auto_link.hpp>
#include <boost/container/detail/dlmalloc.hpp>
#include <boost/container/allocator.hpp>
#include <boost/container/vector.hpp>
#include <boost/container/list.hpp>
@@ -18,50 +18,50 @@ using namespace boost::container;
bool basic_test()
{
size_t received = 0;
if(!boost_cont_all_deallocated())
if(!dlmalloc_all_deallocated())
return false;
void *ptr = boost_cont_alloc(50, 98, &received);
if(boost_cont_size(ptr) != received)
void *ptr = dlmalloc_alloc(50, 98, &received);
if(dlmalloc_size(ptr) != received)
return false;
if(boost_cont_allocated_memory() != boost_cont_chunksize(ptr))
if(dlmalloc_allocated_memory() != dlmalloc_chunksize(ptr))
return false;
if(boost_cont_all_deallocated())
if(dlmalloc_all_deallocated())
return false;
boost_cont_grow(ptr, received + 20, received + 30, &received);
dlmalloc_grow(ptr, received + 20, received + 30, &received);
if(boost_cont_allocated_memory() != boost_cont_chunksize(ptr))
if(dlmalloc_allocated_memory() != dlmalloc_chunksize(ptr))
return false;
if(boost_cont_size(ptr) != received)
if(dlmalloc_size(ptr) != received)
return false;
if(!boost_cont_shrink(ptr, 100, 140, &received, 1))
if(!dlmalloc_shrink(ptr, 100, 140, &received, 1))
return false;
if(boost_cont_allocated_memory() != boost_cont_chunksize(ptr))
if(dlmalloc_allocated_memory() != dlmalloc_chunksize(ptr))
return false;
if(!boost_cont_shrink(ptr, 0, 140, &received, 1))
if(!dlmalloc_shrink(ptr, 0, 140, &received, 1))
return false;
if(boost_cont_allocated_memory() != boost_cont_chunksize(ptr))
if(dlmalloc_allocated_memory() != dlmalloc_chunksize(ptr))
return false;
if(boost_cont_shrink(ptr, 0, received/2, &received, 1))
if(dlmalloc_shrink(ptr, 0, received/2, &received, 1))
return false;
if(boost_cont_allocated_memory() != boost_cont_chunksize(ptr))
if(dlmalloc_allocated_memory() != dlmalloc_chunksize(ptr))
return false;
if(boost_cont_size(ptr) != received)
if(dlmalloc_size(ptr) != received)
return false;
boost_cont_free(ptr);
dlmalloc_free(ptr);
boost_cont_malloc_check();
if(!boost_cont_all_deallocated())
dlmalloc_malloc_check();
if(!dlmalloc_all_deallocated())
return false;
return true;
}
@@ -69,7 +69,7 @@ bool basic_test()
bool vector_test()
{
typedef boost::container::vector<int, allocator<int> > Vector;
if(!boost_cont_all_deallocated())
if(!dlmalloc_all_deallocated())
return false;
{
const int NumElem = 1000;
@@ -86,7 +86,7 @@ bool vector_test()
new_buf = &v[0];
}
}
if(!boost_cont_all_deallocated())
if(!dlmalloc_all_deallocated())
return false;
return true;
}
@@ -94,7 +94,7 @@ bool vector_test()
bool list_test()
{
typedef boost::container::list<int, allocator<int> > List;
if(!boost_cont_all_deallocated())
if(!dlmalloc_all_deallocated())
return false;
{
const int NumElem = 1000;
@@ -102,7 +102,7 @@ bool list_test()
int values[NumElem];
l.insert(l.end(), &values[0], &values[NumElem]);
}
if(!boost_cont_all_deallocated())
if(!dlmalloc_all_deallocated())
return false;
return true;
}
+91 -91
View File
@@ -17,7 +17,7 @@
#include <iostream>
#include <cstring>
#include <algorithm> //std::remove
#include <boost/container/detail/alloc_lib_auto_link.hpp>
#include <boost/container/detail/dlmalloc.hpp>
namespace boost { namespace container { namespace test {
@@ -30,9 +30,9 @@ enum deallocation_type { DirectDeallocation, InverseDeallocation, MixedDeallocat
bool test_allocation()
{
if(!boost_cont_all_deallocated())
if(!dlmalloc_all_deallocated())
return false;
boost_cont_malloc_check();
dlmalloc_malloc_check();
for( deallocation_type t = DirectDeallocation
; t != EndDeallocationType
; t = (deallocation_type)((int)t + 1)){
@@ -40,7 +40,7 @@ bool test_allocation()
//std::size_t free_memory = a.get_free_memory();
for(int i = 0; i != NumIt; ++i){
void *ptr = boost_cont_malloc(i);
void *ptr = dlmalloc_malloc(i);
if(!ptr)
break;
buffers.push_back(ptr);
@@ -52,7 +52,7 @@ bool test_allocation()
for(int j = 0, max = (int)buffers.size()
;j < max
;++j){
boost_cont_free(buffers[j]);
dlmalloc_free(buffers[j]);
}
}
break;
@@ -61,7 +61,7 @@ bool test_allocation()
for(int j = (int)buffers.size()
;j--
;){
boost_cont_free(buffers[j]);
dlmalloc_free(buffers[j]);
}
}
break;
@@ -71,7 +71,7 @@ bool test_allocation()
;j < max
;++j){
int pos = (j%4)*((int)buffers.size())/4;
boost_cont_free(buffers[pos]);
dlmalloc_free(buffers[pos]);
buffers.erase(buffers.begin()+pos);
}
}
@@ -79,14 +79,14 @@ bool test_allocation()
default:
break;
}
if(!boost_cont_all_deallocated())
if(!dlmalloc_all_deallocated())
return false;
//bool ok = free_memory == a.get_free_memory() &&
//a.all_memory_deallocated() && a.check_sanity();
//if(!ok) return ok;
}
boost_cont_malloc_check();
return 0 != boost_cont_all_deallocated();
dlmalloc_malloc_check();
return 0 != dlmalloc_all_deallocated();
}
//This test allocates until there is no more memory
@@ -95,12 +95,12 @@ bool test_allocation()
bool test_allocation_shrink()
{
boost_cont_malloc_check();
dlmalloc_malloc_check();
std::vector<void*> buffers;
//Allocate buffers with extra memory
for(int i = 0; i != NumIt; ++i){
void *ptr = boost_cont_malloc(i*2);
void *ptr = dlmalloc_malloc(i*2);
if(!ptr)
break;
buffers.push_back(ptr);
@@ -111,12 +111,12 @@ bool test_allocation_shrink()
;i < max
; ++i){
std::size_t try_received_size = 0;
void* try_result = boost_cont_allocation_command
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 = boost_cont_allocation_command
void* result = dlmalloc_allocation_command
( BOOST_CONTAINER_SHRINK_IN_PLACE, 1, i*2
, i, &received_size, (char*)buffers[i]).first;
@@ -141,11 +141,11 @@ bool test_allocation_shrink()
;j < max
;++j){
int pos = (j%4)*((int)buffers.size())/4;
boost_cont_free(buffers[pos]);
dlmalloc_free(buffers[pos]);
buffers.erase(buffers.begin()+pos);
}
boost_cont_malloc_check();
return 0 != boost_cont_all_deallocated();//a.all_memory_deallocated() && a.check_sanity();
dlmalloc_malloc_check();
return 0 != dlmalloc_all_deallocated();//a.all_memory_deallocated() && a.check_sanity();
}
//This test allocates until there is no more memory
@@ -154,12 +154,12 @@ bool test_allocation_shrink()
bool test_allocation_expand()
{
boost_cont_malloc_check();
dlmalloc_malloc_check();
std::vector<void*> buffers;
//Allocate buffers with extra memory
for(int i = 0; i != NumIt; ++i){
void *ptr = boost_cont_malloc(i);
void *ptr = dlmalloc_malloc(i);
if(!ptr)
break;
buffers.push_back(ptr);
@@ -173,7 +173,7 @@ bool test_allocation_expand()
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(boost_cont_allocation_command
while(dlmalloc_allocation_command
( BOOST_CONTAINER_EXPAND_FWD, 1, min_size
, preferred_size, &received_size, (char*)buffers[i]).first){
//Check received size is bigger than minimum
@@ -191,11 +191,11 @@ bool test_allocation_expand()
;j < max
;++j){
int pos = (j%4)*((int)buffers.size())/4;
boost_cont_free(buffers[pos]);
dlmalloc_free(buffers[pos]);
buffers.erase(buffers.begin()+pos);
}
boost_cont_malloc_check();
return 0 != boost_cont_all_deallocated();//a.all_memory_deallocated() && a.check_sanity();
dlmalloc_malloc_check();
return 0 != dlmalloc_all_deallocated();//a.all_memory_deallocated() && a.check_sanity();
}
//This test allocates until there is no more memory
@@ -210,10 +210,10 @@ bool test_allocation_shrink_and_expand()
//Allocate buffers wand store received sizes
for(int i = 0; i != NumIt; ++i){
std::size_t received_size = 0;
void *ptr = boost_cont_allocation_command
void *ptr = dlmalloc_allocation_command
(BOOST_CONTAINER_ALLOCATE_NEW, 1, i, i*2, &received_size, 0).first;
if(!ptr){
ptr = boost_cont_allocation_command
ptr = dlmalloc_allocation_command
( BOOST_CONTAINER_ALLOCATE_NEW, 1, 1, i*2, &received_size, 0).first;
if(!ptr)
break;
@@ -229,7 +229,7 @@ bool test_allocation_shrink_and_expand()
std::size_t received_size = 0;
bool size_reduced_flag;
if(true == (size_reduced_flag = !!
boost_cont_allocation_command
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])){
@@ -249,7 +249,7 @@ bool test_allocation_shrink_and_expand()
if(!size_reduced[i]) continue;
std::size_t received_size = 0;
std::size_t request_size = received_sizes[i];
if(boost_cont_allocation_command
if(dlmalloc_allocation_command
( BOOST_CONTAINER_EXPAND_FWD, 1, request_size
, request_size, &received_size, (char*)buffers[i]).first){
if(received_size != request_size){
@@ -266,11 +266,11 @@ bool test_allocation_shrink_and_expand()
;j < max
;++j){
int pos = (j%4)*((int)buffers.size())/4;
boost_cont_free(buffers[pos]);
dlmalloc_free(buffers[pos]);
buffers.erase(buffers.begin()+pos);
}
return 0 != boost_cont_all_deallocated();//a.all_memory_deallocated() && a.check_sanity();
return 0 != dlmalloc_all_deallocated();//a.all_memory_deallocated() && a.check_sanity();
}
//This test allocates until there is no more memory
@@ -280,12 +280,12 @@ bool test_allocation_shrink_and_expand()
bool test_allocation_deallocation_expand()
{
boost_cont_malloc_check();
dlmalloc_malloc_check();
std::vector<void*> buffers;
//Allocate buffers with extra memory
for(int i = 0; i != NumIt; ++i){
void *ptr = boost_cont_malloc(i);
void *ptr = dlmalloc_malloc(i);
if(!ptr)
break;
buffers.push_back(ptr);
@@ -297,7 +297,7 @@ bool test_allocation_deallocation_expand()
;i < max
;++i){
if(i%2){
boost_cont_free(buffers[i]);
dlmalloc_free(buffers[i]);
buffers[i] = 0;
}
}
@@ -313,7 +313,7 @@ bool test_allocation_deallocation_expand()
std::size_t preferred_size = i*2;
preferred_size = min_size > preferred_size ? min_size : preferred_size;
while(boost_cont_allocation_command
while(dlmalloc_allocation_command
( BOOST_CONTAINER_EXPAND_FWD, 1, min_size
, preferred_size, &received_size, (char*)buffers[i]).first){
//Check received size is bigger than minimum
@@ -336,11 +336,11 @@ bool test_allocation_deallocation_expand()
;j < max
;++j){
int pos = (j%4)*((int)buffers.size())/4;
boost_cont_free(buffers[pos]);
dlmalloc_free(buffers[pos]);
buffers.erase(buffers.begin()+pos);
}
boost_cont_malloc_check();
return 0 != boost_cont_all_deallocated();//a.all_memory_deallocated() && a.check_sanity();
dlmalloc_malloc_check();
return 0 != dlmalloc_all_deallocated();//a.all_memory_deallocated() && a.check_sanity();
}
//This test allocates until there is no more memory
@@ -352,14 +352,14 @@ bool test_allocation_deallocation_expand()
bool test_allocation_with_reuse()
{
boost_cont_malloc_check();
dlmalloc_malloc_check();
//We will repeat this test for different sized elements
for(int sizeof_object = 1; sizeof_object < 20; ++sizeof_object){
std::vector<void*> buffers;
//Allocate buffers with extra memory
for(int i = 0; i != NumIt; ++i){
void *ptr = boost_cont_malloc(i*sizeof_object);
void *ptr = dlmalloc_malloc(i*sizeof_object);
if(!ptr)
break;
buffers.push_back(ptr);
@@ -370,7 +370,7 @@ bool test_allocation_with_reuse()
for(int i = 0, max = (int)buffers.size() - 1
;i < max
;++i){
boost_cont_free(buffers[i]);
dlmalloc_free(buffers[i]);
}
//Save the unique buffer and clear vector
@@ -382,7 +382,7 @@ bool test_allocation_with_reuse()
for(int i = 0; i != NumIt; ++i){
std::size_t min_size = (received_size/sizeof_object + 1)*sizeof_object;
std::size_t prf_size = (received_size/sizeof_object + (i+1)*2)*sizeof_object;
boost_cont_command_ret_t ret = boost_cont_allocation_command
dlmalloc_command_ret_t ret = dlmalloc_allocation_command
( BOOST_CONTAINER_EXPAND_BWD, sizeof_object, min_size
, prf_size, &received_size, (char*)ptr);
//If we have memory, this must be a buffer reuse
@@ -396,9 +396,9 @@ bool test_allocation_with_reuse()
ptr = ret.first;
}
//There should be only a single block so deallocate it
boost_cont_free(ptr);
boost_cont_malloc_check();
if(!boost_cont_all_deallocated())
dlmalloc_free(ptr);
dlmalloc_malloc_check();
if(!dlmalloc_all_deallocated())
return false;
}
return true;
@@ -410,26 +410,26 @@ bool test_allocation_with_reuse()
bool test_aligned_allocation()
{
boost_cont_malloc_check();
dlmalloc_malloc_check();
//Allocate aligned buffers in a loop
//and then deallocate it
for(unsigned int i = 1; i != (1 << (sizeof(int)/2)); i <<= 1){
for(unsigned int j = 1; j != 512; j <<= 1){
void *ptr = boost_cont_memalign(i-1, j);
void *ptr = dlmalloc_memalign(i-1, j);
if(!ptr){
return false;
}
if(((std::size_t)ptr & (j - 1)) != 0)
return false;
boost_cont_free(ptr);
dlmalloc_free(ptr);
//if(!a.all_memory_deallocated() || !a.check_sanity()){
// return false;
//}
}
}
boost_cont_malloc_check();
return 0 != boost_cont_all_deallocated();//a.all_memory_deallocated() && a.check_sanity();
dlmalloc_malloc_check();
return 0 != dlmalloc_all_deallocated();//a.all_memory_deallocated() && a.check_sanity();
}
//This test allocates memory with different alignments
@@ -437,7 +437,7 @@ bool test_aligned_allocation()
bool test_continuous_aligned_allocation()
{
boost_cont_malloc_check();
dlmalloc_malloc_check();
std::vector<void*> buffers;
//Allocate aligned buffers in a loop
//and then deallocate it
@@ -447,7 +447,7 @@ bool test_continuous_aligned_allocation()
for(unsigned i = 1; i < MaxSize; i <<= 1){
for(unsigned int j = 1; j < MaxAlign; j <<= 1){
for(int k = 0; k != NumIt; ++k){
void *ptr = boost_cont_memalign(i-1, j);
void *ptr = dlmalloc_memalign(i-1, j);
buffers.push_back(ptr);
if(!ptr){
continue_loop = false;
@@ -459,7 +459,7 @@ bool test_continuous_aligned_allocation()
}
//Deallocate all
for(int k = (int)buffers.size(); k--;){
boost_cont_free(buffers[k]);
dlmalloc_free(buffers[k]);
}
buffers.clear();
//if(!a.all_memory_deallocated() && a.check_sanity())
@@ -468,15 +468,15 @@ bool test_continuous_aligned_allocation()
break;
}
}
boost_cont_malloc_check();
return 0 != boost_cont_all_deallocated();//a.all_memory_deallocated() && a.check_sanity();
dlmalloc_malloc_check();
return 0 != dlmalloc_all_deallocated();//a.all_memory_deallocated() && a.check_sanity();
}
//This test allocates multiple values until there is no more memory
//and after that deallocates all in the inverse order
bool test_many_equal_allocation()
{
boost_cont_malloc_check();
dlmalloc_malloc_check();
for( deallocation_type t = DirectDeallocation
; t != EndDeallocationType
; t = (deallocation_type)((int)t + 1)){
@@ -486,7 +486,7 @@ bool test_many_equal_allocation()
//Allocate buffers with extra memory
for(int i = 0; i != NumIt; ++i){
void *ptr = boost_cont_malloc(i);
void *ptr = dlmalloc_malloc(i);
if(!ptr)
break;
//if(!a.check_sanity())
@@ -500,7 +500,7 @@ bool test_many_equal_allocation()
;i < max
;++i){
if(i%2){
boost_cont_free(buffers2[i]);
dlmalloc_free(buffers2[i]);
buffers2[i] = 0;
}
}
@@ -510,10 +510,10 @@ bool test_many_equal_allocation()
std::vector<void*> buffers;
for(int i = 0; i != NumIt/10; ++i){
boost_cont_memchain chain;
dlmalloc_memchain chain;
BOOST_CONTAINER_MEMCHAIN_INIT(&chain);
boost_cont_multialloc_nodes((i+1)*2, i+1, DL_MULTIALLOC_DEFAULT_CONTIGUOUS, &chain);
boost_cont_memchain_it it = BOOST_CONTAINER_MEMCHAIN_BEGIN_IT(&chain);
dlmalloc_multialloc_nodes((i+1)*2, i+1, 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;
@@ -535,7 +535,7 @@ bool test_many_equal_allocation()
for(int j = 0, max = (int)buffers.size()
;j < max
;++j){
boost_cont_free(buffers[j]);
dlmalloc_free(buffers[j]);
}
}
break;
@@ -544,7 +544,7 @@ bool test_many_equal_allocation()
for(int j = (int)buffers.size()
;j--
;){
boost_cont_free(buffers[j]);
dlmalloc_free(buffers[j]);
}
}
break;
@@ -554,7 +554,7 @@ bool test_many_equal_allocation()
;j < max
;++j){
int pos = (j%4)*((int)buffers.size())/4;
boost_cont_free(buffers[pos]);
dlmalloc_free(buffers[pos]);
buffers.erase(buffers.begin()+pos);
}
}
@@ -570,7 +570,7 @@ bool test_many_equal_allocation()
;j < max
;++j){
int pos = (j%4)*((int)buffers2.size())/4;
boost_cont_free(buffers2[pos]);
dlmalloc_free(buffers2[pos]);
buffers2.erase(buffers2.begin()+pos);
}
@@ -578,8 +578,8 @@ bool test_many_equal_allocation()
//a.all_memory_deallocated() && a.check_sanity();
//if(!ok) return ok;
}
boost_cont_malloc_check();
return 0 != boost_cont_all_deallocated();
dlmalloc_malloc_check();
return 0 != dlmalloc_all_deallocated();
}
//This test allocates multiple values until there is no more memory
@@ -587,7 +587,7 @@ bool test_many_equal_allocation()
bool test_many_different_allocation()
{
boost_cont_malloc_check();
dlmalloc_malloc_check();
const std::size_t ArraySize = 11;
std::size_t requested_sizes[ArraySize];
for(std::size_t i = 0; i < ArraySize; ++i){
@@ -603,7 +603,7 @@ bool test_many_different_allocation()
//Allocate buffers with extra memory
for(int i = 0; i != NumIt; ++i){
void *ptr = boost_cont_malloc(i);
void *ptr = dlmalloc_malloc(i);
if(!ptr)
break;
buffers2.push_back(ptr);
@@ -615,17 +615,17 @@ bool test_many_different_allocation()
;i < max
;++i){
if(i%2){
boost_cont_free(buffers2[i]);
dlmalloc_free(buffers2[i]);
buffers2[i] = 0;
}
}
std::vector<void*> buffers;
for(int i = 0; i != NumIt; ++i){
boost_cont_memchain chain;
dlmalloc_memchain chain;
BOOST_CONTAINER_MEMCHAIN_INIT(&chain);
boost_cont_multialloc_arrays(ArraySize, requested_sizes, 1, DL_MULTIALLOC_DEFAULT_CONTIGUOUS, &chain);
boost_cont_memchain_it it = BOOST_CONTAINER_MEMCHAIN_BEGIN_IT(&chain);
dlmalloc_multialloc_arrays(ArraySize, requested_sizes, 1, 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;
@@ -643,7 +643,7 @@ bool test_many_different_allocation()
for(int j = 0, max = (int)buffers.size()
;j < max
;++j){
boost_cont_free(buffers[j]);
dlmalloc_free(buffers[j]);
}
}
break;
@@ -652,7 +652,7 @@ bool test_many_different_allocation()
for(int j = (int)buffers.size()
;j--
;){
boost_cont_free(buffers[j]);
dlmalloc_free(buffers[j]);
}
}
break;
@@ -662,7 +662,7 @@ bool test_many_different_allocation()
;j < max
;++j){
int pos = (j%4)*((int)buffers.size())/4;
boost_cont_free(buffers[pos]);
dlmalloc_free(buffers[pos]);
buffers.erase(buffers.begin()+pos);
}
}
@@ -678,7 +678,7 @@ bool test_many_different_allocation()
;j < max
;++j){
int pos = (j%4)*((int)buffers2.size())/4;
boost_cont_free(buffers2[pos]);
dlmalloc_free(buffers2[pos]);
buffers2.erase(buffers2.begin()+pos);
}
@@ -686,53 +686,53 @@ bool test_many_different_allocation()
//a.all_memory_deallocated() && a.check_sanity();
//if(!ok) return ok;
}
boost_cont_malloc_check();
return 0 != boost_cont_all_deallocated();
dlmalloc_malloc_check();
return 0 != dlmalloc_all_deallocated();
}
bool test_many_deallocation()
{
const std::size_t ArraySize = 11;
std::vector<boost_cont_memchain> buffers;
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(int i = 0; i != NumIt; ++i){
boost_cont_memchain chain;
dlmalloc_memchain chain;
BOOST_CONTAINER_MEMCHAIN_INIT(&chain);
boost_cont_multialloc_arrays(ArraySize, requested_sizes, 1, DL_MULTIALLOC_DEFAULT_CONTIGUOUS, &chain);
boost_cont_memchain_it it = BOOST_CONTAINER_MEMCHAIN_BEGIN_IT(&chain);
dlmalloc_multialloc_arrays(ArraySize, requested_sizes, 1, 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(int i = 0; i != NumIt; ++i){
boost_cont_multidealloc(&buffers[i]);
dlmalloc_multidealloc(&buffers[i]);
}
buffers.clear();
boost_cont_malloc_check();
if(!boost_cont_all_deallocated())
dlmalloc_malloc_check();
if(!dlmalloc_all_deallocated())
return false;
for(int i = 0; i != NumIt; ++i){
boost_cont_memchain chain;
dlmalloc_memchain chain;
BOOST_CONTAINER_MEMCHAIN_INIT(&chain);
boost_cont_multialloc_nodes(ArraySize, i*4+1, DL_MULTIALLOC_DEFAULT_CONTIGUOUS, &chain);
boost_cont_memchain_it it = BOOST_CONTAINER_MEMCHAIN_BEGIN_IT(&chain);
dlmalloc_multialloc_nodes(ArraySize, i*4+1, 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(int i = 0; i != NumIt; ++i){
boost_cont_multidealloc(&buffers[i]);
dlmalloc_multidealloc(&buffers[i]);
}
buffers.clear();
boost_cont_malloc_check();
if(!boost_cont_all_deallocated())
dlmalloc_malloc_check();
if(!dlmalloc_all_deallocated())
return false;
return true;
@@ -835,7 +835,7 @@ bool test_all_allocation()
return false;
}
return 0 != boost_cont_all_deallocated();
return 0 != dlmalloc_all_deallocated();
}
}}} //namespace boost { namespace container { namespace test {
+233
View File
@@ -0,0 +1,233 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2015-2015. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_CONTAINER_TEST_ALLOCATOR_ARGUMENT_TESTER_HPP
#define BOOST_CONTAINER_TEST_ALLOCATOR_ARGUMENT_TESTER_HPP
#include <boost/container/uses_allocator.hpp>
#include <boost/container/detail/mpl.hpp>
#include <boost/move/core.hpp>
template<class T, unsigned int Id, bool HasTrueTypes = false>
class propagation_test_allocator
{
BOOST_COPYABLE_AND_MOVABLE(propagation_test_allocator)
public:
template<class U>
struct rebind
{
typedef propagation_test_allocator<U, Id, HasTrueTypes> other;
};
typedef boost::container::container_detail::bool_<HasTrueTypes> propagate_on_container_copy_assignment;
typedef boost::container::container_detail::bool_<HasTrueTypes> propagate_on_container_move_assignment;
typedef boost::container::container_detail::bool_<HasTrueTypes> propagate_on_container_swap;
typedef boost::container::container_detail::bool_<HasTrueTypes> is_always_equal;
typedef T value_type;
propagation_test_allocator()
: m_move_contructed(false), m_move_assigned(false)
{}
propagation_test_allocator(const propagation_test_allocator&)
: m_move_contructed(false), m_move_assigned(false)
{}
propagation_test_allocator(BOOST_RV_REF(propagation_test_allocator) )
: m_move_contructed(true), m_move_assigned(false)
{}
template<class U>
propagation_test_allocator(BOOST_RV_REF_BEG propagation_test_allocator<U, Id, HasTrueTypes> BOOST_RV_REF_END)
: m_move_contructed(true), m_move_assigned(false)
{}
template<class U>
propagation_test_allocator(const propagation_test_allocator<U, Id, HasTrueTypes> &)
{}
propagation_test_allocator & operator=(BOOST_COPY_ASSIGN_REF(propagation_test_allocator))
{
return *this;
}
propagation_test_allocator & operator=(BOOST_RV_REF(propagation_test_allocator))
{
m_move_assigned = true;
return *this;
}
std::size_t max_size() const
{ return std::size_t(-1); }
T* allocate(std::size_t n)
{ return (T*)::new char[n*sizeof(T)]; }
void deallocate(T*p, std::size_t)
{ delete []static_cast<char*>(static_cast<void*>(p)); }
bool m_move_contructed;
bool m_move_assigned;
};
template <class T1, class T2, unsigned int Id, bool HasTrueTypes>
bool operator==( const propagation_test_allocator<T1, Id, HasTrueTypes>&
, const propagation_test_allocator<T2, Id, HasTrueTypes>&)
{ return true; }
template <class T1, class T2, unsigned int Id, bool HasTrueTypes>
bool operator!=( const propagation_test_allocator<T1, Id, HasTrueTypes>&
, const propagation_test_allocator<T2, Id, HasTrueTypes>&)
{ return false; }
//This enum lists the construction options
//for an allocator-aware type
enum ConstructionTypeEnum
{
ConstructiblePrefix,
ConstructibleSuffix,
NotUsesAllocator
};
//This base class provices types for
//the derived class to implement each construction
//type. If a construction type does not apply
//the typedef is set to an internal nat
//so that the class is not constructible from
//the user arguments.
template<ConstructionTypeEnum ConstructionType, unsigned int AllocatorTag>
struct uses_allocator_base;
template<unsigned int AllocatorTag>
struct uses_allocator_base<ConstructibleSuffix, AllocatorTag>
{
typedef propagation_test_allocator<int, AllocatorTag> allocator_type;
typedef allocator_type allocator_constructor_type;
struct nat{};
typedef nat allocator_arg_type;
};
template<unsigned int AllocatorTag>
struct uses_allocator_base<ConstructiblePrefix, AllocatorTag>
{
typedef propagation_test_allocator<int, AllocatorTag> allocator_type;
typedef allocator_type allocator_constructor_type;
typedef boost::container::allocator_arg_t allocator_arg_type;
};
template<unsigned int AllocatorTag>
struct uses_allocator_base<NotUsesAllocator, AllocatorTag>
{
struct nat{};
typedef nat allocator_constructor_type;
typedef nat allocator_arg_type;
};
template<ConstructionTypeEnum ConstructionType, unsigned int AllocatorTag>
struct allocator_argument_tester
: uses_allocator_base<ConstructionType, AllocatorTag>
{
private:
BOOST_COPYABLE_AND_MOVABLE(allocator_argument_tester)
public:
typedef uses_allocator_base<ConstructionType, AllocatorTag> base_type;
//0 user argument constructors
allocator_argument_tester()
: construction_type(NotUsesAllocator), value(0)
{}
explicit allocator_argument_tester
(typename base_type::allocator_constructor_type)
: construction_type(ConstructibleSuffix), value(0)
{}
explicit allocator_argument_tester
(typename base_type::allocator_arg_type, typename base_type::allocator_constructor_type)
: construction_type(ConstructiblePrefix), value(0)
{}
//1 user argument constructors
explicit allocator_argument_tester(int i)
: construction_type(NotUsesAllocator), value(i)
{}
allocator_argument_tester
(int i, typename base_type::allocator_constructor_type)
: construction_type(ConstructibleSuffix), value(i)
{}
allocator_argument_tester
( typename base_type::allocator_arg_type
, typename base_type::allocator_constructor_type
, int i)
: construction_type(ConstructiblePrefix), value(i)
{}
//Copy constructors
allocator_argument_tester(const allocator_argument_tester &other)
: construction_type(NotUsesAllocator), value(other.value)
{}
allocator_argument_tester( const allocator_argument_tester &other
, typename base_type::allocator_constructor_type)
: construction_type(ConstructibleSuffix), value(other.value)
{}
allocator_argument_tester( typename base_type::allocator_arg_type
, typename base_type::allocator_constructor_type
, const allocator_argument_tester &other)
: construction_type(ConstructiblePrefix), value(other.value)
{}
//Move constructors
allocator_argument_tester(BOOST_RV_REF(allocator_argument_tester) other)
: construction_type(NotUsesAllocator), value(other.value)
{ other.value = 0; other.construction_type = NotUsesAllocator; }
allocator_argument_tester( BOOST_RV_REF(allocator_argument_tester) other
, typename base_type::allocator_constructor_type)
: construction_type(ConstructibleSuffix), value(other.value)
{ other.value = 0; other.construction_type = ConstructibleSuffix; }
allocator_argument_tester( typename base_type::allocator_arg_type
, typename base_type::allocator_constructor_type
, BOOST_RV_REF(allocator_argument_tester) other)
: construction_type(ConstructiblePrefix), value(other.value)
{ other.value = 0; other.construction_type = ConstructiblePrefix; }
ConstructionTypeEnum construction_type;
int value;
};
namespace boost {
namespace container {
template<unsigned int AllocatorTag>
struct constructible_with_allocator_prefix
< ::allocator_argument_tester<ConstructiblePrefix, AllocatorTag> >
{
static const bool value = true;
};
template<unsigned int AllocatorTag>
struct constructible_with_allocator_suffix
< ::allocator_argument_tester<ConstructibleSuffix, AllocatorTag> >
{
static const bool value = true;
};
} //namespace container {
} //namespace boost {
#endif //BOOST_CONTAINER_TEST_ALLOCATOR_ARGUMENT_TESTER_HPP
+87
View File
@@ -0,0 +1,87 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2015-2015. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_CONTAINER_TEST_DERIVED_FROM_MEMORY_RESOURCE_HPP
#define BOOST_CONTAINER_TEST_DERIVED_FROM_MEMORY_RESOURCE_HPP
#include <boost/container/pmr/memory_resource.hpp>
class derived_from_memory_resource
: public boost::container::pmr::memory_resource
{
public:
explicit derived_from_memory_resource(unsigned i = 0u)
: id(i)
{}
virtual ~derived_from_memory_resource()
{ destructor_called = true; }
virtual void* do_allocate(std::size_t bytes, std::size_t alignment)
{
do_allocate_called = true;
do_allocate_bytes = bytes;
do_allocate_alignment = alignment;
return do_allocate_return;
}
virtual void do_deallocate(void* p, std::size_t bytes, std::size_t alignment)
{
do_deallocate_called = true;
do_deallocate_p = p;
do_deallocate_bytes = bytes;
do_deallocate_alignment = alignment;
}
virtual bool do_is_equal(const boost::container::pmr::memory_resource& other) const BOOST_NOEXCEPT
{
do_is_equal_called = true;
do_is_equal_other = &other;
return static_cast<const derived_from_memory_resource&>(other).id == this->id;
}
void reset()
{
destructor_called = false;
do_allocate_return = 0;
do_allocate_called = false;
do_allocate_bytes = 0u;
do_allocate_alignment = 0u;
do_deallocate_called = false;
do_deallocate_p = 0;
do_deallocate_bytes = 0u;
do_deallocate_alignment = 0u;
do_is_equal_called = false;
do_is_equal_other = 0;
}
//checkers
static bool destructor_called;
unsigned id;
void *do_allocate_return;
mutable bool do_allocate_called;
mutable std::size_t do_allocate_bytes;
mutable std::size_t do_allocate_alignment;
mutable bool do_deallocate_called;
mutable void *do_deallocate_p;
mutable std::size_t do_deallocate_bytes;
mutable std::size_t do_deallocate_alignment;
mutable bool do_is_equal_called;
mutable const boost::container::pmr::memory_resource *do_is_equal_other;
};
bool derived_from_memory_resource::destructor_called = false;
#endif //#ifndef BOOST_CONTAINER_TEST_DERIVED_FROM_MEMORY_RESOURCE_HPP
+116
View File
@@ -0,0 +1,116 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2015-2015. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#include <boost/container/pmr/global_resource.hpp>
#include <boost/container/pmr/memory_resource.hpp>
#include <boost/core/lightweight_test.hpp>
#include <boost/core/no_exceptions_support.hpp>
#include "derived_from_memory_resource.hpp"
#include <cstdlib>
#include <new>
using namespace boost::container;
using namespace boost::container::pmr;
std::size_t allocation_count = 0;
#ifdef BOOST_MSVC
#pragma warning (push)
#pragma warning (disable : 4290)
#endif
#if defined(BOOST_GCC) && (BOOST_GCC >= 40700) && (__cplusplus >= 201103L)
#define BOOST_CONTAINER_NEW_EXCEPTION_SPECIFIER
#define BOOST_CONTAINER_DELETE_EXCEPTION_SPECIFIER noexcept
#else
#define BOOST_CONTAINER_NEW_EXCEPTION_SPECIFIER throw(std::bad_alloc)
#define BOOST_CONTAINER_DELETE_EXCEPTION_SPECIFIER throw()
#endif
#if defined(BOOST_GCC) && (BOOST_GCC >= 50000)
#pragma GCC diagnostic ignored "-Wsized-deallocation"
#endif
void* operator new[](std::size_t count) BOOST_CONTAINER_NEW_EXCEPTION_SPECIFIER
{
++allocation_count;
return std::malloc(count);
}
void operator delete[](void *p) BOOST_CONTAINER_DELETE_EXCEPTION_SPECIFIER
{
--allocation_count;
return std::free(p);
}
#ifdef BOOST_MSVC
#pragma warning (pop)
#endif
void test_new_delete_resource()
{
//Make sure new_delete_resource calls new[]/delete[]
std::size_t memcount = allocation_count;
memory_resource *mr = new_delete_resource();
//each time should return the same pointer
BOOST_TEST(mr == new_delete_resource());
#if !defined(BOOST_CONTAINER_DYNAMIC_LINKING) //No new delete replacement possible new_delete is a DLL
BOOST_TEST(memcount == allocation_count);
#endif
void *addr = mr->allocate(16, 1);
#if !defined(BOOST_CONTAINER_DYNAMIC_LINKING) //No new delete replacement possible new_delete is a DLL
BOOST_TEST((allocation_count - memcount) == 1);
#endif
mr->deallocate(addr, 16, 1);
BOOST_TEST(memcount == allocation_count);
}
void test_null_memory_resource()
{
//Make sure it throw or returns null
memory_resource *mr = null_memory_resource();
#if !defined(BOOST_NO_EXCEPTIONS)
bool bad_allocexception_thrown = false;
try{
mr->allocate(1, 1);
}
catch(std::bad_alloc&) {
bad_allocexception_thrown = true;
}
catch(...) {
}
BOOST_TEST(bad_allocexception_thrown == true);
#else
BOOST_TEST(0 == mr->allocate(1, 1));
#endif
}
void test_default_resource()
{
//Default resource must be new/delete before set_default_resource
BOOST_TEST(get_default_resource() == new_delete_resource());
//Set default resource and obtain previous
derived_from_memory_resource d;
memory_resource *prev_default = set_default_resource(&d);
BOOST_TEST(get_default_resource() == &d);
//Set default resource with null, which should be new/delete
prev_default = set_default_resource(0);
BOOST_TEST(prev_default == &d);
BOOST_TEST(get_default_resource() == new_delete_resource());
}
int main()
{
test_new_delete_resource();
test_null_memory_resource();
test_default_resource();
return ::boost::report_errors();
}
+86
View File
@@ -0,0 +1,86 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2015-2015. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_CONTAINER_TEST_MEMORY_RESOURCE_TESTER_HPP
#define BOOST_CONTAINER_TEST_MEMORY_RESOURCE_TESTER_HPP
#include <boost/container/pmr/memory_resource.hpp>
#include <boost/container/vector.hpp>
#include <cstdlib>
class memory_resource_logger
: public boost::container::pmr::memory_resource
{
public:
struct allocation_info
{
char *address;
std::size_t bytes;
std::size_t alignment;
};
boost::container::vector<allocation_info> m_info;
unsigned m_mismatches;
explicit memory_resource_logger()
: m_info()
, m_mismatches()
{}
virtual ~memory_resource_logger()
{ this->reset(); }
virtual void* do_allocate(std::size_t bytes, std::size_t alignment)
{
char *addr =(char*)std::malloc(bytes);
if(!addr){
throw std::bad_alloc();
}
allocation_info info;
info.address = addr;
info.bytes = bytes;
info.alignment = alignment;
m_info.push_back(info);
return addr;
}
virtual void do_deallocate(void* p, std::size_t bytes, std::size_t alignment)
{
std::size_t i = 0, max = m_info.size();
while(i != max && m_info[i].address != p){
++i;
}
if(i == max){
++m_mismatches;
}
else{
const allocation_info &info = m_info[i];
m_mismatches += info.bytes != bytes || info.alignment != alignment;
std::free(p);
m_info.erase(m_info.nth(i));
}
}
virtual bool do_is_equal(const boost::container::pmr::memory_resource& other) const BOOST_NOEXCEPT
{
return static_cast<const memory_resource *>(this) == &other;
}
void reset()
{
while(!m_info.empty()){
std::free(m_info.back().address);
m_info.pop_back();
}
m_mismatches = 0u;
}
};
#endif //#ifndef BOOST_CONTAINER_TEST_MEMORY_RESOURCE_TESTER_HPP
+135
View File
@@ -0,0 +1,135 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2015-2015. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#include <boost/container/pmr/memory_resource.hpp>
#include <boost/core/lightweight_test.hpp>
#include <boost/core/no_exceptions_support.hpp>
#include "derived_from_memory_resource.hpp"
#include <cstdlib>
using namespace boost::container;
using namespace boost::container::pmr;
void test_allocate()
{
derived_from_memory_resource d;
memory_resource &mr = d;
d.reset();
BOOST_TEST(d.do_allocate_called == false);
BOOST_TEST(d.do_allocate_bytes == 0);
BOOST_TEST(d.do_allocate_alignment == 0);
mr.allocate(2, 4);
BOOST_TEST(d.do_allocate_called == true);
BOOST_TEST(d.do_allocate_bytes == 2);
BOOST_TEST(d.do_allocate_alignment == 4);
}
void test_deallocate()
{
derived_from_memory_resource d;
memory_resource &mr = d;
d.reset();
BOOST_TEST(d.do_deallocate_called == false);
BOOST_TEST(d.do_deallocate_p == 0);
BOOST_TEST(d.do_allocate_bytes == 0);
BOOST_TEST(d.do_allocate_alignment == 0);
mr.deallocate(&d, 2, 4);
BOOST_TEST(d.do_deallocate_called == true);
BOOST_TEST(d.do_deallocate_p == &d);
BOOST_TEST(d.do_deallocate_bytes == 2);
BOOST_TEST(d.do_deallocate_alignment == 4);
}
void test_destructor()
{
{
derived_from_memory_resource d;
d.reset();
BOOST_TEST(derived_from_memory_resource::destructor_called == false);
}
BOOST_TEST(derived_from_memory_resource::destructor_called == true);
}
void test_is_equal()
{
derived_from_memory_resource d;
memory_resource &mr = d;
d.reset();
BOOST_TEST(d.do_is_equal_called == false);
BOOST_TEST(d.do_is_equal_other == 0);
mr.is_equal(d);
BOOST_TEST(d.do_is_equal_called == true);
BOOST_TEST(d.do_is_equal_other == &d);
}
void test_equality_operator()
{
derived_from_memory_resource d;
memory_resource &mr = d;
d.reset();
BOOST_TEST(d.do_is_equal_called == false);
BOOST_TEST(d.do_is_equal_other == 0);
//equal addresses are shorcircuited
BOOST_TEST((mr == mr) == true);
BOOST_TEST(d.do_is_equal_called == false);
BOOST_TEST(d.do_is_equal_other == 0);
//unequal addresses are dispatched to is_equal which in turn calls do_is_equal
derived_from_memory_resource d2(1);
d.reset();
d2.reset();
memory_resource &mr2 = d2;
BOOST_TEST((mr == mr2) == false);
BOOST_TEST(d.do_is_equal_called == true);
BOOST_TEST(d.do_is_equal_other == &d2);
}
void test_inequality_operator()
{
derived_from_memory_resource d;
memory_resource &mr = d;
d.reset();
BOOST_TEST(d.do_is_equal_called == false);
BOOST_TEST(d.do_is_equal_other == 0);
//equal addresses are shorcircuited
BOOST_TEST((mr != mr) == false);
BOOST_TEST(d.do_is_equal_called == false);
BOOST_TEST(d.do_is_equal_other == 0);
//unequal addresses are dispatched to is_equal which in turn calls do_is_equal
derived_from_memory_resource d2(1);
d.reset();
d2.reset();
memory_resource &mr2 = d2;
BOOST_TEST((mr != mr2) == true);
BOOST_TEST(d.do_is_equal_called == true);
BOOST_TEST(d.do_is_equal_other == &d2);
}
int main()
{
test_destructor();
test_allocate();
test_deallocate();
test_is_equal();
test_equality_operator();
test_inequality_operator();
return ::boost::report_errors();
}
+462
View File
@@ -0,0 +1,462 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2015-2015. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#include <boost/container/pmr/monotonic_buffer_resource.hpp>
#include <boost/container/pmr/global_resource.hpp>
#include <boost/core/lightweight_test.hpp>
#include "derived_from_memory_resource.hpp"
#include "memory_resource_logger.hpp"
using namespace boost::container::pmr;
static const std::size_t AllocCount = 32u;
namespace test_block_chain{
//explicit block_slist(memory_resource &upstream_rsrc)
void test_constructor()
{
memory_resource_logger mrl;
block_slist bc(mrl);
//Resource stored
BOOST_TEST(&bc.upstream_resource() == &mrl);
//No allocation performed
BOOST_TEST(mrl.m_info.size() == 0u);
}
//void *allocate(std::size_t size)
void test_allocate()
{
memory_resource_logger mrl;
block_slist bc(mrl);
for(unsigned i = 0; i != unsigned(AllocCount); ++i){
//Allocate and trace data
const std::size_t alloc = i+1;
char *const addr = (char*)bc.allocate(alloc);
//Should have allocated a new entry
BOOST_TEST(mrl.m_info.size() == (i+1));
//Requested size must be bigger to include metadata
BOOST_TEST(mrl.m_info[i].bytes > alloc);
BOOST_TEST(mrl.m_info[i].alignment == memory_resource::max_align);
//Returned address should be between the allocated buffer
BOOST_TEST(mrl.m_info[i].address < addr);
BOOST_TEST(addr < (mrl.m_info[i].address + mrl.m_info[i].bytes));
//Allocate size should include all requested size
BOOST_TEST((addr + alloc) <= (mrl.m_info[i].address + mrl.m_info[i].bytes));
//Allocation must be max-aligned
BOOST_TEST((std::size_t(addr) % memory_resource::max_align) == 0);
}
}
//void release() BOOST_NOEXCEPT
void test_release()
{
memory_resource_logger mrl;
block_slist bc(mrl);
//Allocate and trace data
char *bufs[AllocCount];
for(unsigned i = 0; i != unsigned(AllocCount); ++i){
bufs[i] = (char*)bc.allocate(i+1);
}
(void)bufs;
//Should have allocated a new entry
BOOST_TEST(mrl.m_info.size() == AllocCount);
//Now release and check all allocations match deallocations
bc.release();
BOOST_TEST(mrl.m_mismatches == 0);
BOOST_TEST(mrl.m_info.size() == 0u);
}
//memory_resource* upstream_resource()
void test_memory_resource()
{
derived_from_memory_resource d;
block_slist bc(d);
//Resource stored
BOOST_TEST(&bc.upstream_resource() == &d);
}
//~block_slist() { this->release(); }
void test_destructor()
{
memory_resource_logger mrl;
{
block_slist bc(mrl);
//Allocate and trace data
char *bufs[AllocCount];
for(unsigned i = 0; i != unsigned(AllocCount); ++i){
bufs[i] = (char*)bc.allocate(i+1);
}
(void)bufs;
//Should have allocated a new entry
BOOST_TEST(mrl.m_info.size() == AllocCount);
//Destructor should release all memory
}
BOOST_TEST(mrl.m_mismatches == 0);
BOOST_TEST(mrl.m_info.size() == 0u);
}
} //namespace test_block_chain {
void test_resource_constructor()
{
//First constructor, null resource
{
memory_resource_logger mrl;
BOOST_TEST(mrl.m_info.size() == 0u);
set_default_resource(&mrl);
monotonic_buffer_resource m;
//test postconditions
BOOST_TEST(m.upstream_resource() == get_default_resource());
//test it does not allocate any memory
BOOST_TEST(mrl.m_info.size() == 0u);
set_default_resource(0);
}
//First constructor, non-null resource
{
derived_from_memory_resource dmr;
dmr.reset();
monotonic_buffer_resource m(&dmr);
//test postconditions
BOOST_TEST(m.upstream_resource() == &dmr);
BOOST_TEST(m.next_buffer_size() == monotonic_buffer_resource::initial_next_buffer_size);
BOOST_TEST(m.current_buffer() == 0);
//test it does not allocate any memory
BOOST_TEST(dmr.do_allocate_called == false);
}
}
void test_initial_size_constructor()
{
//Second constructor, null resource
const std::size_t initial_size = monotonic_buffer_resource::initial_next_buffer_size*2;
{
memory_resource_logger mrl;
BOOST_TEST(mrl.m_info.size() == 0u);
set_default_resource(&mrl);
monotonic_buffer_resource m(initial_size);
//test postconditions
BOOST_TEST(m.upstream_resource() == get_default_resource());
BOOST_TEST(m.next_buffer_size() >= initial_size);
BOOST_TEST(m.current_buffer() == 0);
//test it does not allocate any memory
BOOST_TEST(mrl.m_info.size() == 0u);
set_default_resource(0);
}
//Second constructor, non-null resource
{
derived_from_memory_resource dmr;
dmr.reset();
monotonic_buffer_resource m(initial_size, &dmr);
//test postconditions
BOOST_TEST(m.upstream_resource() == &dmr);
BOOST_TEST(m.next_buffer_size() >= initial_size);
BOOST_TEST(m.current_buffer() == 0);
//test it does not allocate any memory
BOOST_TEST(dmr.do_allocate_called == false);
}
}
void test_buffer_constructor()
{
const std::size_t BufSz = monotonic_buffer_resource::initial_next_buffer_size*2;
unsigned char buf[BufSz];
//Third constructor, null resource
{
memory_resource_logger mrl;
BOOST_TEST(mrl.m_info.size() == 0u);
set_default_resource(&mrl);
monotonic_buffer_resource m(buf, BufSz);
//test postconditions
BOOST_TEST(m.upstream_resource() == get_default_resource());
BOOST_TEST(m.next_buffer_size() >= BufSz*2);
BOOST_TEST(m.current_buffer() == buf);
//test it does not allocate any memory
BOOST_TEST(mrl.m_info.size() == 0u);
set_default_resource(0);
}
//Third constructor, non-null resource
{
derived_from_memory_resource dmr;
dmr.reset();
monotonic_buffer_resource m(buf, sizeof(buf), &dmr);
//test postconditions
BOOST_TEST(m.upstream_resource() == &dmr);
BOOST_TEST(m.next_buffer_size() >= sizeof(buf)*2);
BOOST_TEST(m.current_buffer() == buf);
//test it does not allocate any memory
BOOST_TEST(dmr.do_allocate_called == false);
}
//Check for empty buffers
{
monotonic_buffer_resource m(buf, 0);
BOOST_TEST(m.upstream_resource() == get_default_resource());
BOOST_TEST(m.next_buffer_size() > 1);
BOOST_TEST(m.current_buffer() == buf);
}
}
struct derived_from_monotonic_buffer_resource
: public monotonic_buffer_resource
{
explicit derived_from_monotonic_buffer_resource(memory_resource *p)
: monotonic_buffer_resource(p)
{}
explicit derived_from_monotonic_buffer_resource(std::size_t initial_size, memory_resource* upstream)
: monotonic_buffer_resource(initial_size, upstream)
{}
explicit derived_from_monotonic_buffer_resource(void* buffer, std::size_t buffer_size, memory_resource* upstream)
: monotonic_buffer_resource(buffer, buffer_size, upstream)
{}
using monotonic_buffer_resource::do_allocate;
using monotonic_buffer_resource::do_deallocate;
using monotonic_buffer_resource::do_is_equal;
};
void test_upstream_resource()
{
//Test stores the resource and uses it to allocate memory
derived_from_memory_resource dmr;
dmr.reset();
derived_from_monotonic_buffer_resource dmbr(&dmr);
//Resource must be stored and initial values given (no current buffer)
BOOST_TEST(dmbr.upstream_resource() == &dmr);
BOOST_TEST(dmbr.next_buffer_size() == monotonic_buffer_resource::initial_next_buffer_size);
BOOST_TEST(dmbr.current_buffer() == 0);
//Test it does not allocate any memory
BOOST_TEST(dmr.do_allocate_called == false);
const std::size_t BufSz = monotonic_buffer_resource::initial_next_buffer_size;
//Now allocate storage, and stub it as the return buffer
//for "derived_from_memory_resource":
boost::move_detail::aligned_storage<BufSz+block_slist::header_size>::type buf;
dmr.do_allocate_return = &buf;
//Test that allocation uses the upstream_resource()
void *addr = dmbr.do_allocate(1u, 1u);
//Test returns stubbed memory with the internal initial size plus metadata size
BOOST_TEST(addr > (char*)&buf);
BOOST_TEST(addr < (char*)(&buf+1));
BOOST_TEST(dmr.do_allocate_called == true);
BOOST_TEST(dmr.do_allocate_bytes > BufSz);
//Alignment for the resource must be max_align
BOOST_TEST(dmr.do_allocate_alignment == memory_resource::max_align);
}
void test_do_allocate()
{
memory_resource_logger mrl;
{
std::size_t remaining_storage = 0u;
derived_from_monotonic_buffer_resource dmbr(&mrl);
//First test, no buffer
{
dmbr.do_allocate(1, 1);
//It should allocate initial size
BOOST_TEST(mrl.m_info.size() == 1u);
//... which requests the initial size plus the header size to the allcoator
BOOST_TEST(mrl.m_info[0].bytes == monotonic_buffer_resource::initial_next_buffer_size+block_slist::header_size);
std::size_t remaining = dmbr.remaining_storage(1u);
//Remaining storage should be one less than initial, as we requested 1 byte with minimal alignment
BOOST_TEST(remaining == monotonic_buffer_resource::initial_next_buffer_size-1u);
remaining_storage = remaining;
}
//Now ask for more internal storage with misaligned current buffer
{
//Test wasted space
std::size_t wasted_due_to_alignment;
dmbr.remaining_storage(4u, wasted_due_to_alignment);
BOOST_TEST(wasted_due_to_alignment == 3u);
dmbr.do_allocate(4, 4);
//It should not have allocated
BOOST_TEST(mrl.m_info.size() == 1u);
std::size_t remaining = dmbr.remaining_storage(1u);
//We wasted some bytes due to alignment plus 4 bytes of real storage
BOOST_TEST(remaining == remaining_storage - 4 - wasted_due_to_alignment);
remaining_storage = remaining;
}
//Now request the same alignment to test no storage is wasted
{
std::size_t wasted_due_to_alignment;
std::size_t remaining = dmbr.remaining_storage(1u, wasted_due_to_alignment);
BOOST_TEST(mrl.m_info.size() == 1u);
dmbr.do_allocate(4, 4);
//It should not have allocated
BOOST_TEST(mrl.m_info.size() == 1u);
remaining = dmbr.remaining_storage(1u);
//We wasted no bytes due to alignment plus 4 bytes of real storage
BOOST_TEST(remaining == remaining_storage - 4u);
remaining_storage = remaining;
}
//Now exhaust the remaining storage with 2 byte alignment (the last allocation
//was 4 bytes with 4 byte alignment) so it should be already 2-byte aligned.
{
dmbr.do_allocate(remaining_storage, 2);
std::size_t wasted_due_to_alignment;
std::size_t remaining = dmbr.remaining_storage(1u, wasted_due_to_alignment);
BOOST_TEST(wasted_due_to_alignment == 0u);
BOOST_TEST(remaining == 0u);
//It should not have allocated
BOOST_TEST(mrl.m_info.size() == 1u);
remaining_storage = 0u;
}
//The next allocation should trigger the upstream resource, even with a 1 byte
//allocation.
{
dmbr.do_allocate(1u, 1u);
BOOST_TEST(mrl.m_info.size() == 2u);
//The next allocation should be geometrically bigger.
BOOST_TEST(mrl.m_info[1].bytes == 2*monotonic_buffer_resource::initial_next_buffer_size+block_slist::header_size);
std::size_t wasted_due_to_alignment;
//For a 2 byte alignment one byte will be wasted from the previous 1 byte allocation
std::size_t remaining = dmbr.remaining_storage(2u, wasted_due_to_alignment);
BOOST_TEST(wasted_due_to_alignment == 1u);
BOOST_TEST(remaining == (mrl.m_info[1].bytes - 1u - wasted_due_to_alignment - block_slist::header_size));
//It should not have allocated
remaining_storage = dmbr.remaining_storage(1u);
}
//Now try a bigger than next allocation and see if next_buffer_size is doubled.
{
std::size_t next_alloc = 5*monotonic_buffer_resource::initial_next_buffer_size;
dmbr.do_allocate(next_alloc, 1u);
BOOST_TEST(mrl.m_info.size() == 3u);
//The next allocation should be geometrically bigger.
BOOST_TEST(mrl.m_info[2].bytes == 8*monotonic_buffer_resource::initial_next_buffer_size+block_slist::header_size);
remaining_storage = dmbr.remaining_storage(1u);
}
}
//derived_from_monotonic_buffer_resource dmbr(&mrl) is destroyed
BOOST_TEST(mrl.m_mismatches == 0u);
BOOST_TEST(mrl.m_info.size() == 0u);
//Now use a local buffer
{
boost::move_detail::aligned_storage
<monotonic_buffer_resource::initial_next_buffer_size>::type buf;
//Supply an external buffer
derived_from_monotonic_buffer_resource dmbr(&buf, sizeof(buf), &mrl);
BOOST_TEST(dmbr.remaining_storage(1u) == sizeof(buf));
//Allocate all remaining storage
dmbr.do_allocate(dmbr.remaining_storage(1u), 1u);
//No new allocation should have ocurred
BOOST_TEST(mrl.m_info.size() == 0u);
BOOST_TEST(dmbr.remaining_storage(1u) == 0u);
}
BOOST_TEST(mrl.m_mismatches == 0u);
BOOST_TEST(mrl.m_info.size() == 0u);
}
void test_do_deallocate()
{
memory_resource_logger mrl;
const std::size_t initial_size = 1u;
{
derived_from_monotonic_buffer_resource dmbr(initial_size, &mrl);
//First test, no buffer
const unsigned iterations = 8;
char *bufs[iterations];
std::size_t sizes[iterations];
//Test each iteration allocates memory
for(unsigned i = 0; i != iterations; ++i)
{
sizes[i] = dmbr.remaining_storage()+1;
bufs[i] = (char*)dmbr.do_allocate(sizes[i], 1);
BOOST_TEST(mrl.m_info.size() == (i+1));
}
std::size_t remaining = dmbr.remaining_storage();
//Test do_deallocate does not release any storage
for(unsigned i = 0; i != iterations; ++i)
{
dmbr.do_deallocate(bufs[i], sizes[i], 1u);
BOOST_TEST(mrl.m_info.size() == iterations);
BOOST_TEST(remaining == dmbr.remaining_storage());
BOOST_TEST(mrl.m_mismatches == 0u);
}
}
}
void test_do_is_equal()
{
//! <b>Returns</b>:
//! `this == dynamic_cast<const monotonic_buffer_resource*>(&other)`.
memory_resource_logger mrl;
derived_from_monotonic_buffer_resource dmbr(&mrl);
derived_from_monotonic_buffer_resource dmbr2(&mrl);
BOOST_TEST(true == dmbr.do_is_equal(dmbr));
BOOST_TEST(false == dmbr.do_is_equal(dmbr2));
//A different type should be always different
derived_from_memory_resource dmr;
BOOST_TEST(false == dmbr.do_is_equal(dmr));
}
void test_release()
{
memory_resource_logger mrl;
const std::size_t initial_size = 1u;
derived_from_monotonic_buffer_resource dmbr(initial_size, &mrl);
//First test, no buffer
const unsigned iterations = 8;
//Test each iteration allocates memory
for(unsigned i = 0; i != iterations; ++i)
{
dmbr.do_allocate(dmbr.remaining_storage()+1, 1);
BOOST_TEST(mrl.m_info.size() == (i+1));
}
//Release and check memory was released
dmbr.release();
BOOST_TEST(mrl.m_mismatches == 0u);
BOOST_TEST(mrl.m_info.size() == 0u);
}
void test_destructor()
{
memory_resource_logger mrl;
const std::size_t initial_size = 1u;
{
derived_from_monotonic_buffer_resource dmbr(initial_size, &mrl);
//First test, no buffer
const unsigned iterations = 8;
//Test each iteration allocates memory
for(unsigned i = 0; i != iterations; ++i)
{
dmbr.do_allocate(dmbr.remaining_storage()+1, 1);
BOOST_TEST(mrl.m_info.size() == (i+1));
}
} //dmbr is destroyed, memory should be released
BOOST_TEST(mrl.m_mismatches == 0u);
BOOST_TEST(mrl.m_info.size() == 0u);
}
int main()
{
test_block_chain::test_constructor();
test_block_chain::test_allocate();
test_block_chain::test_release();
test_block_chain::test_memory_resource();
test_block_chain::test_destructor();
test_resource_constructor();
test_initial_size_constructor();
test_buffer_constructor();
test_upstream_resource();
test_do_allocate();
test_do_deallocate();
test_do_is_equal();
test_release();
test_destructor();
return ::boost::report_errors();
}
+26
View File
@@ -0,0 +1,26 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2015-2015. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#include <boost/container/pmr/deque.hpp>
#include <boost/static_assert.hpp>
#include <boost/container/detail/type_traits.hpp>
int main()
{
using namespace boost::container;
using boost::container::container_detail::is_same;
typedef deque<int, pmr::polymorphic_allocator<int> > intcontainer_t;
BOOST_STATIC_ASSERT(( is_same<intcontainer_t, pmr::deque_of<int>::type >::value ));
#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
BOOST_STATIC_ASSERT(( is_same<intcontainer_t, pmr::deque<int> >::value ));
#endif
return 0;
}
+26
View File
@@ -0,0 +1,26 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2015-2015. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#include <boost/container/pmr/flat_map.hpp>
#include <boost/static_assert.hpp>
#include <boost/container/detail/type_traits.hpp>
int main()
{
using namespace boost::container;
using boost::container::container_detail::is_same;
typedef flat_map<int, float, std::less<int>, pmr::polymorphic_allocator<std::pair<int, float> > > intcontainer_t;
BOOST_STATIC_ASSERT(( is_same<intcontainer_t, pmr::flat_map_of<int, float>::type >::value ));
#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
BOOST_STATIC_ASSERT(( is_same<intcontainer_t, pmr::flat_map<int, float> >::value ));
#endif
return 0;
}
+26
View File
@@ -0,0 +1,26 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2015-2015. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#include <boost/container/pmr/flat_set.hpp>
#include <boost/static_assert.hpp>
#include <boost/container/detail/type_traits.hpp>
int main()
{
using namespace boost::container;
using boost::container::container_detail::is_same;
typedef flat_set<int, std::less<int>, pmr::polymorphic_allocator<int> > intcontainer_t;
BOOST_STATIC_ASSERT(( is_same<intcontainer_t, pmr::flat_set_of<int>::type >::value ));
#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
BOOST_STATIC_ASSERT(( is_same<intcontainer_t, pmr::flat_set<int> >::value ));
#endif
return 0;
}
+26
View File
@@ -0,0 +1,26 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2015-2015. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#include <boost/container/pmr/list.hpp>
#include <boost/static_assert.hpp>
#include <boost/container/detail/type_traits.hpp>
int main()
{
using namespace boost::container;
using boost::container::container_detail::is_same;
typedef list<int, pmr::polymorphic_allocator<int> > intcontainer_t;
BOOST_STATIC_ASSERT(( is_same<intcontainer_t, pmr::list_of<int>::type >::value ));
#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
BOOST_STATIC_ASSERT(( is_same<intcontainer_t, pmr::list<int> >::value ));
#endif
return 0;
}
+26
View File
@@ -0,0 +1,26 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2015-2015. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#include <boost/container/pmr/map.hpp>
#include <boost/static_assert.hpp>
#include <boost/container/detail/type_traits.hpp>
int main()
{
using namespace boost::container;
using boost::container::container_detail::is_same;
typedef map<int, float, std::less<int>, pmr::polymorphic_allocator<std::pair<const int, float> > > intcontainer_t;
BOOST_STATIC_ASSERT(( is_same<intcontainer_t, pmr::map_of<int, float>::type >::value ));
#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
BOOST_STATIC_ASSERT(( is_same<intcontainer_t, pmr::map<int, float> >::value ));
#endif
return 0;
}
+26
View File
@@ -0,0 +1,26 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2015-2015. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#include <boost/container/pmr/set.hpp>
#include <boost/static_assert.hpp>
#include <boost/container/detail/type_traits.hpp>
int main()
{
using namespace boost::container;
using boost::container::container_detail::is_same;
typedef set<int, std::less<int>, pmr::polymorphic_allocator<int> > intcontainer_t;
BOOST_STATIC_ASSERT(( is_same<intcontainer_t, pmr::set_of<int>::type >::value ));
#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
BOOST_STATIC_ASSERT(( is_same<intcontainer_t, pmr::set<int> >::value ));
#endif
return 0;
}
+26
View File
@@ -0,0 +1,26 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2015-2015. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#include <boost/container/slist.hpp>
struct empty
{
friend bool operator == (const empty &, const empty &){ return true; }
friend bool operator < (const empty &, const empty &){ return true; }
};
template class ::boost::container::slist<empty>;
int main()
{
::boost::container::slist<empty> dummy;
(void)dummy;
return 0;
}
+26
View File
@@ -0,0 +1,26 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2015-2015. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#include <boost/container/pmr/small_vector.hpp>
#include <boost/static_assert.hpp>
#include <boost/container/detail/type_traits.hpp>
int main()
{
using namespace boost::container;
using boost::container::container_detail::is_same;
typedef small_vector<int, 2, pmr::polymorphic_allocator<int> > intcontainer_t;
BOOST_STATIC_ASSERT(( is_same<intcontainer_t, pmr::small_vector_of<int, 2>::type >::value ));
#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
BOOST_STATIC_ASSERT(( is_same<intcontainer_t, pmr::small_vector<int, 2> >::value ));
#endif
return 0;
}
+26
View File
@@ -0,0 +1,26 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2015-2015. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#include <boost/container/pmr/stable_vector.hpp>
#include <boost/static_assert.hpp>
#include <boost/container/detail/type_traits.hpp>
int main()
{
using namespace boost::container;
using boost::container::container_detail::is_same;
typedef stable_vector<int, pmr::polymorphic_allocator<int> > intcontainer_t;
BOOST_STATIC_ASSERT(( is_same<intcontainer_t, pmr::stable_vector_of<int>::type >::value ));
#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
BOOST_STATIC_ASSERT(( is_same<intcontainer_t, pmr::stable_vector<int> >::value ));
#endif
return 0;
}
+26
View File
@@ -0,0 +1,26 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2015-2015. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#include <boost/container/static_vector.hpp>
struct empty
{
friend bool operator == (const empty &, const empty &){ return true; }
friend bool operator < (const empty &, const empty &){ return true; }
};
template class ::boost::container::static_vector<empty, 2>;
int main()
{
::boost::container::static_vector<empty, 2> dummy;
(void)dummy;
return 0;
}
+31
View File
@@ -0,0 +1,31 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2015-2015. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#include <boost/container/pmr/string.hpp>
#include <boost/static_assert.hpp>
#include <boost/container/detail/type_traits.hpp>
int main()
{
using namespace boost::container;
using boost::container::container_detail::is_same;
typedef basic_string<char, std::char_traits<char>, pmr::polymorphic_allocator<char> > string_t;
typedef basic_string<wchar_t, std::char_traits<wchar_t>, pmr::polymorphic_allocator<wchar_t> > wstring_t;
BOOST_STATIC_ASSERT(( is_same<string_t, pmr::string>::value ));
BOOST_STATIC_ASSERT(( is_same<string_t, pmr::basic_string_of<char>::type>::value ));
BOOST_STATIC_ASSERT(( is_same<wstring_t, pmr::wstring>::value ));
BOOST_STATIC_ASSERT(( is_same<wstring_t, pmr::basic_string_of<wchar_t>::type>::value ));
#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
BOOST_STATIC_ASSERT(( is_same<string_t, pmr::string >::value ));
BOOST_STATIC_ASSERT(( is_same<wstring_t, pmr::wstring >::value ));
#endif
return 0;
}
+26
View File
@@ -0,0 +1,26 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2015-2015. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#include <boost/container/pmr/vector.hpp>
#include <boost/static_assert.hpp>
#include <boost/container/detail/type_traits.hpp>
int main()
{
using namespace boost::container;
using boost::container::container_detail::is_same;
typedef vector<int, pmr::polymorphic_allocator<int> > intcontainer_t;
BOOST_STATIC_ASSERT(( is_same<intcontainer_t, pmr::vector_of<int>::type >::value ));
#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
BOOST_STATIC_ASSERT(( is_same<intcontainer_t, pmr::vector<int> >::value ));
#endif
return 0;
}
+198
View File
@@ -0,0 +1,198 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2015-2015. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#include <boost/container/pmr/polymorphic_allocator.hpp>
#include <boost/container/pmr/global_resource.hpp>
#include <boost/core/lightweight_test.hpp>
#include "derived_from_memory_resource.hpp"
#include "propagation_test_allocator.hpp"
using namespace boost::container::pmr;
using namespace boost::container;
void test_default_constructor()
{
polymorphic_allocator<int> a;
BOOST_TEST(a.resource() == get_default_resource());
}
void test_resource_constructor()
{
polymorphic_allocator<int> a(0);
BOOST_TEST(a.resource() == get_default_resource());
derived_from_memory_resource d;
polymorphic_allocator<int> b(&d);
BOOST_TEST(&d == b.resource());
}
void test_copy_constructor()
{
derived_from_memory_resource d;
polymorphic_allocator<int> b(&d);
polymorphic_allocator<int> c(b);
BOOST_TEST(b.resource() == c.resource());
}
void test_copy_assignment()
{
derived_from_memory_resource d;
polymorphic_allocator<int> b(&d);
polymorphic_allocator<int> c;
BOOST_TEST(c.resource() == get_default_resource());
c = b;
BOOST_TEST(c.resource() == b.resource());
}
void test_allocate()
{
int dummy;
derived_from_memory_resource d;
polymorphic_allocator<int> p(&d);
d.reset();
d.do_allocate_return = &dummy;
p.allocate(2);
BOOST_TEST(d.do_allocate_called == true);
BOOST_TEST(d.do_allocate_return == &dummy);
//It shall allocate 2*sizeof(int), alignment_of<int>
BOOST_TEST(d.do_allocate_bytes == 2*sizeof(int));
BOOST_TEST(d.do_allocate_alignment == container_detail::alignment_of<int>::value);
}
void test_deallocate()
{
int dummy;
derived_from_memory_resource d;
polymorphic_allocator<int> p(&d);
d.reset();
p.deallocate(&dummy, 3);
BOOST_TEST(d.do_deallocate_called == true);
//It shall deallocate 2*sizeof(int), alignment_of<int>
BOOST_TEST(d.do_deallocate_p == &dummy);
BOOST_TEST(d.do_deallocate_bytes == 3*sizeof(int));
BOOST_TEST(d.do_deallocate_alignment == container_detail::alignment_of<int>::value);
}
void test_construct()
{
//0 arg
{
typedef allocator_argument_tester<NotUsesAllocator, 0> value_type;
value_type value;
value.~value_type();
polymorphic_allocator<int> pa;
pa.construct(&value);
BOOST_TEST(value.construction_type == NotUsesAllocator);
BOOST_TEST(value.value == 0);
value.~value_type();
}
{
typedef allocator_argument_tester<ErasedTypePrefix, 0> value_type;
value_type value;
value.~value_type();
polymorphic_allocator<int> pa;
pa.construct(&value);
BOOST_TEST(value.construction_type == ConstructiblePrefix);
BOOST_TEST(value.value == 0);
value.~value_type();
}
{
typedef allocator_argument_tester<ErasedTypeSuffix, 0> value_type;
value_type value;
value.~value_type();
polymorphic_allocator<int> pa;
pa.construct(&value);
BOOST_TEST(value.construction_type == ConstructibleSuffix);
BOOST_TEST(value.value == 0);
value.~value_type();
}
//1 arg
{
typedef allocator_argument_tester<NotUsesAllocator, 0> value_type;
value_type value;
value.~value_type();
polymorphic_allocator<int> pa;
pa.construct(&value, 2);
BOOST_TEST(value.construction_type == NotUsesAllocator);
BOOST_TEST(value.value == 2);
value.~value_type();
}
{
typedef allocator_argument_tester<ErasedTypePrefix, 0> value_type;
value_type value;
value.~value_type();
polymorphic_allocator<int> pa;
pa.construct(&value, 3);
BOOST_TEST(value.construction_type == ConstructiblePrefix);
BOOST_TEST(value.value == 3);
value.~value_type();
}
{
typedef allocator_argument_tester<ErasedTypeSuffix, 0> value_type;
value_type value;
value.~value_type();
polymorphic_allocator<int> pa;
pa.construct(&value, 4);
BOOST_TEST(value.construction_type == ConstructibleSuffix);
BOOST_TEST(value.value == 4);
value.~value_type();
}
}
struct char_holder
{
char m_char;
~char_holder()
{ destructor_called = true; }
static bool destructor_called;
};
bool char_holder::destructor_called = false;
void test_destroy()
{
char_holder ch;
polymorphic_allocator<int> p;
BOOST_TEST(char_holder::destructor_called == false);
p.destroy(&ch);
BOOST_TEST(char_holder::destructor_called == true);
}
void test_select_on_container_copy_construction()
{
//select_on_container_copy_construction shall return
//a default constructed polymorphic_allocator
//which uses the default resource.
derived_from_memory_resource d;
polymorphic_allocator<int> p(&d);
BOOST_TEST(get_default_resource() == p.select_on_container_copy_construction().resource());
}
void test_resource()
{
derived_from_memory_resource d;
polymorphic_allocator<int> p(&d);
BOOST_TEST(&d == p.resource());
}
int main()
{
test_default_constructor();
test_resource_constructor();
test_copy_constructor();
test_copy_assignment();
test_allocate();
test_deallocate();
test_construct();
test_destroy();
test_select_on_container_copy_construction();
test_resource();
return ::boost::report_errors();
}
+493
View File
@@ -0,0 +1,493 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2015-2015. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#include <boost/container/pmr/global_resource.hpp>
#include <boost/core/lightweight_test.hpp>
#include <boost/intrusive/detail/math.hpp>
#include "derived_from_memory_resource.hpp"
#include "memory_resource_logger.hpp"
using namespace boost::container::pmr;
template<class PoolResource>
struct derived_from_pool_resource
: public PoolResource
{
derived_from_pool_resource(const pool_options& opts, memory_resource* upstream)
: PoolResource(opts, upstream)
{}
explicit derived_from_pool_resource(memory_resource *p)
: PoolResource(p)
{}
explicit derived_from_pool_resource(const pool_options &opts)
: PoolResource(opts)
{}
derived_from_pool_resource()
: PoolResource()
{}
using PoolResource::do_allocate;
using PoolResource::do_deallocate;
using PoolResource::do_is_equal;
};
template<class PoolResource>
void test_default_constructor()
{
//With default options/resource
{
derived_from_memory_resource dmr;
dmr.reset();
PoolResource m;
//test postconditions
BOOST_TEST(m.upstream_resource() == get_default_resource());
BOOST_TEST(m.options().max_blocks_per_chunk == pool_options_default_max_blocks_per_chunk);
BOOST_TEST(m.options().largest_required_pool_block == pool_options_default_largest_required_pool_block);
//test it does not allocate any memory
BOOST_TEST(dmr.do_allocate_called == false);
}
}
template<class PoolResource>
void test_upstream_constructor()
{
//With a resource, default options
{
derived_from_memory_resource dmr;
dmr.reset();
PoolResource m(&dmr);
//test postconditions
BOOST_TEST(m.upstream_resource() == &dmr);
BOOST_TEST(m.options().max_blocks_per_chunk == pool_options_default_max_blocks_per_chunk);
BOOST_TEST(m.options().largest_required_pool_block == pool_options_default_largest_required_pool_block);
//test it does not allocate any memory
BOOST_TEST(dmr.do_allocate_called == false);
}
}
template<class PoolResource>
void test_options_constructor()
{
//Default options
{
memory_resource_logger mrl;
BOOST_TEST(mrl.m_info.size() == 0u);
set_default_resource(&mrl);
pool_options opts;
PoolResource m(opts);
//test postconditions
BOOST_TEST(m.upstream_resource() == get_default_resource());
BOOST_TEST(m.options().max_blocks_per_chunk == pool_options_default_max_blocks_per_chunk);
BOOST_TEST(m.options().largest_required_pool_block == pool_options_default_largest_required_pool_block);
//test it does not allocate any memory
BOOST_TEST(mrl.m_info.size() == 0u);
}
//Too large option values
{
memory_resource_logger mrl;
BOOST_TEST(mrl.m_info.size() == 0u);
set_default_resource(&mrl);
pool_options opts;
opts.max_blocks_per_chunk = pool_options_default_max_blocks_per_chunk+1;
opts.largest_required_pool_block = pool_options_default_largest_required_pool_block+1;
PoolResource m(opts);
//test postconditions
BOOST_TEST(m.upstream_resource() == get_default_resource());
BOOST_TEST(m.options().max_blocks_per_chunk == pool_options_default_max_blocks_per_chunk);
BOOST_TEST(m.options().largest_required_pool_block == pool_options_default_largest_required_pool_block);
//test it does not allocate any memory
BOOST_TEST(mrl.m_info.size() == 0u);
}
//Too small option values
{
memory_resource_logger mrl;
BOOST_TEST(mrl.m_info.size() == 0u);
set_default_resource(&mrl);
pool_options opts;
opts.largest_required_pool_block = pool_options_minimum_largest_required_pool_block-1u;
PoolResource m(opts);
//test postconditions
BOOST_TEST(m.upstream_resource() == get_default_resource());
BOOST_TEST(m.options().max_blocks_per_chunk == pool_options_default_max_blocks_per_chunk);
BOOST_TEST(m.options().largest_required_pool_block == pool_options_minimum_largest_required_pool_block);
//test it does not allocate any memory
BOOST_TEST(mrl.m_info.size() == 0u);
}
//In range option values
{
memory_resource_logger mrl;
BOOST_TEST(mrl.m_info.size() == 0u);
set_default_resource(&mrl);
pool_options opts;
opts.max_blocks_per_chunk = pool_options_default_max_blocks_per_chunk;
opts.largest_required_pool_block = pool_options_minimum_largest_required_pool_block;
PoolResource m(opts);
//test postconditions
BOOST_TEST(m.upstream_resource() == get_default_resource());
BOOST_TEST(m.options().max_blocks_per_chunk == pool_options_default_max_blocks_per_chunk);
BOOST_TEST(m.options().largest_required_pool_block == pool_options_minimum_largest_required_pool_block);
//test it does not allocate any memory
BOOST_TEST(mrl.m_info.size() == 0u);
}
}
template<class PoolResource>
void test_options_upstream_constructor()
{
//Default options
{
derived_from_memory_resource dmr;
dmr.reset();
pool_options opts;
PoolResource m(opts, &dmr);
//test postconditions
BOOST_TEST(m.upstream_resource() == &dmr);
BOOST_TEST(m.options().max_blocks_per_chunk == pool_options_default_max_blocks_per_chunk);
BOOST_TEST(m.options().largest_required_pool_block == pool_options_default_largest_required_pool_block);
//test it does not allocate any memory
BOOST_TEST(dmr.do_allocate_called == false);
}
//Too large option values
{
derived_from_memory_resource dmr;
dmr.reset();
pool_options opts;
opts.max_blocks_per_chunk = pool_options_default_max_blocks_per_chunk+1;
opts.largest_required_pool_block = pool_options_default_largest_required_pool_block+1;
PoolResource m(opts, &dmr);
//test postconditions
BOOST_TEST(m.upstream_resource() == &dmr);
BOOST_TEST(m.options().max_blocks_per_chunk == pool_options_default_max_blocks_per_chunk);
BOOST_TEST(m.options().largest_required_pool_block == pool_options_default_largest_required_pool_block);
//test it does not allocate any memory
BOOST_TEST(dmr.do_allocate_called == false);
}
//Too small option values
{
derived_from_memory_resource dmr;
dmr.reset();
pool_options opts;
opts.largest_required_pool_block = pool_options_minimum_largest_required_pool_block-1u;
PoolResource m(opts, &dmr);
//test postconditions
BOOST_TEST(m.upstream_resource() == &dmr);
BOOST_TEST(m.options().max_blocks_per_chunk == pool_options_default_max_blocks_per_chunk);
BOOST_TEST(m.options().largest_required_pool_block == pool_options_minimum_largest_required_pool_block);
//test it does not allocate any memory
BOOST_TEST(dmr.do_allocate_called == false);
}
//In range option values
{
derived_from_memory_resource dmr;
dmr.reset();
pool_options opts;
opts.max_blocks_per_chunk = pool_options_default_max_blocks_per_chunk;
opts.largest_required_pool_block = pool_options_minimum_largest_required_pool_block;
PoolResource m(opts, &dmr);
//test postconditions
BOOST_TEST(m.upstream_resource() == &dmr);
//max blocks is unchanged in this implementation
BOOST_TEST(m.options().max_blocks_per_chunk == pool_options_default_max_blocks_per_chunk);
//largest block is rounded to pow2
BOOST_TEST(m.options().largest_required_pool_block == bi::detail::ceil_pow2(opts.largest_required_pool_block));
//test it does not allocate any memory
BOOST_TEST(dmr.do_allocate_called == false);
}
}
template<class PoolResource>
void test_options()
{
//In range option values
{
derived_from_memory_resource dmr;
dmr.reset();
pool_options opts;
opts.max_blocks_per_chunk = pool_options_default_max_blocks_per_chunk/2u;
opts.largest_required_pool_block = (pool_options_default_largest_required_pool_block
- pool_options_minimum_largest_required_pool_block) | std::size_t(1); //guaranteed to be non power of 2.
PoolResource m(opts, &dmr);
//test postconditions
BOOST_TEST(m.upstream_resource() == &dmr);
//max blocks is unchanged in this implementation
BOOST_TEST(m.options().max_blocks_per_chunk == opts.max_blocks_per_chunk);
//largest block is rounded to pow2
BOOST_TEST(m.options().largest_required_pool_block == bi::detail::ceil_pow2(opts.largest_required_pool_block));
//test it does not allocate any memory
BOOST_TEST(dmr.do_allocate_called == false);
}
}
template<class PoolResource>
void test_do_allocate_deallocate()
{
memory_resource_logger mrl;
{
derived_from_pool_resource<PoolResource> dmbr(&mrl);
{
//First block from pool 0
dmbr.do_allocate(1, 1);
//It should allocate the pool array plus an initial block
BOOST_TEST(mrl.m_info.size() == 2u);
//Second block from pool 0
dmbr.do_allocate(1, 1);
//It should allocate again (with 2 chunks per block)
BOOST_TEST(mrl.m_info.size() == 3u);
//Third block from pool 0
dmbr.do_allocate(1, 1);
//It should NOT allocate again (previous was a 2 block chunk)
BOOST_TEST(mrl.m_info.size() == 3u);
}
}
BOOST_TEST(mrl.m_mismatches == 0u);
BOOST_TEST(mrl.m_info.size() == 0u);
//Allocate and deallocate from the same chunk to test block caching
{
derived_from_pool_resource<PoolResource> dmbr(&mrl);
{
//First block from pool 0
void *p = dmbr.do_allocate(1, 1);
//It should allocate the pool array plus an initial block
BOOST_TEST(mrl.m_info.size() == 2u);
//No cached, as initial blocks per chunk is 1
BOOST_TEST(dmbr.pool_cached_blocks(0u) == 0u);
//Deallocate and allocate again
dmbr.do_deallocate(p, 1, 1);
//Cached
BOOST_TEST(dmbr.pool_cached_blocks(0u) == 1u);
p = dmbr.do_allocate(1, 1);
//Reused
BOOST_TEST(dmbr.pool_cached_blocks(0u) == 0u);
//It should have NOT allocated (block reuse)
BOOST_TEST(mrl.m_info.size() == 2u);
//Allocate again 2 times (a 2 block chunk is exhausted)
void *p2 = dmbr.do_allocate(1, 1);
//1 left cached
BOOST_TEST(dmbr.pool_cached_blocks(0u) == 1u);
void *p3 = dmbr.do_allocate(1, 1);
//Cache exhausted
BOOST_TEST(dmbr.pool_cached_blocks(0u) == 0u);
//Single chunk allocation happened
BOOST_TEST(mrl.m_info.size() == 3u);
//Now deallocate all (no memory is freed, all cached)
dmbr.do_deallocate(p2, 1, 1);
dmbr.do_deallocate(p3, 1, 1);
dmbr.do_deallocate(p, 1, 1);
BOOST_TEST(dmbr.pool_cached_blocks(0u) == 3u);
BOOST_TEST(mrl.m_info.size() == 3u);
}
}
BOOST_TEST(mrl.m_mismatches == 0u);
BOOST_TEST(mrl.m_info.size() == 0u);
//Now test max block per chunk
{
pool_options opts;
//so after max_blocks_per_chunk*2-1 allocations, all new chunks must hold max_blocks_per_chunk blocks
opts.max_blocks_per_chunk = 32u;
derived_from_pool_resource<PoolResource> dmbr(opts, &mrl);
{
std::size_t loops = opts.max_blocks_per_chunk*2-1u;
while(loops--){
dmbr.do_allocate(1, 1);
}
//pool array + log2(max_blocks_per_chunk)+1 chunks (sizes [1, 2, 4, ...])
const std::size_t num_chunks = bi::detail::floor_log2(opts.max_blocks_per_chunk)+1u;
BOOST_TEST(mrl.m_info.size() == 1u + num_chunks);
//Next allocation should allocate max_blocks_per_chunk blocks in a chunk so max_blocks_per_chunk-1 should remain free
dmbr.do_allocate(1, 1);
BOOST_TEST(mrl.m_info.size() == 1u + num_chunks + 1u);
BOOST_TEST(dmbr.pool_cached_blocks(0u) == (opts.max_blocks_per_chunk-1u));
//Exhaust the chunk and allocate a new one, test max_blocks_per_chunk is not passed again
loops = opts.max_blocks_per_chunk;
while(loops--){
dmbr.do_allocate(1, 1);
}
BOOST_TEST(mrl.m_info.size() == 1u + num_chunks + 2u);
BOOST_TEST(dmbr.pool_cached_blocks(0u) == (opts.max_blocks_per_chunk-1u));
}
}
BOOST_TEST(mrl.m_mismatches == 0u);
BOOST_TEST(mrl.m_info.size() == 0u);
//Now test max block per chunk
{
pool_options opts;
//so after max_blocks_per_chunk*2-1 allocations, all new chunks must hold max_blocks_per_chunk blocks
opts.max_blocks_per_chunk = 32u;
derived_from_pool_resource<PoolResource> dmbr(opts, &mrl);
{
std::size_t loops = opts.max_blocks_per_chunk*2-1u;
while(loops--){
dmbr.do_allocate(1, 1);
}
//pool array + log2(max_blocks_per_chunk)+1 chunks (sizes [1, 2, 4, ...])
BOOST_TEST(dmbr.pool_next_blocks_per_chunk(0u) == opts.max_blocks_per_chunk);
const std::size_t num_chunks = bi::detail::floor_log2(opts.max_blocks_per_chunk)+1u;
BOOST_TEST(mrl.m_info.size() == 1u + num_chunks);
//Next allocation should allocate max_blocks_per_chunk blocks in a chunk so max_blocks_per_chunk-1 should remain free
dmbr.do_allocate(1, 1);
BOOST_TEST(dmbr.pool_next_blocks_per_chunk(0u) == opts.max_blocks_per_chunk);
BOOST_TEST(mrl.m_info.size() == 1u + num_chunks + 1u);
BOOST_TEST(dmbr.pool_cached_blocks(0u) == (opts.max_blocks_per_chunk-1u));
}
}
BOOST_TEST(mrl.m_mismatches == 0u);
BOOST_TEST(mrl.m_info.size() == 0u);
//Now test different pool sizes
{
pool_options opts;
//so after max_blocks_per_chunk*2-1 allocations, all new chunks must hold max_blocks_per_chunk blocks
opts.max_blocks_per_chunk = 1u;
derived_from_pool_resource<PoolResource> dmbr(opts, &mrl);
const pool_options &final_opts = dmbr.options();
//Force pool creation
dmbr.do_deallocate(dmbr.do_allocate(1, 1), 1, 1);
//pool array plus first pool's chunk allocation
BOOST_TEST(mrl.m_info.size() == 2u);
//pool count must be:
// log2(the maximum block) - log2(the minimum block) + 1. Example if minimum block is 8, and maximum 32:
// log(32) - log2(8) + 1u = 3 pools (block sizes: 8, 16, and 32)
const std::size_t minimum_size = dmbr.pool_block(0u);
const std::size_t maximum_size = final_opts.largest_required_pool_block;
BOOST_TEST(dmbr.pool_count() == (1u + bi::detail::floor_log2(maximum_size) - bi::detail::floor_log2(minimum_size)));
for(std::size_t i = 0, s = minimum_size, max = dmbr.pool_count(); i != max; ++i, s*=2){
//Except in the first pool, each cache should be empty
BOOST_TEST(dmbr.pool_cached_blocks(i) == std::size_t(i == 0));
dmbr.do_deallocate(dmbr.do_allocate(s/2+1, 1), s/2+1, 1);
dmbr.do_deallocate(dmbr.do_allocate(s-1, 1), s-1, 1);
dmbr.do_deallocate(dmbr.do_allocate(s, 1), s, 1);
//pool array plus each previous chunk allocation
BOOST_TEST(mrl.m_info.size() == (1u + i + 1u));
//as we limited max_blocks_per_chunk to 1, no cached blocks should be available except one
BOOST_TEST(dmbr.pool_cached_blocks(i) == 1u);
}
//Now test out of maximum values, which should go directly to upstream
//it should be directly deallocated.
void *p = dmbr.do_allocate(maximum_size+1, 1);
BOOST_TEST(mrl.m_info.size() == (1u + dmbr.pool_count() + 1u));
dmbr.do_deallocate(p, maximum_size+1, 1);
BOOST_TEST(mrl.m_info.size() == (1u + dmbr.pool_count()));
}
BOOST_TEST(mrl.m_mismatches == 0u);
BOOST_TEST(mrl.m_info.size() == 0u);
}
template<class PoolResource>
void test_do_is_equal()
{
//`this == dynamic_cast<const PoolResource*>(&other)`.
memory_resource_logger mrl;
derived_from_pool_resource<PoolResource> dmbr(&mrl);
derived_from_pool_resource<PoolResource> dmbr2(&mrl);
BOOST_TEST(true == dmbr.do_is_equal(dmbr));
BOOST_TEST(false == dmbr.do_is_equal(dmbr2));
//A different type should be always different
derived_from_memory_resource dmr;
BOOST_TEST(false == dmbr.do_is_equal(dmr));
}
template<class PoolResource>
void test_release()
{
memory_resource_logger mrl;
{
pool_options opts;
//so after max_blocks_per_chunk*2-1 allocations, all new chunks must hold max_blocks_per_chunk blocks
opts.max_blocks_per_chunk = 4u;
derived_from_pool_resource<PoolResource> dmbr(opts, &mrl);
const pool_options &final_opts = dmbr.options();
const std::size_t minimum_size = dmbr.pool_block(0u);
const std::size_t maximum_size = final_opts.largest_required_pool_block;
const std::size_t pool_count = 1u + bi::detail::floor_log2(maximum_size) - bi::detail::floor_log2(minimum_size);
std::size_t expected_memory_allocs = 0;
for(std::size_t i = 0, imax = pool_count, s = minimum_size; i != imax; s*=2, ++i){
for(std::size_t j = 0, j_max = opts.max_blocks_per_chunk*2u-1u; j != j_max; ++j){
dmbr.do_allocate(s, 1);
}
//One due to the pool array, and for each pool, log2(max_blocks_per_chunk)+1 allocations
expected_memory_allocs = 1 + (bid::floor_log2(opts.max_blocks_per_chunk) + 1u)*(i+1);
//pool array plus each previous chunk allocation
BOOST_TEST(mrl.m_info.size() == expected_memory_allocs);
}
//Now with out-of-pool sizes
for(std::size_t j = 0, j_max = opts.max_blocks_per_chunk*2u-1u; j != j_max; ++j){
dmbr.do_allocate(maximum_size+1, 1);
BOOST_TEST(mrl.m_info.size() == ++expected_memory_allocs);
}
//Now release memory and check all memory allocated through do_allocate was deallocated to upstream
dmbr.release();
BOOST_TEST(mrl.m_info.size() == 1u);
}
BOOST_TEST(mrl.m_mismatches == 0u);
BOOST_TEST(mrl.m_info.size() == 0u);
}
template<class PoolResource>
void test_destructor()
{
memory_resource_logger mrl;
{
pool_options opts;
//so after max_blocks_per_chunk*2-1 allocations, all new chunks must hold max_blocks_per_chunk blocks
opts.max_blocks_per_chunk = 4u;
derived_from_pool_resource<PoolResource> dmbr(opts, &mrl);
const pool_options &final_opts = dmbr.options();
const std::size_t minimum_size = dmbr.pool_block(0u);
const std::size_t maximum_size = final_opts.largest_required_pool_block;
const std::size_t pool_count = 1u + bi::detail::floor_log2(maximum_size) - bi::detail::floor_log2(minimum_size);
std::size_t expected_memory_allocs = 0;
for(std::size_t i = 0, imax = pool_count, s = minimum_size; i != imax; s*=2, ++i){
for(std::size_t j = 0, j_max = opts.max_blocks_per_chunk*2u-1u; j != j_max; ++j){
dmbr.do_allocate(s, 1);
}
//One due to the pool array, and for each pool, log2(max_blocks_per_chunk)+1 allocations
expected_memory_allocs = 1 + (bid::floor_log2(opts.max_blocks_per_chunk) + 1u)*(i+1);
//pool array plus each previous chunk allocation
BOOST_TEST(mrl.m_info.size() == expected_memory_allocs);
}
//Now with out-of-pool sizes
for(std::size_t j = 0, j_max = opts.max_blocks_per_chunk*2u-1u; j != j_max; ++j){
dmbr.do_allocate(maximum_size+1, 1);
BOOST_TEST(mrl.m_info.size() == ++expected_memory_allocs);
}
//Don't release, all memory, including internal allocations, should be automatically
//after the destructor is run
}
BOOST_TEST(mrl.m_mismatches == 0u);
BOOST_TEST(mrl.m_info.size() == 0u);
}
template<class PoolResource>
void test_pool_resource()
{
test_options_upstream_constructor<PoolResource>();
test_default_constructor<PoolResource>();
test_upstream_constructor<PoolResource>();
test_options_constructor<PoolResource>();
test_options<PoolResource>();
test_do_allocate_deallocate<PoolResource>();
test_do_is_equal<PoolResource>();
test_release<PoolResource>();
test_destructor<PoolResource>();
}
+268
View File
@@ -0,0 +1,268 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2015-2015. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_CONTAINER_TEST_ALLOCATOR_ARGUMENT_TESTER_HPP
#define BOOST_CONTAINER_TEST_ALLOCATOR_ARGUMENT_TESTER_HPP
#include <boost/container/uses_allocator.hpp>
#include <boost/container/detail/mpl.hpp>
#include <boost/move/core.hpp>
#include <boost/container/pmr/polymorphic_allocator.hpp>
template<class T, unsigned int Id, bool HasTrueTypes = false>
class propagation_test_allocator
{
BOOST_COPYABLE_AND_MOVABLE(propagation_test_allocator)
public:
template<class U>
struct rebind
{
typedef propagation_test_allocator<U, Id, HasTrueTypes> other;
};
typedef boost::container::container_detail::bool_<HasTrueTypes> propagate_on_container_copy_assignment;
typedef boost::container::container_detail::bool_<HasTrueTypes> propagate_on_container_move_assignment;
typedef boost::container::container_detail::bool_<HasTrueTypes> propagate_on_container_swap;
typedef boost::container::container_detail::bool_<HasTrueTypes> is_always_equal;
typedef T value_type;
propagation_test_allocator()
: m_default_contructed(true), m_move_contructed(false), m_move_assigned(false)
{}
propagation_test_allocator(const propagation_test_allocator&)
: m_default_contructed(false), m_move_contructed(false), m_move_assigned(false)
{}
propagation_test_allocator(BOOST_RV_REF(propagation_test_allocator) )
: m_default_contructed(false), m_move_contructed(true), m_move_assigned(false)
{}
template<class U>
propagation_test_allocator(BOOST_RV_REF_BEG propagation_test_allocator<U, Id, HasTrueTypes> BOOST_RV_REF_END)
: m_default_contructed(false), m_move_contructed(true), m_move_assigned(false)
{}
template<class U>
propagation_test_allocator(const propagation_test_allocator<U, Id, HasTrueTypes> &)
{}
propagation_test_allocator & operator=(BOOST_COPY_ASSIGN_REF(propagation_test_allocator))
{ return *this; }
propagation_test_allocator & operator=(BOOST_RV_REF(propagation_test_allocator))
{
m_move_assigned = true;
return *this;
}
std::size_t max_size() const
{ return std::size_t(-1); }
T* allocate(std::size_t n)
{ return (T*)::new char[n*sizeof(T)]; }
void deallocate(T*p, std::size_t)
{ delete []static_cast<char*>(static_cast<void*>(p)); }
bool m_default_contructed;
bool m_move_contructed;
bool m_move_assigned;
};
template <class T1, class T2, unsigned int Id, bool HasTrueTypes>
bool operator==( const propagation_test_allocator<T1, Id, HasTrueTypes>&
, const propagation_test_allocator<T2, Id, HasTrueTypes>&)
{ return true; }
template <class T1, class T2, unsigned int Id, bool HasTrueTypes>
bool operator!=( const propagation_test_allocator<T1, Id, HasTrueTypes>&
, const propagation_test_allocator<T2, Id, HasTrueTypes>&)
{ return false; }
//This enum lists the construction options
//for an allocator-aware type
enum ConstructionTypeEnum
{
ConstructiblePrefix,
ConstructibleSuffix,
ErasedTypePrefix,
ErasedTypeSuffix,
NotUsesAllocator
};
//This base class provices types for
//the derived class to implement each construction
//type. If a construction type does not apply
//the typedef is set to an internal nat
//so that the class is not constructible from
//the user arguments.
template<ConstructionTypeEnum ConstructionType, unsigned int AllocatorTag>
struct uses_allocator_base;
template<unsigned int AllocatorTag>
struct uses_allocator_base<ConstructibleSuffix, AllocatorTag>
{
typedef propagation_test_allocator<int, AllocatorTag> allocator_type;
typedef allocator_type allocator_constructor_type;
struct nat{};
typedef nat allocator_arg_type;
};
template<unsigned int AllocatorTag>
struct uses_allocator_base<ConstructiblePrefix, AllocatorTag>
{
typedef propagation_test_allocator<int, AllocatorTag> allocator_type;
typedef allocator_type allocator_constructor_type;
typedef boost::container::allocator_arg_t allocator_arg_type;
};
template<unsigned int AllocatorTag>
struct uses_allocator_base<ErasedTypePrefix, AllocatorTag>
{
typedef boost::container::erased_type allocator_type;
typedef boost::container::pmr::polymorphic_allocator<int> allocator_constructor_type;
typedef boost::container::allocator_arg_t allocator_arg_type;
};
template<unsigned int AllocatorTag>
struct uses_allocator_base<ErasedTypeSuffix, AllocatorTag>
{
typedef boost::container::erased_type allocator_type;
typedef boost::container::pmr::polymorphic_allocator<int> allocator_constructor_type;
struct nat{};
typedef nat allocator_arg_type;
};
template<unsigned int AllocatorTag>
struct uses_allocator_base<NotUsesAllocator, AllocatorTag>
{
struct nat{};
typedef nat allocator_constructor_type;
typedef nat allocator_arg_type;
};
template<ConstructionTypeEnum ConstructionType, unsigned int AllocatorTag>
struct allocator_argument_tester
: uses_allocator_base<ConstructionType, AllocatorTag>
{
private:
BOOST_COPYABLE_AND_MOVABLE(allocator_argument_tester)
public:
typedef uses_allocator_base<ConstructionType, AllocatorTag> base_type;
//0 user argument constructors
allocator_argument_tester()
: construction_type(NotUsesAllocator), value(0)
{}
explicit allocator_argument_tester
(typename base_type::allocator_constructor_type)
: construction_type(ConstructibleSuffix), value(0)
{}
explicit allocator_argument_tester
(typename base_type::allocator_arg_type, typename base_type::allocator_constructor_type)
: construction_type(ConstructiblePrefix), value(0)
{}
//1 user argument constructors
explicit allocator_argument_tester(int i)
: construction_type(NotUsesAllocator), value(i)
{}
allocator_argument_tester
(int i, typename base_type::allocator_constructor_type)
: construction_type(ConstructibleSuffix), value(i)
{}
allocator_argument_tester
( typename base_type::allocator_arg_type
, typename base_type::allocator_constructor_type
, int i)
: construction_type(ConstructiblePrefix), value(i)
{}
//Copy constructors
allocator_argument_tester(const allocator_argument_tester &other)
: construction_type(NotUsesAllocator), value(other.value)
{}
allocator_argument_tester( const allocator_argument_tester &other
, typename base_type::allocator_constructor_type)
: construction_type(ConstructibleSuffix), value(other.value)
{}
allocator_argument_tester( typename base_type::allocator_arg_type
, typename base_type::allocator_constructor_type
, const allocator_argument_tester &other)
: construction_type(ConstructiblePrefix), value(other.value)
{}
//Move constructors
allocator_argument_tester(BOOST_RV_REF(allocator_argument_tester) other)
: construction_type(NotUsesAllocator), value(other.value)
{ other.value = 0; other.construction_type = NotUsesAllocator; }
allocator_argument_tester( BOOST_RV_REF(allocator_argument_tester) other
, typename base_type::allocator_constructor_type)
: construction_type(ConstructibleSuffix), value(other.value)
{ other.value = 0; other.construction_type = ConstructibleSuffix; }
allocator_argument_tester( typename base_type::allocator_arg_type
, typename base_type::allocator_constructor_type
, BOOST_RV_REF(allocator_argument_tester) other)
: construction_type(ConstructiblePrefix), value(other.value)
{ other.value = 0; other.construction_type = ConstructiblePrefix; }
ConstructionTypeEnum construction_type;
int value;
};
namespace boost {
namespace container {
template<unsigned int AllocatorTag>
struct constructible_with_allocator_prefix
< ::allocator_argument_tester<ConstructiblePrefix, AllocatorTag> >
{
static const bool value = true;
};
template<unsigned int AllocatorTag>
struct constructible_with_allocator_prefix
< ::allocator_argument_tester<ErasedTypePrefix, AllocatorTag> >
{
static const bool value = true;
};
template<unsigned int AllocatorTag>
struct constructible_with_allocator_suffix
< ::allocator_argument_tester<ConstructibleSuffix, AllocatorTag> >
{
static const bool value = true;
};
template<unsigned int AllocatorTag>
struct constructible_with_allocator_suffix
< ::allocator_argument_tester<ErasedTypeSuffix, AllocatorTag> >
{
static const bool value = true;
};
} //namespace container {
} //namespace boost {
#endif //BOOST_CONTAINER_TEST_ALLOCATOR_ARGUMENT_TESTER_HPP
+186
View File
@@ -0,0 +1,186 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2015-2015. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#include <boost/container/pmr/resource_adaptor.hpp>
#include <boost/core/lightweight_test.hpp>
#include "propagation_test_allocator.hpp"
#include "derived_from_memory_resource.hpp"
using namespace boost::container::pmr;
void test_default_constructor()
{
typedef propagation_test_allocator<char, 0> alloc_t;
resource_adaptor<alloc_t> ra;
BOOST_TEST(ra.get_allocator().m_default_contructed == true);
}
void test_copy_constructor()
{
typedef propagation_test_allocator<char, 0> alloc_t;
resource_adaptor<alloc_t> ra;
BOOST_TEST(ra.get_allocator().m_default_contructed == true);
resource_adaptor<alloc_t> rb(ra);
BOOST_TEST(rb.get_allocator().m_default_contructed == false);
BOOST_TEST(rb.get_allocator().m_move_contructed == false);
}
void test_move_constructor()
{
typedef propagation_test_allocator<char, 0> alloc_t;
resource_adaptor<alloc_t> ra;
BOOST_TEST(ra.get_allocator().m_default_contructed == true);
resource_adaptor<alloc_t> rb(::boost::move(ra));
BOOST_TEST(rb.get_allocator().m_default_contructed == false);
BOOST_TEST(rb.get_allocator().m_move_contructed == true);
}
void test_lvalue_alloc_constructor()
{
typedef propagation_test_allocator<char, 0> alloc_t;
alloc_t a;
resource_adaptor<alloc_t> ra(a);
BOOST_TEST(ra.get_allocator().m_default_contructed == false);
BOOST_TEST(ra.get_allocator().m_move_contructed == false);
}
void test_rvalue_alloc_constructor()
{
typedef propagation_test_allocator<char, 0> alloc_t;
alloc_t a;
resource_adaptor<alloc_t> ra(::boost::move(a));
BOOST_TEST(ra.get_allocator().m_default_contructed == false);
BOOST_TEST(ra.get_allocator().m_move_contructed == true);
}
void test_copy_assign()
{
typedef propagation_test_allocator<char, 0> alloc_t;
resource_adaptor<alloc_t> ra;
BOOST_TEST(ra.get_allocator().m_default_contructed == true);
resource_adaptor<alloc_t> rb;
BOOST_TEST(ra.get_allocator().m_default_contructed == true);
rb = ra;
BOOST_TEST(rb.get_allocator().m_move_contructed == false);
BOOST_TEST(rb.get_allocator().m_move_assigned == false);
}
void test_move_assign()
{
typedef propagation_test_allocator<char, 0> alloc_t;
resource_adaptor<alloc_t> ra;
BOOST_TEST(ra.get_allocator().m_default_contructed == true);
resource_adaptor<alloc_t> rb;
BOOST_TEST(ra.get_allocator().m_default_contructed == true);
rb = ::boost::move(ra);
BOOST_TEST(rb.get_allocator().m_move_contructed == false);
BOOST_TEST(rb.get_allocator().m_move_assigned == true);
}
struct stateful
{
public:
typedef char value_type;
template<class U>
struct rebind
{ typedef stateful other; };
char *allocate(std::size_t n)
{ allocate_size = n; return allocate_return; }
void deallocate(char *p, std::size_t n)
{ deallocate_p = p; deallocate_size = n; }
friend bool operator==(const stateful &l, const stateful &r)
{ return l.m_u == r.m_u; }
friend bool operator!=(const stateful &l, const stateful &r)
{ return l.m_u != r.m_u; }
public:
unsigned m_u;
std::size_t allocate_size;
char *allocate_return;
std::size_t deallocate_size;
char *deallocate_p;
};
void test_get_allocator()
{
stateful a;
a.m_u = 999;
resource_adaptor<stateful> ra(a);
const resource_adaptor<stateful> & cra = ra;
BOOST_TEST( ra.get_allocator().m_u == 999);
BOOST_TEST(cra.get_allocator().m_u == 999);
}
typedef resource_adaptor<stateful> stateful_resource_adaptor_t;
struct derived_from_resource_adaptor_stateful
: public stateful_resource_adaptor_t
{
public:
typedef stateful_resource_adaptor_t base_t;
using base_t::do_allocate;
using base_t::do_deallocate;
using base_t::do_is_equal;
};
void test_do_allocate()
{
derived_from_resource_adaptor_stateful dra;
char dummy = 0;
dra.get_allocator().allocate_return = &dummy;
void *allocate_ret = dra.do_allocate(998, 1234);
BOOST_TEST(allocate_ret == &dummy);
BOOST_TEST(dra.get_allocator().allocate_size == 998);
}
void test_do_deallocate()
{
derived_from_resource_adaptor_stateful dra;
char dummy = 0;
dra.do_deallocate(&dummy, 1234, 753);
BOOST_TEST(dra.get_allocator().deallocate_p == &dummy);
BOOST_TEST(dra.get_allocator().deallocate_size == 1234);
}
void test_do_is_equal()
{
derived_from_resource_adaptor_stateful dra;
derived_from_memory_resource dmr;
//Different dynamic type must return false
BOOST_TEST(dra.do_is_equal(dmr) == false);
//Same dynamic type with same state must return true
derived_from_resource_adaptor_stateful dra2;
BOOST_TEST(dra.do_is_equal(dra2) == true);
//Same dynamic type with different state must return false
dra2.get_allocator().m_u = 1234;
BOOST_TEST(dra.do_is_equal(dra2) == false);
}
int main()
{
test_default_constructor();
test_copy_constructor();
test_move_constructor();
test_lvalue_alloc_constructor();
test_rvalue_alloc_constructor();
test_copy_assign();
test_move_assign();
test_get_allocator();
test_do_allocate();
test_do_deallocate();
test_do_is_equal();
return ::boost::report_errors();
}
+109 -341
View File
@@ -19,81 +19,7 @@
#include <memory>
#include <cstddef>
using namespace boost::container;
template<class T, unsigned int Id, bool HasTrueTypes = false>
class test_allocator
{
BOOST_COPYABLE_AND_MOVABLE(test_allocator)
public:
template<class U>
struct rebind
{
typedef test_allocator<U, Id, HasTrueTypes> other;
};
typedef container_detail::bool_<HasTrueTypes> propagate_on_container_copy_assignment;
typedef container_detail::bool_<HasTrueTypes> propagate_on_container_move_assignment;
typedef container_detail::bool_<HasTrueTypes> propagate_on_container_swap;
typedef container_detail::bool_<HasTrueTypes> is_always_equal;
typedef T value_type;
test_allocator()
: m_move_contructed(false), m_move_assigned(false)
{}
test_allocator(const test_allocator&)
: m_move_contructed(false), m_move_assigned(false)
{}
test_allocator(BOOST_RV_REF(test_allocator) )
: m_move_contructed(true), m_move_assigned(false)
{}
template<class U>
test_allocator(BOOST_RV_REF_BEG test_allocator<U, Id, HasTrueTypes> BOOST_RV_REF_END)
: m_move_contructed(true), m_move_assigned(false)
{}
template<class U>
test_allocator(const test_allocator<U, Id, HasTrueTypes> &)
{}
test_allocator & operator=(BOOST_COPY_ASSIGN_REF(test_allocator))
{
return *this;
}
test_allocator & operator=(BOOST_RV_REF(test_allocator))
{
m_move_assigned = true;
return *this;
}
std::size_t max_size() const
{ return std::size_t(-1); }
T* allocate(std::size_t n)
{ return (T*)::new char[n*sizeof(T)]; }
void deallocate(T*p, std::size_t)
{ delete []static_cast<char*>(static_cast<void*>(p)); }
bool m_move_contructed;
bool m_move_assigned;
};
template <class T1, class T2, unsigned int Id, bool HasTrueTypes>
bool operator==( const test_allocator<T1, Id, HasTrueTypes>&
, const test_allocator<T2, Id, HasTrueTypes>&)
{ return true; }
template <class T1, class T2, unsigned int Id, bool HasTrueTypes>
bool operator!=( const test_allocator<T1, Id, HasTrueTypes>&
, const test_allocator<T2, Id, HasTrueTypes>&)
{ return false; }
#include "allocator_argument_tester.hpp"
template<unsigned int Type>
struct tagged_integer
@@ -113,148 +39,6 @@ struct mark_on_destructor
bool destroyed;
};
//This enum lists the construction options
//for an allocator-aware type
enum ConstructionTypeEnum
{
ConstructiblePrefix,
ConstructibleSuffix,
NotUsesAllocator
};
//This base class provices types for
//the derived class to implement each construction
//type. If a construction type does not apply
//the typedef is set to an internal nat
//so that the class is not constructible from
//the user arguments.
template<ConstructionTypeEnum ConstructionType, unsigned int AllocatorTag>
struct uses_allocator_base;
template<unsigned int AllocatorTag>
struct uses_allocator_base<ConstructibleSuffix, AllocatorTag>
{
typedef test_allocator<int, AllocatorTag> allocator_type;
typedef allocator_type allocator_constructor_type;
struct nat{};
typedef nat allocator_arg_type;
};
template<unsigned int AllocatorTag>
struct uses_allocator_base<ConstructiblePrefix, AllocatorTag>
{
typedef test_allocator<int, AllocatorTag> allocator_type;
typedef allocator_type allocator_constructor_type;
typedef allocator_arg_t allocator_arg_type;
};
template<unsigned int AllocatorTag>
struct uses_allocator_base<NotUsesAllocator, AllocatorTag>
{
struct nat{};
typedef nat allocator_constructor_type;
typedef nat allocator_arg_type;
};
template<ConstructionTypeEnum ConstructionType, unsigned int AllocatorTag>
struct mark_on_scoped_allocation
: uses_allocator_base<ConstructionType, AllocatorTag>
{
private:
BOOST_COPYABLE_AND_MOVABLE(mark_on_scoped_allocation)
public:
typedef uses_allocator_base<ConstructionType, AllocatorTag> base_type;
//0 user argument constructors
mark_on_scoped_allocation()
: construction_type(NotUsesAllocator), value(0)
{}
explicit mark_on_scoped_allocation
(typename base_type::allocator_constructor_type)
: construction_type(ConstructibleSuffix), value(0)
{}
explicit mark_on_scoped_allocation
(typename base_type::allocator_arg_type, typename base_type::allocator_constructor_type)
: construction_type(ConstructiblePrefix), value(0)
{}
//1 user argument constructors
explicit mark_on_scoped_allocation(int i)
: construction_type(NotUsesAllocator), value(i)
{}
mark_on_scoped_allocation
(int i, typename base_type::allocator_constructor_type)
: construction_type(ConstructibleSuffix), value(i)
{}
mark_on_scoped_allocation
( typename base_type::allocator_arg_type
, typename base_type::allocator_constructor_type
, int i)
: construction_type(ConstructiblePrefix), value(i)
{}
//Copy constructors
mark_on_scoped_allocation(const mark_on_scoped_allocation &other)
: construction_type(NotUsesAllocator), value(other.value)
{}
mark_on_scoped_allocation( const mark_on_scoped_allocation &other
, typename base_type::allocator_constructor_type)
: construction_type(ConstructibleSuffix), value(other.value)
{}
mark_on_scoped_allocation( typename base_type::allocator_arg_type
, typename base_type::allocator_constructor_type
, const mark_on_scoped_allocation &other)
: construction_type(ConstructiblePrefix), value(other.value)
{}
//Move constructors
mark_on_scoped_allocation(BOOST_RV_REF(mark_on_scoped_allocation) other)
: construction_type(NotUsesAllocator), value(other.value)
{ other.value = 0; other.construction_type = NotUsesAllocator; }
mark_on_scoped_allocation( BOOST_RV_REF(mark_on_scoped_allocation) other
, typename base_type::allocator_constructor_type)
: construction_type(ConstructibleSuffix), value(other.value)
{ other.value = 0; other.construction_type = ConstructibleSuffix; }
mark_on_scoped_allocation( typename base_type::allocator_arg_type
, typename base_type::allocator_constructor_type
, BOOST_RV_REF(mark_on_scoped_allocation) other)
: construction_type(ConstructiblePrefix), value(other.value)
{ other.value = 0; other.construction_type = ConstructiblePrefix; }
ConstructionTypeEnum construction_type;
int value;
};
namespace boost {
namespace container {
template<unsigned int AllocatorTag>
struct constructible_with_allocator_prefix
< ::mark_on_scoped_allocation<ConstructiblePrefix, AllocatorTag> >
{
static const bool value = true;
};
template<unsigned int AllocatorTag>
struct constructible_with_allocator_suffix
< ::mark_on_scoped_allocation<ConstructibleSuffix, AllocatorTag> >
{
static const bool value = true;
};
} //namespace container {
} //namespace boost {
#include <boost/container/scoped_allocator.hpp>
#include <boost/static_assert.hpp>
@@ -263,19 +47,21 @@ struct constructible_with_allocator_suffix
int main()
{
typedef test_allocator<tagged_integer<0>, 0> OuterAlloc;
typedef test_allocator<tagged_integer<0>, 10> Outer10IdAlloc;
typedef test_allocator<tagged_integer<9>, 0> Rebound9OuterAlloc;
typedef test_allocator<tagged_integer<1>, 1> InnerAlloc1;
typedef test_allocator<tagged_integer<2>, 2> InnerAlloc2;
typedef test_allocator<tagged_integer<1>, 11> Inner11IdAlloc1;
using namespace boost::container;
typedef test_allocator<tagged_integer<0>, 0, false> OuterAllocFalseHasTrueTypes;
typedef test_allocator<tagged_integer<0>, 0, true> OuterAllocTrueHasTrueTypes;
typedef test_allocator<tagged_integer<1>, 1, false> InnerAlloc1FalseHasTrueTypes;
typedef test_allocator<tagged_integer<1>, 1, true> InnerAlloc1TrueHasTrueTypes;
typedef test_allocator<tagged_integer<2>, 2, false> InnerAlloc2FalseHasTrueTypes;
typedef test_allocator<tagged_integer<2>, 2, true> InnerAlloc2TrueHasTrueTypes;
typedef propagation_test_allocator<tagged_integer<0>, 0> OuterAlloc;
typedef propagation_test_allocator<tagged_integer<0>, 10> Outer10IdAlloc;
typedef propagation_test_allocator<tagged_integer<9>, 0> Rebound9OuterAlloc;
typedef propagation_test_allocator<tagged_integer<1>, 1> InnerAlloc1;
typedef propagation_test_allocator<tagged_integer<2>, 2> InnerAlloc2;
typedef propagation_test_allocator<tagged_integer<1>, 11> Inner11IdAlloc1;
typedef propagation_test_allocator<tagged_integer<0>, 0, false> OuterAllocFalseHasTrueTypes;
typedef propagation_test_allocator<tagged_integer<0>, 0, true> OuterAllocTrueHasTrueTypes;
typedef propagation_test_allocator<tagged_integer<1>, 1, false> InnerAlloc1FalseHasTrueTypes;
typedef propagation_test_allocator<tagged_integer<1>, 1, true> InnerAlloc1TrueHasTrueTypes;
typedef propagation_test_allocator<tagged_integer<2>, 2, false> InnerAlloc2FalseHasTrueTypes;
typedef propagation_test_allocator<tagged_integer<2>, 2, true> InnerAlloc2TrueHasTrueTypes;
//
typedef scoped_allocator_adaptor< OuterAlloc > Scoped0Inner;
@@ -301,81 +87,81 @@ int main()
, InnerAlloc2 > Rebound9Scoped2Inner;
//outer_allocator_type
BOOST_STATIC_ASSERT(( boost::container::container_detail::is_same< OuterAlloc
BOOST_STATIC_ASSERT(( container_detail::is_same< OuterAlloc
, Scoped0Inner::outer_allocator_type>::value ));
BOOST_STATIC_ASSERT(( boost::container::container_detail::is_same< OuterAlloc
BOOST_STATIC_ASSERT(( container_detail::is_same< OuterAlloc
, Scoped1Inner::outer_allocator_type>::value ));
BOOST_STATIC_ASSERT(( boost::container::container_detail::is_same< OuterAlloc
BOOST_STATIC_ASSERT(( container_detail::is_same< OuterAlloc
, Scoped2Inner::outer_allocator_type>::value ));
//value_type
BOOST_STATIC_ASSERT(( boost::container::container_detail::is_same< allocator_traits<OuterAlloc>::value_type
BOOST_STATIC_ASSERT(( container_detail::is_same< allocator_traits<OuterAlloc>::value_type
, Scoped0Inner::value_type>::value ));
BOOST_STATIC_ASSERT(( boost::container::container_detail::is_same< allocator_traits<OuterAlloc>::value_type
BOOST_STATIC_ASSERT(( container_detail::is_same< allocator_traits<OuterAlloc>::value_type
, Scoped1Inner::value_type>::value ));
BOOST_STATIC_ASSERT(( boost::container::container_detail::is_same< allocator_traits<OuterAlloc>::value_type
BOOST_STATIC_ASSERT(( container_detail::is_same< allocator_traits<OuterAlloc>::value_type
, Scoped2Inner::value_type>::value ));
//size_type
BOOST_STATIC_ASSERT(( boost::container::container_detail::is_same< allocator_traits<OuterAlloc>::size_type
BOOST_STATIC_ASSERT(( container_detail::is_same< allocator_traits<OuterAlloc>::size_type
, Scoped0Inner::size_type>::value ));
BOOST_STATIC_ASSERT(( boost::container::container_detail::is_same< allocator_traits<OuterAlloc>::size_type
BOOST_STATIC_ASSERT(( container_detail::is_same< allocator_traits<OuterAlloc>::size_type
, Scoped1Inner::size_type>::value ));
BOOST_STATIC_ASSERT(( boost::container::container_detail::is_same< allocator_traits<OuterAlloc>::size_type
BOOST_STATIC_ASSERT(( container_detail::is_same< allocator_traits<OuterAlloc>::size_type
, Scoped2Inner::size_type>::value ));
//difference_type
BOOST_STATIC_ASSERT(( boost::container::container_detail::is_same< allocator_traits<OuterAlloc>::difference_type
BOOST_STATIC_ASSERT(( container_detail::is_same< allocator_traits<OuterAlloc>::difference_type
, Scoped0Inner::difference_type>::value ));
BOOST_STATIC_ASSERT(( boost::container::container_detail::is_same< allocator_traits<OuterAlloc>::difference_type
BOOST_STATIC_ASSERT(( container_detail::is_same< allocator_traits<OuterAlloc>::difference_type
, Scoped1Inner::difference_type>::value ));
BOOST_STATIC_ASSERT(( boost::container::container_detail::is_same< allocator_traits<OuterAlloc>::difference_type
BOOST_STATIC_ASSERT(( container_detail::is_same< allocator_traits<OuterAlloc>::difference_type
, Scoped2Inner::difference_type>::value ));
//pointer
BOOST_STATIC_ASSERT(( boost::container::container_detail::is_same< allocator_traits<OuterAlloc>::pointer
BOOST_STATIC_ASSERT(( container_detail::is_same< allocator_traits<OuterAlloc>::pointer
, Scoped0Inner::pointer>::value ));
BOOST_STATIC_ASSERT(( boost::container::container_detail::is_same< allocator_traits<OuterAlloc>::pointer
BOOST_STATIC_ASSERT(( container_detail::is_same< allocator_traits<OuterAlloc>::pointer
, Scoped1Inner::pointer>::value ));
BOOST_STATIC_ASSERT(( boost::container::container_detail::is_same< allocator_traits<OuterAlloc>::pointer
BOOST_STATIC_ASSERT(( container_detail::is_same< allocator_traits<OuterAlloc>::pointer
, Scoped2Inner::pointer>::value ));
//const_pointer
BOOST_STATIC_ASSERT(( boost::container::container_detail::is_same< allocator_traits<OuterAlloc>::const_pointer
BOOST_STATIC_ASSERT(( container_detail::is_same< allocator_traits<OuterAlloc>::const_pointer
, Scoped0Inner::const_pointer>::value ));
BOOST_STATIC_ASSERT(( boost::container::container_detail::is_same< allocator_traits<OuterAlloc>::const_pointer
BOOST_STATIC_ASSERT(( container_detail::is_same< allocator_traits<OuterAlloc>::const_pointer
, Scoped1Inner::const_pointer>::value ));
BOOST_STATIC_ASSERT(( boost::container::container_detail::is_same< allocator_traits<OuterAlloc>::const_pointer
BOOST_STATIC_ASSERT(( container_detail::is_same< allocator_traits<OuterAlloc>::const_pointer
, Scoped2Inner::const_pointer>::value ));
//void_pointer
BOOST_STATIC_ASSERT(( boost::container::container_detail::is_same< allocator_traits<OuterAlloc>::void_pointer
BOOST_STATIC_ASSERT(( container_detail::is_same< allocator_traits<OuterAlloc>::void_pointer
, Scoped0Inner::void_pointer>::value ));
BOOST_STATIC_ASSERT(( boost::container::container_detail::is_same< allocator_traits<OuterAlloc>::void_pointer
BOOST_STATIC_ASSERT(( container_detail::is_same< allocator_traits<OuterAlloc>::void_pointer
, Scoped1Inner::void_pointer>::value ));
BOOST_STATIC_ASSERT(( boost::container::container_detail::is_same< allocator_traits<OuterAlloc>::void_pointer
BOOST_STATIC_ASSERT(( container_detail::is_same< allocator_traits<OuterAlloc>::void_pointer
, Scoped2Inner::void_pointer>::value ));
//const_void_pointer
BOOST_STATIC_ASSERT(( boost::container::container_detail::is_same< allocator_traits<OuterAlloc>::const_void_pointer
BOOST_STATIC_ASSERT(( container_detail::is_same< allocator_traits<OuterAlloc>::const_void_pointer
, Scoped0Inner::const_void_pointer>::value ));
BOOST_STATIC_ASSERT(( boost::container::container_detail::is_same< allocator_traits<OuterAlloc>::const_void_pointer
BOOST_STATIC_ASSERT(( container_detail::is_same< allocator_traits<OuterAlloc>::const_void_pointer
, Scoped1Inner::const_void_pointer>::value ));
BOOST_STATIC_ASSERT(( boost::container::container_detail::is_same< allocator_traits<OuterAlloc>::const_void_pointer
BOOST_STATIC_ASSERT(( container_detail::is_same< allocator_traits<OuterAlloc>::const_void_pointer
, Scoped2Inner::const_void_pointer>::value ));
//rebind
BOOST_STATIC_ASSERT(( boost::container::container_detail::is_same<Scoped0Inner::rebind< tagged_integer<9> >::other
BOOST_STATIC_ASSERT(( container_detail::is_same<Scoped0Inner::rebind< tagged_integer<9> >::other
, Rebound9Scoped0Inner >::value ));
BOOST_STATIC_ASSERT(( boost::container::container_detail::is_same<Scoped1Inner::rebind< tagged_integer<9> >::other
BOOST_STATIC_ASSERT(( container_detail::is_same<Scoped1Inner::rebind< tagged_integer<9> >::other
, Rebound9Scoped1Inner >::value ));
BOOST_STATIC_ASSERT(( boost::container::container_detail::is_same<Scoped2Inner::rebind< tagged_integer<9> >::other
BOOST_STATIC_ASSERT(( container_detail::is_same<Scoped2Inner::rebind< tagged_integer<9> >::other
, Rebound9Scoped2Inner >::value ));
//inner_allocator_type
BOOST_STATIC_ASSERT(( boost::container::container_detail::is_same< Scoped0Inner
BOOST_STATIC_ASSERT(( container_detail::is_same< Scoped0Inner
, Scoped0Inner::inner_allocator_type>::value ));
BOOST_STATIC_ASSERT(( boost::container::container_detail::is_same< scoped_allocator_adaptor<InnerAlloc1>
BOOST_STATIC_ASSERT(( container_detail::is_same< scoped_allocator_adaptor<InnerAlloc1>
, Scoped1Inner::inner_allocator_type>::value ));
BOOST_STATIC_ASSERT(( boost::container::container_detail::is_same< scoped_allocator_adaptor<InnerAlloc1, InnerAlloc2>
BOOST_STATIC_ASSERT(( container_detail::is_same< scoped_allocator_adaptor<InnerAlloc1, InnerAlloc2>
, Scoped2Inner::inner_allocator_type>::value ));
{
@@ -746,7 +532,7 @@ int main()
}
{
vector<int, scoped_allocator_adaptor< test_allocator<int, 0> > > dummy;
vector<int, scoped_allocator_adaptor< propagation_test_allocator<int, 0> > > dummy;
dummy.push_back(0);
}
@@ -781,34 +567,16 @@ int main()
//construct
{
BOOST_STATIC_ASSERT(( !boost::container::uses_allocator
< ::mark_on_scoped_allocation<NotUsesAllocator, 0>
, test_allocator<float, 0>
>::value ));
BOOST_STATIC_ASSERT(( boost::container::uses_allocator
< ::mark_on_scoped_allocation<ConstructiblePrefix, 0>
, test_allocator<float, 0>
>::value ));
BOOST_STATIC_ASSERT(( boost::container::uses_allocator
< ::mark_on_scoped_allocation<ConstructibleSuffix, 0>
, test_allocator<float, 0>
>::value ));
BOOST_STATIC_ASSERT(( boost::container::constructible_with_allocator_prefix
< ::mark_on_scoped_allocation<ConstructiblePrefix, 0> >::value ));
BOOST_STATIC_ASSERT(( boost::container::constructible_with_allocator_suffix
< ::mark_on_scoped_allocation<ConstructibleSuffix, 0> >::value ));
////////////////////////////////////////////////////////////
//First check scoped allocator with just OuterAlloc.
//In this case OuterAlloc (test_allocator with tag 0) should be
//In this case OuterAlloc (propagation_test_allocator with tag 0) should be
//used to construct types.
////////////////////////////////////////////////////////////
{
Scoped0Inner s0i;
//Check construction with 0 user arguments
{
typedef ::mark_on_scoped_allocation<NotUsesAllocator, 0> MarkType;
typedef ::allocator_argument_tester<NotUsesAllocator, 0> MarkType;
MarkType dummy;
dummy.~MarkType();
s0i.construct(&dummy);
@@ -820,7 +588,7 @@ int main()
dummy.~MarkType();
}
{
typedef ::mark_on_scoped_allocation<ConstructibleSuffix, 0> MarkType;
typedef ::allocator_argument_tester<ConstructibleSuffix, 0> MarkType;
MarkType dummy;
dummy.~MarkType();
s0i.construct(&dummy);
@@ -832,7 +600,7 @@ int main()
dummy.~MarkType();
}
{
typedef ::mark_on_scoped_allocation<ConstructiblePrefix, 0> MarkType;
typedef ::allocator_argument_tester<ConstructiblePrefix, 0> MarkType;
MarkType dummy;
dummy.~MarkType();
s0i.construct(&dummy);
@@ -846,7 +614,7 @@ int main()
//Check construction with 1 user arguments
{
typedef ::mark_on_scoped_allocation<NotUsesAllocator, 0> MarkType;
typedef ::allocator_argument_tester<NotUsesAllocator, 0> MarkType;
MarkType dummy;
dummy.~MarkType();
s0i.construct(&dummy, 1);
@@ -858,7 +626,7 @@ int main()
dummy.~MarkType();
}
{
typedef ::mark_on_scoped_allocation<ConstructibleSuffix, 0> MarkType;
typedef ::allocator_argument_tester<ConstructibleSuffix, 0> MarkType;
MarkType dummy;
dummy.~MarkType();
s0i.construct(&dummy, 2);
@@ -870,7 +638,7 @@ int main()
dummy.~MarkType();
}
{
typedef ::mark_on_scoped_allocation<ConstructiblePrefix, 0> MarkType;
typedef ::allocator_argument_tester<ConstructiblePrefix, 0> MarkType;
MarkType dummy;
dummy.~MarkType();
s0i.construct(&dummy, 3);
@@ -884,14 +652,14 @@ int main()
}
////////////////////////////////////////////////////////////
//Then check scoped allocator with OuterAlloc and InnerAlloc.
//In this case InnerAlloc (test_allocator with tag 1) should be
//In this case InnerAlloc (propagation_test_allocator with tag 1) should be
//used to construct types.
////////////////////////////////////////////////////////////
{
Scoped1Inner s1i;
//Check construction with 0 user arguments
{
typedef ::mark_on_scoped_allocation<NotUsesAllocator, 1> MarkType;
typedef ::allocator_argument_tester<NotUsesAllocator, 1> MarkType;
MarkType dummy;
dummy.~MarkType();
s1i.construct(&dummy);
@@ -903,7 +671,7 @@ int main()
dummy.~MarkType();
}
{
typedef ::mark_on_scoped_allocation<ConstructibleSuffix, 1> MarkType;
typedef ::allocator_argument_tester<ConstructibleSuffix, 1> MarkType;
MarkType dummy;
dummy.~MarkType();
s1i.construct(&dummy);
@@ -915,7 +683,7 @@ int main()
dummy.~MarkType();
}
{
typedef ::mark_on_scoped_allocation<ConstructiblePrefix, 1> MarkType;
typedef ::allocator_argument_tester<ConstructiblePrefix, 1> MarkType;
MarkType dummy;
dummy.~MarkType();
s1i.construct(&dummy);
@@ -929,7 +697,7 @@ int main()
//Check construction with 1 user arguments
{
typedef ::mark_on_scoped_allocation<NotUsesAllocator, 1> MarkType;
typedef ::allocator_argument_tester<NotUsesAllocator, 1> MarkType;
MarkType dummy;
dummy.~MarkType();
s1i.construct(&dummy, 1);
@@ -941,7 +709,7 @@ int main()
dummy.~MarkType();
}
{
typedef ::mark_on_scoped_allocation<ConstructibleSuffix, 1> MarkType;
typedef ::allocator_argument_tester<ConstructibleSuffix, 1> MarkType;
MarkType dummy;
dummy.~MarkType();
s1i.construct(&dummy, 2);
@@ -953,7 +721,7 @@ int main()
dummy.~MarkType();
}
{
typedef ::mark_on_scoped_allocation<ConstructiblePrefix, 1> MarkType;
typedef ::allocator_argument_tester<ConstructiblePrefix, 1> MarkType;
MarkType dummy;
dummy.~MarkType();
s1i.construct(&dummy, 3);
@@ -972,31 +740,31 @@ int main()
////////////////////////////////////////////////////////////
//First check scoped allocator with just OuterAlloc.
//In this case OuterAlloc (test_allocator with tag 0) should be
//In this case OuterAlloc (propagation_test_allocator with tag 0) should be
//used to construct types.
////////////////////////////////////////////////////////////
{
//Check outer_allocator_type is scoped
BOOST_STATIC_ASSERT(( boost::container::is_scoped_allocator
BOOST_STATIC_ASSERT(( is_scoped_allocator
<ScopedScoped0Inner::outer_allocator_type>::value ));
BOOST_STATIC_ASSERT(( ::boost::container::container_detail::is_same
< boost::container::outermost_allocator<ScopedScoped0Inner>::type
BOOST_STATIC_ASSERT(( container_detail::is_same
< outermost_allocator<ScopedScoped0Inner>::type
, Outer10IdAlloc
>::value ));
BOOST_STATIC_ASSERT(( ::boost::container::container_detail::is_same
BOOST_STATIC_ASSERT(( container_detail::is_same
< ScopedScoped0Inner::outer_allocator_type
, scoped_allocator_adaptor<Outer10IdAlloc>
>::value ));
BOOST_STATIC_ASSERT(( ::boost::container::container_detail::is_same
BOOST_STATIC_ASSERT(( container_detail::is_same
< scoped_allocator_adaptor<Outer10IdAlloc>::outer_allocator_type
, Outer10IdAlloc
>::value ));
ScopedScoped0Inner ssro0i;
Outer10IdAlloc & val = boost::container::outermost_allocator<ScopedScoped0Inner>::get(ssro0i);
Outer10IdAlloc & val = outermost_allocator<ScopedScoped0Inner>::get(ssro0i);
(void)val;
//Check construction with 0 user arguments
{
typedef ::mark_on_scoped_allocation<NotUsesAllocator, 10> MarkType;
typedef ::allocator_argument_tester<NotUsesAllocator, 10> MarkType;
MarkType dummy;
dummy.~MarkType();
ssro0i.construct(&dummy);
@@ -1008,7 +776,7 @@ int main()
dummy.~MarkType();
}
{
typedef ::mark_on_scoped_allocation<ConstructibleSuffix, 10> MarkType;
typedef ::allocator_argument_tester<ConstructibleSuffix, 10> MarkType;
MarkType dummy;
dummy.~MarkType();
ssro0i.construct(&dummy);
@@ -1020,7 +788,7 @@ int main()
dummy.~MarkType();
}
{
typedef ::mark_on_scoped_allocation<ConstructiblePrefix, 10> MarkType;
typedef ::allocator_argument_tester<ConstructiblePrefix, 10> MarkType;
MarkType dummy;
dummy.~MarkType();
ssro0i.construct(&dummy);
@@ -1034,7 +802,7 @@ int main()
//Check construction with 1 user arguments
{
typedef ::mark_on_scoped_allocation<NotUsesAllocator, 10> MarkType;
typedef ::allocator_argument_tester<NotUsesAllocator, 10> MarkType;
MarkType dummy;
dummy.~MarkType();
ssro0i.construct(&dummy, 1);
@@ -1046,7 +814,7 @@ int main()
dummy.~MarkType();
}
{
typedef ::mark_on_scoped_allocation<ConstructibleSuffix, 10> MarkType;
typedef ::allocator_argument_tester<ConstructibleSuffix, 10> MarkType;
MarkType dummy;
dummy.~MarkType();
ssro0i.construct(&dummy, 2);
@@ -1058,7 +826,7 @@ int main()
dummy.~MarkType();
}
{
typedef ::mark_on_scoped_allocation<ConstructiblePrefix, 10> MarkType;
typedef ::allocator_argument_tester<ConstructiblePrefix, 10> MarkType;
MarkType dummy;
dummy.~MarkType();
ssro0i.construct(&dummy, 3);
@@ -1073,37 +841,37 @@ int main()
////////////////////////////////////////////////////////////
//Then check scoped allocator with OuterAlloc and InnerAlloc.
//In this case inner_allocator_type is not convertible to
//::mark_on_scoped_allocation<XXX, 10> so uses_allocator
//::allocator_argument_tester<XXX, 10> so uses_allocator
//should be false on all tests.
////////////////////////////////////////////////////////////
{
//Check outer_allocator_type is scoped
BOOST_STATIC_ASSERT(( boost::container::is_scoped_allocator
BOOST_STATIC_ASSERT(( is_scoped_allocator
<ScopedScoped1Inner::outer_allocator_type>::value ));
BOOST_STATIC_ASSERT(( ::boost::container::container_detail::is_same
< boost::container::outermost_allocator<ScopedScoped1Inner>::type
BOOST_STATIC_ASSERT(( container_detail::is_same
< outermost_allocator<ScopedScoped1Inner>::type
, Outer10IdAlloc
>::value ));
BOOST_STATIC_ASSERT(( ::boost::container::container_detail::is_same
BOOST_STATIC_ASSERT(( container_detail::is_same
< ScopedScoped1Inner::outer_allocator_type
, scoped_allocator_adaptor<Outer10IdAlloc, Inner11IdAlloc1>
>::value ));
BOOST_STATIC_ASSERT(( ::boost::container::container_detail::is_same
BOOST_STATIC_ASSERT(( container_detail::is_same
< scoped_allocator_adaptor<Outer10IdAlloc, Inner11IdAlloc1>::outer_allocator_type
, Outer10IdAlloc
>::value ));
BOOST_STATIC_ASSERT(( !
::boost::container::uses_allocator
< ::mark_on_scoped_allocation<ConstructibleSuffix, 10>
uses_allocator
< ::allocator_argument_tester<ConstructibleSuffix, 10>
, ScopedScoped1Inner::inner_allocator_type::outer_allocator_type
>::value ));
ScopedScoped1Inner ssro1i;
Outer10IdAlloc & val = boost::container::outermost_allocator<ScopedScoped1Inner>::get(ssro1i);
Outer10IdAlloc & val = outermost_allocator<ScopedScoped1Inner>::get(ssro1i);
(void)val;
//Check construction with 0 user arguments
{
typedef ::mark_on_scoped_allocation<NotUsesAllocator, 10> MarkType;
typedef ::allocator_argument_tester<NotUsesAllocator, 10> MarkType;
MarkType dummy;
dummy.~MarkType();
ssro1i.construct(&dummy);
@@ -1115,7 +883,7 @@ int main()
dummy.~MarkType();
}
{
typedef ::mark_on_scoped_allocation<ConstructibleSuffix, 10> MarkType;
typedef ::allocator_argument_tester<ConstructibleSuffix, 10> MarkType;
MarkType dummy;
dummy.~MarkType();
ssro1i.construct(&dummy);
@@ -1127,7 +895,7 @@ int main()
dummy.~MarkType();
}
{
typedef ::mark_on_scoped_allocation<ConstructiblePrefix, 10> MarkType;
typedef ::allocator_argument_tester<ConstructiblePrefix, 10> MarkType;
MarkType dummy;
dummy.~MarkType();
ssro1i.construct(&dummy);
@@ -1141,7 +909,7 @@ int main()
//Check construction with 1 user arguments
{
typedef ::mark_on_scoped_allocation<NotUsesAllocator, 10> MarkType;
typedef ::allocator_argument_tester<NotUsesAllocator, 10> MarkType;
MarkType dummy;
dummy.~MarkType();
ssro1i.construct(&dummy, 1);
@@ -1153,7 +921,7 @@ int main()
dummy.~MarkType();
}
{
typedef ::mark_on_scoped_allocation<ConstructibleSuffix, 10> MarkType;
typedef ::allocator_argument_tester<ConstructibleSuffix, 10> MarkType;
MarkType dummy;
dummy.~MarkType();
ssro1i.construct(&dummy, 2);
@@ -1165,7 +933,7 @@ int main()
dummy.~MarkType();
}
{
typedef ::mark_on_scoped_allocation<ConstructiblePrefix, 10> MarkType;
typedef ::allocator_argument_tester<ConstructiblePrefix, 10> MarkType;
MarkType dummy;
dummy.~MarkType();
ssro1i.construct(&dummy, 3);
@@ -1182,12 +950,12 @@ int main()
//Now check propagation to pair
////////////////////////////////////////////////////////////
//First check scoped allocator with just OuterAlloc.
//In this case OuterAlloc (test_allocator with tag 0) should be
//In this case OuterAlloc (propagation_test_allocator with tag 0) should be
//used to construct types.
////////////////////////////////////////////////////////////
{
using boost::container::container_detail::pair;
typedef test_allocator< pair< tagged_integer<0>
using container_detail::pair;
typedef propagation_test_allocator< pair< tagged_integer<0>
, tagged_integer<0> >, 0> OuterPairAlloc;
//
typedef scoped_allocator_adaptor < OuterPairAlloc > ScopedPair0Inner;
@@ -1195,7 +963,7 @@ int main()
ScopedPair0Inner s0i;
//Check construction with 0 user arguments
{
typedef ::mark_on_scoped_allocation<NotUsesAllocator, 0> MarkType;
typedef ::allocator_argument_tester<NotUsesAllocator, 0> MarkType;
typedef pair<MarkType, MarkType> MarkTypePair;
MarkTypePair dummy;
dummy.~MarkTypePair();
@@ -1210,7 +978,7 @@ int main()
dummy.~MarkTypePair();
}
{
typedef ::mark_on_scoped_allocation<ConstructibleSuffix, 0> MarkType;
typedef ::allocator_argument_tester<ConstructibleSuffix, 0> MarkType;
typedef pair<MarkType, MarkType> MarkTypePair;
MarkTypePair dummy;
dummy.~MarkTypePair();
@@ -1225,7 +993,7 @@ int main()
dummy.~MarkTypePair();
}
{
typedef ::mark_on_scoped_allocation<ConstructiblePrefix, 0> MarkType;
typedef ::allocator_argument_tester<ConstructiblePrefix, 0> MarkType;
typedef pair<MarkType, MarkType> MarkTypePair;
MarkTypePair dummy;
dummy.~MarkTypePair();
@@ -1242,7 +1010,7 @@ int main()
//Check construction with 1 user arguments for each pair
{
typedef ::mark_on_scoped_allocation<NotUsesAllocator, 0> MarkType;
typedef ::allocator_argument_tester<NotUsesAllocator, 0> MarkType;
typedef pair<MarkType, MarkType> MarkTypePair;
MarkTypePair dummy;
dummy.~MarkTypePair();
@@ -1257,7 +1025,7 @@ int main()
dummy.~MarkTypePair();
}
{
typedef ::mark_on_scoped_allocation<ConstructibleSuffix, 0> MarkType;
typedef ::allocator_argument_tester<ConstructibleSuffix, 0> MarkType;
typedef pair<MarkType, MarkType> MarkTypePair;
MarkTypePair dummy;
dummy.~MarkTypePair();
@@ -1272,7 +1040,7 @@ int main()
dummy.~MarkTypePair();
}
{
typedef ::mark_on_scoped_allocation<ConstructiblePrefix, 0> MarkType;
typedef ::allocator_argument_tester<ConstructiblePrefix, 0> MarkType;
typedef pair<MarkType, MarkType> MarkTypePair;
MarkTypePair dummy;
dummy.~MarkTypePair();
@@ -1288,7 +1056,7 @@ int main()
}
//Check construction with pair copy construction
{
typedef ::mark_on_scoped_allocation<NotUsesAllocator, 0> MarkType;
typedef ::allocator_argument_tester<NotUsesAllocator, 0> MarkType;
typedef pair<MarkType, MarkType> MarkTypePair;
MarkTypePair dummy, dummy2;
dummy.~MarkTypePair();
@@ -1303,7 +1071,7 @@ int main()
dummy.~MarkTypePair();
}
{
typedef ::mark_on_scoped_allocation<ConstructibleSuffix, 0> MarkType;
typedef ::allocator_argument_tester<ConstructibleSuffix, 0> MarkType;
typedef pair<MarkType, MarkType> MarkTypePair;
MarkTypePair dummy, dummy2(1, 1);
dummy.~MarkTypePair();
@@ -1318,7 +1086,7 @@ int main()
dummy.~MarkTypePair();
}
{
typedef ::mark_on_scoped_allocation<ConstructiblePrefix, 0> MarkType;
typedef ::allocator_argument_tester<ConstructiblePrefix, 0> MarkType;
typedef pair<MarkType, MarkType> MarkTypePair;
MarkTypePair dummy, dummy2(2, 2);
dummy.~MarkTypePair();
@@ -1334,7 +1102,7 @@ int main()
}
//Check construction with pair move construction
{
typedef ::mark_on_scoped_allocation<NotUsesAllocator, 0> MarkType;
typedef ::allocator_argument_tester<NotUsesAllocator, 0> MarkType;
typedef pair<MarkType, MarkType> MarkTypePair;
MarkTypePair dummy, dummy2(3, 3);
dummy2.first.construction_type = dummy2.second.construction_type = ConstructibleSuffix;
@@ -1354,7 +1122,7 @@ int main()
dummy.~MarkTypePair();
}
{
typedef ::mark_on_scoped_allocation<ConstructibleSuffix, 0> MarkType;
typedef ::allocator_argument_tester<ConstructibleSuffix, 0> MarkType;
typedef pair<MarkType, MarkType> MarkTypePair;
MarkTypePair dummy, dummy2(1, 1);
dummy.~MarkTypePair();
@@ -1373,7 +1141,7 @@ int main()
dummy.~MarkTypePair();
}
{
typedef ::mark_on_scoped_allocation<ConstructiblePrefix, 0> MarkType;
typedef ::allocator_argument_tester<ConstructiblePrefix, 0> MarkType;
typedef pair<MarkType, MarkType> MarkTypePair;
MarkTypePair dummy, dummy2(2, 2);
dummy.~MarkTypePair();
@@ -1393,7 +1161,7 @@ int main()
}
//Check construction with related pair copy construction
{
typedef ::mark_on_scoped_allocation<NotUsesAllocator, 0> MarkType;
typedef ::allocator_argument_tester<NotUsesAllocator, 0> MarkType;
typedef pair<MarkType, MarkType> MarkTypePair;
MarkTypePair dummy;
pair<int, int> dummy2;
@@ -1409,7 +1177,7 @@ int main()
dummy.~MarkTypePair();
}
{
typedef ::mark_on_scoped_allocation<ConstructibleSuffix, 0> MarkType;
typedef ::allocator_argument_tester<ConstructibleSuffix, 0> MarkType;
typedef pair<MarkType, MarkType> MarkTypePair;
MarkTypePair dummy;
pair<int, int> dummy2(1, 1);
@@ -1425,7 +1193,7 @@ int main()
dummy.~MarkTypePair();
}
{
typedef ::mark_on_scoped_allocation<ConstructiblePrefix, 0> MarkType;
typedef ::allocator_argument_tester<ConstructiblePrefix, 0> MarkType;
typedef pair<MarkType, MarkType> MarkTypePair;
MarkTypePair dummy;
pair<int, int> dummy2(2, 2);
@@ -1442,7 +1210,7 @@ int main()
}
//Check construction with related pair move construction
{
typedef ::mark_on_scoped_allocation<NotUsesAllocator, 0> MarkType;
typedef ::allocator_argument_tester<NotUsesAllocator, 0> MarkType;
typedef pair<MarkType, MarkType> MarkTypePair;
MarkTypePair dummy;
pair<int, int> dummy2(3, 3);
@@ -1458,7 +1226,7 @@ int main()
dummy.~MarkTypePair();
}
{
typedef ::mark_on_scoped_allocation<ConstructibleSuffix, 0> MarkType;
typedef ::allocator_argument_tester<ConstructibleSuffix, 0> MarkType;
typedef pair<MarkType, MarkType> MarkTypePair;
MarkTypePair dummy;
pair<int, int> dummy2(1, 1);
@@ -1474,7 +1242,7 @@ int main()
dummy.~MarkTypePair();
}
{
typedef ::mark_on_scoped_allocation<ConstructiblePrefix, 0> MarkType;
typedef ::allocator_argument_tester<ConstructiblePrefix, 0> MarkType;
typedef pair<MarkType, MarkType> MarkTypePair;
MarkTypePair dummy;
pair<int, int> dummy2(2, 2);
+19
View File
@@ -0,0 +1,19 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2015-2015. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#include <boost/container/pmr/synchronized_pool_resource.hpp>
#include <boost/core/lightweight_test.hpp>
#include "pool_resource_test.hpp"
int main()
{
test_pool_resource<boost::container::pmr::synchronized_pool_resource>();
return ::boost::report_errors();
}
@@ -0,0 +1,19 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2015-2015. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#include <boost/container/pmr/unsynchronized_pool_resource.hpp>
#include <boost/core/lightweight_test.hpp>
#include "pool_resource_test.hpp"
int main()
{
test_pool_resource<boost::container::pmr::unsynchronized_pool_resource>();
return ::boost::report_errors();
}
+84
View File
@@ -0,0 +1,84 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2011-2013. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#include <boost/container/detail/config_begin.hpp>
#include <boost/container/uses_allocator_fwd.hpp>
#include <boost/container/uses_allocator.hpp>
#include "propagation_test_allocator.hpp"
struct not_uses_allocator
{};
struct uses_allocator_and_not_convertible_to_int
{
typedef uses_allocator_and_not_convertible_to_int allocator_type;
};
struct uses_allocator_and_convertible_to_int
{
typedef char allocator_type;
};
struct uses_erased_type_allocator
{
typedef boost::container::erased_type allocator_type;
};
int main()
{
using namespace boost::container;
//Using dummy classes
BOOST_STATIC_ASSERT(( false == uses_allocator
< not_uses_allocator, int>::value ));
BOOST_STATIC_ASSERT(( false == uses_allocator
< uses_allocator_and_not_convertible_to_int, int>::value ));
BOOST_STATIC_ASSERT(( true == uses_allocator
< uses_allocator_and_convertible_to_int, int>::value ));
BOOST_STATIC_ASSERT(( true == uses_allocator
< uses_erased_type_allocator, int>::value ));
//Using an allocator-like class
BOOST_STATIC_ASSERT(( false == uses_allocator
< allocator_argument_tester<NotUsesAllocator, 0>
, propagation_test_allocator<float, 0>
>::value ));
BOOST_STATIC_ASSERT(( true == uses_allocator
< allocator_argument_tester<ConstructiblePrefix, 0>
, propagation_test_allocator<float, 0>
>::value ));
BOOST_STATIC_ASSERT(( true == uses_allocator
< allocator_argument_tester<ConstructibleSuffix, 0>
, propagation_test_allocator<float, 0>
>::value ));
BOOST_STATIC_ASSERT(( true == uses_allocator
< allocator_argument_tester<ErasedTypeSuffix, 0>
, propagation_test_allocator<float, 0>
>::value ));
BOOST_STATIC_ASSERT(( true == uses_allocator
< allocator_argument_tester<ErasedTypePrefix, 0>
, propagation_test_allocator<float, 0>
>::value ));
BOOST_STATIC_ASSERT(( true == constructible_with_allocator_prefix
< allocator_argument_tester<ConstructiblePrefix, 0> >::value ));
BOOST_STATIC_ASSERT(( true == constructible_with_allocator_suffix
< allocator_argument_tester<ConstructibleSuffix, 0> >::value ));
BOOST_STATIC_ASSERT(( true == constructible_with_allocator_prefix
< allocator_argument_tester<ErasedTypePrefix, 0> >::value ));
BOOST_STATIC_ASSERT(( true == constructible_with_allocator_suffix
< allocator_argument_tester<ErasedTypeSuffix, 0> >::value ));
return 0;
}