115551efdSEric Fiselier// -*- C++ -*-
2eb8650a7SLouis Dionne//===----------------------------------------------------------------------===//
315551efdSEric Fiselier//
42946cd70SChandler Carruth// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
52946cd70SChandler Carruth// See https://llvm.org/LICENSE.txt for license information.
62946cd70SChandler Carruth// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
715551efdSEric Fiselier//
815551efdSEric Fiselier//===----------------------------------------------------------------------===//
915551efdSEric Fiselier
1015551efdSEric Fiselier#ifndef _LIBCPP_EXPERIMENTAL_MEMORY_RESOURCE
1115551efdSEric Fiselier#define _LIBCPP_EXPERIMENTAL_MEMORY_RESOURCE
1215551efdSEric Fiselier
1315551efdSEric Fiselier/**
1415551efdSEric Fiselier    experimental/memory_resource synopsis
1515551efdSEric Fiselier
1615551efdSEric Fiselier// C++1y
1715551efdSEric Fiselier
1815551efdSEric Fiseliernamespace std {
1915551efdSEric Fiseliernamespace experimental {
2015551efdSEric Fiselierinline namespace fundamentals_v1 {
2115551efdSEric Fiseliernamespace pmr {
2215551efdSEric Fiselier
2315551efdSEric Fiselier  class memory_resource;
2415551efdSEric Fiselier
2515551efdSEric Fiselier  bool operator==(const memory_resource& a,
2615551efdSEric Fiselier                  const memory_resource& b) noexcept;
2715551efdSEric Fiselier  bool operator!=(const memory_resource& a,
2815551efdSEric Fiselier                  const memory_resource& b) noexcept;
2915551efdSEric Fiselier
3015551efdSEric Fiselier  template <class Tp> class polymorphic_allocator;
3115551efdSEric Fiselier
3215551efdSEric Fiselier  template <class T1, class T2>
3315551efdSEric Fiselier  bool operator==(const polymorphic_allocator<T1>& a,
3415551efdSEric Fiselier                  const polymorphic_allocator<T2>& b) noexcept;
3515551efdSEric Fiselier  template <class T1, class T2>
3615551efdSEric Fiselier  bool operator!=(const polymorphic_allocator<T1>& a,
3715551efdSEric Fiselier                  const polymorphic_allocator<T2>& b) noexcept;
3815551efdSEric Fiselier
3915551efdSEric Fiselier  // The name resource_adaptor_imp is for exposition only.
4015551efdSEric Fiselier  template <class Allocator> class resource_adaptor_imp;
4115551efdSEric Fiselier
4215551efdSEric Fiselier  template <class Allocator>
4315551efdSEric Fiselier    using resource_adaptor = resource_adaptor_imp<
4415551efdSEric Fiselier      allocator_traits<Allocator>::rebind_alloc<char>>;
4515551efdSEric Fiselier
4615551efdSEric Fiselier  // Global memory resources
4715551efdSEric Fiselier  memory_resource* new_delete_resource() noexcept;
4815551efdSEric Fiselier  memory_resource* null_memory_resource() noexcept;
4915551efdSEric Fiselier
5015551efdSEric Fiselier  // The default memory resource
5115551efdSEric Fiselier  memory_resource* set_default_resource(memory_resource* r) noexcept;
5215551efdSEric Fiselier  memory_resource* get_default_resource() noexcept;
5315551efdSEric Fiselier
5415551efdSEric Fiselier  // Standard memory resources
5515551efdSEric Fiselier  struct pool_options;
5615551efdSEric Fiselier  class synchronized_pool_resource;
5715551efdSEric Fiselier  class unsynchronized_pool_resource;
5815551efdSEric Fiselier  class monotonic_buffer_resource;
5915551efdSEric Fiselier
6015551efdSEric Fiselier} // namespace pmr
6115551efdSEric Fiselier} // namespace fundamentals_v1
6215551efdSEric Fiselier} // namespace experimental
6315551efdSEric Fiselier} // namespace std
6415551efdSEric Fiselier
6515551efdSEric Fiselier */
6615551efdSEric Fiselier
67*385cc25aSLouis Dionne#include <__assert> // all public C++ headers provide the assertion handler
684d81a46fSArthur O'Dwyer#include <__tuple>
6952915d78SNikolas Klauser#include <__utility/move.h>
704d81a46fSArthur O'Dwyer#include <cstddef>
714d81a46fSArthur O'Dwyer#include <cstdlib>
7215551efdSEric Fiselier#include <experimental/__config>
7315551efdSEric Fiselier#include <experimental/__memory>
7415551efdSEric Fiselier#include <limits>
7515551efdSEric Fiselier#include <memory>
7615551efdSEric Fiselier#include <new>
7715551efdSEric Fiselier#include <stdexcept>
7815551efdSEric Fiselier#include <type_traits>
7952915d78SNikolas Klauser
8015551efdSEric Fiselier#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
8115551efdSEric Fiselier#  pragma GCC system_header
8215551efdSEric Fiselier#endif
8315551efdSEric Fiselier
84a016efb1SEric Fiselier_LIBCPP_PUSH_MACROS
85a016efb1SEric Fiselier#include <__undef_macros>
86a016efb1SEric Fiselier
8715551efdSEric Fiselier_LIBCPP_BEGIN_NAMESPACE_LFTS_PMR
8815551efdSEric Fiselier
89b66754a2SBrian Gesiak// Round __s up to next multiple of __a.
90b66754a2SBrian Gesiakinline _LIBCPP_INLINE_VISIBILITY
91b66754a2SBrian Gesiaksize_t __aligned_allocation_size(size_t __s, size_t __a) _NOEXCEPT
92b66754a2SBrian Gesiak{
93b66754a2SBrian Gesiak    _LIBCPP_ASSERT(__s + __a > __s, "aligned allocation size overflows");
94b66754a2SBrian Gesiak    return (__s + __a - 1) & ~(__a - 1);
95b66754a2SBrian Gesiak}
96b66754a2SBrian Gesiak
9715551efdSEric Fiselier// 8.5, memory.resource
98cb5b004aSEric Fiselierclass _LIBCPP_TYPE_VIS memory_resource
9915551efdSEric Fiselier{
100d108bf85SEric Fiselier    static const size_t __max_align = _LIBCPP_ALIGNOF(max_align_t);
10115551efdSEric Fiselier
10215551efdSEric Fiselier// 8.5.2, memory.resource.public
10315551efdSEric Fiselierpublic:
10415551efdSEric Fiselier    virtual ~memory_resource() = default;
10515551efdSEric Fiselier
10615551efdSEric Fiselier    _LIBCPP_INLINE_VISIBILITY
10715551efdSEric Fiselier    void* allocate(size_t __bytes, size_t __align = __max_align)
10815551efdSEric Fiselier        { return do_allocate(__bytes, __align); }
10915551efdSEric Fiselier
11015551efdSEric Fiselier    _LIBCPP_INLINE_VISIBILITY
11115551efdSEric Fiselier    void deallocate(void * __p, size_t __bytes, size_t __align = __max_align)
11215551efdSEric Fiselier        { do_deallocate(__p, __bytes, __align); }
11315551efdSEric Fiselier
11415551efdSEric Fiselier    _LIBCPP_INLINE_VISIBILITY
11515551efdSEric Fiselier    bool is_equal(memory_resource const & __other) const _NOEXCEPT
11615551efdSEric Fiselier        { return do_is_equal(__other); }
11715551efdSEric Fiselier
11815551efdSEric Fiselier// 8.5.3, memory.resource.priv
1190a20660cSzoecarverprivate:
12015551efdSEric Fiselier    virtual void* do_allocate(size_t, size_t) = 0;
12115551efdSEric Fiselier    virtual void do_deallocate(void*, size_t, size_t) = 0;
12215551efdSEric Fiselier    virtual bool do_is_equal(memory_resource const &) const _NOEXCEPT = 0;
12315551efdSEric Fiselier};
12415551efdSEric Fiselier
12515551efdSEric Fiselier// 8.5.4, memory.resource.eq
12615551efdSEric Fiselierinline _LIBCPP_INLINE_VISIBILITY
12715551efdSEric Fiselierbool operator==(memory_resource const & __lhs,
12815551efdSEric Fiselier                memory_resource const & __rhs) _NOEXCEPT
12915551efdSEric Fiselier{
13015551efdSEric Fiselier    return &__lhs == &__rhs || __lhs.is_equal(__rhs);
13115551efdSEric Fiselier}
13215551efdSEric Fiselier
13315551efdSEric Fiselierinline _LIBCPP_INLINE_VISIBILITY
13415551efdSEric Fiselierbool operator!=(memory_resource const & __lhs,
13515551efdSEric Fiselier                memory_resource const & __rhs) _NOEXCEPT
13615551efdSEric Fiselier{
13715551efdSEric Fiselier    return !(__lhs == __rhs);
13815551efdSEric Fiselier}
13915551efdSEric Fiselier
14015551efdSEric Fiselier_LIBCPP_FUNC_VIS
14115551efdSEric Fiseliermemory_resource * new_delete_resource() _NOEXCEPT;
14215551efdSEric Fiselier
14315551efdSEric Fiselier_LIBCPP_FUNC_VIS
14415551efdSEric Fiseliermemory_resource * null_memory_resource() _NOEXCEPT;
14515551efdSEric Fiselier
14615551efdSEric Fiselier_LIBCPP_FUNC_VIS
14715551efdSEric Fiseliermemory_resource * get_default_resource() _NOEXCEPT;
14815551efdSEric Fiselier
14915551efdSEric Fiselier_LIBCPP_FUNC_VIS
15015551efdSEric Fiseliermemory_resource * set_default_resource(memory_resource * __new_res) _NOEXCEPT;
15115551efdSEric Fiselier
15215551efdSEric Fiselier// 8.6, memory.polymorphic.allocator.class
15315551efdSEric Fiselier
15415551efdSEric Fiselier// 8.6.1, memory.polymorphic.allocator.overview
15515551efdSEric Fiseliertemplate <class _ValueType>
156e2f2d1edSEric Fiselierclass _LIBCPP_TEMPLATE_VIS polymorphic_allocator
15715551efdSEric Fiselier{
15815551efdSEric Fiselierpublic:
15915551efdSEric Fiselier    typedef _ValueType value_type;
16015551efdSEric Fiselier
16115551efdSEric Fiselier    // 8.6.2, memory.polymorphic.allocator.ctor
16215551efdSEric Fiselier    _LIBCPP_INLINE_VISIBILITY
16315551efdSEric Fiselier    polymorphic_allocator() _NOEXCEPT
16415551efdSEric Fiselier      : __res_(_VSTD_LFTS_PMR::get_default_resource())
16515551efdSEric Fiselier    {}
16615551efdSEric Fiselier
16715551efdSEric Fiselier    _LIBCPP_INLINE_VISIBILITY
16815551efdSEric Fiselier    polymorphic_allocator(memory_resource * __r) _NOEXCEPT
16915551efdSEric Fiselier      : __res_(__r)
17015551efdSEric Fiselier    {}
17115551efdSEric Fiselier
17215551efdSEric Fiselier    polymorphic_allocator(polymorphic_allocator const &) = default;
17315551efdSEric Fiselier
17415551efdSEric Fiselier    template <class _Tp>
17515551efdSEric Fiselier    _LIBCPP_INLINE_VISIBILITY
17615551efdSEric Fiselier    polymorphic_allocator(polymorphic_allocator<_Tp> const & __other) _NOEXCEPT
17715551efdSEric Fiselier      : __res_(__other.resource())
17815551efdSEric Fiselier    {}
17915551efdSEric Fiselier
18015551efdSEric Fiselier    polymorphic_allocator &
1818b7faa68SEric Fiselier    operator=(polymorphic_allocator const &) = delete;
18215551efdSEric Fiselier
18315551efdSEric Fiselier    // 8.6.3, memory.polymorphic.allocator.mem
18415551efdSEric Fiselier    _LIBCPP_INLINE_VISIBILITY
18515551efdSEric Fiselier    _ValueType* allocate(size_t __n) {
186be10b1f1SMikhail Maltsev        if (__n > __max_size())
187be10b1f1SMikhail Maltsev            __throw_bad_array_new_length();
18815551efdSEric Fiselier        return static_cast<_ValueType*>(
189d108bf85SEric Fiselier            __res_->allocate(__n * sizeof(_ValueType), _LIBCPP_ALIGNOF(_ValueType))
19015551efdSEric Fiselier        );
19115551efdSEric Fiselier    }
19215551efdSEric Fiselier
19315551efdSEric Fiselier    _LIBCPP_INLINE_VISIBILITY
19415551efdSEric Fiselier    void deallocate(_ValueType * __p, size_t __n) _NOEXCEPT {
19525f9f927SEric Fiselier        _LIBCPP_ASSERT(__n <= __max_size(),
19615551efdSEric Fiselier                       "deallocate called for size which exceeds max_size()");
197d108bf85SEric Fiselier        __res_->deallocate(__p, __n * sizeof(_ValueType), _LIBCPP_ALIGNOF(_ValueType));
19815551efdSEric Fiselier    }
19915551efdSEric Fiselier
20015551efdSEric Fiselier    template <class _Tp, class ..._Ts>
20115551efdSEric Fiselier    _LIBCPP_INLINE_VISIBILITY
20215551efdSEric Fiselier    void construct(_Tp* __p, _Ts &&... __args)
20315551efdSEric Fiselier    {
20415551efdSEric Fiselier        _VSTD_LFTS::__lfts_user_alloc_construct(
205bd2e9498SEric Fiselier            __p, *this, _VSTD::forward<_Ts>(__args)...
20615551efdSEric Fiselier          );
20715551efdSEric Fiselier    }
20815551efdSEric Fiselier
20915551efdSEric Fiselier    template <class _T1, class _T2, class ..._Args1, class ..._Args2>
21015551efdSEric Fiselier    _LIBCPP_INLINE_VISIBILITY
21115551efdSEric Fiselier    void construct(pair<_T1, _T2>* __p, piecewise_construct_t,
21215551efdSEric Fiselier                   tuple<_Args1...> __x, tuple<_Args2...> __y)
21315551efdSEric Fiselier    {
21415551efdSEric Fiselier        ::new ((void*)__p) pair<_T1, _T2>(piecewise_construct
21515551efdSEric Fiselier          , __transform_tuple(
21615551efdSEric Fiselier              typename __lfts_uses_alloc_ctor<
217bd2e9498SEric Fiselier                  _T1, polymorphic_allocator&, _Args1...
21815551efdSEric Fiselier              >::type()
21915551efdSEric Fiselier            , _VSTD::move(__x)
22015551efdSEric Fiselier            , typename __make_tuple_indices<sizeof...(_Args1)>::type{}
22115551efdSEric Fiselier          )
22215551efdSEric Fiselier          , __transform_tuple(
22315551efdSEric Fiselier              typename __lfts_uses_alloc_ctor<
224bd2e9498SEric Fiselier                  _T2, polymorphic_allocator&, _Args2...
22515551efdSEric Fiselier              >::type()
22615551efdSEric Fiselier            , _VSTD::move(__y)
22715551efdSEric Fiselier            , typename __make_tuple_indices<sizeof...(_Args2)>::type{}
22815551efdSEric Fiselier          )
22915551efdSEric Fiselier        );
23015551efdSEric Fiselier    }
23115551efdSEric Fiselier
23215551efdSEric Fiselier    template <class _T1, class _T2>
23315551efdSEric Fiselier    _LIBCPP_INLINE_VISIBILITY
23415551efdSEric Fiselier    void construct(pair<_T1, _T2>* __p) {
23515551efdSEric Fiselier        construct(__p, piecewise_construct, tuple<>(), tuple<>());
23615551efdSEric Fiselier    }
23715551efdSEric Fiselier
23815551efdSEric Fiselier    template <class _T1, class _T2, class _Up, class _Vp>
23915551efdSEric Fiselier    _LIBCPP_INLINE_VISIBILITY
24015551efdSEric Fiselier    void construct(pair<_T1, _T2> * __p, _Up && __u, _Vp && __v) {
24115551efdSEric Fiselier        construct(__p, piecewise_construct
24215551efdSEric Fiselier          , _VSTD::forward_as_tuple(_VSTD::forward<_Up>(__u))
24315551efdSEric Fiselier          , _VSTD::forward_as_tuple(_VSTD::forward<_Vp>(__v)));
24415551efdSEric Fiselier    }
24515551efdSEric Fiselier
24615551efdSEric Fiselier    template <class _T1, class _T2, class _U1, class _U2>
24715551efdSEric Fiselier    _LIBCPP_INLINE_VISIBILITY
24815551efdSEric Fiselier    void construct(pair<_T1, _T2> * __p, pair<_U1, _U2> const & __pr) {
24915551efdSEric Fiselier        construct(__p, piecewise_construct
25015551efdSEric Fiselier            , _VSTD::forward_as_tuple(__pr.first)
25115551efdSEric Fiselier            , _VSTD::forward_as_tuple(__pr.second));
25215551efdSEric Fiselier    }
25315551efdSEric Fiselier
25415551efdSEric Fiselier    template <class _T1, class _T2, class _U1, class _U2>
25515551efdSEric Fiselier    _LIBCPP_INLINE_VISIBILITY
25615551efdSEric Fiselier    void construct(pair<_T1, _T2> * __p, pair<_U1, _U2> && __pr){
25715551efdSEric Fiselier        construct(__p, piecewise_construct
25815551efdSEric Fiselier            , _VSTD::forward_as_tuple(_VSTD::forward<_U1>(__pr.first))
25915551efdSEric Fiselier            , _VSTD::forward_as_tuple(_VSTD::forward<_U2>(__pr.second)));
26015551efdSEric Fiselier    }
26115551efdSEric Fiselier
26215551efdSEric Fiselier    template <class _Tp>
26315551efdSEric Fiselier    _LIBCPP_INLINE_VISIBILITY
26415551efdSEric Fiselier    void destroy(_Tp * __p) _NOEXCEPT
26515551efdSEric Fiselier        { __p->~_Tp(); }
26615551efdSEric Fiselier
26715551efdSEric Fiselier    _LIBCPP_INLINE_VISIBILITY
26815551efdSEric Fiselier    polymorphic_allocator
26915551efdSEric Fiselier    select_on_container_copy_construction() const _NOEXCEPT
27015551efdSEric Fiselier        { return polymorphic_allocator(); }
27115551efdSEric Fiselier
27215551efdSEric Fiselier    _LIBCPP_INLINE_VISIBILITY
27315551efdSEric Fiselier    memory_resource * resource() const _NOEXCEPT
27415551efdSEric Fiselier        { return __res_; }
27515551efdSEric Fiselier
27615551efdSEric Fiselierprivate:
27715551efdSEric Fiselier    template <class ..._Args, size_t ..._Idx>
27815551efdSEric Fiselier    _LIBCPP_INLINE_VISIBILITY
27915551efdSEric Fiselier    tuple<_Args&&...>
28015551efdSEric Fiselier    __transform_tuple(integral_constant<int, 0>, tuple<_Args...>&& __t,
28115551efdSEric Fiselier                      __tuple_indices<_Idx...>) const
28215551efdSEric Fiselier    {
28315551efdSEric Fiselier        return _VSTD::forward_as_tuple(_VSTD::get<_Idx>(_VSTD::move(__t))...);
28415551efdSEric Fiselier    }
28515551efdSEric Fiselier
28615551efdSEric Fiselier    template <class ..._Args, size_t ..._Idx>
28715551efdSEric Fiselier    _LIBCPP_INLINE_VISIBILITY
288bd2e9498SEric Fiselier    tuple<allocator_arg_t const&, polymorphic_allocator&, _Args&&...>
28915551efdSEric Fiselier    __transform_tuple(integral_constant<int, 1>, tuple<_Args...> && __t,
290bd2e9498SEric Fiselier                      __tuple_indices<_Idx...>)
29115551efdSEric Fiselier    {
292bd2e9498SEric Fiselier        using _Tup = tuple<allocator_arg_t const&, polymorphic_allocator&, _Args&&...>;
293bd2e9498SEric Fiselier        return _Tup(allocator_arg, *this,
29415551efdSEric Fiselier                    _VSTD::get<_Idx>(_VSTD::move(__t))...);
29515551efdSEric Fiselier    }
29615551efdSEric Fiselier
29715551efdSEric Fiselier    template <class ..._Args, size_t ..._Idx>
29815551efdSEric Fiselier    _LIBCPP_INLINE_VISIBILITY
299bd2e9498SEric Fiselier    tuple<_Args&&..., polymorphic_allocator&>
30015551efdSEric Fiselier    __transform_tuple(integral_constant<int, 2>, tuple<_Args...> && __t,
301bd2e9498SEric Fiselier                      __tuple_indices<_Idx...>)
30215551efdSEric Fiselier    {
303bd2e9498SEric Fiselier        using _Tup = tuple<_Args&&..., polymorphic_allocator&>;
304bd2e9498SEric Fiselier        return _Tup(_VSTD::get<_Idx>(_VSTD::move(__t))..., *this);
30515551efdSEric Fiselier    }
30615551efdSEric Fiselier
30725f9f927SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
30825f9f927SEric Fiselier    size_t __max_size() const _NOEXCEPT
30925f9f927SEric Fiselier        { return numeric_limits<size_t>::max() / sizeof(value_type); }
31025f9f927SEric Fiselier
31115551efdSEric Fiselier    memory_resource * __res_;
31215551efdSEric Fiselier};
31315551efdSEric Fiselier
31415551efdSEric Fiselier// 8.6.4, memory.polymorphic.allocator.eq
31515551efdSEric Fiselier
31615551efdSEric Fiseliertemplate <class _Tp, class _Up>
31715551efdSEric Fiselierinline _LIBCPP_INLINE_VISIBILITY
31815551efdSEric Fiselierbool operator==(polymorphic_allocator<_Tp> const & __lhs,
31915551efdSEric Fiselier                polymorphic_allocator<_Up> const & __rhs) _NOEXCEPT
32015551efdSEric Fiselier{
32115551efdSEric Fiselier    return *__lhs.resource() == *__rhs.resource();
32215551efdSEric Fiselier}
32315551efdSEric Fiselier
32415551efdSEric Fiseliertemplate <class _Tp, class _Up>
32515551efdSEric Fiselierinline _LIBCPP_INLINE_VISIBILITY
32615551efdSEric Fiselierbool operator!=(polymorphic_allocator<_Tp> const & __lhs,
32715551efdSEric Fiselier                polymorphic_allocator<_Up> const & __rhs) _NOEXCEPT
32815551efdSEric Fiselier{
32915551efdSEric Fiselier    return !(__lhs == __rhs);
33015551efdSEric Fiselier}
33115551efdSEric Fiselier
33215551efdSEric Fiselier// 8.7, memory.resource.adaptor
33315551efdSEric Fiselier
33415551efdSEric Fiselier// 8.7.1, memory.resource.adaptor.overview
33515551efdSEric Fiseliertemplate <class _CharAlloc>
336e2f2d1edSEric Fiselierclass _LIBCPP_TEMPLATE_VIS __resource_adaptor_imp
33715551efdSEric Fiselier  : public memory_resource
33815551efdSEric Fiselier{
33915551efdSEric Fiselier    using _CTraits = allocator_traits<_CharAlloc>;
34015551efdSEric Fiselier    static_assert(is_same<typename _CTraits::value_type, char>::value
34115551efdSEric Fiselier               && is_same<typename _CTraits::pointer, char*>::value
34215551efdSEric Fiselier               && is_same<typename _CTraits::void_pointer, void*>::value, "");
34315551efdSEric Fiselier
344d108bf85SEric Fiselier    static const size_t _MaxAlign = _LIBCPP_ALIGNOF(max_align_t);
34515551efdSEric Fiselier
34615551efdSEric Fiselier    using _Alloc = typename _CTraits::template rebind_alloc<
34715551efdSEric Fiselier            typename aligned_storage<_MaxAlign, _MaxAlign>::type
34815551efdSEric Fiselier        >;
34915551efdSEric Fiselier
35015551efdSEric Fiselier    using _ValueType = typename _Alloc::value_type;
35115551efdSEric Fiselier
35215551efdSEric Fiselier    _Alloc __alloc_;
35315551efdSEric Fiselier
35415551efdSEric Fiselierpublic:
35515551efdSEric Fiselier    typedef _CharAlloc allocator_type;
35615551efdSEric Fiselier
35715551efdSEric Fiselier    __resource_adaptor_imp() = default;
35815551efdSEric Fiselier    __resource_adaptor_imp(__resource_adaptor_imp const &) = default;
35915551efdSEric Fiselier    __resource_adaptor_imp(__resource_adaptor_imp &&) = default;
36015551efdSEric Fiselier
36115551efdSEric Fiselier    // 8.7.2, memory.resource.adaptor.ctor
36215551efdSEric Fiselier
36315551efdSEric Fiselier    _LIBCPP_INLINE_VISIBILITY
36415551efdSEric Fiselier    explicit __resource_adaptor_imp(allocator_type const & __a)
36515551efdSEric Fiselier      : __alloc_(__a)
36615551efdSEric Fiselier    {}
36715551efdSEric Fiselier
36815551efdSEric Fiselier    _LIBCPP_INLINE_VISIBILITY
36915551efdSEric Fiselier    explicit __resource_adaptor_imp(allocator_type && __a)
37015551efdSEric Fiselier      : __alloc_(_VSTD::move(__a))
37115551efdSEric Fiselier    {}
37215551efdSEric Fiselier
37315551efdSEric Fiselier    __resource_adaptor_imp &
37415551efdSEric Fiselier    operator=(__resource_adaptor_imp const &) = default;
37515551efdSEric Fiselier
37615551efdSEric Fiselier    _LIBCPP_INLINE_VISIBILITY
37715551efdSEric Fiselier    allocator_type get_allocator() const
37815551efdSEric Fiselier    { return __alloc_; }
37915551efdSEric Fiselier
38015551efdSEric Fiselier// 8.7.3, memory.resource.adaptor.mem
3810a20660cSzoecarverprivate:
38215551efdSEric Fiselier    virtual void * do_allocate(size_t __bytes, size_t)
38315551efdSEric Fiselier    {
384be10b1f1SMikhail Maltsev        if (__bytes > __max_size())
385be10b1f1SMikhail Maltsev            __throw_bad_array_new_length();
38615551efdSEric Fiselier        size_t __s = __aligned_allocation_size(__bytes, _MaxAlign) / _MaxAlign;
38715551efdSEric Fiselier        return __alloc_.allocate(__s);
38815551efdSEric Fiselier    }
38915551efdSEric Fiselier
39015551efdSEric Fiselier    virtual void do_deallocate(void * __p, size_t __bytes, size_t)
39115551efdSEric Fiselier    {
39215551efdSEric Fiselier        _LIBCPP_ASSERT(__bytes <= __max_size(),
39315551efdSEric Fiselier            "do_deallocate called for size which exceeds the maximum allocation size");
39415551efdSEric Fiselier        size_t __s = __aligned_allocation_size(__bytes, _MaxAlign) / _MaxAlign;
39515551efdSEric Fiselier        __alloc_.deallocate((_ValueType*)__p, __s);
39615551efdSEric Fiselier    }
39715551efdSEric Fiselier
39815551efdSEric Fiselier    virtual bool do_is_equal(memory_resource const & __other) const _NOEXCEPT {
39915551efdSEric Fiselier        __resource_adaptor_imp const * __p
40015551efdSEric Fiselier          = dynamic_cast<__resource_adaptor_imp const *>(&__other);
40115551efdSEric Fiselier        return __p  ? __alloc_ == __p->__alloc_ : false;
40215551efdSEric Fiselier    }
40315551efdSEric Fiselier
40415551efdSEric Fiselier    _LIBCPP_INLINE_VISIBILITY
40515551efdSEric Fiselier    size_t __max_size() const _NOEXCEPT {
40615551efdSEric Fiselier        return numeric_limits<size_t>::max() - _MaxAlign;
40715551efdSEric Fiselier    }
40815551efdSEric Fiselier};
40915551efdSEric Fiselier
41015551efdSEric Fiseliertemplate <class _Alloc>
41115551efdSEric Fiselierusing resource_adaptor = __resource_adaptor_imp<
41215551efdSEric Fiselier    typename allocator_traits<_Alloc>::template rebind_alloc<char>
41315551efdSEric Fiselier  >;
41415551efdSEric Fiselier
41515551efdSEric Fiselier_LIBCPP_END_NAMESPACE_LFTS_PMR
41615551efdSEric Fiselier
417a016efb1SEric Fiselier_LIBCPP_POP_MACROS
418a016efb1SEric Fiselier
41915551efdSEric Fiselier#endif /* _LIBCPP_EXPERIMENTAL_MEMORY_RESOURCE */
420