Commit 7a4be380 by Jonathan Wakely Committed by Jonathan Wakely

Make __resource_adaptor_imp usable with C++17 memory_resource

By making the memory_resource base class a template parameter the
__resource_adaptor_imp can be used to adapt an allocator into a
std::pmr::memory_resource instead of experimental::pmr::memory_resource.

	* include/experimental/memory_resource: Adjust comments and
	whitespace.
	(__resource_adaptor_imp): Add second template parameter for type of
	memory resource base class.
	(memory_resource): Define default constructor, destructor, copy
	constructor and copy assignment operator as defaulted.

From-SVN: r262944
parent 0568ade6
2018-07-24 Jonathan Wakely <jwakely@redhat.com> 2018-07-24 Jonathan Wakely <jwakely@redhat.com>
* include/experimental/memory_resource: Adjust comments and
whitespace.
(__resource_adaptor_imp): Add second template parameter for type of
memory resource base class.
(memory_resource): Define default constructor, destructor, copy
constructor and copy assignment operator as defaulted.
PR libstdc++/70966 PR libstdc++/70966
* include/experimental/memory_resource (__get_default_resource): Use * include/experimental/memory_resource (__get_default_resource): Use
placement new to create an object with dynamic storage duration. placement new to create an object with dynamic storage duration.
......
...@@ -29,12 +29,12 @@ ...@@ -29,12 +29,12 @@
#ifndef _GLIBCXX_EXPERIMENTAL_MEMORY_RESOURCE #ifndef _GLIBCXX_EXPERIMENTAL_MEMORY_RESOURCE
#define _GLIBCXX_EXPERIMENTAL_MEMORY_RESOURCE 1 #define _GLIBCXX_EXPERIMENTAL_MEMORY_RESOURCE 1
#include <memory> #include <memory> // align, uses_allocator, __uses_alloc
#include <experimental/utility> // pair, experimental::erased_type
#include <atomic> // atomic
#include <new> #include <new>
#include <atomic>
#include <cstddef>
#include <ext/new_allocator.h> #include <ext/new_allocator.h>
#include <experimental/bits/lfts_config.h> #include <debug/assertions.h>
namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) namespace __gnu_cxx _GLIBCXX_VISIBILITY(default)
{ {
...@@ -51,39 +51,41 @@ inline namespace fundamentals_v2 { ...@@ -51,39 +51,41 @@ inline namespace fundamentals_v2 {
namespace pmr { namespace pmr {
#define __cpp_lib_experimental_memory_resources 201402L #define __cpp_lib_experimental_memory_resources 201402L
// Standard memory resources
// 8.5 Class memory_resource
class memory_resource; class memory_resource;
template <typename _Tp> // 8.6 Class template polymorphic_allocator
template<typename _Tp>
class polymorphic_allocator; class polymorphic_allocator;
template <typename _Alloc> template<typename _Alloc, typename _Resource = memory_resource>
class __resource_adaptor_imp; class __resource_adaptor_imp;
template <typename _Alloc> // 8.7 Alias template resource_adaptor
template<typename _Alloc>
using resource_adaptor = __resource_adaptor_imp< using resource_adaptor = __resource_adaptor_imp<
typename allocator_traits<_Alloc>::template rebind_alloc<char>>; typename allocator_traits<_Alloc>::template rebind_alloc<char>>;
template <typename _Tp> // 8.8 Global memory resources
struct __uses_allocator_construction_helper;
// Global memory resources
memory_resource* new_delete_resource() noexcept; memory_resource* new_delete_resource() noexcept;
memory_resource* null_memory_resource() noexcept; memory_resource* null_memory_resource() noexcept;
// The default memory resource
memory_resource* get_default_resource() noexcept; memory_resource* get_default_resource() noexcept;
memory_resource* set_default_resource(memory_resource* __r) noexcept; memory_resource* set_default_resource(memory_resource* __r) noexcept;
// Standard memory resources // TODO 8.9 Pool resource classes
// 8.5 Class memory_resource
class memory_resource class memory_resource
{ {
protected:
static constexpr size_t _S_max_align = alignof(max_align_t); static constexpr size_t _S_max_align = alignof(max_align_t);
public: public:
virtual ~memory_resource() { } memory_resource() = default;
memory_resource(const memory_resource&) = default;
virtual ~memory_resource() = default;
memory_resource& operator=(const memory_resource&) = default;
void* void*
allocate(size_t __bytes, size_t __alignment = _S_max_align) allocate(size_t __bytes, size_t __alignment = _S_max_align)
...@@ -109,18 +111,15 @@ namespace pmr { ...@@ -109,18 +111,15 @@ namespace pmr {
}; };
inline bool inline bool
operator==(const memory_resource& __a, operator==(const memory_resource& __a, const memory_resource& __b) noexcept
const memory_resource& __b) noexcept
{ return &__a == &__b || __a.is_equal(__b); } { return &__a == &__b || __a.is_equal(__b); }
inline bool inline bool
operator!=(const memory_resource& __a, operator!=(const memory_resource& __a, const memory_resource& __b) noexcept
const memory_resource& __b) noexcept
{ return !(__a == __b); } { return !(__a == __b); }
// 8.6 Class template polymorphic_allocator template<typename _Tp>
template <class _Tp>
class polymorphic_allocator class polymorphic_allocator
{ {
using __uses_alloc1_ = __uses_alloc1<memory_resource*>; using __uses_alloc1_ = __uses_alloc1<memory_resource*>;
...@@ -134,14 +133,15 @@ namespace pmr { ...@@ -134,14 +133,15 @@ namespace pmr {
template<typename _Tp1, typename... _Args> template<typename _Tp1, typename... _Args>
void void
_M_construct(__uses_alloc1_, _Tp1* __p, _Args&&... __args) _M_construct(__uses_alloc1_, _Tp1* __p, _Args&&... __args)
{ ::new(__p) _Tp1(allocator_arg, this->resource(), {
std::forward<_Args>(__args)...); } ::new(__p) _Tp1(allocator_arg, this->resource(),
std::forward<_Args>(__args)...);
}
template<typename _Tp1, typename... _Args> template<typename _Tp1, typename... _Args>
void void
_M_construct(__uses_alloc2_, _Tp1* __p, _Args&&... __args) _M_construct(__uses_alloc2_, _Tp1* __p, _Args&&... __args)
{ ::new(__p) _Tp1(std::forward<_Args>(__args)..., { ::new(__p) _Tp1(std::forward<_Args>(__args)..., this->resource()); }
this->resource()); }
public: public:
using value_type = _Tp; using value_type = _Tp;
...@@ -169,11 +169,13 @@ namespace pmr { ...@@ -169,11 +169,13 @@ namespace pmr {
{ return static_cast<_Tp*>(_M_resource->allocate(__n * sizeof(_Tp), { return static_cast<_Tp*>(_M_resource->allocate(__n * sizeof(_Tp),
alignof(_Tp))); } alignof(_Tp))); }
void deallocate(_Tp* __p, size_t __n) void
deallocate(_Tp* __p, size_t __n)
{ _M_resource->deallocate(__p, __n * sizeof(_Tp), alignof(_Tp)); } { _M_resource->deallocate(__p, __n * sizeof(_Tp), alignof(_Tp)); }
template <typename _Tp1, typename... _Args> //used here template <typename _Tp1, typename... _Args> //used here
void construct(_Tp1* __p, _Args&&... __args) void
construct(_Tp1* __p, _Args&&... __args)
{ {
memory_resource* const __resource = this->resource(); memory_resource* const __resource = this->resource();
auto __use_tag auto __use_tag
...@@ -184,9 +186,9 @@ namespace pmr { ...@@ -184,9 +186,9 @@ namespace pmr {
// Specializations for pair using piecewise construction // Specializations for pair using piecewise construction
template <typename _Tp1, typename _Tp2, template <typename _Tp1, typename _Tp2,
typename... _Args1, typename... _Args2> typename... _Args1, typename... _Args2>
void construct(pair<_Tp1, _Tp2>* __p, piecewise_construct_t, void
tuple<_Args1...> __x, construct(pair<_Tp1, _Tp2>* __p, piecewise_construct_t,
tuple<_Args2...> __y) tuple<_Args1...> __x, tuple<_Args2...> __y)
{ {
memory_resource* const __resource = this->resource(); memory_resource* const __resource = this->resource();
auto __x_use_tag = auto __x_use_tag =
...@@ -200,36 +202,48 @@ namespace pmr { ...@@ -200,36 +202,48 @@ namespace pmr {
} }
template <typename _Tp1, typename _Tp2> template <typename _Tp1, typename _Tp2>
void construct(pair<_Tp1,_Tp2>* __p) void
construct(pair<_Tp1,_Tp2>* __p)
{ this->construct(__p, piecewise_construct, tuple<>(), tuple<>()); } { this->construct(__p, piecewise_construct, tuple<>(), tuple<>()); }
template <typename _Tp1, typename _Tp2, typename _Up, typename _Vp> template <typename _Tp1, typename _Tp2, typename _Up, typename _Vp>
void construct(pair<_Tp1,_Tp2>* __p, _Up&& __x, _Vp&& __y) void
{ this->construct(__p, piecewise_construct, construct(pair<_Tp1,_Tp2>* __p, _Up&& __x, _Vp&& __y)
{
this->construct(__p, piecewise_construct,
forward_as_tuple(std::forward<_Up>(__x)), forward_as_tuple(std::forward<_Up>(__x)),
forward_as_tuple(std::forward<_Vp>(__y))); } forward_as_tuple(std::forward<_Vp>(__y)));
}
template <typename _Tp1, typename _Tp2, typename _Up, typename _Vp> template <typename _Tp1, typename _Tp2, typename _Up, typename _Vp>
void construct(pair<_Tp1,_Tp2>* __p, const std::pair<_Up, _Vp>& __pr) void
{ this->construct(__p, piecewise_construct, forward_as_tuple(__pr.first), construct(pair<_Tp1,_Tp2>* __p, const std::pair<_Up, _Vp>& __pr)
forward_as_tuple(__pr.second)); } {
this->construct(__p, piecewise_construct,
forward_as_tuple(__pr.first),
forward_as_tuple(__pr.second));
}
template <typename _Tp1, typename _Tp2, typename _Up, typename _Vp> template <typename _Tp1, typename _Tp2, typename _Up, typename _Vp>
void construct(pair<_Tp1,_Tp2>* __p, pair<_Up, _Vp>&& __pr) void
{ this->construct(__p, piecewise_construct, construct(pair<_Tp1,_Tp2>* __p, pair<_Up, _Vp>&& __pr)
{
this->construct(__p, piecewise_construct,
forward_as_tuple(std::forward<_Up>(__pr.first)), forward_as_tuple(std::forward<_Up>(__pr.first)),
forward_as_tuple(std::forward<_Vp>(__pr.second))); } forward_as_tuple(std::forward<_Vp>(__pr.second)));
}
template <typename _Up> template <typename _Up>
void destroy(_Up* __p) void
destroy(_Up* __p)
{ __p->~_Up(); } { __p->~_Up(); }
// Return a default-constructed allocator (no allocator propagation) // Return a default-constructed allocator (no allocator propagation)
polymorphic_allocator select_on_container_copy_construction() const polymorphic_allocator
select_on_container_copy_construction() const
{ return polymorphic_allocator(); } { return polymorphic_allocator(); }
memory_resource* resource() const memory_resource* resource() const { return _M_resource; }
{ return _M_resource; }
private: private:
template<typename _Tuple> template<typename _Tuple>
...@@ -252,18 +266,21 @@ namespace pmr { ...@@ -252,18 +266,21 @@ namespace pmr {
}; };
template <class _Tp1, class _Tp2> template <class _Tp1, class _Tp2>
bool operator==(const polymorphic_allocator<_Tp1>& __a, bool
operator==(const polymorphic_allocator<_Tp1>& __a,
const polymorphic_allocator<_Tp2>& __b) noexcept const polymorphic_allocator<_Tp2>& __b) noexcept
{ return *__a.resource() == *__b.resource(); } { return *__a.resource() == *__b.resource(); }
template <class _Tp1, class _Tp2> template <class _Tp1, class _Tp2>
bool operator!=(const polymorphic_allocator<_Tp1>& __a, bool
operator!=(const polymorphic_allocator<_Tp1>& __a,
const polymorphic_allocator<_Tp2>& __b) noexcept const polymorphic_allocator<_Tp2>& __b) noexcept
{ return !(__a == __b); } { return !(__a == __b); }
class __resource_adaptor_common class __resource_adaptor_common
{ {
template<typename> friend class __resource_adaptor_imp; template<typename, typename> friend class __resource_adaptor_imp;
struct _AlignMgr struct _AlignMgr
{ {
...@@ -376,10 +393,12 @@ namespace pmr { ...@@ -376,10 +393,12 @@ namespace pmr {
}; };
// 8.7.1 __resource_adaptor_imp // 8.7.1 __resource_adaptor_imp
template <typename _Alloc> template<typename _Alloc, typename _Resource>
class __resource_adaptor_imp class __resource_adaptor_imp
: public memory_resource, private __resource_adaptor_common : public _Resource, private __resource_adaptor_common
{ {
using memory_resource = _Resource;
static_assert(is_same<char, static_assert(is_same<char,
typename allocator_traits<_Alloc>::value_type>::value, typename allocator_traits<_Alloc>::value_type>::value,
"Allocator's value_type is char"); "Allocator's value_type is char");
...@@ -514,11 +533,11 @@ namespace pmr { ...@@ -514,11 +533,11 @@ namespace pmr {
__r = new_delete_resource(); __r = new_delete_resource();
return __get_default_resource().exchange(__r); return __get_default_resource().exchange(__r);
} }
} // namespace pmr } // namespace pmr
} // namespace fundamentals_v2 } // namespace fundamentals_v2
} // namespace experimental } // namespace experimental
_GLIBCXX_END_NAMESPACE_VERSION _GLIBCXX_END_NAMESPACE_VERSION
} // namespace std } // namespace std
#endif // _GLIBCXX_EXPERIMENTAL_MEMORY_RESOURCE
#endif
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