[libc++] Make test_allocator constexpr-friendly for constexpr string/vector
Make test_allocator etc. constexpr-friendly so they can be used to test constexpr string and possibly constexpr vector Reviewed By: Quuxplusone, #libc, ldionne Differential Revision: https://reviews.llvm.org/D110994
This commit is contained in:
parent
f057756a1a
commit
9a140a1586
|
@ -74,17 +74,18 @@ void test_basic() {
|
|||
|
||||
|
||||
void duplicate_keys_test() {
|
||||
test_allocator_statistics alloc_stats;
|
||||
typedef std::map<int, int, std::less<int>, test_allocator<std::pair<const int, int> > > Map;
|
||||
{
|
||||
LIBCPP_ASSERT(test_alloc_base::alloc_count == 0);
|
||||
Map s = {{1, 0}, {2, 0}, {3, 0}};
|
||||
LIBCPP_ASSERT(test_alloc_base::alloc_count == 3);
|
||||
LIBCPP_ASSERT(alloc_stats.alloc_count == 0);
|
||||
Map s({{1, 0}, {2, 0}, {3, 0}}, std::less<int>(), test_allocator<std::pair<const int, int> >(&alloc_stats));
|
||||
LIBCPP_ASSERT(alloc_stats.alloc_count == 3);
|
||||
s = {{4, 0}, {4, 0}, {4, 0}, {4, 0}};
|
||||
LIBCPP_ASSERT(test_alloc_base::alloc_count == 1);
|
||||
LIBCPP_ASSERT(alloc_stats.alloc_count == 1);
|
||||
assert(s.size() == 1);
|
||||
assert(s.begin()->first == 4);
|
||||
}
|
||||
LIBCPP_ASSERT(test_alloc_base::alloc_count == 0);
|
||||
LIBCPP_ASSERT(alloc_stats.alloc_count == 0);
|
||||
}
|
||||
|
||||
int main(int, char**)
|
||||
|
|
|
@ -55,17 +55,18 @@ void basic_test() {
|
|||
}
|
||||
|
||||
void duplicate_keys_test() {
|
||||
test_allocator_statistics alloc_stats;
|
||||
typedef std::set<int, std::less<int>, test_allocator<int> > Set;
|
||||
{
|
||||
LIBCPP_ASSERT(test_alloc_base::alloc_count == 0);
|
||||
Set s = {1, 2, 3};
|
||||
LIBCPP_ASSERT(test_alloc_base::alloc_count == 3);
|
||||
LIBCPP_ASSERT(alloc_stats.alloc_count == 0);
|
||||
Set s({1, 2, 3}, std::less<int>(), test_allocator<int>(&alloc_stats));
|
||||
LIBCPP_ASSERT(alloc_stats.alloc_count == 3);
|
||||
s = {4, 4, 4, 4, 4};
|
||||
LIBCPP_ASSERT(test_alloc_base::alloc_count == 1);
|
||||
LIBCPP_ASSERT(alloc_stats.alloc_count == 1);
|
||||
assert(s.size() == 1);
|
||||
assert(*s.begin() == 4);
|
||||
}
|
||||
LIBCPP_ASSERT(test_alloc_base::alloc_count == 0);
|
||||
LIBCPP_ASSERT(alloc_stats.alloc_count == 0);
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
|
|
|
@ -27,27 +27,28 @@
|
|||
|
||||
template <class C>
|
||||
void test(int expected_num_allocs = 1) {
|
||||
test_allocator_statistics alloc_stats;
|
||||
{
|
||||
test_alloc_base::clear();
|
||||
alloc_stats.clear();
|
||||
using AllocT = typename C::allocator_type;
|
||||
C v(AllocT(42, 101));
|
||||
C v(AllocT(42, 101, &alloc_stats));
|
||||
|
||||
assert(test_alloc_base::count == expected_num_allocs);
|
||||
assert(alloc_stats.count == expected_num_allocs);
|
||||
|
||||
const int num_stored_allocs = test_alloc_base::count;
|
||||
const int num_stored_allocs = alloc_stats.count;
|
||||
{
|
||||
const AllocT& a = v.get_allocator();
|
||||
assert(test_alloc_base::count == 1 + num_stored_allocs);
|
||||
assert(alloc_stats.count == 1 + num_stored_allocs);
|
||||
assert(a.get_data() == 42);
|
||||
assert(a.get_id() == 101);
|
||||
}
|
||||
assert(test_alloc_base::count == num_stored_allocs);
|
||||
test_alloc_base::clear_ctor_counters();
|
||||
assert(alloc_stats.count == num_stored_allocs);
|
||||
alloc_stats.clear_ctor_counters();
|
||||
|
||||
C v2 = std::move(v);
|
||||
assert(test_alloc_base::count == num_stored_allocs * 2);
|
||||
assert(test_alloc_base::copied == 0);
|
||||
assert(test_alloc_base::moved == num_stored_allocs);
|
||||
assert(alloc_stats.count == num_stored_allocs * 2);
|
||||
assert(alloc_stats.copied == 0);
|
||||
assert(alloc_stats.moved == num_stored_allocs);
|
||||
{
|
||||
const AllocT& a = v.get_allocator();
|
||||
assert(a.get_id() == test_alloc_base::moved_value);
|
||||
|
|
|
@ -86,11 +86,12 @@ int main(int, char**)
|
|||
}
|
||||
|
||||
{
|
||||
test_allocator_statistics alloc_stats;
|
||||
typedef std::deque<CMyClass, test_allocator<CMyClass> > C;
|
||||
C vec;
|
||||
C vec2(vec);
|
||||
C vec((test_allocator<CMyClass>(&alloc_stats)));
|
||||
C vec2(vec, test_allocator<CMyClass>(&alloc_stats));
|
||||
|
||||
C::allocator_type::throw_after = 1;
|
||||
alloc_stats.throw_after = 1;
|
||||
try {
|
||||
vec.push_back(instance);
|
||||
assert(false);
|
||||
|
|
|
@ -86,11 +86,12 @@ int main(int, char**)
|
|||
}
|
||||
|
||||
{
|
||||
test_allocator_statistics alloc_stats;
|
||||
typedef std::deque<CMyClass, test_allocator<CMyClass> > C;
|
||||
C vec;
|
||||
C vec2(vec);
|
||||
C vec((test_allocator<CMyClass>(&alloc_stats)));
|
||||
C vec2(vec, test_allocator<CMyClass>(&alloc_stats));
|
||||
|
||||
C::allocator_type::throw_after = 1;
|
||||
alloc_stats.throw_after = 1;
|
||||
try {
|
||||
vec.push_front(instance);
|
||||
assert(false);
|
||||
|
|
|
@ -20,9 +20,10 @@
|
|||
|
||||
int main(int, char**)
|
||||
{
|
||||
test_allocator_statistics alloc_stats;
|
||||
{
|
||||
std::vector<bool, test_allocator<bool> > l(test_allocator<bool>(5));
|
||||
std::vector<bool, test_allocator<bool> > lo(test_allocator<bool>(5));
|
||||
std::vector<bool, test_allocator<bool> > l(test_allocator<bool>(5, &alloc_stats));
|
||||
std::vector<bool, test_allocator<bool> > lo(test_allocator<bool>(5, &alloc_stats));
|
||||
for (int i = 1; i <= 3; ++i)
|
||||
{
|
||||
l.push_back(true);
|
||||
|
@ -60,24 +61,24 @@ int main(int, char**)
|
|||
assert(l2.get_allocator() == lo.get_allocator());
|
||||
}
|
||||
{
|
||||
test_alloc_base::clear();
|
||||
alloc_stats.clear();
|
||||
using Vect = std::vector<bool, test_allocator<bool> >;
|
||||
using AllocT = Vect::allocator_type;
|
||||
Vect v(test_allocator<bool>(42, 101));
|
||||
assert(test_alloc_base::count == 1);
|
||||
Vect v(test_allocator<bool>(42, 101, &alloc_stats));
|
||||
assert(alloc_stats.count == 1);
|
||||
{
|
||||
const AllocT& a = v.get_allocator();
|
||||
assert(test_alloc_base::count == 2);
|
||||
assert(alloc_stats.count == 2);
|
||||
assert(a.get_data() == 42);
|
||||
assert(a.get_id() == 101);
|
||||
}
|
||||
assert(test_alloc_base::count == 1);
|
||||
test_alloc_base::clear_ctor_counters();
|
||||
assert(alloc_stats.count == 1);
|
||||
alloc_stats.clear_ctor_counters();
|
||||
|
||||
Vect v2 = std::move(v);
|
||||
assert(test_alloc_base::count == 2);
|
||||
assert(test_alloc_base::copied == 0);
|
||||
assert(test_alloc_base::moved == 1);
|
||||
assert(alloc_stats.count == 2);
|
||||
assert(alloc_stats.copied == 0);
|
||||
assert(alloc_stats.moved == 1);
|
||||
{
|
||||
const AllocT& a = v.get_allocator();
|
||||
assert(a.get_id() == test_alloc_base::moved_value);
|
||||
|
|
|
@ -23,9 +23,10 @@
|
|||
|
||||
int main(int, char**)
|
||||
{
|
||||
test_allocator_statistics alloc_stats;
|
||||
{
|
||||
std::vector<MoveOnly, test_allocator<MoveOnly> > l(test_allocator<MoveOnly>(5));
|
||||
std::vector<MoveOnly, test_allocator<MoveOnly> > lo(test_allocator<MoveOnly>(5));
|
||||
std::vector<MoveOnly, test_allocator<MoveOnly> > l(test_allocator<MoveOnly>(5, &alloc_stats));
|
||||
std::vector<MoveOnly, test_allocator<MoveOnly> > lo(test_allocator<MoveOnly>(5, &alloc_stats));
|
||||
assert(is_contiguous_container_asan_correct(l));
|
||||
assert(is_contiguous_container_asan_correct(lo));
|
||||
for (int i = 1; i <= 3; ++i)
|
||||
|
@ -100,24 +101,24 @@ int main(int, char**)
|
|||
assert(is_contiguous_container_asan_correct(c2));
|
||||
}
|
||||
{
|
||||
test_alloc_base::clear();
|
||||
alloc_stats.clear();
|
||||
using Vect = std::vector<int, test_allocator<int> >;
|
||||
Vect v(test_allocator<int>(42, 101));
|
||||
assert(test_alloc_base::count == 1);
|
||||
assert(test_alloc_base::copied == 1);
|
||||
assert(test_alloc_base::moved == 0);
|
||||
Vect v(test_allocator<int>(42, 101, &alloc_stats));
|
||||
assert(alloc_stats.count == 1);
|
||||
assert(alloc_stats.copied == 1);
|
||||
assert(alloc_stats.moved == 0);
|
||||
{
|
||||
const test_allocator<int>& a = v.get_allocator();
|
||||
assert(a.get_data() == 42);
|
||||
assert(a.get_id() == 101);
|
||||
}
|
||||
assert(test_alloc_base::count == 1);
|
||||
test_alloc_base::clear_ctor_counters();
|
||||
assert(alloc_stats.count == 1);
|
||||
alloc_stats.clear_ctor_counters();
|
||||
|
||||
Vect v2 = std::move(v);
|
||||
assert(test_alloc_base::count == 2);
|
||||
assert(test_alloc_base::copied == 0);
|
||||
assert(test_alloc_base::moved == 1);
|
||||
assert(alloc_stats.count == 2);
|
||||
assert(alloc_stats.copied == 0);
|
||||
assert(alloc_stats.moved == 1);
|
||||
{
|
||||
const test_allocator<int>& a = v.get_allocator();
|
||||
assert(a.get_id() == test_alloc_base::moved_value);
|
||||
|
|
|
@ -37,16 +37,17 @@ test(const Allocator& a)
|
|||
|
||||
int main(int, char**)
|
||||
{
|
||||
test_allocator_statistics alloc_stats;
|
||||
test<char> (std::allocator<std::sub_match<const char *> >());
|
||||
#ifndef TEST_HAS_NO_WIDE_CHARACTERS
|
||||
test<wchar_t>(std::allocator<std::sub_match<const wchar_t *> >());
|
||||
#endif
|
||||
|
||||
test<char> (test_allocator<std::sub_match<const char*> >(3));
|
||||
assert(test_alloc_base::moved == 1);
|
||||
test<char> (test_allocator<std::sub_match<const char*> >(3, &alloc_stats));
|
||||
assert(alloc_stats.moved == 1);
|
||||
#ifndef TEST_HAS_NO_WIDE_CHARACTERS
|
||||
test<wchar_t>(test_allocator<std::sub_match<const wchar_t*> >(3));
|
||||
assert(test_alloc_base::moved == 2);
|
||||
test<wchar_t>(test_allocator<std::sub_match<const wchar_t*> >(3, &alloc_stats));
|
||||
assert(alloc_stats.moved == 2);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -18,11 +18,13 @@
|
|||
|
||||
#include "test_macros.h"
|
||||
|
||||
test_allocator_statistics alloc_stats;
|
||||
|
||||
template <class S>
|
||||
void
|
||||
test(S s)
|
||||
{
|
||||
S::allocator_type::throw_after = 0;
|
||||
alloc_stats.throw_after = 0;
|
||||
#ifndef TEST_HAS_NO_EXCEPTIONS
|
||||
try
|
||||
#endif
|
||||
|
@ -37,14 +39,14 @@ test(S s)
|
|||
assert(false);
|
||||
}
|
||||
#endif
|
||||
S::allocator_type::throw_after = INT_MAX;
|
||||
alloc_stats.throw_after = INT_MAX;
|
||||
}
|
||||
|
||||
int main(int, char**)
|
||||
{
|
||||
{
|
||||
typedef std::basic_string<char, std::char_traits<char>, test_allocator<char> > S;
|
||||
S s;
|
||||
S s((test_allocator<char>(&alloc_stats)));
|
||||
test(s);
|
||||
s.assign(10, 'a');
|
||||
s.erase(5);
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
#include "test_allocator.h"
|
||||
#include "min_allocator.h"
|
||||
|
||||
|
||||
template <class S>
|
||||
void
|
||||
test(S s0, const typename S::allocator_type& a)
|
||||
|
@ -33,9 +32,9 @@ test(S s0, const typename S::allocator_type& a)
|
|||
assert(s2.get_allocator() == a);
|
||||
}
|
||||
|
||||
|
||||
int main(int, char**)
|
||||
{
|
||||
test_allocator_statistics alloc_stats;
|
||||
{
|
||||
typedef test_allocator<char> A;
|
||||
typedef std::basic_string<char, std::char_traits<char>, A> S;
|
||||
|
@ -44,12 +43,12 @@ int main(int, char**)
|
|||
#elif TEST_STD_VER >= 11
|
||||
static_assert((noexcept(S()) == std::is_nothrow_move_constructible<A>::value), "" );
|
||||
#endif
|
||||
test(S(), A(3));
|
||||
test(S("1"), A(5));
|
||||
test(S("1234567890123456789012345678901234567890123456789012345678901234567890"), A(7));
|
||||
test(S(), A(3, &alloc_stats));
|
||||
test(S("1"), A(5, &alloc_stats));
|
||||
test(S("1234567890123456789012345678901234567890123456789012345678901234567890"), A(7, &alloc_stats));
|
||||
}
|
||||
|
||||
int alloc_count = test_alloc_base::alloc_count;
|
||||
int alloc_count = alloc_stats.alloc_count;
|
||||
{
|
||||
typedef test_allocator<char> A;
|
||||
typedef std::basic_string<char, std::char_traits<char>, A> S;
|
||||
|
@ -58,10 +57,10 @@ int main(int, char**)
|
|||
#elif TEST_STD_VER >= 11
|
||||
static_assert((noexcept(S()) == std::is_nothrow_move_constructible<A>::value), "" );
|
||||
#endif
|
||||
S s1 ( "Twas brillig, and the slivy toves did gyre and gymbal in the wabe" );
|
||||
S s2 (std::move(s1), A(1));
|
||||
S s1 ( "Twas brillig, and the slivy toves did gyre and gymbal in the wabe", A(&alloc_stats));
|
||||
S s2 (std::move(s1), A(1, &alloc_stats));
|
||||
}
|
||||
assert ( test_alloc_base::alloc_count == alloc_count );
|
||||
assert ( alloc_stats.alloc_count == alloc_count );
|
||||
{
|
||||
typedef min_allocator<char> A;
|
||||
typedef std::basic_string<char, std::char_traits<char>, A> S;
|
||||
|
|
|
@ -25,31 +25,32 @@
|
|||
|
||||
int main(int, char**)
|
||||
{
|
||||
assert(test_alloc_base::alloc_count == 0);
|
||||
test_allocator_statistics alloc_stats;
|
||||
assert(alloc_stats.alloc_count == 0);
|
||||
{
|
||||
std::promise<int> p(std::allocator_arg, test_allocator<int>(42));
|
||||
assert(test_alloc_base::alloc_count == 1);
|
||||
std::promise<int> p(std::allocator_arg, test_allocator<int>(42, &alloc_stats));
|
||||
assert(alloc_stats.alloc_count == 1);
|
||||
std::future<int> f = p.get_future();
|
||||
assert(test_alloc_base::alloc_count == 1);
|
||||
assert(alloc_stats.alloc_count == 1);
|
||||
assert(f.valid());
|
||||
}
|
||||
assert(test_alloc_base::alloc_count == 0);
|
||||
assert(alloc_stats.alloc_count == 0);
|
||||
{
|
||||
std::promise<int&> p(std::allocator_arg, test_allocator<int>(42));
|
||||
assert(test_alloc_base::alloc_count == 1);
|
||||
std::promise<int&> p(std::allocator_arg, test_allocator<int>(42, &alloc_stats));
|
||||
assert(alloc_stats.alloc_count == 1);
|
||||
std::future<int&> f = p.get_future();
|
||||
assert(test_alloc_base::alloc_count == 1);
|
||||
assert(alloc_stats.alloc_count == 1);
|
||||
assert(f.valid());
|
||||
}
|
||||
assert(test_alloc_base::alloc_count == 0);
|
||||
assert(alloc_stats.alloc_count == 0);
|
||||
{
|
||||
std::promise<void> p(std::allocator_arg, test_allocator<void>(42));
|
||||
assert(test_alloc_base::alloc_count == 1);
|
||||
std::promise<void> p(std::allocator_arg, test_allocator<void>(42, &alloc_stats));
|
||||
assert(alloc_stats.alloc_count == 1);
|
||||
std::future<void> f = p.get_future();
|
||||
assert(test_alloc_base::alloc_count == 1);
|
||||
assert(alloc_stats.alloc_count == 1);
|
||||
assert(f.valid());
|
||||
}
|
||||
assert(test_alloc_base::alloc_count == 0);
|
||||
assert(alloc_stats.alloc_count == 0);
|
||||
// Test with a minimal allocator
|
||||
{
|
||||
std::promise<int> p(std::allocator_arg, bare_allocator<void>());
|
||||
|
|
|
@ -23,15 +23,16 @@
|
|||
|
||||
int main(int, char**)
|
||||
{
|
||||
assert(test_alloc_base::alloc_count == 0);
|
||||
test_allocator_statistics alloc_stats;
|
||||
assert(alloc_stats.alloc_count == 0);
|
||||
{
|
||||
std::promise<int> p0(std::allocator_arg, test_allocator<int>());
|
||||
std::promise<int> p(std::allocator_arg, test_allocator<int>());
|
||||
assert(test_alloc_base::alloc_count == 2);
|
||||
std::promise<int> p0(std::allocator_arg, test_allocator<int>(&alloc_stats));
|
||||
std::promise<int> p(std::allocator_arg, test_allocator<int>(&alloc_stats));
|
||||
assert(alloc_stats.alloc_count == 2);
|
||||
p = std::move(p0);
|
||||
assert(test_alloc_base::alloc_count == 1);
|
||||
assert(alloc_stats.alloc_count == 1);
|
||||
std::future<int> f = p.get_future();
|
||||
assert(test_alloc_base::alloc_count == 1);
|
||||
assert(alloc_stats.alloc_count == 1);
|
||||
assert(f.valid());
|
||||
#ifndef TEST_HAS_NO_EXCEPTIONS
|
||||
try
|
||||
|
@ -44,17 +45,17 @@ int main(int, char**)
|
|||
assert(e.code() == make_error_code(std::future_errc::no_state));
|
||||
}
|
||||
#endif
|
||||
assert(test_alloc_base::alloc_count == 1);
|
||||
assert(alloc_stats.alloc_count == 1);
|
||||
}
|
||||
assert(test_alloc_base::alloc_count == 0);
|
||||
assert(alloc_stats.alloc_count == 0);
|
||||
{
|
||||
std::promise<int&> p0(std::allocator_arg, test_allocator<int>());
|
||||
std::promise<int&> p(std::allocator_arg, test_allocator<int>());
|
||||
assert(test_alloc_base::alloc_count == 2);
|
||||
std::promise<int&> p0(std::allocator_arg, test_allocator<int>(&alloc_stats));
|
||||
std::promise<int&> p(std::allocator_arg, test_allocator<int>(&alloc_stats));
|
||||
assert(alloc_stats.alloc_count == 2);
|
||||
p = std::move(p0);
|
||||
assert(test_alloc_base::alloc_count == 1);
|
||||
assert(alloc_stats.alloc_count == 1);
|
||||
std::future<int&> f = p.get_future();
|
||||
assert(test_alloc_base::alloc_count == 1);
|
||||
assert(alloc_stats.alloc_count == 1);
|
||||
assert(f.valid());
|
||||
#ifndef TEST_HAS_NO_EXCEPTIONS
|
||||
try
|
||||
|
@ -67,17 +68,17 @@ int main(int, char**)
|
|||
assert(e.code() == make_error_code(std::future_errc::no_state));
|
||||
}
|
||||
#endif
|
||||
assert(test_alloc_base::alloc_count == 1);
|
||||
assert(alloc_stats.alloc_count == 1);
|
||||
}
|
||||
assert(test_alloc_base::alloc_count == 0);
|
||||
assert(alloc_stats.alloc_count == 0);
|
||||
{
|
||||
std::promise<void> p0(std::allocator_arg, test_allocator<void>());
|
||||
std::promise<void> p(std::allocator_arg, test_allocator<void>());
|
||||
assert(test_alloc_base::alloc_count == 2);
|
||||
std::promise<void> p0(std::allocator_arg, test_allocator<void>(&alloc_stats));
|
||||
std::promise<void> p(std::allocator_arg, test_allocator<void>(&alloc_stats));
|
||||
assert(alloc_stats.alloc_count == 2);
|
||||
p = std::move(p0);
|
||||
assert(test_alloc_base::alloc_count == 1);
|
||||
assert(alloc_stats.alloc_count == 1);
|
||||
std::future<void> f = p.get_future();
|
||||
assert(test_alloc_base::alloc_count == 1);
|
||||
assert(alloc_stats.alloc_count == 1);
|
||||
assert(f.valid());
|
||||
#ifndef TEST_HAS_NO_EXCEPTIONS
|
||||
try
|
||||
|
@ -90,9 +91,9 @@ int main(int, char**)
|
|||
assert(e.code() == make_error_code(std::future_errc::no_state));
|
||||
}
|
||||
#endif
|
||||
assert(test_alloc_base::alloc_count == 1);
|
||||
assert(alloc_stats.alloc_count == 1);
|
||||
}
|
||||
assert(test_alloc_base::alloc_count == 0);
|
||||
assert(alloc_stats.alloc_count == 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -23,13 +23,14 @@
|
|||
|
||||
int main(int, char**)
|
||||
{
|
||||
assert(test_alloc_base::alloc_count == 0);
|
||||
test_allocator_statistics alloc_stats;
|
||||
assert(alloc_stats.alloc_count == 0);
|
||||
{
|
||||
std::promise<int> p0(std::allocator_arg, test_allocator<int>());
|
||||
std::promise<int> p0(std::allocator_arg, test_allocator<int>(&alloc_stats));
|
||||
std::promise<int> p(std::move(p0));
|
||||
assert(test_alloc_base::alloc_count == 1);
|
||||
assert(alloc_stats.alloc_count == 1);
|
||||
std::future<int> f = p.get_future();
|
||||
assert(test_alloc_base::alloc_count == 1);
|
||||
assert(alloc_stats.alloc_count == 1);
|
||||
assert(f.valid());
|
||||
#ifndef TEST_HAS_NO_EXCEPTIONS
|
||||
try
|
||||
|
@ -41,16 +42,16 @@ int main(int, char**)
|
|||
{
|
||||
assert(e.code() == make_error_code(std::future_errc::no_state));
|
||||
}
|
||||
assert(test_alloc_base::alloc_count == 1);
|
||||
assert(alloc_stats.alloc_count == 1);
|
||||
#endif
|
||||
}
|
||||
assert(test_alloc_base::alloc_count == 0);
|
||||
assert(alloc_stats.alloc_count == 0);
|
||||
{
|
||||
std::promise<int&> p0(std::allocator_arg, test_allocator<int>());
|
||||
std::promise<int&> p0(std::allocator_arg, test_allocator<int>(&alloc_stats));
|
||||
std::promise<int&> p(std::move(p0));
|
||||
assert(test_alloc_base::alloc_count == 1);
|
||||
assert(alloc_stats.alloc_count == 1);
|
||||
std::future<int&> f = p.get_future();
|
||||
assert(test_alloc_base::alloc_count == 1);
|
||||
assert(alloc_stats.alloc_count == 1);
|
||||
assert(f.valid());
|
||||
#ifndef TEST_HAS_NO_EXCEPTIONS
|
||||
try
|
||||
|
@ -62,16 +63,16 @@ int main(int, char**)
|
|||
{
|
||||
assert(e.code() == make_error_code(std::future_errc::no_state));
|
||||
}
|
||||
assert(test_alloc_base::alloc_count == 1);
|
||||
assert(alloc_stats.alloc_count == 1);
|
||||
#endif
|
||||
}
|
||||
assert(test_alloc_base::alloc_count == 0);
|
||||
assert(alloc_stats.alloc_count == 0);
|
||||
{
|
||||
std::promise<void> p0(std::allocator_arg, test_allocator<void>());
|
||||
std::promise<void> p0(std::allocator_arg, test_allocator<void>(&alloc_stats));
|
||||
std::promise<void> p(std::move(p0));
|
||||
assert(test_alloc_base::alloc_count == 1);
|
||||
assert(alloc_stats.alloc_count == 1);
|
||||
std::future<void> f = p.get_future();
|
||||
assert(test_alloc_base::alloc_count == 1);
|
||||
assert(alloc_stats.alloc_count == 1);
|
||||
assert(f.valid());
|
||||
#ifndef TEST_HAS_NO_EXCEPTIONS
|
||||
try
|
||||
|
@ -83,10 +84,10 @@ int main(int, char**)
|
|||
{
|
||||
assert(e.code() == make_error_code(std::future_errc::no_state));
|
||||
}
|
||||
assert(test_alloc_base::alloc_count == 1);
|
||||
assert(alloc_stats.alloc_count == 1);
|
||||
#endif
|
||||
}
|
||||
assert(test_alloc_base::alloc_count == 0);
|
||||
assert(alloc_stats.alloc_count == 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -25,63 +25,64 @@
|
|||
|
||||
int main(int, char**)
|
||||
{
|
||||
assert(test_alloc_base::alloc_count == 0);
|
||||
test_allocator_statistics alloc_stats;
|
||||
assert(alloc_stats.alloc_count == 0);
|
||||
{
|
||||
std::promise<int> p0(std::allocator_arg, test_allocator<int>());
|
||||
std::promise<int> p(std::allocator_arg, test_allocator<int>());
|
||||
assert(test_alloc_base::alloc_count == 2);
|
||||
std::promise<int> p0(std::allocator_arg, test_allocator<int>(&alloc_stats));
|
||||
std::promise<int> p(std::allocator_arg, test_allocator<int>(&alloc_stats));
|
||||
assert(alloc_stats.alloc_count == 2);
|
||||
p.swap(p0);
|
||||
assert(test_alloc_base::alloc_count == 2);
|
||||
assert(alloc_stats.alloc_count == 2);
|
||||
std::future<int> f = p.get_future();
|
||||
assert(test_alloc_base::alloc_count == 2);
|
||||
assert(alloc_stats.alloc_count == 2);
|
||||
assert(f.valid());
|
||||
f = p0.get_future();
|
||||
assert(f.valid());
|
||||
assert(test_alloc_base::alloc_count == 2);
|
||||
assert(alloc_stats.alloc_count == 2);
|
||||
}
|
||||
assert(test_alloc_base::alloc_count == 0);
|
||||
assert(alloc_stats.alloc_count == 0);
|
||||
{
|
||||
std::promise<int> p0(std::allocator_arg, test_allocator<int>());
|
||||
std::promise<int> p(std::allocator_arg, test_allocator<int>());
|
||||
assert(test_alloc_base::alloc_count == 2);
|
||||
std::promise<int> p0(std::allocator_arg, test_allocator<int>(&alloc_stats));
|
||||
std::promise<int> p(std::allocator_arg, test_allocator<int>(&alloc_stats));
|
||||
assert(alloc_stats.alloc_count == 2);
|
||||
swap(p, p0);
|
||||
assert(test_alloc_base::alloc_count == 2);
|
||||
assert(alloc_stats.alloc_count == 2);
|
||||
std::future<int> f = p.get_future();
|
||||
assert(test_alloc_base::alloc_count == 2);
|
||||
assert(alloc_stats.alloc_count == 2);
|
||||
assert(f.valid());
|
||||
f = p0.get_future();
|
||||
assert(f.valid());
|
||||
assert(test_alloc_base::alloc_count == 2);
|
||||
assert(alloc_stats.alloc_count == 2);
|
||||
}
|
||||
assert(test_alloc_base::alloc_count == 0);
|
||||
assert(alloc_stats.alloc_count == 0);
|
||||
{
|
||||
std::promise<int> p0(std::allocator_arg, test_allocator<int>());
|
||||
std::promise<int> p0(std::allocator_arg, test_allocator<int>(&alloc_stats));
|
||||
std::promise<int> p;
|
||||
assert(test_alloc_base::alloc_count == 1);
|
||||
assert(alloc_stats.alloc_count == 1);
|
||||
p.swap(p0);
|
||||
assert(test_alloc_base::alloc_count == 1);
|
||||
assert(alloc_stats.alloc_count == 1);
|
||||
std::future<int> f = p.get_future();
|
||||
assert(test_alloc_base::alloc_count == 1);
|
||||
assert(alloc_stats.alloc_count == 1);
|
||||
assert(f.valid());
|
||||
f = p0.get_future();
|
||||
assert(f.valid());
|
||||
assert(test_alloc_base::alloc_count == 1);
|
||||
assert(alloc_stats.alloc_count == 1);
|
||||
}
|
||||
assert(test_alloc_base::alloc_count == 0);
|
||||
assert(alloc_stats.alloc_count == 0);
|
||||
{
|
||||
std::promise<int> p0(std::allocator_arg, test_allocator<int>());
|
||||
std::promise<int> p0(std::allocator_arg, test_allocator<int>(&alloc_stats));
|
||||
std::promise<int> p;
|
||||
assert(test_alloc_base::alloc_count == 1);
|
||||
assert(alloc_stats.alloc_count == 1);
|
||||
swap(p, p0);
|
||||
assert(test_alloc_base::alloc_count == 1);
|
||||
assert(alloc_stats.alloc_count == 1);
|
||||
std::future<int> f = p.get_future();
|
||||
assert(test_alloc_base::alloc_count == 1);
|
||||
assert(alloc_stats.alloc_count == 1);
|
||||
assert(f.valid());
|
||||
f = p0.get_future();
|
||||
assert(f.valid());
|
||||
assert(test_alloc_base::alloc_count == 1);
|
||||
assert(alloc_stats.alloc_count == 1);
|
||||
}
|
||||
assert(test_alloc_base::alloc_count == 0);
|
||||
assert(alloc_stats.alloc_count == 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -24,49 +24,50 @@
|
|||
|
||||
int main(int, char**)
|
||||
{
|
||||
assert(test_alloc_base::alloc_count == 0);
|
||||
test_allocator_statistics alloc_stats;
|
||||
assert(alloc_stats.alloc_count == 0);
|
||||
{
|
||||
typedef int T;
|
||||
std::shared_future<T> f;
|
||||
{
|
||||
std::promise<T> p(std::allocator_arg, test_allocator<T>());
|
||||
assert(test_alloc_base::alloc_count == 1);
|
||||
std::promise<T> p(std::allocator_arg, test_allocator<T>(&alloc_stats));
|
||||
assert(alloc_stats.alloc_count == 1);
|
||||
f = p.get_future();
|
||||
assert(test_alloc_base::alloc_count == 1);
|
||||
assert(alloc_stats.alloc_count == 1);
|
||||
assert(f.valid());
|
||||
}
|
||||
assert(test_alloc_base::alloc_count == 1);
|
||||
assert(alloc_stats.alloc_count == 1);
|
||||
assert(f.valid());
|
||||
}
|
||||
assert(test_alloc_base::alloc_count == 0);
|
||||
assert(alloc_stats.alloc_count == 0);
|
||||
{
|
||||
typedef int& T;
|
||||
std::shared_future<T> f;
|
||||
{
|
||||
std::promise<T> p(std::allocator_arg, test_allocator<int>());
|
||||
assert(test_alloc_base::alloc_count == 1);
|
||||
std::promise<T> p(std::allocator_arg, test_allocator<int>(&alloc_stats));
|
||||
assert(alloc_stats.alloc_count == 1);
|
||||
f = p.get_future();
|
||||
assert(test_alloc_base::alloc_count == 1);
|
||||
assert(alloc_stats.alloc_count == 1);
|
||||
assert(f.valid());
|
||||
}
|
||||
assert(test_alloc_base::alloc_count == 1);
|
||||
assert(alloc_stats.alloc_count == 1);
|
||||
assert(f.valid());
|
||||
}
|
||||
assert(test_alloc_base::alloc_count == 0);
|
||||
assert(alloc_stats.alloc_count == 0);
|
||||
{
|
||||
typedef void T;
|
||||
std::shared_future<T> f;
|
||||
{
|
||||
std::promise<T> p(std::allocator_arg, test_allocator<T>());
|
||||
assert(test_alloc_base::alloc_count == 1);
|
||||
std::promise<T> p(std::allocator_arg, test_allocator<T>(&alloc_stats));
|
||||
assert(alloc_stats.alloc_count == 1);
|
||||
f = p.get_future();
|
||||
assert(test_alloc_base::alloc_count == 1);
|
||||
assert(alloc_stats.alloc_count == 1);
|
||||
assert(f.valid());
|
||||
}
|
||||
assert(test_alloc_base::alloc_count == 1);
|
||||
assert(alloc_stats.alloc_count == 1);
|
||||
assert(f.valid());
|
||||
}
|
||||
assert(test_alloc_base::alloc_count == 0);
|
||||
assert(alloc_stats.alloc_count == 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -47,10 +47,11 @@ int func(int i) { return i; }
|
|||
|
||||
int main(int, char**)
|
||||
{
|
||||
test_allocator_statistics alloc_stats;
|
||||
{
|
||||
std::packaged_task<double(int, char)> p(std::allocator_arg,
|
||||
test_allocator<A>(), A(5));
|
||||
assert(test_alloc_base::alloc_count > 0);
|
||||
test_allocator<A>(&alloc_stats), A(5));
|
||||
assert(alloc_stats.alloc_count > 0);
|
||||
assert(p.valid());
|
||||
std::future<double> f = p.get_future();
|
||||
p(3, 'a');
|
||||
|
@ -58,14 +59,14 @@ int main(int, char**)
|
|||
assert(A::n_copies == 0);
|
||||
assert(A::n_moves > 0);
|
||||
}
|
||||
assert(test_alloc_base::alloc_count == 0);
|
||||
assert(alloc_stats.alloc_count == 0);
|
||||
A::n_copies = 0;
|
||||
A::n_moves = 0;
|
||||
{
|
||||
A a(5);
|
||||
std::packaged_task<double(int, char)> p(std::allocator_arg,
|
||||
test_allocator<A>(), a);
|
||||
assert(test_alloc_base::alloc_count > 0);
|
||||
test_allocator<A>(&alloc_stats), a);
|
||||
assert(alloc_stats.alloc_count > 0);
|
||||
assert(p.valid());
|
||||
std::future<double> f = p.get_future();
|
||||
p(3, 'a');
|
||||
|
@ -73,31 +74,31 @@ int main(int, char**)
|
|||
assert(A::n_copies > 0);
|
||||
assert(A::n_moves >= 0);
|
||||
}
|
||||
assert(test_alloc_base::alloc_count == 0);
|
||||
assert(alloc_stats.alloc_count == 0);
|
||||
A::n_copies = 0;
|
||||
A::n_moves = 0;
|
||||
{
|
||||
A a(5);
|
||||
std::packaged_task<int(int)> p(std::allocator_arg, test_allocator<A>(), &func);
|
||||
assert(test_alloc_base::alloc_count > 0);
|
||||
std::packaged_task<int(int)> p(std::allocator_arg, test_allocator<A>(&alloc_stats), &func);
|
||||
assert(alloc_stats.alloc_count > 0);
|
||||
assert(p.valid());
|
||||
std::future<int> f = p.get_future();
|
||||
p(4);
|
||||
assert(f.get() == 4);
|
||||
}
|
||||
assert(test_alloc_base::alloc_count == 0);
|
||||
assert(alloc_stats.alloc_count == 0);
|
||||
A::n_copies = 0;
|
||||
A::n_moves = 0;
|
||||
{
|
||||
A a(5);
|
||||
std::packaged_task<int(int)> p(std::allocator_arg, test_allocator<A>(), func);
|
||||
assert(test_alloc_base::alloc_count > 0);
|
||||
std::packaged_task<int(int)> p(std::allocator_arg, test_allocator<A>(&alloc_stats), func);
|
||||
assert(alloc_stats.alloc_count > 0);
|
||||
assert(p.valid());
|
||||
std::future<int> f = p.get_future();
|
||||
p(4);
|
||||
assert(f.get() == 4);
|
||||
}
|
||||
assert(test_alloc_base::alloc_count == 0);
|
||||
assert(alloc_stats.alloc_count == 0);
|
||||
A::n_copies = 0;
|
||||
A::n_moves = 0;
|
||||
{
|
||||
|
|
|
@ -24,49 +24,50 @@
|
|||
|
||||
int main(int, char**)
|
||||
{
|
||||
assert(test_alloc_base::alloc_count == 0);
|
||||
test_allocator_statistics alloc_stats;
|
||||
assert(alloc_stats.alloc_count == 0);
|
||||
{
|
||||
typedef int T;
|
||||
std::future<T> f;
|
||||
{
|
||||
std::promise<T> p(std::allocator_arg, test_allocator<T>());
|
||||
assert(test_alloc_base::alloc_count == 1);
|
||||
std::promise<T> p(std::allocator_arg, test_allocator<T>(&alloc_stats));
|
||||
assert(alloc_stats.alloc_count == 1);
|
||||
f = p.get_future();
|
||||
assert(test_alloc_base::alloc_count == 1);
|
||||
assert(alloc_stats.alloc_count == 1);
|
||||
assert(f.valid());
|
||||
}
|
||||
assert(test_alloc_base::alloc_count == 1);
|
||||
assert(alloc_stats.alloc_count == 1);
|
||||
assert(f.valid());
|
||||
}
|
||||
assert(test_alloc_base::alloc_count == 0);
|
||||
assert(alloc_stats.alloc_count == 0);
|
||||
{
|
||||
typedef int& T;
|
||||
std::future<T> f;
|
||||
{
|
||||
std::promise<T> p(std::allocator_arg, test_allocator<int>());
|
||||
assert(test_alloc_base::alloc_count == 1);
|
||||
std::promise<T> p(std::allocator_arg, test_allocator<int>(&alloc_stats));
|
||||
assert(alloc_stats.alloc_count == 1);
|
||||
f = p.get_future();
|
||||
assert(test_alloc_base::alloc_count == 1);
|
||||
assert(alloc_stats.alloc_count == 1);
|
||||
assert(f.valid());
|
||||
}
|
||||
assert(test_alloc_base::alloc_count == 1);
|
||||
assert(alloc_stats.alloc_count == 1);
|
||||
assert(f.valid());
|
||||
}
|
||||
assert(test_alloc_base::alloc_count == 0);
|
||||
assert(alloc_stats.alloc_count == 0);
|
||||
{
|
||||
typedef void T;
|
||||
std::future<T> f;
|
||||
{
|
||||
std::promise<T> p(std::allocator_arg, test_allocator<T>());
|
||||
assert(test_alloc_base::alloc_count == 1);
|
||||
std::promise<T> p(std::allocator_arg, test_allocator<T>(&alloc_stats));
|
||||
assert(alloc_stats.alloc_count == 1);
|
||||
f = p.get_future();
|
||||
assert(test_alloc_base::alloc_count == 1);
|
||||
assert(alloc_stats.alloc_count == 1);
|
||||
assert(f.valid());
|
||||
}
|
||||
assert(test_alloc_base::alloc_count == 1);
|
||||
assert(alloc_stats.alloc_count == 1);
|
||||
assert(f.valid());
|
||||
}
|
||||
assert(test_alloc_base::alloc_count == 0);
|
||||
assert(alloc_stats.alloc_count == 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -25,7 +25,6 @@
|
|||
#include "count_new.h"
|
||||
#include "../function_types.h"
|
||||
|
||||
|
||||
#if TEST_STD_VER >= 11
|
||||
struct RValueCallable {
|
||||
template <class ...Args>
|
||||
|
@ -37,6 +36,8 @@ struct LValueCallable {
|
|||
};
|
||||
#endif
|
||||
|
||||
test_allocator_statistics alloc_stats;
|
||||
|
||||
class DummyClass {};
|
||||
|
||||
template <class FuncType, class AllocType>
|
||||
|
@ -69,7 +70,7 @@ void test_FreeFunction(AllocType& alloc)
|
|||
std::function<FuncType> f2(std::allocator_arg, alloc, target);
|
||||
// The allocator may not fit in the small object buffer, if we allocated
|
||||
// check it was done via the allocator.
|
||||
assert(globalMemCounter.checkOutstandingNewEq(test_alloc_base::alloc_count));
|
||||
assert(globalMemCounter.checkOutstandingNewEq(alloc_stats.alloc_count));
|
||||
assert(f2.template target<FuncType*>());
|
||||
assert(*f2.template target<FuncType*>() == target);
|
||||
assert(f2.template target<FuncType>() == 0);
|
||||
|
@ -86,7 +87,7 @@ void test_MemFunClass(AllocType& alloc)
|
|||
TargetType target = &MemFunClass::foo;
|
||||
assert(globalMemCounter.checkOutstandingNewEq(0));
|
||||
std::function<FuncType> f2(std::allocator_arg, alloc, target);
|
||||
assert(globalMemCounter.checkOutstandingNewEq(test_alloc_base::alloc_count));
|
||||
assert(globalMemCounter.checkOutstandingNewEq(alloc_stats.alloc_count));
|
||||
assert(f2.template target<TargetType>());
|
||||
assert(*f2.template target<TargetType>() == target);
|
||||
assert(f2.template target<FuncType*>() == 0);
|
||||
|
@ -111,15 +112,14 @@ void test_for_alloc(Alloc& alloc) {
|
|||
test_MemFunClass<int(MemFunClass::*)(int, int) const, int(MemFunClass&, int, int)>(alloc);
|
||||
}
|
||||
|
||||
int main(int, char**)
|
||||
{
|
||||
int main(int, char**) {
|
||||
globalMemCounter.reset();
|
||||
{
|
||||
bare_allocator<DummyClass> bare_alloc;
|
||||
test_for_alloc(bare_alloc);
|
||||
}
|
||||
{
|
||||
non_default_test_allocator<DummyClass> non_default_alloc(42);
|
||||
non_default_test_allocator<DummyClass> non_default_alloc(42, &alloc_stats);
|
||||
test_for_alloc(non_default_alloc);
|
||||
}
|
||||
#if TEST_STD_VER >= 11
|
||||
|
|
|
@ -30,8 +30,9 @@ int A::count = 0;
|
|||
|
||||
int main(int, char**)
|
||||
{
|
||||
test_allocator_statistics alloc_stats;
|
||||
{
|
||||
std::shared_ptr<A> p(nullptr, test_deleter<A>(3), test_allocator<A>(5));
|
||||
std::shared_ptr<A> p(nullptr, test_deleter<A>(3), test_allocator<A>(5, &alloc_stats));
|
||||
assert(A::count == 0);
|
||||
assert(p.use_count() == 1);
|
||||
assert(p.get() == 0);
|
||||
|
@ -42,14 +43,14 @@ int main(int, char**)
|
|||
assert(d);
|
||||
assert(d->state() == 3);
|
||||
#endif
|
||||
assert(test_allocator<A>::count == 1);
|
||||
assert(test_allocator<A>::alloc_count == 1);
|
||||
assert(alloc_stats.count == 1);
|
||||
assert(alloc_stats.alloc_count == 1);
|
||||
}
|
||||
assert(A::count == 0);
|
||||
assert(test_deleter<A>::count == 0);
|
||||
assert(test_deleter<A>::dealloc_count == 1);
|
||||
assert(test_allocator<A>::count == 0);
|
||||
assert(test_allocator<A>::alloc_count == 0);
|
||||
assert(alloc_stats.count == 0);
|
||||
assert(alloc_stats.alloc_count == 0);
|
||||
test_deleter<A>::dealloc_count = 0;
|
||||
// Test an allocator with a minimal interface
|
||||
{
|
||||
|
|
|
@ -30,10 +30,11 @@ int A::count = 0;
|
|||
|
||||
int main(int, char**)
|
||||
{
|
||||
test_allocator_statistics alloc_stats;
|
||||
try
|
||||
{
|
||||
test_allocator<A>::throw_after = 0;
|
||||
std::shared_ptr<A> p(nullptr, test_deleter<A>(3), test_allocator<A>(5));
|
||||
alloc_stats.throw_after = 0;
|
||||
std::shared_ptr<A> p(nullptr, test_deleter<A>(3), test_allocator<A>(5, &alloc_stats));
|
||||
assert(false);
|
||||
}
|
||||
catch (std::bad_alloc&)
|
||||
|
@ -41,8 +42,8 @@ int main(int, char**)
|
|||
assert(A::count == 0);
|
||||
assert(test_deleter<A>::count == 0);
|
||||
assert(test_deleter<A>::dealloc_count == 1);
|
||||
assert(test_allocator<A>::count == 0);
|
||||
assert(test_allocator<A>::alloc_count == 0);
|
||||
assert(alloc_stats.count == 0);
|
||||
assert(alloc_stats.alloc_count == 0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -62,9 +62,10 @@ public:
|
|||
|
||||
int main(int, char**)
|
||||
{
|
||||
test_allocator_statistics alloc_stats;
|
||||
{
|
||||
A* ptr = new A;
|
||||
std::shared_ptr<A> p(ptr, test_deleter<A>(3), test_allocator<A>(5));
|
||||
std::shared_ptr<A> p(ptr, test_deleter<A>(3), test_allocator<A>(5, &alloc_stats));
|
||||
assert(A::count == 1);
|
||||
assert(p.use_count() == 1);
|
||||
assert(p.get() == ptr);
|
||||
|
@ -75,14 +76,14 @@ int main(int, char**)
|
|||
assert(d);
|
||||
assert(d->state() == 3);
|
||||
#endif
|
||||
assert(test_allocator<A>::count == 1);
|
||||
assert(test_allocator<A>::alloc_count == 1);
|
||||
assert(alloc_stats.count == 1);
|
||||
assert(alloc_stats.alloc_count == 1);
|
||||
}
|
||||
assert(A::count == 0);
|
||||
assert(test_deleter<A>::count == 0);
|
||||
assert(test_deleter<A>::dealloc_count == 1);
|
||||
assert(test_allocator<A>::count == 0);
|
||||
assert(test_allocator<A>::alloc_count == 0);
|
||||
assert(alloc_stats.count == 0);
|
||||
assert(alloc_stats.alloc_count == 0);
|
||||
test_deleter<A>::dealloc_count = 0;
|
||||
// Test an allocator with a minimal interface
|
||||
{
|
||||
|
|
|
@ -30,20 +30,21 @@ int A::count = 0;
|
|||
|
||||
int main(int, char**)
|
||||
{
|
||||
test_allocator_statistics alloc_stats;
|
||||
A* ptr = new A;
|
||||
try
|
||||
{
|
||||
test_allocator<A>::throw_after = 0;
|
||||
std::shared_ptr<A> p(ptr, test_deleter<A>(3), test_allocator<A>(5));
|
||||
alloc_stats.throw_after = 0;
|
||||
std::shared_ptr<A> p(ptr, test_deleter<A>(3), test_allocator<A>(5, &alloc_stats));
|
||||
assert(false);
|
||||
}
|
||||
catch (std::bad_alloc&)
|
||||
{
|
||||
assert(A::count == 0);
|
||||
assert(test_deleter<A>::count == 0);
|
||||
assert(alloc_stats.count == 0);
|
||||
assert(alloc_stats.count == 0);
|
||||
assert(test_deleter<A>::dealloc_count == 1);
|
||||
assert(test_allocator<A>::count == 0);
|
||||
assert(test_allocator<A>::alloc_count == 0);
|
||||
assert(alloc_stats.count == 0);
|
||||
assert(alloc_stats.alloc_count == 0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -141,17 +141,18 @@ int main(int, char**)
|
|||
test<bare_allocator<void> >();
|
||||
test<test_allocator<void> >();
|
||||
|
||||
test_allocator_statistics alloc_stats;
|
||||
{
|
||||
int i = 67;
|
||||
char c = 'e';
|
||||
std::shared_ptr<A> p = std::allocate_shared<A>(test_allocator<A>(54), i, c);
|
||||
assert(test_allocator<A>::alloc_count == 1);
|
||||
std::shared_ptr<A> p = std::allocate_shared<A>(test_allocator<A>(54, &alloc_stats), i, c);
|
||||
assert(alloc_stats.alloc_count == 1);
|
||||
assert(A::count == 1);
|
||||
assert(p->get_int() == 67);
|
||||
assert(p->get_char() == 'e');
|
||||
}
|
||||
assert(A::count == 0);
|
||||
assert(test_allocator<A>::alloc_count == 0);
|
||||
assert(alloc_stats.alloc_count == 0);
|
||||
{
|
||||
int i = 67;
|
||||
char c = 'e';
|
||||
|
|
|
@ -43,10 +43,11 @@ int A::count = 0;
|
|||
|
||||
int main(int, char**)
|
||||
{
|
||||
test_allocator_statistics alloc_stats;
|
||||
{
|
||||
std::shared_ptr<B> p(new B);
|
||||
A* ptr = new A;
|
||||
p.reset(ptr, test_deleter<A>(3), test_allocator<A>(4));
|
||||
p.reset(ptr, test_deleter<A>(3), test_allocator<A>(4, &alloc_stats));
|
||||
assert(A::count == 1);
|
||||
assert(B::count == 1);
|
||||
assert(p.use_count() == 1);
|
||||
|
@ -58,18 +59,18 @@ int main(int, char**)
|
|||
assert(d);
|
||||
assert(d->state() == 3);
|
||||
#endif
|
||||
assert(test_allocator<A>::count == 1);
|
||||
assert(test_allocator<A>::alloc_count == 1);
|
||||
assert(alloc_stats.count == 1);
|
||||
assert(alloc_stats.alloc_count == 1);
|
||||
}
|
||||
assert(A::count == 0);
|
||||
assert(test_deleter<A>::count == 0);
|
||||
assert(test_deleter<A>::dealloc_count == 1);
|
||||
assert(test_allocator<A>::count == 0);
|
||||
assert(test_allocator<A>::alloc_count == 0);
|
||||
assert(alloc_stats.count == 0);
|
||||
assert(alloc_stats.alloc_count == 0);
|
||||
{
|
||||
std::shared_ptr<B> p;
|
||||
A* ptr = new A;
|
||||
p.reset(ptr, test_deleter<A>(3), test_allocator<A>(4));
|
||||
p.reset(ptr, test_deleter<A>(3), test_allocator<A>(4, &alloc_stats));
|
||||
assert(A::count == 1);
|
||||
assert(B::count == 1);
|
||||
assert(p.use_count() == 1);
|
||||
|
@ -81,14 +82,14 @@ int main(int, char**)
|
|||
assert(d);
|
||||
assert(d->state() == 3);
|
||||
#endif
|
||||
assert(test_allocator<A>::count == 1);
|
||||
assert(test_allocator<A>::alloc_count == 1);
|
||||
assert(alloc_stats.count == 1);
|
||||
assert(alloc_stats.alloc_count == 1);
|
||||
}
|
||||
assert(A::count == 0);
|
||||
assert(test_deleter<A>::count == 0);
|
||||
assert(test_deleter<A>::dealloc_count == 2);
|
||||
assert(test_allocator<A>::count == 0);
|
||||
assert(test_allocator<A>::alloc_count == 0);
|
||||
assert(alloc_stats.count == 0);
|
||||
assert(alloc_stats.alloc_count == 0);
|
||||
|
||||
#if TEST_STD_VER > 14
|
||||
{
|
||||
|
|
|
@ -26,23 +26,16 @@ inline typename std::allocator_traits<Alloc>::size_type alloc_max_size(Alloc con
|
|||
return AT::max_size(a);
|
||||
}
|
||||
|
||||
class test_alloc_base {
|
||||
protected:
|
||||
static int time_to_throw;
|
||||
struct test_allocator_statistics {
|
||||
int time_to_throw = 0;
|
||||
int throw_after = INT_MAX;
|
||||
int count = 0;
|
||||
int alloc_count = 0;
|
||||
int copied = 0;
|
||||
int moved = 0;
|
||||
int converted = 0;
|
||||
|
||||
public:
|
||||
static int throw_after;
|
||||
static int count;
|
||||
static int alloc_count;
|
||||
static int copied;
|
||||
static int moved;
|
||||
static int converted;
|
||||
|
||||
const static int destructed_value = -1;
|
||||
const static int default_value = 0;
|
||||
const static int moved_value = INT_MAX;
|
||||
|
||||
static void clear() {
|
||||
TEST_CONSTEXPR_CXX14 void clear() {
|
||||
assert(count == 0 && "clearing leaking allocator data?");
|
||||
count = 0;
|
||||
time_to_throw = 0;
|
||||
|
@ -51,25 +44,24 @@ public:
|
|||
clear_ctor_counters();
|
||||
}
|
||||
|
||||
static void clear_ctor_counters() {
|
||||
TEST_CONSTEXPR_CXX14 void clear_ctor_counters() {
|
||||
copied = 0;
|
||||
moved = 0;
|
||||
converted = 0;
|
||||
}
|
||||
};
|
||||
|
||||
int test_alloc_base::count = 0;
|
||||
int test_alloc_base::time_to_throw = 0;
|
||||
int test_alloc_base::alloc_count = 0;
|
||||
int test_alloc_base::throw_after = INT_MAX;
|
||||
int test_alloc_base::copied = 0;
|
||||
int test_alloc_base::moved = 0;
|
||||
int test_alloc_base::converted = 0;
|
||||
struct test_alloc_base {
|
||||
TEST_CONSTEXPR static const int destructed_value = -1;
|
||||
TEST_CONSTEXPR static const int moved_value = INT_MAX;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
class test_allocator : public test_alloc_base {
|
||||
int data_; // participates in equality
|
||||
int id_; // unique identifier, doesn't participate in equality
|
||||
class test_allocator {
|
||||
int data_ = 0; // participates in equality
|
||||
int id_ = 0; // unique identifier, doesn't participate in equality
|
||||
test_allocator_statistics* stats_ = nullptr;
|
||||
|
||||
template <class U>
|
||||
friend class test_allocator;
|
||||
|
||||
|
@ -87,74 +79,113 @@ public:
|
|||
typedef test_allocator<U> other;
|
||||
};
|
||||
|
||||
test_allocator() TEST_NOEXCEPT : data_(0), id_(0) { ++count; }
|
||||
explicit test_allocator(int i, int id = 0) TEST_NOEXCEPT : data_(i), id_(id) { ++count; }
|
||||
test_allocator(const test_allocator& a) TEST_NOEXCEPT : data_(a.data_), id_(a.id_) {
|
||||
++count;
|
||||
++copied;
|
||||
assert(a.data_ != destructed_value && a.id_ != destructed_value && "copying from destroyed allocator");
|
||||
TEST_CONSTEXPR test_allocator() TEST_NOEXCEPT = default;
|
||||
|
||||
TEST_CONSTEXPR_CXX14 explicit test_allocator(test_allocator_statistics* stats) TEST_NOEXCEPT : stats_(stats) {
|
||||
if (stats_ != nullptr)
|
||||
++stats_->count;
|
||||
}
|
||||
#if TEST_STD_VER >= 11
|
||||
test_allocator(test_allocator&& a) TEST_NOEXCEPT : data_(a.data_), id_(a.id_) {
|
||||
++count;
|
||||
++moved;
|
||||
assert(a.data_ != destructed_value && a.id_ != destructed_value && "moving from destroyed allocator");
|
||||
a.data_ = moved_value;
|
||||
a.id_ = moved_value;
|
||||
|
||||
TEST_CONSTEXPR explicit test_allocator(int data) TEST_NOEXCEPT : data_(data) {}
|
||||
|
||||
TEST_CONSTEXPR_CXX14 explicit test_allocator(int data, test_allocator_statistics* stats) TEST_NOEXCEPT
|
||||
: data_(data), stats_(stats) {
|
||||
if (stats != nullptr)
|
||||
++stats_->count;
|
||||
}
|
||||
#endif
|
||||
template <class U>
|
||||
test_allocator(const test_allocator<U>& a) TEST_NOEXCEPT : data_(a.data_), id_(a.id_) {
|
||||
++count;
|
||||
++converted;
|
||||
|
||||
TEST_CONSTEXPR explicit test_allocator(int data, int id) TEST_NOEXCEPT : data_(data), id_(id) {}
|
||||
|
||||
TEST_CONSTEXPR_CXX14 explicit test_allocator(int data, int id, test_allocator_statistics* stats) TEST_NOEXCEPT
|
||||
: data_(data), id_(id), stats_(stats) {
|
||||
if (stats_ != nullptr)
|
||||
++stats_->count;
|
||||
}
|
||||
~test_allocator() TEST_NOEXCEPT {
|
||||
assert(data_ >= 0);
|
||||
assert(id_ >= 0);
|
||||
--count;
|
||||
data_ = destructed_value;
|
||||
id_ = destructed_value;
|
||||
}
|
||||
pointer address(reference x) const { return &x; }
|
||||
const_pointer address(const_reference x) const { return &x; }
|
||||
pointer allocate(size_type n, const void* = 0) {
|
||||
assert(data_ >= 0);
|
||||
if (time_to_throw >= throw_after) {
|
||||
#ifndef TEST_HAS_NO_EXCEPTIONS
|
||||
throw std::bad_alloc();
|
||||
#else
|
||||
std::terminate();
|
||||
#endif
|
||||
|
||||
TEST_CONSTEXPR_CXX14 test_allocator(const test_allocator& a) TEST_NOEXCEPT
|
||||
: data_(a.data_), id_(a.id_), stats_(a.stats_) {
|
||||
assert(a.data_ != test_alloc_base::destructed_value && a.id_ != test_alloc_base::destructed_value &&
|
||||
"copying from destroyed allocator");
|
||||
if (stats_ != nullptr) {
|
||||
++stats_->count;
|
||||
++stats_->copied;
|
||||
}
|
||||
++time_to_throw;
|
||||
++alloc_count;
|
||||
return (pointer)::operator new(n * sizeof(T));
|
||||
}
|
||||
void deallocate(pointer p, size_type) {
|
||||
assert(data_ >= 0);
|
||||
--alloc_count;
|
||||
::operator delete((void*)p);
|
||||
|
||||
#if TEST_STD_VER >= 11
|
||||
TEST_CONSTEXPR_CXX14 test_allocator(test_allocator&& a) TEST_NOEXCEPT : data_(a.data_), id_(a.id_), stats_(a.stats_) {
|
||||
if (stats_ != nullptr) {
|
||||
++stats_->count;
|
||||
++stats_->moved;
|
||||
}
|
||||
assert(a.data_ != test_alloc_base::destructed_value && a.id_ != test_alloc_base::destructed_value &&
|
||||
"moving from destroyed allocator");
|
||||
a.data_ = test_alloc_base::moved_value;
|
||||
a.id_ = test_alloc_base::moved_value;
|
||||
}
|
||||
size_type max_size() const TEST_NOEXCEPT { return UINT_MAX / sizeof(T); }
|
||||
#endif
|
||||
|
||||
template <class U>
|
||||
TEST_CONSTEXPR_CXX14 test_allocator(const test_allocator<U>& a) TEST_NOEXCEPT
|
||||
: data_(a.data_), id_(a.id_), stats_(a.stats_) {
|
||||
if (stats_ != nullptr) {
|
||||
++stats_->count;
|
||||
++stats_->converted;
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CONSTEXPR_CXX20 ~test_allocator() TEST_NOEXCEPT {
|
||||
assert(data_ != test_alloc_base::destructed_value);
|
||||
assert(id_ != test_alloc_base::destructed_value);
|
||||
if (stats_ != nullptr)
|
||||
--stats_->count;
|
||||
data_ = test_alloc_base::destructed_value;
|
||||
id_ = test_alloc_base::destructed_value;
|
||||
}
|
||||
|
||||
TEST_CONSTEXPR pointer address(reference x) const { return &x; }
|
||||
TEST_CONSTEXPR const_pointer address(const_reference x) const { return &x; }
|
||||
|
||||
TEST_CONSTEXPR_CXX14 pointer allocate(size_type n, const void* = 0) {
|
||||
assert(data_ != test_alloc_base::destructed_value);
|
||||
if (stats_ != nullptr) {
|
||||
if (stats_->time_to_throw >= stats_->throw_after)
|
||||
TEST_THROW(std::bad_alloc());
|
||||
++stats_->time_to_throw;
|
||||
++stats_->alloc_count;
|
||||
}
|
||||
return std::allocator<value_type>().allocate(n);
|
||||
}
|
||||
|
||||
TEST_CONSTEXPR_CXX14 void deallocate(pointer p, size_type s) {
|
||||
assert(data_ != test_alloc_base::destructed_value);
|
||||
if (stats_ != nullptr)
|
||||
--stats_->alloc_count;
|
||||
std::allocator<value_type>().deallocate(p, s);
|
||||
}
|
||||
|
||||
TEST_CONSTEXPR size_type max_size() const TEST_NOEXCEPT { return UINT_MAX / sizeof(T); }
|
||||
|
||||
#if TEST_STD_VER < 11
|
||||
void construct(pointer p, const T& val) { ::new (static_cast<void*>(p)) T(val); }
|
||||
#else
|
||||
template <class U>
|
||||
void construct(pointer p, U&& val) {
|
||||
TEST_CONSTEXPR_CXX14 void construct(pointer p, U&& val) {
|
||||
::new (static_cast<void*>(p)) T(std::forward<U>(val));
|
||||
}
|
||||
#endif
|
||||
void destroy(pointer p) { p->~T(); }
|
||||
friend bool operator==(const test_allocator& x, const test_allocator& y) { return x.data_ == y.data_; }
|
||||
friend bool operator!=(const test_allocator& x, const test_allocator& y) { return !(x == y); }
|
||||
TEST_CONSTEXPR_CXX14 void destroy(pointer p) { p->~T(); }
|
||||
TEST_CONSTEXPR friend bool operator==(const test_allocator& x, const test_allocator& y) { return x.data_ == y.data_; }
|
||||
TEST_CONSTEXPR friend bool operator!=(const test_allocator& x, const test_allocator& y) { return !(x == y); }
|
||||
|
||||
int get_data() const { return data_; }
|
||||
int get_id() const { return id_; }
|
||||
TEST_CONSTEXPR int get_data() const { return data_; }
|
||||
TEST_CONSTEXPR int get_id() const { return id_; }
|
||||
};
|
||||
|
||||
template <class T>
|
||||
class non_default_test_allocator : public test_alloc_base {
|
||||
int data_;
|
||||
class non_default_test_allocator {
|
||||
int data_ = 0;
|
||||
test_allocator_statistics* stats_ = nullptr;
|
||||
|
||||
template <class U>
|
||||
friend class non_default_test_allocator;
|
||||
|
@ -173,59 +204,71 @@ public:
|
|||
typedef non_default_test_allocator<U> other;
|
||||
};
|
||||
|
||||
// non_default_test_allocator() TEST_NOEXCEPT : data_(0) {++count;}
|
||||
explicit non_default_test_allocator(int i) TEST_NOEXCEPT : data_(i) { ++count; }
|
||||
non_default_test_allocator(const non_default_test_allocator& a) TEST_NOEXCEPT : data_(a.data_) { ++count; }
|
||||
template <class U>
|
||||
non_default_test_allocator(const non_default_test_allocator<U>& a) TEST_NOEXCEPT : data_(a.data_) {
|
||||
++count;
|
||||
}
|
||||
~non_default_test_allocator() TEST_NOEXCEPT {
|
||||
assert(data_ >= 0);
|
||||
--count;
|
||||
data_ = -1;
|
||||
}
|
||||
pointer address(reference x) const { return &x; }
|
||||
const_pointer address(const_reference x) const { return &x; }
|
||||
pointer allocate(size_type n, const void* = 0) {
|
||||
assert(data_ >= 0);
|
||||
if (time_to_throw >= throw_after) {
|
||||
#ifndef TEST_HAS_NO_EXCEPTIONS
|
||||
throw std::bad_alloc();
|
||||
#else
|
||||
std::terminate();
|
||||
#endif
|
||||
TEST_CONSTEXPR_CXX14
|
||||
explicit non_default_test_allocator(int i, test_allocator_statistics* stats = nullptr) TEST_NOEXCEPT
|
||||
: data_(i), stats_(stats) {
|
||||
if (stats_ != nullptr) {
|
||||
++stats_->count;
|
||||
}
|
||||
++time_to_throw;
|
||||
++alloc_count;
|
||||
return (pointer)::operator new(n * sizeof(T));
|
||||
}
|
||||
void deallocate(pointer p, size_type) {
|
||||
assert(data_ >= 0);
|
||||
--alloc_count;
|
||||
::operator delete((void*)p);
|
||||
}
|
||||
size_type max_size() const TEST_NOEXCEPT { return UINT_MAX / sizeof(T); }
|
||||
#if TEST_STD_VER < 11
|
||||
void construct(pointer p, const T& val) { ::new (static_cast<void*>(p)) T(val); }
|
||||
#else
|
||||
template <class U>
|
||||
void construct(pointer p, U&& val) {
|
||||
::new (static_cast<void*>(p)) T(std::forward<U>(val));
|
||||
}
|
||||
#endif
|
||||
void destroy(pointer p) { p->~T(); }
|
||||
|
||||
friend bool operator==(const non_default_test_allocator& x, const non_default_test_allocator& y) {
|
||||
TEST_CONSTEXPR_CXX14
|
||||
non_default_test_allocator(const non_default_test_allocator& a) TEST_NOEXCEPT : data_(a.data_), stats_(a.stats_) {
|
||||
if (stats_ != nullptr)
|
||||
++stats_->count;
|
||||
}
|
||||
|
||||
template <class U>
|
||||
TEST_CONSTEXPR_CXX14 non_default_test_allocator(const non_default_test_allocator<U>& a) TEST_NOEXCEPT
|
||||
: data_(a.data_), stats_(a.stats_) {
|
||||
if (stats_ != nullptr)
|
||||
++stats_->count;
|
||||
}
|
||||
|
||||
TEST_CONSTEXPR_CXX20 ~non_default_test_allocator() TEST_NOEXCEPT {
|
||||
assert(data_ != test_alloc_base::destructed_value);
|
||||
if (stats_ != nullptr)
|
||||
--stats_->count;
|
||||
data_ = test_alloc_base::destructed_value;
|
||||
}
|
||||
|
||||
TEST_CONSTEXPR pointer address(reference x) const { return &x; }
|
||||
TEST_CONSTEXPR const_pointer address(const_reference x) const { return &x; }
|
||||
|
||||
TEST_CONSTEXPR_CXX20 pointer allocate(size_type n, const void* = nullptr) {
|
||||
assert(data_ != test_alloc_base::destructed_value);
|
||||
if (stats_ != nullptr) {
|
||||
if (stats_->time_to_throw >= stats_->throw_after)
|
||||
TEST_THROW(std::bad_alloc());
|
||||
++stats_->time_to_throw;
|
||||
++stats_->alloc_count;
|
||||
}
|
||||
return std::allocator<value_type>().allocate(n);
|
||||
}
|
||||
|
||||
TEST_CONSTEXPR_CXX20 void deallocate(pointer p, size_type n) {
|
||||
assert(data_ != test_alloc_base::destructed_value);
|
||||
if (stats_ != nullptr)
|
||||
--stats_->alloc_count;
|
||||
std::allocator<value_type>().deallocate(p, n);
|
||||
}
|
||||
|
||||
TEST_CONSTEXPR size_type max_size() const TEST_NOEXCEPT { return UINT_MAX / sizeof(T); }
|
||||
|
||||
TEST_CONSTEXPR friend bool operator==(const non_default_test_allocator& x, const non_default_test_allocator& y) {
|
||||
return x.data_ == y.data_;
|
||||
}
|
||||
friend bool operator!=(const non_default_test_allocator& x, const non_default_test_allocator& y) { return !(x == y); }
|
||||
|
||||
TEST_CONSTEXPR friend bool operator!=(const non_default_test_allocator& x, const non_default_test_allocator& y) {
|
||||
return !(x == y);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
class test_allocator<void> : public test_alloc_base {
|
||||
int data_;
|
||||
int id_;
|
||||
class test_allocator<void> {
|
||||
int data_ = 0;
|
||||
int id_ = 0;
|
||||
test_allocator_statistics* stats_ = nullptr;
|
||||
|
||||
template <class U>
|
||||
friend class test_allocator;
|
||||
|
@ -242,26 +285,46 @@ public:
|
|||
typedef test_allocator<U> other;
|
||||
};
|
||||
|
||||
test_allocator() TEST_NOEXCEPT : data_(0), id_(0) {}
|
||||
explicit test_allocator(int i, int id = 0) TEST_NOEXCEPT : data_(i), id_(id) {}
|
||||
test_allocator(const test_allocator& a) TEST_NOEXCEPT : data_(a.data_), id_(a.id_) {}
|
||||
TEST_CONSTEXPR test_allocator() TEST_NOEXCEPT = default;
|
||||
|
||||
TEST_CONSTEXPR_CXX14 explicit test_allocator(test_allocator_statistics* stats) TEST_NOEXCEPT : stats_(stats) {}
|
||||
|
||||
TEST_CONSTEXPR explicit test_allocator(int data) TEST_NOEXCEPT : data_(data) {}
|
||||
|
||||
TEST_CONSTEXPR explicit test_allocator(int data, test_allocator_statistics* stats) TEST_NOEXCEPT
|
||||
: data_(data), stats_(stats)
|
||||
{}
|
||||
|
||||
TEST_CONSTEXPR explicit test_allocator(int data, int id) : data_(data), id_(id) {}
|
||||
|
||||
TEST_CONSTEXPR_CXX14 explicit test_allocator(int data, int id, test_allocator_statistics* stats) TEST_NOEXCEPT
|
||||
: data_(data), id_(id), stats_(stats)
|
||||
{}
|
||||
|
||||
TEST_CONSTEXPR_CXX14 explicit test_allocator(const test_allocator& a) TEST_NOEXCEPT
|
||||
: data_(a.data_), id_(a.id_), stats_(a.stats_)
|
||||
{}
|
||||
|
||||
template <class U>
|
||||
test_allocator(const test_allocator<U>& a) TEST_NOEXCEPT : data_(a.data_), id_(a.id_) {}
|
||||
~test_allocator() TEST_NOEXCEPT {
|
||||
data_ = -1;
|
||||
id_ = -1;
|
||||
TEST_CONSTEXPR_CXX14 test_allocator(const test_allocator<U>& a) TEST_NOEXCEPT
|
||||
: data_(a.data_), id_(a.id_), stats_(a.stats_)
|
||||
{}
|
||||
|
||||
TEST_CONSTEXPR_CXX20 ~test_allocator() TEST_NOEXCEPT {
|
||||
data_ = test_alloc_base::destructed_value;
|
||||
id_ = test_alloc_base::destructed_value;
|
||||
}
|
||||
|
||||
int get_id() const { return id_; }
|
||||
int get_data() const { return data_; }
|
||||
TEST_CONSTEXPR int get_id() const { return id_; }
|
||||
TEST_CONSTEXPR int get_data() const { return data_; }
|
||||
|
||||
friend bool operator==(const test_allocator& x, const test_allocator& y) { return x.data_ == y.data_; }
|
||||
friend bool operator!=(const test_allocator& x, const test_allocator& y) { return !(x == y); }
|
||||
TEST_CONSTEXPR friend bool operator==(const test_allocator& x, const test_allocator& y) { return x.data_ == y.data_; }
|
||||
TEST_CONSTEXPR friend bool operator!=(const test_allocator& x, const test_allocator& y) { return !(x == y); }
|
||||
};
|
||||
|
||||
template <class T>
|
||||
class other_allocator {
|
||||
int data_;
|
||||
int data_ = -1;
|
||||
|
||||
template <class U>
|
||||
friend class other_allocator;
|
||||
|
@ -269,17 +332,22 @@ class other_allocator {
|
|||
public:
|
||||
typedef T value_type;
|
||||
|
||||
other_allocator() : data_(-1) {}
|
||||
explicit other_allocator(int i) : data_(i) {}
|
||||
TEST_CONSTEXPR_CXX14 other_allocator() {}
|
||||
TEST_CONSTEXPR_CXX14 explicit other_allocator(int i) : data_(i) {}
|
||||
|
||||
template <class U>
|
||||
other_allocator(const other_allocator<U>& a) : data_(a.data_) {}
|
||||
T* allocate(std::size_t n) { return (T*)::operator new(n * sizeof(T)); }
|
||||
void deallocate(T* p, std::size_t) { ::operator delete((void*)p); }
|
||||
TEST_CONSTEXPR_CXX14 other_allocator(const other_allocator<U>& a) : data_(a.data_) {}
|
||||
|
||||
other_allocator select_on_container_copy_construction() const { return other_allocator(-2); }
|
||||
TEST_CONSTEXPR_CXX20 T* allocate(std::size_t n) { return std::allocator<value_type>().allocate(n); }
|
||||
TEST_CONSTEXPR_CXX20 void deallocate(T* p, std::size_t s) { std::allocator<value_type>().deallocate(p, s); }
|
||||
|
||||
friend bool operator==(const other_allocator& x, const other_allocator& y) { return x.data_ == y.data_; }
|
||||
friend bool operator!=(const other_allocator& x, const other_allocator& y) { return !(x == y); }
|
||||
TEST_CONSTEXPR_CXX14 other_allocator select_on_container_copy_construction() const { return other_allocator(-2); }
|
||||
|
||||
TEST_CONSTEXPR_CXX14 friend bool operator==(const other_allocator& x, const other_allocator& y) {
|
||||
return x.data_ == y.data_;
|
||||
}
|
||||
|
||||
TEST_CONSTEXPR_CXX14 friend bool operator!=(const other_allocator& x, const other_allocator& y) { return !(x == y); }
|
||||
|
||||
typedef std::true_type propagate_on_container_copy_assignment;
|
||||
typedef std::true_type propagate_on_container_move_assignment;
|
||||
|
@ -301,15 +369,15 @@ struct Tag_X {
|
|||
// All constructors must be passed the Tag type.
|
||||
|
||||
// DefaultInsertable into vector<X, TaggingAllocator<X>>,
|
||||
Tag_X(Ctor_Tag) {}
|
||||
constexpr Tag_X(Ctor_Tag) {}
|
||||
// CopyInsertable into vector<X, TaggingAllocator<X>>,
|
||||
Tag_X(Ctor_Tag, const Tag_X&) {}
|
||||
constexpr Tag_X(Ctor_Tag, const Tag_X&) {}
|
||||
// MoveInsertable into vector<X, TaggingAllocator<X>>, and
|
||||
Tag_X(Ctor_Tag, Tag_X&&) {}
|
||||
constexpr Tag_X(Ctor_Tag, Tag_X&&) {}
|
||||
|
||||
// EmplaceConstructible into vector<X, TaggingAllocator<X>> from args.
|
||||
template <typename... Args>
|
||||
Tag_X(Ctor_Tag, Args&&...) {}
|
||||
constexpr Tag_X(Ctor_Tag, Args&&...) {}
|
||||
|
||||
// not DefaultConstructible, CopyConstructible or MoveConstructible.
|
||||
Tag_X() = delete;
|
||||
|
@ -317,15 +385,13 @@ struct Tag_X {
|
|||
Tag_X(Tag_X&&) = delete;
|
||||
|
||||
// CopyAssignable.
|
||||
Tag_X& operator=(const Tag_X&) { return *this; }
|
||||
TEST_CONSTEXPR_CXX14 Tag_X& operator=(const Tag_X&) { return *this; };
|
||||
|
||||
// MoveAssignable.
|
||||
Tag_X& operator=(Tag_X&&) { return *this; }
|
||||
TEST_CONSTEXPR_CXX14 Tag_X& operator=(Tag_X&&) { return *this; };
|
||||
|
||||
private:
|
||||
// Not Destructible.
|
||||
~Tag_X() {}
|
||||
|
||||
~Tag_X() = default;
|
||||
// Erasable from vector<X, TaggingAllocator<X>>.
|
||||
friend class TaggingAllocator<Tag_X>;
|
||||
};
|
||||
|
@ -337,71 +403,109 @@ public:
|
|||
TaggingAllocator() = default;
|
||||
|
||||
template <typename U>
|
||||
TaggingAllocator(const TaggingAllocator<U>&) {}
|
||||
|
||||
T* allocate(std::size_t n) { return std::allocator<T>{}.allocate(n); }
|
||||
|
||||
void deallocate(T* p, std::size_t n) { std::allocator<T>{}.deallocate(p, n); }
|
||||
constexpr TaggingAllocator(const TaggingAllocator<U>&){};
|
||||
|
||||
template <typename... Args>
|
||||
void construct(Tag_X* p, Args&&... args) {
|
||||
::new ((void*)p) Tag_X(Ctor_Tag{}, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <typename U, typename... Args>
|
||||
void construct(U* p, Args&&... args) {
|
||||
::new ((void*)p) U(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <typename U, typename... Args>
|
||||
template <typename U>
|
||||
void destroy(U* p) {
|
||||
p->~U();
|
||||
}
|
||||
|
||||
TEST_CONSTEXPR_CXX20 T* allocate(std::size_t n) { return std::allocator<T>{}.allocate(n); }
|
||||
TEST_CONSTEXPR_CXX20 void deallocate(T* p, std::size_t n) { std::allocator<T>{}.deallocate(p, n); }
|
||||
};
|
||||
|
||||
template <typename T, typename U>
|
||||
bool operator==(const TaggingAllocator<T>&, const TaggingAllocator<U>&) {
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename T, typename U>
|
||||
bool operator!=(const TaggingAllocator<T>&, const TaggingAllocator<U>&) {
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
template <std::size_t MaxAllocs>
|
||||
struct limited_alloc_handle {
|
||||
std::size_t outstanding_;
|
||||
void* last_alloc_;
|
||||
|
||||
limited_alloc_handle() : outstanding_(0), last_alloc_(nullptr) {}
|
||||
std::size_t outstanding_ = 0;
|
||||
void* last_alloc_ = nullptr;
|
||||
|
||||
template <class T>
|
||||
T* allocate(std::size_t N) {
|
||||
TEST_CONSTEXPR_CXX20 T* allocate(std::size_t N) {
|
||||
if (N + outstanding_ > MaxAllocs)
|
||||
TEST_THROW(std::bad_alloc());
|
||||
last_alloc_ = ::operator new(N * sizeof(T));
|
||||
last_alloc_ = std::allocator<T>().allocate(N);
|
||||
outstanding_ += N;
|
||||
return static_cast<T*>(last_alloc_);
|
||||
}
|
||||
|
||||
void deallocate(void* ptr, std::size_t N) {
|
||||
template <class T>
|
||||
TEST_CONSTEXPR_CXX20 void deallocate(T* ptr, std::size_t N) {
|
||||
if (ptr == last_alloc_) {
|
||||
last_alloc_ = nullptr;
|
||||
assert(outstanding_ >= N);
|
||||
outstanding_ -= N;
|
||||
}
|
||||
::operator delete(ptr);
|
||||
std::allocator<T>().deallocate(ptr, N);
|
||||
}
|
||||
};
|
||||
|
||||
namespace detail {
|
||||
template <class T>
|
||||
class thread_unsafe_shared_ptr {
|
||||
public:
|
||||
thread_unsafe_shared_ptr() = default;
|
||||
|
||||
TEST_CONSTEXPR_CXX14 thread_unsafe_shared_ptr(const thread_unsafe_shared_ptr& other) : block(other.block) {
|
||||
++block->ref_count;
|
||||
}
|
||||
|
||||
TEST_CONSTEXPR_CXX20 ~thread_unsafe_shared_ptr() {
|
||||
--block->ref_count;
|
||||
if (block->ref_count != 0)
|
||||
return;
|
||||
typedef std::allocator_traits<std::allocator<control_block> > allocator_traits;
|
||||
std::allocator<control_block> alloc;
|
||||
allocator_traits::destroy(alloc, block);
|
||||
allocator_traits::deallocate(alloc, block, 1);
|
||||
}
|
||||
|
||||
TEST_CONSTEXPR const T& operator*() const { return block->content; }
|
||||
TEST_CONSTEXPR const T* operator->() const { return &block->content; }
|
||||
TEST_CONSTEXPR_CXX14 T& operator*() { return block->content; }
|
||||
TEST_CONSTEXPR_CXX14 T* operator->() { return &block->content; }
|
||||
TEST_CONSTEXPR_CXX14 T* get() { return &block->content; }
|
||||
TEST_CONSTEXPR const T* get() const { return &block->content; }
|
||||
|
||||
private:
|
||||
struct control_block {
|
||||
template <class... Args>
|
||||
TEST_CONSTEXPR control_block(Args... args) : content(std::forward<Args>(args)...) {}
|
||||
size_t ref_count = 1;
|
||||
T content;
|
||||
};
|
||||
|
||||
control_block* block = nullptr;
|
||||
|
||||
template <class U, class... Args>
|
||||
friend TEST_CONSTEXPR_CXX20 thread_unsafe_shared_ptr<U> make_thread_unsafe_shared(Args...);
|
||||
};
|
||||
|
||||
template <class T, class... Args>
|
||||
TEST_CONSTEXPR_CXX20 thread_unsafe_shared_ptr<T> make_thread_unsafe_shared(Args... args) {
|
||||
typedef typename thread_unsafe_shared_ptr<T>::control_block control_block_type;
|
||||
typedef std::allocator_traits<std::allocator<control_block_type> > allocator_traits;
|
||||
|
||||
thread_unsafe_shared_ptr<T> ptr;
|
||||
std::allocator<control_block_type> alloc;
|
||||
ptr.block = allocator_traits::allocate(alloc, 1);
|
||||
allocator_traits::construct(alloc, ptr.block, std::forward<Args>(args)...);
|
||||
|
||||
return ptr;
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
template <class T, std::size_t N>
|
||||
class limited_allocator {
|
||||
template <class U, std::size_t UN>
|
||||
friend class limited_allocator;
|
||||
typedef limited_alloc_handle<N> BuffT;
|
||||
std::shared_ptr<BuffT> handle_;
|
||||
detail::thread_unsafe_shared_ptr<BuffT> handle_;
|
||||
|
||||
public:
|
||||
typedef T value_type;
|
||||
|
@ -417,29 +521,28 @@ public:
|
|||
typedef limited_allocator<U, N> other;
|
||||
};
|
||||
|
||||
limited_allocator() : handle_(new BuffT) {}
|
||||
TEST_CONSTEXPR_CXX20 limited_allocator() : handle_(detail::make_thread_unsafe_shared<BuffT>()) {}
|
||||
|
||||
limited_allocator(limited_allocator const& other) : handle_(other.handle_) {}
|
||||
limited_allocator(limited_allocator const&) = default;
|
||||
|
||||
template <class U>
|
||||
explicit limited_allocator(limited_allocator<U, N> const& other) : handle_(other.handle_) {}
|
||||
TEST_CONSTEXPR explicit limited_allocator(limited_allocator<U, N> const& other) : handle_(other.handle_) {}
|
||||
|
||||
limited_allocator& operator=(const limited_allocator&) = delete;
|
||||
|
||||
pointer allocate(size_type n) { return handle_->template allocate<T>(n); }
|
||||
void deallocate(pointer p, size_type n) { handle_->deallocate(p, n); }
|
||||
size_type max_size() const { return N; }
|
||||
|
||||
BuffT* getHandle() const { return handle_.get(); }
|
||||
TEST_CONSTEXPR_CXX20 pointer allocate(size_type n) { return handle_->template allocate<T>(n); }
|
||||
TEST_CONSTEXPR_CXX20 void deallocate(pointer p, size_type n) { handle_->template deallocate<T>(p, n); }
|
||||
TEST_CONSTEXPR size_type max_size() const { return N; }
|
||||
TEST_CONSTEXPR BuffT* getHandle() const { return handle_.get(); }
|
||||
};
|
||||
|
||||
template <class T, class U, std::size_t N>
|
||||
inline bool operator==(limited_allocator<T, N> const& LHS, limited_allocator<U, N> const& RHS) {
|
||||
TEST_CONSTEXPR inline bool operator==(limited_allocator<T, N> const& LHS, limited_allocator<U, N> const& RHS) {
|
||||
return LHS.getHandle() == RHS.getHandle();
|
||||
}
|
||||
|
||||
template <class T, class U, std::size_t N>
|
||||
inline bool operator!=(limited_allocator<T, N> const& LHS, limited_allocator<U, N> const& RHS) {
|
||||
TEST_CONSTEXPR inline bool operator!=(limited_allocator<T, N> const& LHS, limited_allocator<U, N> const& RHS) {
|
||||
return !(LHS == RHS);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue