mirror of
https://github.com/boostorg/pool.git
synced 2026-07-21 13:33:29 +00:00
Allow object_pool::construct() to use variadic template, if available.
This commit is contained in:
@@ -175,6 +175,18 @@ class object_pool: protected pool<UserAllocator>
|
||||
//! detail/pool_construct.bat and detail/pool_construct.sh are also provided to call m4, defining NumberOfArguments
|
||||
//! to be their command-line parameter. See these files for more details.
|
||||
}
|
||||
#elif defined(BOOST_HAS_VARIADIC_TMPL) && defined(BOOST_HAS_RVALUE_REFS)
|
||||
// When available, use variadic templates to avoid the older '.ipp'/'.m4' implementation
|
||||
template <typename... Args>
|
||||
element_type * construct(Args&&... args)
|
||||
{
|
||||
element_type* const ret = (malloc)();
|
||||
if (ret == 0)
|
||||
return ret;
|
||||
try { new (ret) element_type(std::forward<Args>(args)...); }
|
||||
catch (...) { (free)(ret); throw; }
|
||||
return ret;
|
||||
}
|
||||
#else
|
||||
// Include automatically-generated file for family of template construct() functions.
|
||||
// Copy .inc renamed .ipp to conform to Doxygen include filename expectations, PAB 12 Jan 11.
|
||||
|
||||
@@ -969,6 +969,8 @@ public:
|
||||
if(free_list.empty())
|
||||
{
|
||||
ret = (user_allocator::malloc)(chunk_size);
|
||||
if ( ret == 0 )
|
||||
return ret;
|
||||
VALGRIND_MAKE_MEM_UNDEFINED(ret, chunk_size);
|
||||
}
|
||||
else
|
||||
|
||||
@@ -48,6 +48,10 @@ public:
|
||||
|
||||
void check_out(void * const This)
|
||||
{
|
||||
// Under current usage, 'This' is the 'this'-pointer of a 'tester' object.
|
||||
// If it is NULL here, then something has already gone terribly wrong
|
||||
BOOST_TEST(This != NULL);
|
||||
|
||||
BOOST_TEST(objs.find(This) != objs.end());
|
||||
objs.erase(This);
|
||||
}
|
||||
@@ -66,6 +70,25 @@ struct tester
|
||||
mem.check_in(this);
|
||||
}
|
||||
|
||||
tester(int a0, int a1)
|
||||
{
|
||||
set_values(a0, a1, -1, -1);
|
||||
|
||||
mem.check_in(this);
|
||||
}
|
||||
|
||||
tester(int a0, const int& a1, int a2, const int a3, bool throw_except = false)
|
||||
{
|
||||
if(throw_except)
|
||||
{
|
||||
throw std::logic_error("Deliberate constructor exception");
|
||||
}
|
||||
|
||||
set_values(a0, a1, a2, a3);
|
||||
|
||||
mem.check_in(this);
|
||||
}
|
||||
|
||||
tester(const tester &)
|
||||
{
|
||||
mem.check_in(this);
|
||||
@@ -75,6 +98,32 @@ struct tester
|
||||
{
|
||||
mem.check_out(this);
|
||||
}
|
||||
|
||||
int stored_a0;
|
||||
int stored_a1;
|
||||
int stored_a2;
|
||||
int stored_a3;
|
||||
|
||||
void set_values(int a0, int a1, int a2, int a3)
|
||||
{
|
||||
stored_a0 = a0;
|
||||
stored_a1 = a1;
|
||||
stored_a2 = a2;
|
||||
stored_a3 = a3;
|
||||
}
|
||||
|
||||
void check_values(int a0, int a1)
|
||||
{
|
||||
check_values(a0, a1, -1, -1);
|
||||
}
|
||||
|
||||
void check_values(int a0, int a1, int a2, int a3)
|
||||
{
|
||||
BOOST_TEST( a0 == stored_a0 );
|
||||
BOOST_TEST( a1 == stored_a1 );
|
||||
BOOST_TEST( a2 == stored_a2 );
|
||||
BOOST_TEST( a3 == stored_a3 );
|
||||
}
|
||||
};
|
||||
|
||||
// This is a wrapper around a UserAllocator. It just registers alloc/dealloc
|
||||
@@ -113,6 +162,23 @@ std::set<char *> TrackAlloc<UserAllocator>::allocated_blocks;
|
||||
|
||||
typedef TrackAlloc<boost::default_user_allocator_new_delete> track_alloc;
|
||||
|
||||
// This is a simple UserAllocator to allow coverage-testing of the codepath
|
||||
// where memory allocation fails.
|
||||
struct always_fails_allocation_alloc
|
||||
{
|
||||
typedef std::size_t size_type;
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
|
||||
static char * malloc(const size_type /*bytes*/)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void free(char * const /*block*/)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
void test()
|
||||
{
|
||||
{
|
||||
@@ -162,6 +228,53 @@ void test()
|
||||
}
|
||||
catch(const std::logic_error &) {}
|
||||
}
|
||||
#if defined(BOOST_HAS_VARIADIC_TMPL) && defined(BOOST_HAS_RVALUE_REFS)
|
||||
for(int k=0; k < 5; ++k)
|
||||
{
|
||||
try
|
||||
{
|
||||
// The following constructions will raise an exception.
|
||||
pool.construct(k,2*k,3*k,4*k,true);
|
||||
}
|
||||
catch(const std::logic_error &) {}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
{
|
||||
// Test the 'pool.construct' with 2 ctor parameters
|
||||
boost::object_pool<tester> pool;
|
||||
for(int i=0; i < 5; ++i)
|
||||
{
|
||||
tester * newItem = pool.construct(i, 2*i);
|
||||
newItem->check_values(i, 2*i);
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(BOOST_HAS_VARIADIC_TMPL) && defined(BOOST_HAS_RVALUE_REFS)
|
||||
{
|
||||
// Test the 'pool.construct' with 4 ctor parameters
|
||||
// Without variadic-templates, this functionality requires
|
||||
// that the end-user has run the 'detail/pool_construct.m4'
|
||||
// functionality to generate a larger set of 'construct()'
|
||||
// overloads. [see docs for object_pool::construct()]
|
||||
boost::object_pool<tester> pool;
|
||||
for(int i=0; i < 5; ++i)
|
||||
{
|
||||
tester * newItem = pool.construct(i, 2*i, 3*i, 5*i);
|
||||
newItem->check_values(i, 2*i, 3*i, 5*i);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
{
|
||||
// Test the case where memory allocation intentionally fails
|
||||
boost::object_pool<tester, always_fails_allocation_alloc> pool;
|
||||
BOOST_TEST( pool.construct() == 0 );
|
||||
BOOST_TEST( pool.construct(1,2) == 0 );
|
||||
#if defined(BOOST_HAS_VARIADIC_TMPL) && defined(BOOST_HAS_RVALUE_REFS)
|
||||
BOOST_TEST( pool.construct(1,2,3,4) == 0 );
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user