17c82a1ecSDimitry Andric// -*- C++ -*-
27c82a1ecSDimitry Andric//===------------------------ memory_resource -----------------------------===//
37c82a1ecSDimitry Andric//
47c82a1ecSDimitry Andric//                     The LLVM Compiler Infrastructure
57c82a1ecSDimitry Andric//
67c82a1ecSDimitry Andric// This file is distributed under the University of Illinois Open Source
77c82a1ecSDimitry Andric// License. See LICENSE.TXT for details.
87c82a1ecSDimitry Andric//
97c82a1ecSDimitry Andric//===----------------------------------------------------------------------===//
107c82a1ecSDimitry Andric
117c82a1ecSDimitry Andric#ifndef _LIBCPP_EXPERIMENTAL_MEMORY_RESOURCE
127c82a1ecSDimitry Andric#define _LIBCPP_EXPERIMENTAL_MEMORY_RESOURCE
137c82a1ecSDimitry Andric
147c82a1ecSDimitry Andric/**
157c82a1ecSDimitry Andric    experimental/memory_resource synopsis
167c82a1ecSDimitry Andric
177c82a1ecSDimitry Andric// C++1y
187c82a1ecSDimitry Andric
197c82a1ecSDimitry Andricnamespace std {
207c82a1ecSDimitry Andricnamespace experimental {
217c82a1ecSDimitry Andricinline namespace fundamentals_v1 {
227c82a1ecSDimitry Andricnamespace pmr {
237c82a1ecSDimitry Andric
247c82a1ecSDimitry Andric  class memory_resource;
257c82a1ecSDimitry Andric
267c82a1ecSDimitry Andric  bool operator==(const memory_resource& a,
277c82a1ecSDimitry Andric                  const memory_resource& b) noexcept;
287c82a1ecSDimitry Andric  bool operator!=(const memory_resource& a,
297c82a1ecSDimitry Andric                  const memory_resource& b) noexcept;
307c82a1ecSDimitry Andric
317c82a1ecSDimitry Andric  template <class Tp> class polymorphic_allocator;
327c82a1ecSDimitry Andric
337c82a1ecSDimitry Andric  template <class T1, class T2>
347c82a1ecSDimitry Andric  bool operator==(const polymorphic_allocator<T1>& a,
357c82a1ecSDimitry Andric                  const polymorphic_allocator<T2>& b) noexcept;
367c82a1ecSDimitry Andric  template <class T1, class T2>
377c82a1ecSDimitry Andric  bool operator!=(const polymorphic_allocator<T1>& a,
387c82a1ecSDimitry Andric                  const polymorphic_allocator<T2>& b) noexcept;
397c82a1ecSDimitry Andric
407c82a1ecSDimitry Andric  // The name resource_adaptor_imp is for exposition only.
417c82a1ecSDimitry Andric  template <class Allocator> class resource_adaptor_imp;
427c82a1ecSDimitry Andric
437c82a1ecSDimitry Andric  template <class Allocator>
447c82a1ecSDimitry Andric    using resource_adaptor = resource_adaptor_imp<
457c82a1ecSDimitry Andric      allocator_traits<Allocator>::rebind_alloc<char>>;
467c82a1ecSDimitry Andric
477c82a1ecSDimitry Andric  // Global memory resources
487c82a1ecSDimitry Andric  memory_resource* new_delete_resource() noexcept;
497c82a1ecSDimitry Andric  memory_resource* null_memory_resource() noexcept;
507c82a1ecSDimitry Andric
517c82a1ecSDimitry Andric  // The default memory resource
527c82a1ecSDimitry Andric  memory_resource* set_default_resource(memory_resource* r) noexcept;
537c82a1ecSDimitry Andric  memory_resource* get_default_resource() noexcept;
547c82a1ecSDimitry Andric
557c82a1ecSDimitry Andric  // Standard memory resources
567c82a1ecSDimitry Andric  struct pool_options;
577c82a1ecSDimitry Andric  class synchronized_pool_resource;
587c82a1ecSDimitry Andric  class unsynchronized_pool_resource;
597c82a1ecSDimitry Andric  class monotonic_buffer_resource;
607c82a1ecSDimitry Andric
617c82a1ecSDimitry Andric} // namespace pmr
627c82a1ecSDimitry Andric} // namespace fundamentals_v1
637c82a1ecSDimitry Andric} // namespace experimental
647c82a1ecSDimitry Andric} // namespace std
657c82a1ecSDimitry Andric
667c82a1ecSDimitry Andric */
677c82a1ecSDimitry Andric
687c82a1ecSDimitry Andric#include <experimental/__config>
697c82a1ecSDimitry Andric#include <experimental/__memory>
707c82a1ecSDimitry Andric#include <limits>
717c82a1ecSDimitry Andric#include <memory>
727c82a1ecSDimitry Andric#include <new>
737c82a1ecSDimitry Andric#include <stdexcept>
744ba319b5SDimitry Andric#include <__tuple>
757c82a1ecSDimitry Andric#include <type_traits>
767c82a1ecSDimitry Andric#include <utility>
777c82a1ecSDimitry Andric#include <cstddef>
787c82a1ecSDimitry Andric#include <cstdlib>
797c82a1ecSDimitry Andric#include <__debug>
807c82a1ecSDimitry Andric
817c82a1ecSDimitry Andric#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
827c82a1ecSDimitry Andric#pragma GCC system_header
837c82a1ecSDimitry Andric#endif
847c82a1ecSDimitry Andric
85f9448bf3SDimitry Andric_LIBCPP_PUSH_MACROS
86f9448bf3SDimitry Andric#include <__undef_macros>
87f9448bf3SDimitry Andric
887c82a1ecSDimitry Andric_LIBCPP_BEGIN_NAMESPACE_LFTS_PMR
897c82a1ecSDimitry Andric
907c82a1ecSDimitry Andric// Round __s up to next multiple of __a.
917c82a1ecSDimitry Andricinline _LIBCPP_INLINE_VISIBILITY
927c82a1ecSDimitry Andricsize_t __aligned_allocation_size(size_t __s, size_t __a) _NOEXCEPT
937c82a1ecSDimitry Andric{
947c82a1ecSDimitry Andric    _LIBCPP_ASSERT(__s + __a > __s, "aligned allocation size overflows");
957c82a1ecSDimitry Andric    return (__s + __a - 1) & ~(__a - 1);
967c82a1ecSDimitry Andric}
977c82a1ecSDimitry Andric
987c82a1ecSDimitry Andric// 8.5, memory.resource
994ba319b5SDimitry Andricclass _LIBCPP_TYPE_VIS memory_resource
1007c82a1ecSDimitry Andric{
101*b5893f02SDimitry Andric    static const size_t __max_align = _LIBCPP_ALIGNOF(max_align_t);
1027c82a1ecSDimitry Andric
1037c82a1ecSDimitry Andric// 8.5.2, memory.resource.public
1047c82a1ecSDimitry Andricpublic:
1057c82a1ecSDimitry Andric    virtual ~memory_resource() = default;
1067c82a1ecSDimitry Andric
1077c82a1ecSDimitry Andric    _LIBCPP_INLINE_VISIBILITY
1087c82a1ecSDimitry Andric    void* allocate(size_t __bytes, size_t __align = __max_align)
1097c82a1ecSDimitry Andric        { return do_allocate(__bytes, __align); }
1107c82a1ecSDimitry Andric
1117c82a1ecSDimitry Andric    _LIBCPP_INLINE_VISIBILITY
1127c82a1ecSDimitry Andric    void deallocate(void * __p, size_t __bytes, size_t __align = __max_align)
1137c82a1ecSDimitry Andric        { do_deallocate(__p, __bytes, __align); }
1147c82a1ecSDimitry Andric
1157c82a1ecSDimitry Andric    _LIBCPP_INLINE_VISIBILITY
1167c82a1ecSDimitry Andric    bool is_equal(memory_resource const & __other) const _NOEXCEPT
1177c82a1ecSDimitry Andric        { return do_is_equal(__other); }
1187c82a1ecSDimitry Andric
1197c82a1ecSDimitry Andric// 8.5.3, memory.resource.priv
1207c82a1ecSDimitry Andricprotected:
1217c82a1ecSDimitry Andric    virtual void* do_allocate(size_t, size_t) = 0;
1227c82a1ecSDimitry Andric    virtual void do_deallocate(void*, size_t, size_t) = 0;
1237c82a1ecSDimitry Andric    virtual bool do_is_equal(memory_resource const &) const _NOEXCEPT = 0;
1247c82a1ecSDimitry Andric};
1257c82a1ecSDimitry Andric
1267c82a1ecSDimitry Andric// 8.5.4, memory.resource.eq
1277c82a1ecSDimitry Andricinline _LIBCPP_INLINE_VISIBILITY
1287c82a1ecSDimitry Andricbool operator==(memory_resource const & __lhs,
1297c82a1ecSDimitry Andric                memory_resource const & __rhs) _NOEXCEPT
1307c82a1ecSDimitry Andric{
1317c82a1ecSDimitry Andric    return &__lhs == &__rhs || __lhs.is_equal(__rhs);
1327c82a1ecSDimitry Andric}
1337c82a1ecSDimitry Andric
1347c82a1ecSDimitry Andricinline _LIBCPP_INLINE_VISIBILITY
1357c82a1ecSDimitry Andricbool operator!=(memory_resource const & __lhs,
1367c82a1ecSDimitry Andric                memory_resource const & __rhs) _NOEXCEPT
1377c82a1ecSDimitry Andric{
1387c82a1ecSDimitry Andric    return !(__lhs == __rhs);
1397c82a1ecSDimitry Andric}
1407c82a1ecSDimitry Andric
1417c82a1ecSDimitry Andric_LIBCPP_FUNC_VIS
1427c82a1ecSDimitry Andricmemory_resource * new_delete_resource() _NOEXCEPT;
1437c82a1ecSDimitry Andric
1447c82a1ecSDimitry Andric_LIBCPP_FUNC_VIS
1457c82a1ecSDimitry Andricmemory_resource * null_memory_resource() _NOEXCEPT;
1467c82a1ecSDimitry Andric
1477c82a1ecSDimitry Andric_LIBCPP_FUNC_VIS
1487c82a1ecSDimitry Andricmemory_resource * get_default_resource() _NOEXCEPT;
1497c82a1ecSDimitry Andric
1507c82a1ecSDimitry Andric_LIBCPP_FUNC_VIS
1517c82a1ecSDimitry Andricmemory_resource * set_default_resource(memory_resource * __new_res) _NOEXCEPT;
1527c82a1ecSDimitry Andric
1537c82a1ecSDimitry Andric// 8.6, memory.polymorphic.allocator.class
1547c82a1ecSDimitry Andric
1557c82a1ecSDimitry Andric// 8.6.1, memory.polymorphic.allocator.overview
1567c82a1ecSDimitry Andrictemplate <class _ValueType>
157aed8d94eSDimitry Andricclass _LIBCPP_TEMPLATE_VIS polymorphic_allocator
1587c82a1ecSDimitry Andric{
1597c82a1ecSDimitry Andricpublic:
1607c82a1ecSDimitry Andric    typedef _ValueType value_type;
1617c82a1ecSDimitry Andric
1627c82a1ecSDimitry Andric    // 8.6.2, memory.polymorphic.allocator.ctor
1637c82a1ecSDimitry Andric    _LIBCPP_INLINE_VISIBILITY
1647c82a1ecSDimitry Andric    polymorphic_allocator() _NOEXCEPT
1657c82a1ecSDimitry Andric      : __res_(_VSTD_LFTS_PMR::get_default_resource())
1667c82a1ecSDimitry Andric    {}
1677c82a1ecSDimitry Andric
1687c82a1ecSDimitry Andric    _LIBCPP_INLINE_VISIBILITY
1697c82a1ecSDimitry Andric    polymorphic_allocator(memory_resource * __r) _NOEXCEPT
1707c82a1ecSDimitry Andric      : __res_(__r)
1717c82a1ecSDimitry Andric    {}
1727c82a1ecSDimitry Andric
1737c82a1ecSDimitry Andric    polymorphic_allocator(polymorphic_allocator const &) = default;
1747c82a1ecSDimitry Andric
1757c82a1ecSDimitry Andric    template <class _Tp>
1767c82a1ecSDimitry Andric    _LIBCPP_INLINE_VISIBILITY
1777c82a1ecSDimitry Andric    polymorphic_allocator(polymorphic_allocator<_Tp> const & __other) _NOEXCEPT
1787c82a1ecSDimitry Andric      : __res_(__other.resource())
1797c82a1ecSDimitry Andric    {}
1807c82a1ecSDimitry Andric
1817c82a1ecSDimitry Andric    polymorphic_allocator &
1827c82a1ecSDimitry Andric    operator=(polymorphic_allocator const &) = delete;
1837c82a1ecSDimitry Andric
1847c82a1ecSDimitry Andric    // 8.6.3, memory.polymorphic.allocator.mem
1857c82a1ecSDimitry Andric    _LIBCPP_INLINE_VISIBILITY
1867c82a1ecSDimitry Andric    _ValueType* allocate(size_t __n) {
187540d2a8bSDimitry Andric        if (__n > __max_size()) {
188aed8d94eSDimitry Andric            __throw_length_error(
1897c82a1ecSDimitry Andric                "std::experimental::pmr::polymorphic_allocator<T>::allocate(size_t n)"
190aed8d94eSDimitry Andric                " 'n' exceeds maximum supported size");
1917c82a1ecSDimitry Andric        }
1927c82a1ecSDimitry Andric        return static_cast<_ValueType*>(
193*b5893f02SDimitry Andric            __res_->allocate(__n * sizeof(_ValueType), _LIBCPP_ALIGNOF(_ValueType))
1947c82a1ecSDimitry Andric        );
1957c82a1ecSDimitry Andric    }
1967c82a1ecSDimitry Andric
1977c82a1ecSDimitry Andric    _LIBCPP_INLINE_VISIBILITY
1987c82a1ecSDimitry Andric    void deallocate(_ValueType * __p, size_t __n) _NOEXCEPT {
199540d2a8bSDimitry Andric        _LIBCPP_ASSERT(__n <= __max_size(),
2007c82a1ecSDimitry Andric                       "deallocate called for size which exceeds max_size()");
201*b5893f02SDimitry Andric        __res_->deallocate(__p, __n * sizeof(_ValueType), _LIBCPP_ALIGNOF(_ValueType));
2027c82a1ecSDimitry Andric    }
2037c82a1ecSDimitry Andric
2047c82a1ecSDimitry Andric    template <class _Tp, class ..._Ts>
2057c82a1ecSDimitry Andric    _LIBCPP_INLINE_VISIBILITY
2067c82a1ecSDimitry Andric    void construct(_Tp* __p, _Ts &&... __args)
2077c82a1ecSDimitry Andric    {
2087c82a1ecSDimitry Andric        _VSTD_LFTS::__lfts_user_alloc_construct(
2094ba319b5SDimitry Andric            __p, *this, _VSTD::forward<_Ts>(__args)...
2107c82a1ecSDimitry Andric          );
2117c82a1ecSDimitry Andric    }
2127c82a1ecSDimitry Andric
2137c82a1ecSDimitry Andric    template <class _T1, class _T2, class ..._Args1, class ..._Args2>
2147c82a1ecSDimitry Andric    _LIBCPP_INLINE_VISIBILITY
2157c82a1ecSDimitry Andric    void construct(pair<_T1, _T2>* __p, piecewise_construct_t,
2167c82a1ecSDimitry Andric                   tuple<_Args1...> __x, tuple<_Args2...> __y)
2177c82a1ecSDimitry Andric    {
2187c82a1ecSDimitry Andric        ::new ((void*)__p) pair<_T1, _T2>(piecewise_construct
2197c82a1ecSDimitry Andric          , __transform_tuple(
2207c82a1ecSDimitry Andric              typename __lfts_uses_alloc_ctor<
2214ba319b5SDimitry Andric                  _T1, polymorphic_allocator&, _Args1...
2227c82a1ecSDimitry Andric              >::type()
2237c82a1ecSDimitry Andric            , _VSTD::move(__x)
2247c82a1ecSDimitry Andric            , typename __make_tuple_indices<sizeof...(_Args1)>::type{}
2257c82a1ecSDimitry Andric          )
2267c82a1ecSDimitry Andric          , __transform_tuple(
2277c82a1ecSDimitry Andric              typename __lfts_uses_alloc_ctor<
2284ba319b5SDimitry Andric                  _T2, polymorphic_allocator&, _Args2...
2297c82a1ecSDimitry Andric              >::type()
2307c82a1ecSDimitry Andric            , _VSTD::move(__y)
2317c82a1ecSDimitry Andric            , typename __make_tuple_indices<sizeof...(_Args2)>::type{}
2327c82a1ecSDimitry Andric          )
2337c82a1ecSDimitry Andric        );
2347c82a1ecSDimitry Andric    }
2357c82a1ecSDimitry Andric
2367c82a1ecSDimitry Andric    template <class _T1, class _T2>
2377c82a1ecSDimitry Andric    _LIBCPP_INLINE_VISIBILITY
2387c82a1ecSDimitry Andric    void construct(pair<_T1, _T2>* __p) {
2397c82a1ecSDimitry Andric        construct(__p, piecewise_construct, tuple<>(), tuple<>());
2407c82a1ecSDimitry Andric    }
2417c82a1ecSDimitry Andric
2427c82a1ecSDimitry Andric    template <class _T1, class _T2, class _Up, class _Vp>
2437c82a1ecSDimitry Andric    _LIBCPP_INLINE_VISIBILITY
2447c82a1ecSDimitry Andric    void construct(pair<_T1, _T2> * __p, _Up && __u, _Vp && __v) {
2457c82a1ecSDimitry Andric        construct(__p, piecewise_construct
2467c82a1ecSDimitry Andric          , _VSTD::forward_as_tuple(_VSTD::forward<_Up>(__u))
2477c82a1ecSDimitry Andric          , _VSTD::forward_as_tuple(_VSTD::forward<_Vp>(__v)));
2487c82a1ecSDimitry Andric    }
2497c82a1ecSDimitry Andric
2507c82a1ecSDimitry Andric    template <class _T1, class _T2, class _U1, class _U2>
2517c82a1ecSDimitry Andric    _LIBCPP_INLINE_VISIBILITY
2527c82a1ecSDimitry Andric    void construct(pair<_T1, _T2> * __p, pair<_U1, _U2> const & __pr) {
2537c82a1ecSDimitry Andric        construct(__p, piecewise_construct
2547c82a1ecSDimitry Andric            , _VSTD::forward_as_tuple(__pr.first)
2557c82a1ecSDimitry Andric            , _VSTD::forward_as_tuple(__pr.second));
2567c82a1ecSDimitry Andric    }
2577c82a1ecSDimitry Andric
2587c82a1ecSDimitry Andric    template <class _T1, class _T2, class _U1, class _U2>
2597c82a1ecSDimitry Andric    _LIBCPP_INLINE_VISIBILITY
2607c82a1ecSDimitry Andric    void construct(pair<_T1, _T2> * __p, pair<_U1, _U2> && __pr){
2617c82a1ecSDimitry Andric        construct(__p, piecewise_construct
2627c82a1ecSDimitry Andric            , _VSTD::forward_as_tuple(_VSTD::forward<_U1>(__pr.first))
2637c82a1ecSDimitry Andric            , _VSTD::forward_as_tuple(_VSTD::forward<_U2>(__pr.second)));
2647c82a1ecSDimitry Andric    }
2657c82a1ecSDimitry Andric
2667c82a1ecSDimitry Andric    template <class _Tp>
2677c82a1ecSDimitry Andric    _LIBCPP_INLINE_VISIBILITY
2687c82a1ecSDimitry Andric    void destroy(_Tp * __p) _NOEXCEPT
2697c82a1ecSDimitry Andric        { __p->~_Tp(); }
2707c82a1ecSDimitry Andric
2717c82a1ecSDimitry Andric    _LIBCPP_INLINE_VISIBILITY
2727c82a1ecSDimitry Andric    polymorphic_allocator
2737c82a1ecSDimitry Andric    select_on_container_copy_construction() const _NOEXCEPT
2747c82a1ecSDimitry Andric        { return polymorphic_allocator(); }
2757c82a1ecSDimitry Andric
2767c82a1ecSDimitry Andric    _LIBCPP_INLINE_VISIBILITY
2777c82a1ecSDimitry Andric    memory_resource * resource() const _NOEXCEPT
2787c82a1ecSDimitry Andric        { return __res_; }
2797c82a1ecSDimitry Andric
2807c82a1ecSDimitry Andricprivate:
2817c82a1ecSDimitry Andric    template <class ..._Args, size_t ..._Idx>
2827c82a1ecSDimitry Andric    _LIBCPP_INLINE_VISIBILITY
2837c82a1ecSDimitry Andric    tuple<_Args&&...>
2847c82a1ecSDimitry Andric    __transform_tuple(integral_constant<int, 0>, tuple<_Args...>&& __t,
2857c82a1ecSDimitry Andric                      __tuple_indices<_Idx...>) const
2867c82a1ecSDimitry Andric    {
2877c82a1ecSDimitry Andric        return _VSTD::forward_as_tuple(_VSTD::get<_Idx>(_VSTD::move(__t))...);
2887c82a1ecSDimitry Andric    }
2897c82a1ecSDimitry Andric
2907c82a1ecSDimitry Andric    template <class ..._Args, size_t ..._Idx>
2917c82a1ecSDimitry Andric    _LIBCPP_INLINE_VISIBILITY
2924ba319b5SDimitry Andric    tuple<allocator_arg_t const&, polymorphic_allocator&, _Args&&...>
2937c82a1ecSDimitry Andric    __transform_tuple(integral_constant<int, 1>, tuple<_Args...> && __t,
2944ba319b5SDimitry Andric                      __tuple_indices<_Idx...>)
2957c82a1ecSDimitry Andric    {
2964ba319b5SDimitry Andric        using _Tup = tuple<allocator_arg_t const&, polymorphic_allocator&, _Args&&...>;
2974ba319b5SDimitry Andric        return _Tup(allocator_arg, *this,
2987c82a1ecSDimitry Andric                    _VSTD::get<_Idx>(_VSTD::move(__t))...);
2997c82a1ecSDimitry Andric    }
3007c82a1ecSDimitry Andric
3017c82a1ecSDimitry Andric    template <class ..._Args, size_t ..._Idx>
3027c82a1ecSDimitry Andric    _LIBCPP_INLINE_VISIBILITY
3034ba319b5SDimitry Andric    tuple<_Args&&..., polymorphic_allocator&>
3047c82a1ecSDimitry Andric    __transform_tuple(integral_constant<int, 2>, tuple<_Args...> && __t,
3054ba319b5SDimitry Andric                      __tuple_indices<_Idx...>)
3067c82a1ecSDimitry Andric    {
3074ba319b5SDimitry Andric        using _Tup = tuple<_Args&&..., polymorphic_allocator&>;
3084ba319b5SDimitry Andric        return _Tup(_VSTD::get<_Idx>(_VSTD::move(__t))..., *this);
3097c82a1ecSDimitry Andric    }
3107c82a1ecSDimitry Andric
311540d2a8bSDimitry Andric    _LIBCPP_INLINE_VISIBILITY
312540d2a8bSDimitry Andric    size_t __max_size() const _NOEXCEPT
313540d2a8bSDimitry Andric        { return numeric_limits<size_t>::max() / sizeof(value_type); }
314540d2a8bSDimitry Andric
3157c82a1ecSDimitry Andric    memory_resource * __res_;
3167c82a1ecSDimitry Andric};
3177c82a1ecSDimitry Andric
3187c82a1ecSDimitry Andric// 8.6.4, memory.polymorphic.allocator.eq
3197c82a1ecSDimitry Andric
3207c82a1ecSDimitry Andrictemplate <class _Tp, class _Up>
3217c82a1ecSDimitry Andricinline _LIBCPP_INLINE_VISIBILITY
3227c82a1ecSDimitry Andricbool operator==(polymorphic_allocator<_Tp> const & __lhs,
3237c82a1ecSDimitry Andric                polymorphic_allocator<_Up> const & __rhs) _NOEXCEPT
3247c82a1ecSDimitry Andric{
3257c82a1ecSDimitry Andric    return *__lhs.resource() == *__rhs.resource();
3267c82a1ecSDimitry Andric}
3277c82a1ecSDimitry Andric
3287c82a1ecSDimitry Andrictemplate <class _Tp, class _Up>
3297c82a1ecSDimitry Andricinline _LIBCPP_INLINE_VISIBILITY
3307c82a1ecSDimitry Andricbool operator!=(polymorphic_allocator<_Tp> const & __lhs,
3317c82a1ecSDimitry Andric                polymorphic_allocator<_Up> const & __rhs) _NOEXCEPT
3327c82a1ecSDimitry Andric{
3337c82a1ecSDimitry Andric    return !(__lhs == __rhs);
3347c82a1ecSDimitry Andric}
3357c82a1ecSDimitry Andric
3367c82a1ecSDimitry Andric// 8.7, memory.resource.adaptor
3377c82a1ecSDimitry Andric
3387c82a1ecSDimitry Andric// 8.7.1, memory.resource.adaptor.overview
3397c82a1ecSDimitry Andrictemplate <class _CharAlloc>
340aed8d94eSDimitry Andricclass _LIBCPP_TEMPLATE_VIS __resource_adaptor_imp
3417c82a1ecSDimitry Andric  : public memory_resource
3427c82a1ecSDimitry Andric{
3437c82a1ecSDimitry Andric    using _CTraits = allocator_traits<_CharAlloc>;
3447c82a1ecSDimitry Andric    static_assert(is_same<typename _CTraits::value_type, char>::value
3457c82a1ecSDimitry Andric               && is_same<typename _CTraits::pointer, char*>::value
3467c82a1ecSDimitry Andric               && is_same<typename _CTraits::void_pointer, void*>::value, "");
3477c82a1ecSDimitry Andric
348*b5893f02SDimitry Andric    static const size_t _MaxAlign = _LIBCPP_ALIGNOF(max_align_t);
3497c82a1ecSDimitry Andric
3507c82a1ecSDimitry Andric    using _Alloc = typename _CTraits::template rebind_alloc<
3517c82a1ecSDimitry Andric            typename aligned_storage<_MaxAlign, _MaxAlign>::type
3527c82a1ecSDimitry Andric        >;
3537c82a1ecSDimitry Andric
3547c82a1ecSDimitry Andric    using _ValueType = typename _Alloc::value_type;
3557c82a1ecSDimitry Andric
3567c82a1ecSDimitry Andric    _Alloc __alloc_;
3577c82a1ecSDimitry Andric
3587c82a1ecSDimitry Andricpublic:
3597c82a1ecSDimitry Andric    typedef _CharAlloc allocator_type;
3607c82a1ecSDimitry Andric
3617c82a1ecSDimitry Andric    __resource_adaptor_imp() = default;
3627c82a1ecSDimitry Andric    __resource_adaptor_imp(__resource_adaptor_imp const &) = default;
3637c82a1ecSDimitry Andric    __resource_adaptor_imp(__resource_adaptor_imp &&) = default;
3647c82a1ecSDimitry Andric
3657c82a1ecSDimitry Andric    // 8.7.2, memory.resource.adaptor.ctor
3667c82a1ecSDimitry Andric
3677c82a1ecSDimitry Andric    _LIBCPP_INLINE_VISIBILITY
3687c82a1ecSDimitry Andric    explicit __resource_adaptor_imp(allocator_type const & __a)
3697c82a1ecSDimitry Andric      : __alloc_(__a)
3707c82a1ecSDimitry Andric    {}
3717c82a1ecSDimitry Andric
3727c82a1ecSDimitry Andric    _LIBCPP_INLINE_VISIBILITY
3737c82a1ecSDimitry Andric    explicit __resource_adaptor_imp(allocator_type && __a)
3747c82a1ecSDimitry Andric      : __alloc_(_VSTD::move(__a))
3757c82a1ecSDimitry Andric    {}
3767c82a1ecSDimitry Andric
3777c82a1ecSDimitry Andric    __resource_adaptor_imp &
3787c82a1ecSDimitry Andric    operator=(__resource_adaptor_imp const &) = default;
3797c82a1ecSDimitry Andric
3807c82a1ecSDimitry Andric    _LIBCPP_INLINE_VISIBILITY
3817c82a1ecSDimitry Andric    allocator_type get_allocator() const
3827c82a1ecSDimitry Andric    { return __alloc_; }
3837c82a1ecSDimitry Andric
3847c82a1ecSDimitry Andric// 8.7.3, memory.resource.adaptor.mem
3857c82a1ecSDimitry Andricprotected:
3867c82a1ecSDimitry Andric    virtual void * do_allocate(size_t __bytes, size_t)
3877c82a1ecSDimitry Andric    {
3887c82a1ecSDimitry Andric        if (__bytes > __max_size()) {
389aed8d94eSDimitry Andric            __throw_length_error(
3907c82a1ecSDimitry Andric                "std::experimental::pmr::resource_adaptor<T>::do_allocate(size_t bytes, size_t align)"
391aed8d94eSDimitry Andric                " 'bytes' exceeds maximum supported size");
3927c82a1ecSDimitry Andric        }
3937c82a1ecSDimitry Andric        size_t __s = __aligned_allocation_size(__bytes, _MaxAlign) / _MaxAlign;
3947c82a1ecSDimitry Andric        return __alloc_.allocate(__s);
3957c82a1ecSDimitry Andric    }
3967c82a1ecSDimitry Andric
3977c82a1ecSDimitry Andric    virtual void do_deallocate(void * __p, size_t __bytes, size_t)
3987c82a1ecSDimitry Andric    {
3997c82a1ecSDimitry Andric        _LIBCPP_ASSERT(__bytes <= __max_size(),
4007c82a1ecSDimitry Andric            "do_deallocate called for size which exceeds the maximum allocation size");
4017c82a1ecSDimitry Andric        size_t __s = __aligned_allocation_size(__bytes, _MaxAlign) / _MaxAlign;
4027c82a1ecSDimitry Andric        __alloc_.deallocate((_ValueType*)__p, __s);
4037c82a1ecSDimitry Andric    }
4047c82a1ecSDimitry Andric
4057c82a1ecSDimitry Andric    virtual bool do_is_equal(memory_resource const & __other) const _NOEXCEPT {
4067c82a1ecSDimitry Andric        __resource_adaptor_imp const * __p
4077c82a1ecSDimitry Andric          = dynamic_cast<__resource_adaptor_imp const *>(&__other);
4087c82a1ecSDimitry Andric        return __p  ? __alloc_ == __p->__alloc_ : false;
4097c82a1ecSDimitry Andric    }
4107c82a1ecSDimitry Andric
4117c82a1ecSDimitry Andricprivate:
4127c82a1ecSDimitry Andric    _LIBCPP_INLINE_VISIBILITY
4137c82a1ecSDimitry Andric    size_t __max_size() const _NOEXCEPT {
4147c82a1ecSDimitry Andric        return numeric_limits<size_t>::max() - _MaxAlign;
4157c82a1ecSDimitry Andric    }
4167c82a1ecSDimitry Andric};
4177c82a1ecSDimitry Andric
4187c82a1ecSDimitry Andrictemplate <class _Alloc>
4197c82a1ecSDimitry Andricusing resource_adaptor = __resource_adaptor_imp<
4207c82a1ecSDimitry Andric    typename allocator_traits<_Alloc>::template rebind_alloc<char>
4217c82a1ecSDimitry Andric  >;
4227c82a1ecSDimitry Andric
4237c82a1ecSDimitry Andric_LIBCPP_END_NAMESPACE_LFTS_PMR
4247c82a1ecSDimitry Andric
425f9448bf3SDimitry Andric_LIBCPP_POP_MACROS
426f9448bf3SDimitry Andric
4277c82a1ecSDimitry Andric#endif /* _LIBCPP_EXPERIMENTAL_MEMORY_RESOURCE */
428