Don't track construction when using boost::tuple

Because it doesn't quiet work on C++11 compilers onwards.
This commit is contained in:
Daniel James
2017-04-18 10:14:26 +01:00
parent cafd236a18
commit 7a0a598649
3 changed files with 152 additions and 13 deletions

View File

@ -60,9 +60,11 @@ struct memory_tracker
unsigned int count_allocators;
unsigned int count_allocations;
unsigned int count_constructions;
bool tracking_constructions;
memory_tracker()
: count_allocators(0), count_allocations(0), count_constructions(0)
: count_allocators(0), count_allocations(0), count_constructions(0),
tracking_constructions(true)
{
}
@ -133,14 +135,18 @@ struct memory_tracker
void track_construct(void* /*ptr*/, std::size_t /*size*/, int /*tag*/)
{
++count_constructions;
if (tracking_constructions) {
++count_constructions;
}
}
void track_destroy(void* /*ptr*/, std::size_t /*size*/, int /*tag*/)
{
BOOST_TEST(count_constructions > 0);
if (count_constructions > 0)
--count_constructions;
if (tracking_constructions) {
BOOST_TEST(count_constructions > 0);
if (count_constructions > 0)
--count_constructions;
}
}
};
}
@ -155,6 +161,29 @@ namespace {
test::detail::memory_tracker tracker;
}
}
namespace detail {
struct disable_construction_tracking
{
bool old_value;
disable_construction_tracking()
: old_value(detail::tracker.tracking_constructions)
{
test::detail::tracker.tracking_constructions = false;
}
~disable_construction_tracking()
{
test::detail::tracker.tracking_constructions = old_value;
}
private:
disable_construction_tracking(disable_construction_tracking const&);
disable_construction_tracking& operator=(
disable_construction_tracking const&);
};
}
}
#endif

View File

@ -392,10 +392,10 @@ template <class T> class allocator1
}
#if BOOST_UNORDERED_CXX11_CONSTRUCTION
template <typename... Args> void construct(T* p, Args&&... args)
template <typename U, typename... Args> void construct(U* p, Args&&... args)
{
detail::tracker.track_construct((void*)p, sizeof(T), tag_);
new (p) T(boost::forward<Args>(args)...);
detail::tracker.track_construct((void*)p, sizeof(U), tag_);
new (p) U(boost::forward<Args>(args)...);
}
#else
void construct(T* p, T const& t)
@ -405,10 +405,10 @@ template <class T> class allocator1
}
#endif
void destroy(T* p)
template <typename U> void destroy(U* p)
{
detail::tracker.track_destroy((void*)p, sizeof(T), tag_);
p->~T();
detail::tracker.track_destroy((void*)p, sizeof(U), tag_);
p->~U();
// Work around MSVC buggy unused parameter warning.
ignore_variable(&p);

View File

@ -1120,6 +1120,10 @@ struct convertible_to_piecewise
UNORDERED_AUTO_TEST(map_emplace_test2)
{
// Emulating piecewise construction with boost::tuple bypasses the
// allocator's construct method, but still uses test destroy method.
test::detail::disable_construction_tracking _scoped;
{
boost::unordered_map<overloaded_constructor, overloaded_constructor,
boost::hash<overloaded_constructor>,
@ -1169,8 +1173,8 @@ UNORDERED_AUTO_TEST(map_emplace_test2)
x.find(overloaded_constructor(2, 3))->second ==
overloaded_constructor(4, 5, 6));
}
{
{
boost::unordered_multimap<overloaded_constructor,
overloaded_constructor, boost::hash<overloaded_constructor>,
std::equal_to<overloaded_constructor>,
@ -1220,9 +1224,115 @@ UNORDERED_AUTO_TEST(set_emplace_test2)
boost::make_tuple(2, 3));
check =
std::make_pair(overloaded_constructor(1), overloaded_constructor(2, 3));
;
BOOST_TEST(x.find(check) != x.end() && *x.find(check) == check);
}
#if BOOST_UNORDERED_HAVE_PIECEWISE_CONSTRUCT
UNORDERED_AUTO_TEST(map_std_emplace_test2)
{
{
boost::unordered_map<overloaded_constructor, overloaded_constructor,
boost::hash<overloaded_constructor>,
std::equal_to<overloaded_constructor>,
test::allocator1<std::pair<overloaded_constructor const,
overloaded_constructor> > >
x;
x.emplace(
std::piecewise_construct, std::make_tuple(), std::make_tuple());
BOOST_TEST(x.find(overloaded_constructor()) != x.end() &&
x.find(overloaded_constructor())->second ==
overloaded_constructor());
x.emplace(
convertible_to_piecewise(), std::make_tuple(1), std::make_tuple());
BOOST_TEST(x.find(overloaded_constructor(1)) != x.end() &&
x.find(overloaded_constructor(1))->second ==
overloaded_constructor());
x.emplace(piecewise_rvalue(), std::make_tuple(2, 3),
std::make_tuple(4, 5, 6));
BOOST_TEST(x.find(overloaded_constructor(2, 3)) != x.end() &&
x.find(overloaded_constructor(2, 3))->second ==
overloaded_constructor(4, 5, 6));
derived_from_piecewise_construct_t d;
x.emplace(d, std::make_tuple(9, 3, 1), std::make_tuple(10));
BOOST_TEST(x.find(overloaded_constructor(9, 3, 1)) != x.end() &&
x.find(overloaded_constructor(9, 3, 1))->second ==
overloaded_constructor(10));
x.clear();
x.try_emplace(overloaded_constructor());
BOOST_TEST(x.find(overloaded_constructor()) != x.end() &&
x.find(overloaded_constructor())->second ==
overloaded_constructor());
x.try_emplace(1);
BOOST_TEST(x.find(overloaded_constructor(1)) != x.end() &&
x.find(overloaded_constructor(1))->second ==
overloaded_constructor());
x.try_emplace(overloaded_constructor(2, 3), 4, 5, 6);
BOOST_TEST(x.find(overloaded_constructor(2, 3)) != x.end() &&
x.find(overloaded_constructor(2, 3))->second ==
overloaded_constructor(4, 5, 6));
}
{
boost::unordered_multimap<overloaded_constructor,
overloaded_constructor, boost::hash<overloaded_constructor>,
std::equal_to<overloaded_constructor>,
test::allocator1<std::pair<overloaded_constructor const,
overloaded_constructor> > >
x;
x.emplace(
std::piecewise_construct, std::make_tuple(), std::make_tuple());
BOOST_TEST(x.find(overloaded_constructor()) != x.end() &&
x.find(overloaded_constructor())->second ==
overloaded_constructor());
x.emplace(
convertible_to_piecewise(), std::make_tuple(1), std::make_tuple());
BOOST_TEST(x.find(overloaded_constructor(1)) != x.end() &&
x.find(overloaded_constructor(1))->second ==
overloaded_constructor());
x.emplace(piecewise_rvalue(), std::make_tuple(2, 3),
std::make_tuple(4, 5, 6));
BOOST_TEST(x.find(overloaded_constructor(2, 3)) != x.end() &&
x.find(overloaded_constructor(2, 3))->second ==
overloaded_constructor(4, 5, 6));
derived_from_piecewise_construct_t d;
x.emplace(d, std::make_tuple(9, 3, 1), std::make_tuple(10));
BOOST_TEST(x.find(overloaded_constructor(9, 3, 1)) != x.end() &&
x.find(overloaded_constructor(9, 3, 1))->second ==
overloaded_constructor(10));
}
}
UNORDERED_AUTO_TEST(set_std_emplace_test2)
{
boost::unordered_set<
std::pair<overloaded_constructor, overloaded_constructor> >
x;
std::pair<overloaded_constructor, overloaded_constructor> check;
x.emplace(std::piecewise_construct, std::make_tuple(), std::make_tuple());
BOOST_TEST(x.find(check) != x.end() && *x.find(check) == check);
x.clear();
x.emplace(
std::piecewise_construct, std::make_tuple(1), std::make_tuple(2, 3));
check =
std::make_pair(overloaded_constructor(1), overloaded_constructor(2, 3));
BOOST_TEST(x.find(check) != x.end() && *x.find(check) == check);
}
#endif
}
RUN_TESTS()