[libc++] Fix stack_allocator
Summary: To quote STL the problems with stack allocator are" >"stack_allocator<T, N> is seriously nonconformant to N4582 17.6.3.5 [allocator.requirements]. > First, it lacks a rebinding constructor. (The nested "struct rebind" isn't sufficient.) > Second, it lacks templated equality/inequality. > Third, it completely ignores alignment. > Finally, and most severely, the Standard forbids its existence. Allocators are forbidden from returning memory "inside themselves". This requirement is implied by the Standard's requirements for rebinding and equality. It's permitted to return memory from a separate buffer object on the stack, though." This patch attempts to address all of those issues. First, instead of storing the buffer inside the allocator I've change `stack_allocator` to accept the buffer as an argument. Second, in order to fix rebinding I changed the parameter list from `<class T, size_t NumElements>` to `<class T, size_t NumBytes>`. This allows allocator rebinding between types that have different sizes. Third, I added copy and rebinding constructors and assignment operators. And finally I fixed the allocation logic to always return properly aligned storage. Reviewers: mclow.lists, howard.hinnant, STL_MSFT Subscribers: cfe-commits Differential Revision: https://reviews.llvm.org/D25154 git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@283631 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@@ -14,11 +14,11 @@
|
|||||||
#include <queue>
|
#include <queue>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
|
||||||
#include "../../../stack_allocator.h"
|
#include "test_allocator.h"
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
std::priority_queue<int, std::vector<int, stack_allocator<int, 10> > > q((std::less<int>()));
|
std::priority_queue<int, std::vector<int, limited_allocator<int, 10> > > q((std::less<int>()));
|
||||||
assert(q.size() == 0);
|
assert(q.size() == 0);
|
||||||
q.push(1);
|
q.push(1);
|
||||||
q.push(2);
|
q.push(2);
|
||||||
|
|||||||
@@ -14,11 +14,11 @@
|
|||||||
#include <queue>
|
#include <queue>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
|
||||||
#include "../../../stack_allocator.h"
|
#include "test_allocator.h"
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
std::priority_queue<int, std::vector<int, stack_allocator<int, 10> > > q;
|
std::priority_queue<int, std::vector<int, limited_allocator<int, 10> > > q;
|
||||||
assert(q.size() == 0);
|
assert(q.size() == 0);
|
||||||
q.push(1);
|
q.push(1);
|
||||||
q.push(2);
|
q.push(2);
|
||||||
|
|||||||
@@ -14,11 +14,11 @@
|
|||||||
#include <queue>
|
#include <queue>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
|
||||||
#include "../../../stack_allocator.h"
|
#include "test_allocator.h"
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
std::queue<int, std::vector<int, stack_allocator<int, 10> > > q;
|
std::queue<int, std::vector<int, limited_allocator<int, 10> > > q;
|
||||||
assert(q.size() == 0);
|
assert(q.size() == 0);
|
||||||
q.push(1);
|
q.push(1);
|
||||||
q.push(2);
|
q.push(2);
|
||||||
|
|||||||
@@ -15,11 +15,11 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
|
||||||
#include "../../../stack_allocator.h"
|
#include "test_allocator.h"
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
std::stack<int, std::vector<int, stack_allocator<int, 10> > > q;
|
std::stack<int, std::vector<int, limited_allocator<int, 10> > > q;
|
||||||
assert(q.size() == 0);
|
assert(q.size() == 0);
|
||||||
q.push(1);
|
q.push(1);
|
||||||
q.push(2);
|
q.push(2);
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
#include <deque>
|
#include <deque>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
|
||||||
#include "../../../stack_allocator.h"
|
#include "test_allocator.h"
|
||||||
#include "../../../NotConstructible.h"
|
#include "../../../NotConstructible.h"
|
||||||
#include "min_allocator.h"
|
#include "min_allocator.h"
|
||||||
|
|
||||||
@@ -33,7 +33,7 @@ test()
|
|||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
test<int, std::allocator<int> >();
|
test<int, std::allocator<int> >();
|
||||||
test<NotConstructible, stack_allocator<NotConstructible, 1> >();
|
test<NotConstructible, limited_allocator<NotConstructible, 1> >();
|
||||||
#if TEST_STD_VER >= 11
|
#if TEST_STD_VER >= 11
|
||||||
test<int, min_allocator<int> >();
|
test<int, min_allocator<int> >();
|
||||||
test<NotConstructible, min_allocator<NotConstructible> >();
|
test<NotConstructible, min_allocator<NotConstructible> >();
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
#include <deque>
|
#include <deque>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
|
||||||
#include "../../../stack_allocator.h"
|
#include "test_allocator.h"
|
||||||
#include "test_iterators.h"
|
#include "test_iterators.h"
|
||||||
#include "min_allocator.h"
|
#include "min_allocator.h"
|
||||||
|
|
||||||
@@ -55,7 +55,7 @@ int main()
|
|||||||
test(forward_iterator<const int*>(ab), forward_iterator<const int*>(an));
|
test(forward_iterator<const int*>(ab), forward_iterator<const int*>(an));
|
||||||
test(bidirectional_iterator<const int*>(ab), bidirectional_iterator<const int*>(an));
|
test(bidirectional_iterator<const int*>(ab), bidirectional_iterator<const int*>(an));
|
||||||
test(random_access_iterator<const int*>(ab), random_access_iterator<const int*>(an));
|
test(random_access_iterator<const int*>(ab), random_access_iterator<const int*>(an));
|
||||||
test<stack_allocator<int, 4096> >(ab, an);
|
test<limited_allocator<int, 4096> >(ab, an);
|
||||||
#if TEST_STD_VER >= 11
|
#if TEST_STD_VER >= 11
|
||||||
test<min_allocator<int> >(ab, an);
|
test<min_allocator<int> >(ab, an);
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
#include <deque>
|
#include <deque>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
|
||||||
#include "../../../stack_allocator.h"
|
#include "test_allocator.h"
|
||||||
#include "DefaultOnly.h"
|
#include "DefaultOnly.h"
|
||||||
#include "min_allocator.h"
|
#include "min_allocator.h"
|
||||||
|
|
||||||
@@ -98,7 +98,7 @@ int main()
|
|||||||
test<DefaultOnly, std::allocator<DefaultOnly> >(4096);
|
test<DefaultOnly, std::allocator<DefaultOnly> >(4096);
|
||||||
test<DefaultOnly, std::allocator<DefaultOnly> >(4097);
|
test<DefaultOnly, std::allocator<DefaultOnly> >(4097);
|
||||||
|
|
||||||
test1<DefaultOnly, stack_allocator<DefaultOnly, 4096> >(4095);
|
test1<DefaultOnly, limited_allocator<DefaultOnly, 4096> >(4095);
|
||||||
|
|
||||||
#if TEST_STD_VER >= 11
|
#if TEST_STD_VER >= 11
|
||||||
test<DefaultOnly, min_allocator<DefaultOnly> >(4095);
|
test<DefaultOnly, min_allocator<DefaultOnly> >(4095);
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
#include <deque>
|
#include <deque>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
|
||||||
#include "../../../stack_allocator.h"
|
#include "test_allocator.h"
|
||||||
#include "min_allocator.h"
|
#include "min_allocator.h"
|
||||||
|
|
||||||
template <class T, class Allocator>
|
template <class T, class Allocator>
|
||||||
@@ -44,7 +44,7 @@ int main()
|
|||||||
test<int, std::allocator<int> >(4095, 78);
|
test<int, std::allocator<int> >(4095, 78);
|
||||||
test<int, std::allocator<int> >(4096, 1165);
|
test<int, std::allocator<int> >(4096, 1165);
|
||||||
test<int, std::allocator<int> >(4097, 157);
|
test<int, std::allocator<int> >(4097, 157);
|
||||||
test<int, stack_allocator<int, 4096> >(4095, 90);
|
test<int, limited_allocator<int, 4096> >(4095, 90);
|
||||||
#if TEST_STD_VER >= 11
|
#if TEST_STD_VER >= 11
|
||||||
test<int, min_allocator<int> >(4095, 90);
|
test<int, min_allocator<int> >(4095, 90);
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
#include "test_macros.h"
|
#include "test_macros.h"
|
||||||
#include "test_iterators.h"
|
#include "test_iterators.h"
|
||||||
#include "MoveOnly.h"
|
#include "MoveOnly.h"
|
||||||
#include "../../../stack_allocator.h"
|
#include "test_allocator.h"
|
||||||
#include "min_allocator.h"
|
#include "min_allocator.h"
|
||||||
|
|
||||||
template <class C>
|
template <class C>
|
||||||
@@ -270,7 +270,7 @@ int main()
|
|||||||
testN<std::deque<int> >(rng[i], rng[j], rng[k]);
|
testN<std::deque<int> >(rng[i], rng[j], rng[k]);
|
||||||
testNI<std::deque<int> >(1500, 2000, 1000);
|
testNI<std::deque<int> >(1500, 2000, 1000);
|
||||||
#if TEST_STD_VER >= 11
|
#if TEST_STD_VER >= 11
|
||||||
test_move<std::deque<MoveOnly, stack_allocator<MoveOnly, 2000> > >();
|
test_move<std::deque<MoveOnly, limited_allocator<MoveOnly, 2000> > >();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
#if TEST_STD_VER >= 11
|
#if TEST_STD_VER >= 11
|
||||||
|
|||||||
@@ -13,7 +13,7 @@
|
|||||||
|
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include "../../../stack_allocator.h"
|
#include "test_allocator.h"
|
||||||
#include "min_allocator.h"
|
#include "min_allocator.h"
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
@@ -29,7 +29,7 @@ int main()
|
|||||||
assert(std::distance(l.begin(), l.end()) == 0);
|
assert(std::distance(l.begin(), l.end()) == 0);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
std::list<int, stack_allocator<int, 4> > l;
|
std::list<int, limited_allocator<int, 4> > l;
|
||||||
assert(l.size() == 0);
|
assert(l.size() == 0);
|
||||||
assert(std::distance(l.begin(), l.end()) == 0);
|
assert(std::distance(l.begin(), l.end()) == 0);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,7 @@
|
|||||||
#include <list>
|
#include <list>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include "test_iterators.h"
|
#include "test_iterators.h"
|
||||||
#include "../../../stack_allocator.h"
|
#include "test_allocator.h"
|
||||||
#include "min_allocator.h"
|
#include "min_allocator.h"
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
@@ -43,7 +43,7 @@ int main()
|
|||||||
}
|
}
|
||||||
{
|
{
|
||||||
int a[] = {0, 1, 2, 3};
|
int a[] = {0, 1, 2, 3};
|
||||||
std::list<int, stack_allocator<int, sizeof(a)/sizeof(a[0])> > l(input_iterator<const int*>(a),
|
std::list<int, limited_allocator<int, sizeof(a)/sizeof(a[0])> > l(input_iterator<const int*>(a),
|
||||||
input_iterator<const int*>(a + sizeof(a)/sizeof(a[0])));
|
input_iterator<const int*>(a + sizeof(a)/sizeof(a[0])));
|
||||||
assert(l.size() == sizeof(a)/sizeof(a[0]));
|
assert(l.size() == sizeof(a)/sizeof(a[0]));
|
||||||
assert(std::distance(l.begin(), l.end()) == sizeof(a)/sizeof(a[0]));
|
assert(std::distance(l.begin(), l.end()) == sizeof(a)/sizeof(a[0]));
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
#include <list>
|
#include <list>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include "DefaultOnly.h"
|
#include "DefaultOnly.h"
|
||||||
#include "../../../stack_allocator.h"
|
#include "test_allocator.h"
|
||||||
#include "min_allocator.h"
|
#include "min_allocator.h"
|
||||||
|
|
||||||
template <class T, class Allocator>
|
template <class T, class Allocator>
|
||||||
@@ -48,7 +48,7 @@ int main()
|
|||||||
assert(*i == 0);
|
assert(*i == 0);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
std::list<int, stack_allocator<int, 3> > l(3);
|
std::list<int, limited_allocator<int, 3> > l(3);
|
||||||
assert(l.size() == 3);
|
assert(l.size() == 3);
|
||||||
assert(std::distance(l.begin(), l.end()) == 3);
|
assert(std::distance(l.begin(), l.end()) == 3);
|
||||||
std::list<int>::const_iterator i = l.begin();
|
std::list<int>::const_iterator i = l.begin();
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
#include <list>
|
#include <list>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include "DefaultOnly.h"
|
#include "DefaultOnly.h"
|
||||||
#include "../../../stack_allocator.h"
|
#include "test_allocator.h"
|
||||||
#include "min_allocator.h"
|
#include "min_allocator.h"
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
@@ -42,7 +42,7 @@ int main()
|
|||||||
assert(*i == 2);
|
assert(*i == 2);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
std::list<int, stack_allocator<int, 3> > l(3, 2);
|
std::list<int, limited_allocator<int, 3> > l(3, 2);
|
||||||
assert(l.size() == 3);
|
assert(l.size() == 3);
|
||||||
assert(std::distance(l.begin(), l.end()) == 3);
|
assert(std::distance(l.begin(), l.end()) == 3);
|
||||||
std::list<int>::const_iterator i = l.begin();
|
std::list<int>::const_iterator i = l.begin();
|
||||||
|
|||||||
@@ -13,7 +13,7 @@
|
|||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include "../../../stack_allocator.h"
|
#include "test_allocator.h"
|
||||||
#include "min_allocator.h"
|
#include "min_allocator.h"
|
||||||
#include "asan_testing.h"
|
#include "asan_testing.h"
|
||||||
|
|
||||||
@@ -37,7 +37,7 @@ int main()
|
|||||||
assert(is_contiguous_container_asan_correct(v));
|
assert(is_contiguous_container_asan_correct(v));
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
std::vector<int, stack_allocator<int, 250> > v(100);
|
std::vector<int, limited_allocator<int, 250> > v(100);
|
||||||
assert(v.capacity() == 100);
|
assert(v.capacity() == 100);
|
||||||
v.reserve(50);
|
v.reserve(50);
|
||||||
assert(v.size() == 100);
|
assert(v.size() == 100);
|
||||||
|
|||||||
@@ -13,7 +13,7 @@
|
|||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include "../../../stack_allocator.h"
|
#include "test_allocator.h"
|
||||||
#include "MoveOnly.h"
|
#include "MoveOnly.h"
|
||||||
#include "min_allocator.h"
|
#include "min_allocator.h"
|
||||||
#include "asan_testing.h"
|
#include "asan_testing.h"
|
||||||
@@ -33,7 +33,7 @@ int main()
|
|||||||
assert(is_contiguous_container_asan_correct(v));
|
assert(is_contiguous_container_asan_correct(v));
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
std::vector<MoveOnly, stack_allocator<MoveOnly, 300> > v(100);
|
std::vector<MoveOnly, limited_allocator<MoveOnly, 300> > v(100);
|
||||||
v.resize(50);
|
v.resize(50);
|
||||||
assert(v.size() == 50);
|
assert(v.size() == 50);
|
||||||
assert(v.capacity() == 100);
|
assert(v.capacity() == 100);
|
||||||
@@ -56,7 +56,7 @@ int main()
|
|||||||
assert(is_contiguous_container_asan_correct(v));
|
assert(is_contiguous_container_asan_correct(v));
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
std::vector<int, stack_allocator<int, 300> > v(100);
|
std::vector<int, limited_allocator<int, 300> > v(100);
|
||||||
v.resize(50);
|
v.resize(50);
|
||||||
assert(v.size() == 50);
|
assert(v.size() == 50);
|
||||||
assert(v.capacity() == 100);
|
assert(v.capacity() == 100);
|
||||||
|
|||||||
@@ -13,7 +13,7 @@
|
|||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include "../../../stack_allocator.h"
|
#include "test_allocator.h"
|
||||||
#include "min_allocator.h"
|
#include "min_allocator.h"
|
||||||
#include "asan_testing.h"
|
#include "asan_testing.h"
|
||||||
|
|
||||||
@@ -35,7 +35,7 @@ int main()
|
|||||||
assert(v[i] == 1);
|
assert(v[i] == 1);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
std::vector<int, stack_allocator<int, 300> > v(100);
|
std::vector<int, limited_allocator<int, 300> > v(100);
|
||||||
v.resize(50, 1);
|
v.resize(50, 1);
|
||||||
assert(v.size() == 50);
|
assert(v.size() == 50);
|
||||||
assert(v.capacity() == 100);
|
assert(v.capacity() == 100);
|
||||||
|
|||||||
@@ -13,7 +13,7 @@
|
|||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include "../../../stack_allocator.h"
|
#include "test_allocator.h"
|
||||||
#include "min_allocator.h"
|
#include "min_allocator.h"
|
||||||
#include "asan_testing.h"
|
#include "asan_testing.h"
|
||||||
|
|
||||||
@@ -29,7 +29,7 @@ int main()
|
|||||||
assert(is_contiguous_container_asan_correct(v));
|
assert(is_contiguous_container_asan_correct(v));
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
std::vector<int, stack_allocator<int, 401> > v(100);
|
std::vector<int, limited_allocator<int, 401> > v(100);
|
||||||
v.push_back(1);
|
v.push_back(1);
|
||||||
assert(is_contiguous_container_asan_correct(v));
|
assert(is_contiguous_container_asan_correct(v));
|
||||||
v.shrink_to_fit();
|
v.shrink_to_fit();
|
||||||
@@ -39,7 +39,7 @@ int main()
|
|||||||
}
|
}
|
||||||
#ifndef _LIBCPP_NO_EXCEPTIONS
|
#ifndef _LIBCPP_NO_EXCEPTIONS
|
||||||
{
|
{
|
||||||
std::vector<int, stack_allocator<int, 400> > v(100);
|
std::vector<int, limited_allocator<int, 400> > v(100);
|
||||||
v.push_back(1);
|
v.push_back(1);
|
||||||
assert(is_contiguous_container_asan_correct(v));
|
assert(is_contiguous_container_asan_correct(v));
|
||||||
v.shrink_to_fit();
|
v.shrink_to_fit();
|
||||||
|
|||||||
@@ -18,7 +18,7 @@
|
|||||||
#include "test_macros.h"
|
#include "test_macros.h"
|
||||||
#include "test_allocator.h"
|
#include "test_allocator.h"
|
||||||
#include "../../../NotConstructible.h"
|
#include "../../../NotConstructible.h"
|
||||||
#include "../../../stack_allocator.h"
|
#include "test_allocator.h"
|
||||||
#include "min_allocator.h"
|
#include "min_allocator.h"
|
||||||
#include "asan_testing.h"
|
#include "asan_testing.h"
|
||||||
|
|
||||||
@@ -71,7 +71,7 @@ int main()
|
|||||||
(test_allocator<NotConstructible>(5));
|
(test_allocator<NotConstructible>(5));
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
std::vector<int, stack_allocator<int, 10> > v;
|
std::vector<int, limited_allocator<int, 10> > v;
|
||||||
assert(v.empty());
|
assert(v.empty());
|
||||||
}
|
}
|
||||||
#if TEST_STD_VER >= 11
|
#if TEST_STD_VER >= 11
|
||||||
|
|||||||
@@ -16,7 +16,7 @@
|
|||||||
|
|
||||||
#include "test_macros.h"
|
#include "test_macros.h"
|
||||||
#include "test_iterators.h"
|
#include "test_iterators.h"
|
||||||
#include "../../../stack_allocator.h"
|
#include "test_allocator.h"
|
||||||
#include "min_allocator.h"
|
#include "min_allocator.h"
|
||||||
#include "asan_testing.h"
|
#include "asan_testing.h"
|
||||||
|
|
||||||
@@ -42,11 +42,11 @@ int main()
|
|||||||
test<std::vector<int> >(random_access_iterator<const int*>(a), random_access_iterator<const int*>(an));
|
test<std::vector<int> >(random_access_iterator<const int*>(a), random_access_iterator<const int*>(an));
|
||||||
test<std::vector<int> >(a, an);
|
test<std::vector<int> >(a, an);
|
||||||
|
|
||||||
test<std::vector<int, stack_allocator<int, 63> > >(input_iterator<const int*>(a), input_iterator<const int*>(an));
|
test<std::vector<int, limited_allocator<int, 63> > >(input_iterator<const int*>(a), input_iterator<const int*>(an));
|
||||||
test<std::vector<int, stack_allocator<int, 18> > >(forward_iterator<const int*>(a), forward_iterator<const int*>(an));
|
test<std::vector<int, limited_allocator<int, 18> > >(forward_iterator<const int*>(a), forward_iterator<const int*>(an));
|
||||||
test<std::vector<int, stack_allocator<int, 18> > >(bidirectional_iterator<const int*>(a), bidirectional_iterator<const int*>(an));
|
test<std::vector<int, limited_allocator<int, 18> > >(bidirectional_iterator<const int*>(a), bidirectional_iterator<const int*>(an));
|
||||||
test<std::vector<int, stack_allocator<int, 18> > >(random_access_iterator<const int*>(a), random_access_iterator<const int*>(an));
|
test<std::vector<int, limited_allocator<int, 18> > >(random_access_iterator<const int*>(a), random_access_iterator<const int*>(an));
|
||||||
test<std::vector<int, stack_allocator<int, 18> > >(a, an);
|
test<std::vector<int, limited_allocator<int, 18> > >(a, an);
|
||||||
#if TEST_STD_VER >= 11
|
#if TEST_STD_VER >= 11
|
||||||
test<std::vector<int, min_allocator<int>> >(input_iterator<const int*>(a), input_iterator<const int*>(an));
|
test<std::vector<int, min_allocator<int>> >(input_iterator<const int*>(a), input_iterator<const int*>(an));
|
||||||
test<std::vector<int, min_allocator<int>> >(forward_iterator<const int*>(a), forward_iterator<const int*>(an));
|
test<std::vector<int, min_allocator<int>> >(forward_iterator<const int*>(a), forward_iterator<const int*>(an));
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
|
|
||||||
#include "test_macros.h"
|
#include "test_macros.h"
|
||||||
#include "test_iterators.h"
|
#include "test_iterators.h"
|
||||||
#include "../../../stack_allocator.h"
|
#include "test_allocator.h"
|
||||||
#include "min_allocator.h"
|
#include "min_allocator.h"
|
||||||
#include "asan_testing.h"
|
#include "asan_testing.h"
|
||||||
|
|
||||||
|
|||||||
@@ -15,7 +15,7 @@
|
|||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
|
||||||
#include "test_macros.h"
|
#include "test_macros.h"
|
||||||
#include "../../../stack_allocator.h"
|
#include "test_allocator.h"
|
||||||
#include "min_allocator.h"
|
#include "min_allocator.h"
|
||||||
#include "asan_testing.h"
|
#include "asan_testing.h"
|
||||||
|
|
||||||
@@ -34,7 +34,7 @@ test(typename C::size_type n, const typename C::value_type& x)
|
|||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
test<std::vector<int> >(50, 3);
|
test<std::vector<int> >(50, 3);
|
||||||
test<std::vector<int, stack_allocator<int, 50> > >(50, 5);
|
test<std::vector<int, limited_allocator<int, 50> > >(50, 5);
|
||||||
#if TEST_STD_VER >= 11
|
#if TEST_STD_VER >= 11
|
||||||
test<std::vector<int, min_allocator<int>> >(50, 3);
|
test<std::vector<int, min_allocator<int>> >(50, 3);
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include "../../../stack_allocator.h"
|
#include "test_allocator.h"
|
||||||
#include "min_allocator.h"
|
#include "min_allocator.h"
|
||||||
#include "asan_testing.h"
|
#include "asan_testing.h"
|
||||||
|
|
||||||
@@ -88,8 +88,8 @@ int main()
|
|||||||
assert(is_contiguous_container_asan_correct(c));
|
assert(is_contiguous_container_asan_correct(c));
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
std::vector<A, stack_allocator<A, 7> > c;
|
std::vector<A, limited_allocator<A, 7> > c;
|
||||||
std::vector<A, stack_allocator<A, 7> >::iterator i = c.emplace(c.cbegin(), 2, 3.5);
|
std::vector<A, limited_allocator<A, 7> >::iterator i = c.emplace(c.cbegin(), 2, 3.5);
|
||||||
assert(i == c.begin());
|
assert(i == c.begin());
|
||||||
assert(c.size() == 1);
|
assert(c.size() == 1);
|
||||||
assert(c.front().geti() == 2);
|
assert(c.front().geti() == 2);
|
||||||
|
|||||||
@@ -15,7 +15,7 @@
|
|||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include "../../../stack_allocator.h"
|
#include "test_allocator.h"
|
||||||
#include "min_allocator.h"
|
#include "min_allocator.h"
|
||||||
#include "test_allocator.h"
|
#include "test_allocator.h"
|
||||||
#include "asan_testing.h"
|
#include "asan_testing.h"
|
||||||
@@ -72,7 +72,7 @@ int main()
|
|||||||
assert(is_contiguous_container_asan_correct(c));
|
assert(is_contiguous_container_asan_correct(c));
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
std::vector<A, stack_allocator<A, 4> > c;
|
std::vector<A, limited_allocator<A, 4> > c;
|
||||||
A& r1 = c.emplace_back(2, 3.5);
|
A& r1 = c.emplace_back(2, 3.5);
|
||||||
assert(c.size() == 1);
|
assert(c.size() == 1);
|
||||||
assert(&r1 == &c.back());
|
assert(&r1 == &c.back());
|
||||||
|
|||||||
@@ -18,7 +18,7 @@
|
|||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include "../../../stack_allocator.h"
|
#include "test_allocator.h"
|
||||||
#include "test_iterators.h"
|
#include "test_iterators.h"
|
||||||
#include "min_allocator.h"
|
#include "min_allocator.h"
|
||||||
#include "asan_testing.h"
|
#include "asan_testing.h"
|
||||||
@@ -96,7 +96,7 @@ int main()
|
|||||||
assert(v[j] == 0);
|
assert(v[j] == 0);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
std::vector<int, stack_allocator<int, 308> > v(100);
|
std::vector<int, limited_allocator<int, 308> > v(100);
|
||||||
int a[] = {1, 2, 3, 4, 5};
|
int a[] = {1, 2, 3, 4, 5};
|
||||||
const int N = sizeof(a)/sizeof(a[0]);
|
const int N = sizeof(a)/sizeof(a[0]);
|
||||||
std::vector<int>::iterator i = v.insert(v.cbegin() + 10, input_iterator<const int*>(a),
|
std::vector<int>::iterator i = v.insert(v.cbegin() + 10, input_iterator<const int*>(a),
|
||||||
@@ -113,7 +113,7 @@ int main()
|
|||||||
assert(v[j] == 0);
|
assert(v[j] == 0);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
std::vector<int, stack_allocator<int, 300> > v(100);
|
std::vector<int, limited_allocator<int, 300> > v(100);
|
||||||
int a[] = {1, 2, 3, 4, 5};
|
int a[] = {1, 2, 3, 4, 5};
|
||||||
const int N = sizeof(a)/sizeof(a[0]);
|
const int N = sizeof(a)/sizeof(a[0]);
|
||||||
std::vector<int>::iterator i = v.insert(v.cbegin() + 10, forward_iterator<const int*>(a),
|
std::vector<int>::iterator i = v.insert(v.cbegin() + 10, forward_iterator<const int*>(a),
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include "../../../stack_allocator.h"
|
#include "test_allocator.h"
|
||||||
#include "MoveOnly.h"
|
#include "MoveOnly.h"
|
||||||
#include "min_allocator.h"
|
#include "min_allocator.h"
|
||||||
#include "asan_testing.h"
|
#include "asan_testing.h"
|
||||||
@@ -39,8 +39,8 @@ int main()
|
|||||||
assert(v[j] == MoveOnly());
|
assert(v[j] == MoveOnly());
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
std::vector<MoveOnly, stack_allocator<MoveOnly, 300> > v(100);
|
std::vector<MoveOnly, limited_allocator<MoveOnly, 300> > v(100);
|
||||||
std::vector<MoveOnly, stack_allocator<MoveOnly, 300> >::iterator i = v.insert(v.cbegin() + 10, MoveOnly(3));
|
std::vector<MoveOnly, limited_allocator<MoveOnly, 300> >::iterator i = v.insert(v.cbegin() + 10, MoveOnly(3));
|
||||||
assert(v.size() == 101);
|
assert(v.size() == 101);
|
||||||
assert(is_contiguous_container_asan_correct(v));
|
assert(is_contiguous_container_asan_correct(v));
|
||||||
assert(i == v.begin() + 10);
|
assert(i == v.begin() + 10);
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include "../../../stack_allocator.h"
|
#include "test_allocator.h"
|
||||||
#include "min_allocator.h"
|
#include "min_allocator.h"
|
||||||
#include "asan_testing.h"
|
#include "asan_testing.h"
|
||||||
|
|
||||||
@@ -70,8 +70,8 @@ int main()
|
|||||||
assert(v[j] == 0);
|
assert(v[j] == 0);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
std::vector<int, stack_allocator<int, 300> > v(100);
|
std::vector<int, limited_allocator<int, 300> > v(100);
|
||||||
std::vector<int, stack_allocator<int, 300> >::iterator i = v.insert(v.cbegin() + 10, 5, 1);
|
std::vector<int, limited_allocator<int, 300> >::iterator i = v.insert(v.cbegin() + 10, 5, 1);
|
||||||
assert(v.size() == 105);
|
assert(v.size() == 105);
|
||||||
assert(is_contiguous_container_asan_correct(v));
|
assert(is_contiguous_container_asan_correct(v));
|
||||||
assert(i == v.begin() + 10);
|
assert(i == v.begin() + 10);
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include "../../../stack_allocator.h"
|
#include "test_allocator.h"
|
||||||
#include "min_allocator.h"
|
#include "min_allocator.h"
|
||||||
#include "asan_testing.h"
|
#include "asan_testing.h"
|
||||||
|
|
||||||
@@ -68,8 +68,8 @@ int main()
|
|||||||
assert(v[j] == 0);
|
assert(v[j] == 0);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
std::vector<int, stack_allocator<int, 300> > v(100);
|
std::vector<int, limited_allocator<int, 300> > v(100);
|
||||||
std::vector<int, stack_allocator<int, 300> >::iterator i = v.insert(v.cbegin() + 10, 1);
|
std::vector<int, limited_allocator<int, 300> >::iterator i = v.insert(v.cbegin() + 10, 1);
|
||||||
assert(v.size() == 101);
|
assert(v.size() == 101);
|
||||||
assert(is_contiguous_container_asan_correct(v));
|
assert(is_contiguous_container_asan_correct(v));
|
||||||
assert(i == v.begin() + 10);
|
assert(i == v.begin() + 10);
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include "../../../stack_allocator.h"
|
#include "test_allocator.h"
|
||||||
#include "min_allocator.h"
|
#include "min_allocator.h"
|
||||||
|
|
||||||
#if _LIBCPP_DEBUG >= 1
|
#if _LIBCPP_DEBUG >= 1
|
||||||
|
|||||||
@@ -13,7 +13,7 @@
|
|||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include "../../../stack_allocator.h"
|
#include "test_allocator.h"
|
||||||
#include "min_allocator.h"
|
#include "min_allocator.h"
|
||||||
#include "asan_testing.h"
|
#include "asan_testing.h"
|
||||||
|
|
||||||
@@ -48,7 +48,7 @@ int main()
|
|||||||
assert(c[j] == j);
|
assert(c[j] == j);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
std::vector<int, stack_allocator<int, 15> > c;
|
std::vector<int, limited_allocator<int, 15> > c;
|
||||||
c.push_back(0);
|
c.push_back(0);
|
||||||
assert(c.size() == 1);
|
assert(c.size() == 1);
|
||||||
assert(is_contiguous_container_asan_correct(c));
|
assert(is_contiguous_container_asan_correct(c));
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include "MoveOnly.h"
|
#include "MoveOnly.h"
|
||||||
#include "../../../stack_allocator.h"
|
#include "test_allocator.h"
|
||||||
#include "min_allocator.h"
|
#include "min_allocator.h"
|
||||||
#include "asan_testing.h"
|
#include "asan_testing.h"
|
||||||
|
|
||||||
@@ -50,7 +50,7 @@ int main()
|
|||||||
assert(c[j] == MoveOnly(j));
|
assert(c[j] == MoveOnly(j));
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
std::vector<MoveOnly, stack_allocator<MoveOnly, 15> > c;
|
std::vector<MoveOnly, limited_allocator<MoveOnly, 15> > c;
|
||||||
c.push_back(MoveOnly(0));
|
c.push_back(MoveOnly(0));
|
||||||
assert(c.size() == 1);
|
assert(c.size() == 1);
|
||||||
assert(is_contiguous_container_asan_correct(c));
|
assert(is_contiguous_container_asan_correct(c));
|
||||||
|
|||||||
@@ -1,66 +0,0 @@
|
|||||||
//===----------------------------------------------------------------------===//
|
|
||||||
//
|
|
||||||
// The LLVM Compiler Infrastructure
|
|
||||||
//
|
|
||||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
|
||||||
// Source Licenses. See LICENSE.TXT for details.
|
|
||||||
//
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
|
|
||||||
#ifndef STACK_ALLOCATOR_H
|
|
||||||
#define STACK_ALLOCATOR_H
|
|
||||||
|
|
||||||
#include <cstddef>
|
|
||||||
#include <new>
|
|
||||||
|
|
||||||
template <class T, std::size_t N>
|
|
||||||
class stack_allocator
|
|
||||||
{
|
|
||||||
char buf_[sizeof(T)*N];
|
|
||||||
char* ptr_;
|
|
||||||
public:
|
|
||||||
typedef T value_type;
|
|
||||||
typedef value_type* pointer;
|
|
||||||
typedef const value_type* const_pointer;
|
|
||||||
typedef value_type& reference;
|
|
||||||
typedef const value_type& const_reference;
|
|
||||||
typedef std::size_t size_type;
|
|
||||||
typedef std::ptrdiff_t difference_type;
|
|
||||||
|
|
||||||
template <class U> struct rebind {typedef stack_allocator<U, N> other;};
|
|
||||||
|
|
||||||
stack_allocator() : ptr_(buf_) {}
|
|
||||||
|
|
||||||
private:
|
|
||||||
stack_allocator(const stack_allocator&);// = delete;
|
|
||||||
stack_allocator& operator=(const stack_allocator&);// = delete;
|
|
||||||
|
|
||||||
public:
|
|
||||||
pointer allocate(size_type n, const void* = 0)
|
|
||||||
{
|
|
||||||
if (n > N - (ptr_ - buf_) / sizeof(value_type)) {
|
|
||||||
#ifndef _LIBCPP_NO_EXCEPTIONS
|
|
||||||
throw std::bad_alloc();
|
|
||||||
#else
|
|
||||||
std::terminate();
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
pointer r = (T*)ptr_;
|
|
||||||
ptr_ += n * sizeof(T);
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
void deallocate(pointer p, size_type n)
|
|
||||||
{
|
|
||||||
if ((char*)(p + n) == ptr_)
|
|
||||||
ptr_ = (char*)p;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_type max_size() const {return N;}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <class T, std::size_t N>
|
|
||||||
inline
|
|
||||||
void
|
|
||||||
swap(stack_allocator<T, N>& x, stack_allocator<T, N>& y) {}
|
|
||||||
|
|
||||||
#endif // STACK_ALLOCATOR_H
|
|
||||||
@@ -302,5 +302,78 @@ operator!=(const TaggingAllocator<T>&, const TaggingAllocator<U>&)
|
|||||||
{ return false; }
|
{ return false; }
|
||||||
#endif
|
#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) {}
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
T *allocate(std::size_t N) {
|
||||||
|
if (N + outstanding_ > MaxAllocs)
|
||||||
|
TEST_THROW(std::bad_alloc());
|
||||||
|
last_alloc_ = ::operator new(N*sizeof(T));
|
||||||
|
outstanding_ += N;
|
||||||
|
return static_cast<T*>(last_alloc_);
|
||||||
|
}
|
||||||
|
|
||||||
|
void deallocate(void* ptr, std::size_t N) {
|
||||||
|
if (ptr == last_alloc_) {
|
||||||
|
last_alloc_ = nullptr;
|
||||||
|
assert(outstanding_ >= N);
|
||||||
|
outstanding_ -= N;
|
||||||
|
}
|
||||||
|
::operator delete(ptr);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class T, std::size_t N>
|
||||||
|
class limited_allocator
|
||||||
|
{
|
||||||
|
typedef limited_alloc_handle<N> BuffT;
|
||||||
|
std::shared_ptr<BuffT> handle_;
|
||||||
|
public:
|
||||||
|
typedef T value_type;
|
||||||
|
typedef value_type* pointer;
|
||||||
|
typedef const value_type* const_pointer;
|
||||||
|
typedef value_type& reference;
|
||||||
|
typedef const value_type& const_reference;
|
||||||
|
typedef std::size_t size_type;
|
||||||
|
typedef std::ptrdiff_t difference_type;
|
||||||
|
|
||||||
|
template <class U> struct rebind { typedef limited_allocator<U, N> other; };
|
||||||
|
|
||||||
|
limited_allocator() : handle_(new BuffT) {}
|
||||||
|
|
||||||
|
limited_allocator(limited_allocator const& other) : handle_(other.handle_) {}
|
||||||
|
|
||||||
|
template <class U>
|
||||||
|
explicit limited_allocator(limited_allocator<U, N> const& other)
|
||||||
|
: handle_(other.handle_) {}
|
||||||
|
|
||||||
|
private:
|
||||||
|
limited_allocator& operator=(const limited_allocator&);// = delete;
|
||||||
|
|
||||||
|
public:
|
||||||
|
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(); }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class T, class U, std::size_t N>
|
||||||
|
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) {
|
||||||
|
return !(LHS == RHS);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif // TEST_ALLOCATOR_H
|
#endif // TEST_ALLOCATOR_H
|
||||||
|
|||||||
Reference in New Issue
Block a user