Commit bfeffbd1 by Fan You Committed by Jonathan Wakely

Implement C++ LFTSv1 polymorphic memory resources

2015-11-13  Fan You  <youfan.noey@gmail.com>

	* include/Makefile.am: Add new headers.
	* include/Makefile.in: Regenerate.
	* include/bits/uses_allocator.h (__erased_type): Define.
	(__uses_allocator_helper): Check for __erased_type.
	* include/experimental/memory_resource: New.
	* include/experimental/utlity: New.
	* testsuite/experimental/type_erased_allocator/1.cc: New.
	* testsuite/experimental/type_erased_allocator/1_neg.cc: New.
	* testsuite/experimental/type_erased_allocator/2.cc: New.
	* testsuite/experimental/type_erased_allocator/uses_allocator.cc: New.

From-SVN: r230294
parent 6faa9154
2015-11-13 Fan You <youfan.noey@gmail.com>
* include/Makefile.am: Add new headers.
* include/Makefile.in: Regenerate.
* include/bits/uses_allocator.h (__erased_type): Define.
(__uses_allocator_helper): Check for __erased_type.
* include/experimental/memory_resource: New.
* include/experimental/utlity: New.
* testsuite/experimental/type_erased_allocator/1.cc: New.
* testsuite/experimental/type_erased_allocator/1_neg.cc: New.
* testsuite/experimental/type_erased_allocator/2.cc: New.
* testsuite/experimental/type_erased_allocator/uses_allocator.cc: New.
2015-11-12 Jonathan Wakely <jwakely@redhat.com> 2015-11-12 Jonathan Wakely <jwakely@redhat.com>
PR libstdc++/56158 PR libstdc++/56158
......
...@@ -656,6 +656,7 @@ experimental_headers = \ ...@@ -656,6 +656,7 @@ experimental_headers = \
${experimental_srcdir}/list \ ${experimental_srcdir}/list \
${experimental_srcdir}/map \ ${experimental_srcdir}/map \
${experimental_srcdir}/memory \ ${experimental_srcdir}/memory \
${experimental_srcdir}/memory_resource \
${experimental_srcdir}/numeric \ ${experimental_srcdir}/numeric \
${experimental_srcdir}/optional \ ${experimental_srcdir}/optional \
${experimental_srcdir}/propagate_const \ ${experimental_srcdir}/propagate_const \
...@@ -668,6 +669,7 @@ experimental_headers = \ ...@@ -668,6 +669,7 @@ experimental_headers = \
${experimental_srcdir}/type_traits \ ${experimental_srcdir}/type_traits \
${experimental_srcdir}/unordered_map \ ${experimental_srcdir}/unordered_map \
${experimental_srcdir}/unordered_set \ ${experimental_srcdir}/unordered_set \
${experimental_srcdir}/utility \
${experimental_srcdir}/vector \ ${experimental_srcdir}/vector \
${experimental_filesystem_headers} ${experimental_filesystem_headers}
......
...@@ -945,6 +945,7 @@ experimental_headers = \ ...@@ -945,6 +945,7 @@ experimental_headers = \
${experimental_srcdir}/list \ ${experimental_srcdir}/list \
${experimental_srcdir}/map \ ${experimental_srcdir}/map \
${experimental_srcdir}/memory \ ${experimental_srcdir}/memory \
${experimental_srcdir}/memory_resource \
${experimental_srcdir}/numeric \ ${experimental_srcdir}/numeric \
${experimental_srcdir}/optional \ ${experimental_srcdir}/optional \
${experimental_srcdir}/propagate_const \ ${experimental_srcdir}/propagate_const \
...@@ -957,6 +958,7 @@ experimental_headers = \ ...@@ -957,6 +958,7 @@ experimental_headers = \
${experimental_srcdir}/type_traits \ ${experimental_srcdir}/type_traits \
${experimental_srcdir}/unordered_map \ ${experimental_srcdir}/unordered_map \
${experimental_srcdir}/unordered_set \ ${experimental_srcdir}/unordered_set \
${experimental_srcdir}/utility \
${experimental_srcdir}/vector \ ${experimental_srcdir}/vector \
${experimental_filesystem_headers} ${experimental_filesystem_headers}
......
...@@ -35,6 +35,12 @@ namespace std _GLIBCXX_VISIBILITY(default) ...@@ -35,6 +35,12 @@ namespace std _GLIBCXX_VISIBILITY(default)
{ {
_GLIBCXX_BEGIN_NAMESPACE_VERSION _GLIBCXX_BEGIN_NAMESPACE_VERSION
struct __erased_type { };
template<typename _Alloc, typename _Tp>
using __is_erased_or_convertible
= __or_<is_same<_Tp, __erased_type>, is_convertible<_Alloc, _Tp>>;
/// [allocator.tag] /// [allocator.tag]
struct allocator_arg_t { explicit allocator_arg_t() = default; }; struct allocator_arg_t { explicit allocator_arg_t() = default; };
...@@ -47,7 +53,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -47,7 +53,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _Tp, typename _Alloc> template<typename _Tp, typename _Alloc>
struct __uses_allocator_helper<_Tp, _Alloc, struct __uses_allocator_helper<_Tp, _Alloc,
__void_t<typename _Tp::allocator_type>> __void_t<typename _Tp::allocator_type>>
: is_convertible<_Alloc, typename _Tp::allocator_type>::type : __is_erased_or_convertible<_Alloc, typename _Tp::allocator_type>::type
{ }; { };
/// [allocator.uses.trait] /// [allocator.uses.trait]
......
// <experimental/utility> -*- C++ -*-
// Copyright (C) 2015 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
// terms of the GNU General Public License as published by the
// Free Software Foundation; either version 3, or (at your option)
// any later version.
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// Under Section 7 of GPL version 3, you are granted additional
// permissions described in the GCC Runtime Library Exception, version
// 3.1, as published by the Free Software Foundation.
// You should have received a copy of the GNU General Public License and
// a copy of the GCC Runtime Library Exception along with this program;
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
// <http://www.gnu.org/licenses/>.
/** @file experimental/utility
* This is a TS C++ Library header.
*/
#ifndef _GLIBCXX_EXPERIMENTAL_UTILITY
#define _GLIBCXX_EXPERIMENTAL_UTILITY 1
#include <utility>
#include <bits/uses_allocator.h>
namespace std {
namespace experimental {
inline namespace fundamentals_v2 {
_GLIBCXX_BEGIN_NAMESPACE_VERSION
// 3.1.2, erased-type placeholder
using erased_type = std::__erased_type;
_GLIBCXX_END_NAMESPACE_VERSION
} // namespace fundamentals_v2
} // namespace experimental
} // namespace std
#endif
// { dg-options "-std=gnu++14" }
// Copyright (C) 2015 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
// terms of the GNU General Public License as published by the
// Free Software Foundation; either version 3, or (at your option)
// any later version.
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License along
// with this library; see the file COPYING3. If not see
// <http://www.gnu.org/licenses/>.
#include <memory>
#include <experimental/memory_resource>
#include <vector>
#include <bits/uses_allocator.h>
#include <testsuite_hooks.h>
#include <testsuite_allocator.h>
using std::experimental::pmr::polymorphic_allocator;
using std::experimental::pmr::memory_resource;
using std::experimental::pmr::new_delete_resource;
using std::experimental::pmr::get_default_resource;
using std::experimental::pmr::set_default_resource;
struct A
{
A() { ++ctor_count; }
~A() { ++dtor_count; }
static int ctor_count;
static int dtor_count;
};
int A::ctor_count = 0;
int A::dtor_count = 0;
struct CountedResource : public memory_resource
{
public:
CountedResource() = default;
~ CountedResource() = default;
static size_t get_alloc_count() { return alloc_count; }
static size_t get_dalloc_count() { return dalloc_count; }
static size_t alloc_count;
static size_t dalloc_count;
protected:
void* do_allocate(size_t bytes, size_t alignment)
{
alloc_count += bytes;
if (auto ptr = std::malloc(bytes)) {
return ptr;
}
throw std::bad_alloc();
}
void do_deallocate(void *p, size_t bytes, size_t alignment)
{
dalloc_count += bytes;
free(p);
}
bool do_is_equal(const memory_resource& __other) const noexcept
{ return this == &__other; }
};
size_t CountedResource::alloc_count = 0;
size_t CountedResource::dalloc_count = 0;
void clear()
{
CountedResource::alloc_count = 0;
CountedResource::dalloc_count = 0;
A::ctor_count = 0;
A::dtor_count = 0;
}
// memory resource
void test01()
{
memory_resource* r = new_delete_resource();
VERIFY(get_default_resource() == r);
void *p = get_default_resource()->allocate(5);
VERIFY(p);
get_default_resource()->deallocate(p, 5);
clear();
CountedResource* cr = new CountedResource();
set_default_resource(cr);
VERIFY(get_default_resource() == cr);
void *pc = get_default_resource()->allocate(5);
VERIFY(pc);
get_default_resource()->deallocate(pc, 5);
VERIFY(CountedResource::get_alloc_count() == 5);
VERIFY(CountedResource::get_dalloc_count() == 5);
}
// polymorphic_allocator
void test02()
{
clear();
{
CountedResource cr;
polymorphic_allocator<A> pa(&cr);
std::vector<A, polymorphic_allocator<A>> v(5, A(), pa);
}
VERIFY(A::ctor_count == 1);
VERIFY(A::dtor_count == 6);
VERIFY(CountedResource::get_alloc_count() == 5);
VERIFY(CountedResource::get_dalloc_count() == 5);
}
void test03() {
clear();
CountedResource cr;
polymorphic_allocator<A> pa(&cr);
A* p = pa.allocate(1);
pa.construct(p);
pa.destroy(p);
pa.deallocate(p, 1);
VERIFY(A::ctor_count == 1);
VERIFY(A::dtor_count == 1);
VERIFY(CountedResource::get_alloc_count() == 1);
VERIFY(CountedResource::get_dalloc_count() == 1);
}
void test04() {
polymorphic_allocator<A> pa1(get_default_resource());
polymorphic_allocator<A> pa2(get_default_resource());
VERIFY(pa1 == pa2);
polymorphic_allocator<A> pa3 = pa2.select_on_container_copy_construction();
VERIFY(pa1 == pa3);
}
int main() {
test01();
test02();
test03();
test04();
return 0;
}
// { dg-do run { xfail *-*-* } }
// { dg-options "-std=gnu++14" }
// Copyright (C) 2015 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
// terms of the GNU General Public License as published by the
// Free Software Foundation; either version 3, or (at your option)
// any later version.
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License along
// with this library; see the file COPYING3. If not see
// <http://www.gnu.org/licenses/>.
#include <experimental/memory_resource>
#include <bits/uses_allocator.h>
#include <testsuite_hooks.h>
#include <testsuite_allocator.h>
using std::experimental::pmr::polymorphic_allocator;
using std::experimental::pmr::null_memory_resource;
using std::experimental::pmr::memory_resource;
void test01() {
memory_resource* r = null_memory_resource();
auto p = r->allocate(1);
}
int main() {
test01();
}
// { dg-options "-std=gnu++14" }
// Copyright (C) 2015 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
// terms of the GNU General Public License as published by the
// Free Software Foundation; either version 3, or (at your option)
// any later version.
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License along
// with this library; see the file COPYING3. If not see
// <http://www.gnu.org/licenses/>.
#include <memory>
#include <experimental/memory_resource>
#include <experimental/utility>
#include <bits/uses_allocator.h>
#include <testsuite_hooks.h>
#include <testsuite_allocator.h>
using std::experimental::pmr::polymorphic_allocator;
using std::experimental::pmr::memory_resource;
using std::experimental::pmr::new_delete_resource;
using std::experimental::pmr::get_default_resource;
using std::experimental::pmr::set_default_resource;
using std::allocator_arg_t;
enum CtorType { Default, Copy, Move, Other, Tuple, Piecewise_Default, Piecewise_Copy};
// type that takes a memory_resource before other ctor args
struct A
{
using allocator_type = std::experimental::erased_type;
CtorType type;
memory_resource* alloc = nullptr;
A() : type(Default) { }
A(allocator_arg_t, memory_resource* a) : type(Default), alloc(a) { }
A(const A&) : type(Copy) { }
A(allocator_arg_t, memory_resource* a, const A&) : type(Copy), alloc(a) { }
A(A&&) : type (Move) { }
A(allocator_arg_t, memory_resource* a, A&&) : type (Move), alloc(a) { }
A(int) : type(Other) { }
A(allocator_arg_t, memory_resource* a, int) : type(Other), alloc(a) { }
};
// type that takes a memory_resource after other ctor args
struct B
{
using allocator_type = std::experimental::erased_type;
CtorType type;
memory_resource* alloc = nullptr;
B() : type(Default) { }
B(memory_resource* a) : type(Default), alloc(a) { }
B(const B&) : type(Copy) { }
B(const B&, memory_resource* a) : type(Copy), alloc(a) { }
B(B&&) : type (Move) { }
B(B&&, memory_resource* a) : type(Move), alloc(a) { }
B(int) : type(Other) { }
B(int, memory_resource* a) : type(Other), alloc(a) { }
};
// type that takes no memory_resource
struct C
{
CtorType type;
C() : type(Default) { }
C(const C&) : type(Copy) { }
C(C&&) : type(Move) { }
C(int) : type(Other) { }
};
// test construct for type that
// uses memory_resource* as allocator
template<typename A>
void test_uses_alloc() {
polymorphic_allocator<A> pa;
A* p = pa.allocate(1);
A a;
pa.construct(p);
VERIFY(p->alloc == get_default_resource());
VERIFY(p->type == Default);
pa.destroy(p);
pa.construct(p, a);
VERIFY(p->type == Copy);
pa.destroy(p);
pa.construct(p, A());
VERIFY(p->type == Move);
pa.destroy(p);
pa.construct(p, 1);
VERIFY(p->type == Other);
pa.destroy(p);
pa.deallocate(p, 1);
}
// test construct for type that not using allocator
template <typename C>
void test_non_alloc() {
polymorphic_allocator<C> pa;
C* p = pa.allocate(1);
C b;
pa.construct(p);
VERIFY(p->type == Default);
pa.destroy(p);
pa.construct(p, b);
VERIFY(p->type == Copy);
pa.destroy(p);
pa.construct(p, C());
VERIFY(p->type == Move);
pa.destroy(p);
pa.construct(p, 1);
VERIFY(p->type == Other);
pa.destroy(p);
pa.deallocate(p, 1);
}
// test piecewise_construct
template <typename A, typename B>
void test_pair() {
polymorphic_allocator<std::pair<A, B>> pa;
std::pair<A, B>* p = pa.allocate(1);
std::tuple<> t;
// construct(pair<T1, T2>* p, piecewise_construct_t, tuple<...>, tuple<...>)
pa.construct(p, std::piecewise_construct, t, t);
VERIFY(p->first.type == Default);
VERIFY(p->second.type == Default);
pa.destroy(p);
// construct(pair<T1, T2>* __p)
pa.construct(p);
VERIFY(p->first.type == Default);
VERIFY(p->second.type == Default);
pa.destroy(p);
// construct(pair<T1, T2>* p, U&& x, V&& y)
A a; B b;
pa.construct(p, a, b);
VERIFY(p->first.type == Copy);
VERIFY(p->second.type == Copy);
pa.destroy(p);
pa.construct(p, A(), B());
VERIFY(p->first.type == Move);
VERIFY(p->second.type == Move);
auto pp = *p;
pa.destroy(p);
// construct(pair<T1, T2>* p, const pair<U, V>& x)
pa.construct(p, pp);
VERIFY(p->first.type == Copy);
VERIFY(p->second.type == Copy);
pa.destroy(p);
// construct(pair<T1, T2>* p, pair<U, V>&& x)
pa.construct(p, std::move(pp));
VERIFY(p->first.type == Move);
VERIFY(p->second.type == Move);
pa.destroy(p);
pa.deallocate(p, 1);
}
void test01() {
test_uses_alloc<A>();
test_uses_alloc<B>();
test_non_alloc<C>();
}
void test02() {
test_pair<A, A>();
test_pair<A, B>();
test_pair<A, C>();
test_pair<B, B>();
test_pair<B, A>();
test_pair<B, C>();
test_pair<C, C>();
}
int main() {
test01();
test02();
}
#include <bits/uses_allocator.h>
#include <vector>
#include <experimental/utility>
#include <memory>
using std::vector;
using std::allocator;
using std::uses_allocator;
struct A {
using allocator_type = std::experimental::erased_type;
};
void test01() {
static_assert(uses_allocator<vector<int>, allocator<int>>());
static_assert(uses_allocator<A, allocator<A>>());
}
int main() {
test01();
return 0;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment