mirror of
https://github.com/darlinghq/darling-libcxx.git
synced 2024-11-23 11:59:52 +00:00
Add <experimental/memory_resource>
Reviewers: mclow.lists, EricWF Subscribers: cfe-commits Differential Revision: http://reviews.llvm.org/D20007 git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@268829 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
70487694ba
commit
257fd699fd
@ -80,6 +80,10 @@ template <class E> void rethrow_if_nested(const E& e);
|
||||
#include <__config>
|
||||
#include <cstddef>
|
||||
#include <type_traits>
|
||||
#if defined(_LIBCPP_HAS_NO_EXCEPTIONS)
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#endif
|
||||
|
||||
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
||||
#pragma GCC system_header
|
||||
@ -251,4 +255,19 @@ rethrow_if_nested(const _Ep&, typename enable_if<
|
||||
|
||||
} // std
|
||||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
template <class _Exception>
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
inline void __libcpp_throw(_Exception const& __e) {
|
||||
#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
|
||||
throw __e;
|
||||
#else
|
||||
_VSTD::fprintf(stderr, "%s\n", __e.what());
|
||||
_VSTD::abort();
|
||||
#endif
|
||||
}
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
|
||||
#endif // _LIBCPP_EXCEPTION
|
||||
|
@ -25,6 +25,10 @@
|
||||
#define _LIBCPP_END_NAMESPACE_LFTS } } }
|
||||
#define _VSTD_LFTS _VSTD_EXPERIMENTAL::fundamentals_v1
|
||||
|
||||
#define _LIBCPP_BEGIN_NAMESPACE_LFTS_PMR _LIBCPP_BEGIN_NAMESPACE_LFTS namespace pmr {
|
||||
#define _LIBCPP_END_NAMESPACE_LFTS_PMR _LIBCPP_END_NAMESPACE_LFTS }
|
||||
#define _VSTD_LFTS_PMR _VSTD_LFTS::pmr
|
||||
|
||||
#define _LIBCPP_BEGIN_NAMESPACE_CHRONO_LFTS _LIBCPP_BEGIN_NAMESPACE_STD \
|
||||
namespace chrono { namespace experimental { inline namespace fundamentals_v1 {
|
||||
#define _LIBCPP_END_NAMESPACE_CHRONO_LFTS _LIBCPP_END_NAMESPACE_STD } } }
|
||||
|
90
include/experimental/__memory
Normal file
90
include/experimental/__memory
Normal file
@ -0,0 +1,90 @@
|
||||
// -*- C++ -*-
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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 _LIBCPP_EXPERIMENTAL___MEMORY
|
||||
#define _LIBCPP_EXPERIMENTAL___MEMORY
|
||||
|
||||
#include <experimental/__config>
|
||||
#include <experimental/utility> // for erased_type
|
||||
#include <__functional_base>
|
||||
#include <type_traits>
|
||||
|
||||
_LIBCPP_BEGIN_NAMESPACE_LFTS
|
||||
|
||||
template <
|
||||
class _Tp, class _Alloc
|
||||
, bool = uses_allocator<_Tp, _Alloc>::value
|
||||
, bool = __has_allocator_type<_Tp>::value
|
||||
>
|
||||
struct __lfts_uses_allocator : public false_type {};
|
||||
|
||||
template <class _Tp, class _Alloc>
|
||||
struct __lfts_uses_allocator<_Tp, _Alloc, false, false> : public false_type {};
|
||||
|
||||
template <class _Tp, class _Alloc, bool HasAlloc>
|
||||
struct __lfts_uses_allocator<_Tp, _Alloc, true, HasAlloc> : public true_type {};
|
||||
|
||||
template <class _Tp, class _Alloc>
|
||||
struct __lfts_uses_allocator<_Tp, _Alloc, false, true>
|
||||
: public integral_constant<bool
|
||||
, is_convertible<_Alloc, typename _Tp::allocator_type>::value
|
||||
|| is_same<erased_type, typename _Tp::allocator_type>::value
|
||||
>
|
||||
{};
|
||||
|
||||
template <bool _UsesAlloc, class _Tp, class _Alloc, class ..._Args>
|
||||
struct __lfts_uses_alloc_ctor_imp
|
||||
{
|
||||
static const int value = 0;
|
||||
};
|
||||
|
||||
template <class _Tp, class _Alloc, class ..._Args>
|
||||
struct __lfts_uses_alloc_ctor_imp<true, _Tp, _Alloc, _Args...>
|
||||
{
|
||||
static const bool __ic_first
|
||||
= is_constructible<_Tp, allocator_arg_t, _Alloc, _Args...>::value;
|
||||
|
||||
static const bool __ic_second =
|
||||
conditional<
|
||||
__ic_first,
|
||||
false_type,
|
||||
is_constructible<_Tp, _Args..., _Alloc>
|
||||
>::type::value;
|
||||
|
||||
static_assert(__ic_first || __ic_second,
|
||||
"Request for uses allocator construction is ill-formed");
|
||||
|
||||
static const int value = __ic_first ? 1 : 2;
|
||||
};
|
||||
|
||||
template <class _Tp, class _Alloc, class ..._Args>
|
||||
struct __lfts_uses_alloc_ctor
|
||||
: integral_constant<int,
|
||||
__lfts_uses_alloc_ctor_imp<
|
||||
__lfts_uses_allocator<_Tp, _Alloc>::value
|
||||
, _Tp, _Alloc, _Args...
|
||||
>::value
|
||||
>
|
||||
{};
|
||||
|
||||
template <class _Tp, class _Alloc, class ..._Args>
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
void __lfts_user_alloc_construct(
|
||||
_Tp * __store, const _Alloc & __a, _Args &&... __args)
|
||||
{
|
||||
_VSTD::__user_alloc_construct_impl(
|
||||
typename __lfts_uses_alloc_ctor<_Tp, _Alloc, _Args...>::type()
|
||||
, __store, __a, _VSTD::forward<_Args>(__args)...
|
||||
);
|
||||
}
|
||||
|
||||
_LIBCPP_END_NAMESPACE_LFTS
|
||||
|
||||
#endif /* _LIBCPP_EXPERIMENTAL___MEMORY */
|
422
include/experimental/memory_resource
Normal file
422
include/experimental/memory_resource
Normal file
@ -0,0 +1,422 @@
|
||||
// -*- C++ -*-
|
||||
//===------------------------ memory_resource -----------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef _LIBCPP_EXPERIMENTAL_MEMORY_RESOURCE
|
||||
#define _LIBCPP_EXPERIMENTAL_MEMORY_RESOURCE
|
||||
|
||||
/**
|
||||
experimental/memory_resource synopsis
|
||||
|
||||
// C++1y
|
||||
|
||||
namespace std {
|
||||
namespace experimental {
|
||||
inline namespace fundamentals_v1 {
|
||||
namespace pmr {
|
||||
|
||||
class memory_resource;
|
||||
|
||||
bool operator==(const memory_resource& a,
|
||||
const memory_resource& b) noexcept;
|
||||
bool operator!=(const memory_resource& a,
|
||||
const memory_resource& b) noexcept;
|
||||
|
||||
template <class Tp> class polymorphic_allocator;
|
||||
|
||||
template <class T1, class T2>
|
||||
bool operator==(const polymorphic_allocator<T1>& a,
|
||||
const polymorphic_allocator<T2>& b) noexcept;
|
||||
template <class T1, class T2>
|
||||
bool operator!=(const polymorphic_allocator<T1>& a,
|
||||
const polymorphic_allocator<T2>& b) noexcept;
|
||||
|
||||
// The name resource_adaptor_imp is for exposition only.
|
||||
template <class Allocator> class resource_adaptor_imp;
|
||||
|
||||
template <class Allocator>
|
||||
using resource_adaptor = resource_adaptor_imp<
|
||||
allocator_traits<Allocator>::rebind_alloc<char>>;
|
||||
|
||||
// Global memory resources
|
||||
memory_resource* new_delete_resource() noexcept;
|
||||
memory_resource* null_memory_resource() noexcept;
|
||||
|
||||
// The default memory resource
|
||||
memory_resource* set_default_resource(memory_resource* r) noexcept;
|
||||
memory_resource* get_default_resource() noexcept;
|
||||
|
||||
// Standard memory resources
|
||||
struct pool_options;
|
||||
class synchronized_pool_resource;
|
||||
class unsynchronized_pool_resource;
|
||||
class monotonic_buffer_resource;
|
||||
|
||||
} // namespace pmr
|
||||
} // namespace fundamentals_v1
|
||||
} // namespace experimental
|
||||
} // namespace std
|
||||
|
||||
*/
|
||||
|
||||
#include <experimental/__config>
|
||||
#include <experimental/__memory>
|
||||
#include <limits>
|
||||
#include <memory>
|
||||
#include <new>
|
||||
#include <stdexcept>
|
||||
#include <tuple>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
#include <cstddef>
|
||||
#include <cstdlib>
|
||||
#include <__debug>
|
||||
|
||||
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
||||
#pragma GCC system_header
|
||||
#endif
|
||||
|
||||
_LIBCPP_BEGIN_NAMESPACE_LFTS_PMR
|
||||
|
||||
// Round __s up to next multiple of __a.
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
size_t __aligned_allocation_size(size_t __s, size_t __a) _NOEXCEPT
|
||||
{
|
||||
_LIBCPP_ASSERT(__s + __a > __s, "aligned allocation size overflows");
|
||||
return (__s + __a - 1) & ~(__a - 1);
|
||||
}
|
||||
|
||||
// 8.5, memory.resource
|
||||
class _LIBCPP_TYPE_VIS_ONLY memory_resource
|
||||
{
|
||||
static const size_t __max_align = alignof(max_align_t);
|
||||
|
||||
// 8.5.2, memory.resource.public
|
||||
public:
|
||||
virtual ~memory_resource() = default;
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
void* allocate(size_t __bytes, size_t __align = __max_align)
|
||||
{ return do_allocate(__bytes, __align); }
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
void deallocate(void * __p, size_t __bytes, size_t __align = __max_align)
|
||||
{ do_deallocate(__p, __bytes, __align); }
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
bool is_equal(memory_resource const & __other) const _NOEXCEPT
|
||||
{ return do_is_equal(__other); }
|
||||
|
||||
// 8.5.3, memory.resource.priv
|
||||
protected:
|
||||
virtual void* do_allocate(size_t, size_t) = 0;
|
||||
virtual void do_deallocate(void*, size_t, size_t) = 0;
|
||||
virtual bool do_is_equal(memory_resource const &) const _NOEXCEPT = 0;
|
||||
};
|
||||
|
||||
// 8.5.4, memory.resource.eq
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
bool operator==(memory_resource const & __lhs,
|
||||
memory_resource const & __rhs) _NOEXCEPT
|
||||
{
|
||||
return &__lhs == &__rhs || __lhs.is_equal(__rhs);
|
||||
}
|
||||
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
bool operator!=(memory_resource const & __lhs,
|
||||
memory_resource const & __rhs) _NOEXCEPT
|
||||
{
|
||||
return !(__lhs == __rhs);
|
||||
}
|
||||
|
||||
_LIBCPP_FUNC_VIS
|
||||
memory_resource * new_delete_resource() _NOEXCEPT;
|
||||
|
||||
_LIBCPP_FUNC_VIS
|
||||
memory_resource * null_memory_resource() _NOEXCEPT;
|
||||
|
||||
_LIBCPP_FUNC_VIS
|
||||
memory_resource * get_default_resource() _NOEXCEPT;
|
||||
|
||||
_LIBCPP_FUNC_VIS
|
||||
memory_resource * set_default_resource(memory_resource * __new_res) _NOEXCEPT;
|
||||
|
||||
// 8.6, memory.polymorphic.allocator.class
|
||||
|
||||
// 8.6.1, memory.polymorphic.allocator.overview
|
||||
template <class _ValueType>
|
||||
class _LIBCPP_TYPE_VIS_ONLY polymorphic_allocator
|
||||
{
|
||||
public:
|
||||
typedef _ValueType value_type;
|
||||
|
||||
// 8.6.2, memory.polymorphic.allocator.ctor
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
polymorphic_allocator() _NOEXCEPT
|
||||
: __res_(_VSTD_LFTS_PMR::get_default_resource())
|
||||
{}
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
polymorphic_allocator(memory_resource * __r) _NOEXCEPT
|
||||
: __res_(__r)
|
||||
{}
|
||||
|
||||
polymorphic_allocator(polymorphic_allocator const &) = default;
|
||||
|
||||
template <class _Tp>
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
polymorphic_allocator(polymorphic_allocator<_Tp> const & __other) _NOEXCEPT
|
||||
: __res_(__other.resource())
|
||||
{}
|
||||
|
||||
polymorphic_allocator &
|
||||
operator=(polymorphic_allocator const &) = default;
|
||||
|
||||
// 8.6.3, memory.polymorphic.allocator.mem
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
_ValueType* allocate(size_t __n) {
|
||||
if (__n > max_size()) {
|
||||
__libcpp_throw(length_error(
|
||||
"std::experimental::pmr::polymorphic_allocator<T>::allocate(size_t n)"
|
||||
" 'n' exceeds maximum supported size"));
|
||||
}
|
||||
return static_cast<_ValueType*>(
|
||||
__res_->allocate(__n * sizeof(_ValueType), alignof(_ValueType))
|
||||
);
|
||||
}
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
void deallocate(_ValueType * __p, size_t __n) _NOEXCEPT {
|
||||
_LIBCPP_ASSERT(__n <= max_size(),
|
||||
"deallocate called for size which exceeds max_size()");
|
||||
__res_->deallocate(__p, __n * sizeof(_ValueType), alignof(_ValueType));
|
||||
}
|
||||
|
||||
template <class _Tp, class ..._Ts>
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
void construct(_Tp* __p, _Ts &&... __args)
|
||||
{
|
||||
_VSTD_LFTS::__lfts_user_alloc_construct(
|
||||
__p, resource(), _VSTD::forward<_Ts>(__args)...
|
||||
);
|
||||
}
|
||||
|
||||
template <class _T1, class _T2, class ..._Args1, class ..._Args2>
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
void construct(pair<_T1, _T2>* __p, piecewise_construct_t,
|
||||
tuple<_Args1...> __x, tuple<_Args2...> __y)
|
||||
{
|
||||
::new ((void*)__p) pair<_T1, _T2>(piecewise_construct
|
||||
, __transform_tuple(
|
||||
typename __lfts_uses_alloc_ctor<
|
||||
_T1, memory_resource*, _Args1...
|
||||
>::type()
|
||||
, _VSTD::move(__x)
|
||||
, typename __make_tuple_indices<sizeof...(_Args1)>::type{}
|
||||
)
|
||||
, __transform_tuple(
|
||||
typename __lfts_uses_alloc_ctor<
|
||||
_T2, memory_resource*, _Args2...
|
||||
>::type()
|
||||
, _VSTD::move(__y)
|
||||
, typename __make_tuple_indices<sizeof...(_Args2)>::type{}
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
template <class _T1, class _T2>
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
void construct(pair<_T1, _T2>* __p) {
|
||||
construct(__p, piecewise_construct, tuple<>(), tuple<>());
|
||||
}
|
||||
|
||||
template <class _T1, class _T2, class _Up, class _Vp>
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
void construct(pair<_T1, _T2> * __p, _Up && __u, _Vp && __v) {
|
||||
construct(__p, piecewise_construct
|
||||
, _VSTD::forward_as_tuple(_VSTD::forward<_Up>(__u))
|
||||
, _VSTD::forward_as_tuple(_VSTD::forward<_Vp>(__v)));
|
||||
}
|
||||
|
||||
template <class _T1, class _T2, class _U1, class _U2>
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
void construct(pair<_T1, _T2> * __p, pair<_U1, _U2> const & __pr) {
|
||||
construct(__p, piecewise_construct
|
||||
, _VSTD::forward_as_tuple(__pr.first)
|
||||
, _VSTD::forward_as_tuple(__pr.second));
|
||||
}
|
||||
|
||||
template <class _T1, class _T2, class _U1, class _U2>
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
void construct(pair<_T1, _T2> * __p, pair<_U1, _U2> && __pr){
|
||||
construct(__p, piecewise_construct
|
||||
, _VSTD::forward_as_tuple(_VSTD::forward<_U1>(__pr.first))
|
||||
, _VSTD::forward_as_tuple(_VSTD::forward<_U2>(__pr.second)));
|
||||
}
|
||||
|
||||
template <class _Tp>
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
void destroy(_Tp * __p) _NOEXCEPT
|
||||
{ __p->~_Tp(); }
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
size_t max_size() const _NOEXCEPT
|
||||
{ return numeric_limits<size_t>::max() / sizeof(value_type); }
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
polymorphic_allocator
|
||||
select_on_container_copy_construction() const _NOEXCEPT
|
||||
{ return polymorphic_allocator(); }
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
memory_resource * resource() const _NOEXCEPT
|
||||
{ return __res_; }
|
||||
|
||||
private:
|
||||
template <class ..._Args, size_t ..._Idx>
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
tuple<_Args&&...>
|
||||
__transform_tuple(integral_constant<int, 0>, tuple<_Args...>&& __t,
|
||||
__tuple_indices<_Idx...>) const
|
||||
{
|
||||
return _VSTD::forward_as_tuple(_VSTD::get<_Idx>(_VSTD::move(__t))...);
|
||||
}
|
||||
|
||||
template <class ..._Args, size_t ..._Idx>
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
tuple<allocator_arg_t const&, memory_resource*, _Args&&...>
|
||||
__transform_tuple(integral_constant<int, 1>, tuple<_Args...> && __t,
|
||||
__tuple_indices<_Idx...>) const
|
||||
{
|
||||
using _Tup = tuple<allocator_arg_t const&, memory_resource*, _Args&&...>;
|
||||
return _Tup(allocator_arg, resource(),
|
||||
_VSTD::get<_Idx>(_VSTD::move(__t))...);
|
||||
}
|
||||
|
||||
template <class ..._Args, size_t ..._Idx>
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
tuple<_Args&&..., memory_resource*>
|
||||
__transform_tuple(integral_constant<int, 2>, tuple<_Args...> && __t,
|
||||
__tuple_indices<_Idx...>) const
|
||||
{
|
||||
using _Tup = tuple<_Args&&..., memory_resource*>;
|
||||
return _Tup(_VSTD::get<_Idx>(_VSTD::move(__t))..., resource());
|
||||
}
|
||||
|
||||
memory_resource * __res_;
|
||||
};
|
||||
|
||||
// 8.6.4, memory.polymorphic.allocator.eq
|
||||
|
||||
template <class _Tp, class _Up>
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
bool operator==(polymorphic_allocator<_Tp> const & __lhs,
|
||||
polymorphic_allocator<_Up> const & __rhs) _NOEXCEPT
|
||||
{
|
||||
return *__lhs.resource() == *__rhs.resource();
|
||||
}
|
||||
|
||||
template <class _Tp, class _Up>
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
bool operator!=(polymorphic_allocator<_Tp> const & __lhs,
|
||||
polymorphic_allocator<_Up> const & __rhs) _NOEXCEPT
|
||||
{
|
||||
return !(__lhs == __rhs);
|
||||
}
|
||||
|
||||
// 8.7, memory.resource.adaptor
|
||||
|
||||
// 8.7.1, memory.resource.adaptor.overview
|
||||
template <class _CharAlloc>
|
||||
class _LIBCPP_TYPE_VIS_ONLY __resource_adaptor_imp
|
||||
: public memory_resource
|
||||
{
|
||||
using _CTraits = allocator_traits<_CharAlloc>;
|
||||
static_assert(is_same<typename _CTraits::value_type, char>::value
|
||||
&& is_same<typename _CTraits::pointer, char*>::value
|
||||
&& is_same<typename _CTraits::void_pointer, void*>::value, "");
|
||||
|
||||
static const size_t _MaxAlign = alignof(max_align_t);
|
||||
|
||||
using _Alloc = typename _CTraits::template rebind_alloc<
|
||||
typename aligned_storage<_MaxAlign, _MaxAlign>::type
|
||||
>;
|
||||
|
||||
using _ValueType = typename _Alloc::value_type;
|
||||
|
||||
_Alloc __alloc_;
|
||||
|
||||
public:
|
||||
typedef _CharAlloc allocator_type;
|
||||
|
||||
__resource_adaptor_imp() = default;
|
||||
__resource_adaptor_imp(__resource_adaptor_imp const &) = default;
|
||||
__resource_adaptor_imp(__resource_adaptor_imp &&) = default;
|
||||
|
||||
// 8.7.2, memory.resource.adaptor.ctor
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
explicit __resource_adaptor_imp(allocator_type const & __a)
|
||||
: __alloc_(__a)
|
||||
{}
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
explicit __resource_adaptor_imp(allocator_type && __a)
|
||||
: __alloc_(_VSTD::move(__a))
|
||||
{}
|
||||
|
||||
__resource_adaptor_imp &
|
||||
operator=(__resource_adaptor_imp const &) = default;
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
allocator_type get_allocator() const
|
||||
{ return __alloc_; }
|
||||
|
||||
// 8.7.3, memory.resource.adaptor.mem
|
||||
protected:
|
||||
virtual void * do_allocate(size_t __bytes, size_t)
|
||||
{
|
||||
if (__bytes > __max_size()) {
|
||||
__libcpp_throw(length_error(
|
||||
"std::experimental::pmr::resource_adaptor<T>::do_allocate(size_t bytes, size_t align)"
|
||||
" 'bytes' exceeds maximum supported size"));
|
||||
}
|
||||
size_t __s = __aligned_allocation_size(__bytes, _MaxAlign) / _MaxAlign;
|
||||
return __alloc_.allocate(__s);
|
||||
}
|
||||
|
||||
virtual void do_deallocate(void * __p, size_t __bytes, size_t)
|
||||
{
|
||||
_LIBCPP_ASSERT(__bytes <= __max_size(),
|
||||
"do_deallocate called for size which exceeds the maximum allocation size");
|
||||
size_t __s = __aligned_allocation_size(__bytes, _MaxAlign) / _MaxAlign;
|
||||
__alloc_.deallocate((_ValueType*)__p, __s);
|
||||
}
|
||||
|
||||
virtual bool do_is_equal(memory_resource const & __other) const _NOEXCEPT {
|
||||
__resource_adaptor_imp const * __p
|
||||
= dynamic_cast<__resource_adaptor_imp const *>(&__other);
|
||||
return __p ? __alloc_ == __p->__alloc_ : false;
|
||||
}
|
||||
|
||||
private:
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
size_t __max_size() const _NOEXCEPT {
|
||||
return numeric_limits<size_t>::max() - _MaxAlign;
|
||||
}
|
||||
};
|
||||
|
||||
template <class _Alloc>
|
||||
using resource_adaptor = __resource_adaptor_imp<
|
||||
typename allocator_traits<_Alloc>::template rebind_alloc<char>
|
||||
>;
|
||||
|
||||
_LIBCPP_END_NAMESPACE_LFTS_PMR
|
||||
|
||||
#endif /* _LIBCPP_EXPERIMENTAL_MEMORY_RESOURCE */
|
129
src/experimental/memory_resource.cpp
Normal file
129
src/experimental/memory_resource.cpp
Normal file
@ -0,0 +1,129 @@
|
||||
//===------------------------ memory_resource.cpp -------------------------===//
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "experimental/memory_resource"
|
||||
|
||||
#ifndef _LIBCPP_HAS_NO_ATOMIC_HEADER
|
||||
#include "atomic"
|
||||
#else
|
||||
#include "mutex"
|
||||
#endif
|
||||
|
||||
_LIBCPP_BEGIN_NAMESPACE_LFTS_PMR
|
||||
|
||||
// memory_resource
|
||||
|
||||
//memory_resource::~memory_resource() {}
|
||||
|
||||
// new_delete_resource()
|
||||
|
||||
class _LIBCPP_TYPE_VIS_ONLY __new_delete_memory_resource_imp
|
||||
: public memory_resource
|
||||
{
|
||||
public:
|
||||
~__new_delete_memory_resource_imp() = default;
|
||||
|
||||
protected:
|
||||
virtual void* do_allocate(size_t __size, size_t __align)
|
||||
{ return __allocate(__size); }
|
||||
|
||||
virtual void do_deallocate(void * __p, size_t, size_t)
|
||||
{ __deallocate(__p); }
|
||||
|
||||
virtual bool do_is_equal(memory_resource const & __other) const _NOEXCEPT
|
||||
{ return &__other == this; }
|
||||
};
|
||||
|
||||
// null_memory_resource()
|
||||
|
||||
class _LIBCPP_TYPE_VIS_ONLY __null_memory_resource_imp
|
||||
: public memory_resource
|
||||
{
|
||||
public:
|
||||
~__null_memory_resource_imp() = default;
|
||||
|
||||
protected:
|
||||
virtual void* do_allocate(size_t, size_t) {
|
||||
#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
|
||||
throw std::bad_alloc();
|
||||
#else
|
||||
abort();
|
||||
#endif
|
||||
}
|
||||
virtual void do_deallocate(void *, size_t, size_t) {}
|
||||
virtual bool do_is_equal(memory_resource const & __other) const _NOEXCEPT
|
||||
{ return &__other == this; }
|
||||
};
|
||||
|
||||
union ResourceInitHelper {
|
||||
struct {
|
||||
__new_delete_memory_resource_imp new_delete_res;
|
||||
__null_memory_resource_imp null_res;
|
||||
} resources;
|
||||
char dummy;
|
||||
_LIBCPP_CONSTEXPR_AFTER_CXX11 ResourceInitHelper() : resources() {}
|
||||
~ResourceInitHelper() {}
|
||||
};
|
||||
// When compiled in C++14 this initialization should be a constant expression.
|
||||
// Only in C++11 is "init_priority" needed to ensure initialization order.
|
||||
ResourceInitHelper res_init __attribute__((init_priority (101)));
|
||||
|
||||
memory_resource * new_delete_resource() _NOEXCEPT {
|
||||
return &res_init.resources.new_delete_res;
|
||||
}
|
||||
|
||||
memory_resource * null_memory_resource() _NOEXCEPT {
|
||||
return &res_init.resources.null_res;
|
||||
}
|
||||
|
||||
// default_memory_resource()
|
||||
|
||||
static memory_resource *
|
||||
__default_memory_resource(bool set = false, memory_resource * new_res = nullptr) _NOEXCEPT
|
||||
{
|
||||
#ifndef _LIBCPP_HAS_NO_ATOMIC_HEADER
|
||||
static atomic<memory_resource*> __res =
|
||||
ATOMIC_VAR_INIT(&res_init.resources.new_delete_res);
|
||||
if (set) {
|
||||
new_res = new_res ? new_res : new_delete_resource();
|
||||
// TODO: Can a weaker ordering be used?
|
||||
return _VSTD::atomic_exchange_explicit(
|
||||
&__res, new_res, memory_order::memory_order_acq_rel);
|
||||
}
|
||||
else {
|
||||
return _VSTD::atomic_load_explicit(
|
||||
&__res, memory_order::memory_order_acquire);
|
||||
}
|
||||
#else
|
||||
static memory_resource * res = &res_init.resources.new_delete_res;
|
||||
static mutex res_lock;
|
||||
if (set) {
|
||||
new_res = new_res ? new_res : new_delete_resource();
|
||||
lock_guard<mutex> guard(res_lock);
|
||||
memory_resource * old_res = res;
|
||||
res = new_res;
|
||||
return old_res;
|
||||
} else {
|
||||
lock_guard<mutex> guard(res_lock);
|
||||
return res;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
memory_resource * get_default_resource() _NOEXCEPT
|
||||
{
|
||||
return __default_memory_resource();
|
||||
}
|
||||
|
||||
memory_resource * set_default_resource(memory_resource * __new_res) _NOEXCEPT
|
||||
{
|
||||
return __default_memory_resource(true, __new_res);
|
||||
}
|
||||
|
||||
_LIBCPP_END_NAMESPACE_LFTS_PMR
|
@ -0,0 +1,178 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
|
||||
// <experimental/memory_resource>
|
||||
|
||||
// template <class T> class polymorphic_allocator
|
||||
|
||||
// template <class U1, class U2, class ...Args1, class ...Args2>
|
||||
// void polymorphic_allocator<T>::construct(pair<T1, T2>*, piecewise_construct_t
|
||||
// tuple<Args1...> x, tuple<Args2...>)
|
||||
|
||||
// The stardard specifiers a tranformation to uses-allocator construction as
|
||||
// follows:
|
||||
// - If uses_allocator_v<T1,memory_resource*> is false and
|
||||
// is_constructible_v<T,Args1...> is true, then xprime is x.
|
||||
// - Otherwise, if uses_allocator_v<T1,memory_resource*> is true and
|
||||
// is_constructible_v<T1,allocator_arg_t,memory_resource*,Args1...> is true,
|
||||
// then xprime is
|
||||
// tuple_cat(make_tuple(allocator_arg, this->resource()), std::move(x)).
|
||||
// - Otherwise, if uses_allocator_v<T1,memory_resource*> is true and
|
||||
// is_constructible_v<T1,Args1...,memory_resource*> is true, then xprime is
|
||||
// tuple_cat(std::move(x), make_tuple(this->resource())).
|
||||
// - Otherwise the program is ill formed.
|
||||
//
|
||||
// The use of "xprime = tuple_cat(..., std::move(x), ...)" causes all of the
|
||||
// objects in 'x' to be copied into 'xprime'. If 'x' contains any types which
|
||||
// are stored by value this causes an unessary copy to occur. To prevent this
|
||||
// libc++ changes this call into
|
||||
// "xprime = forward_as_tuple(..., std::get<Idx>(std::move(x))..., ...)".
|
||||
// 'xprime' contains references to the values in 'x' instead of copying them.
|
||||
|
||||
// This test checks the number of copies incurred to the elements in
|
||||
// 'tuple<Args1...>' and 'tuple<Args2...>'.
|
||||
|
||||
#include <experimental/memory_resource>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
#include <tuple>
|
||||
#include <cassert>
|
||||
#include <cstdlib>
|
||||
#include "test_memory_resource.hpp"
|
||||
|
||||
namespace ex = std::experimental::pmr;
|
||||
|
||||
template <class T>
|
||||
struct TestHarness {
|
||||
TestResource R;
|
||||
ex::memory_resource * M = &R;
|
||||
ex::polymorphic_allocator<T> A = M;
|
||||
bool constructed = false;
|
||||
T * ptr;
|
||||
|
||||
TestHarness() : ptr(A.allocate(1)) {}
|
||||
|
||||
template <class ...Args>
|
||||
void construct(Args&&... args) {
|
||||
A.construct(ptr, std::forward<Args>(args)...);
|
||||
constructed = true;
|
||||
}
|
||||
|
||||
~TestHarness() {
|
||||
if (constructed) A.destroy(ptr);
|
||||
A.deallocate(ptr, 1);
|
||||
}
|
||||
};
|
||||
|
||||
struct CountCopies {
|
||||
int count;
|
||||
CountCopies() : count(0) {}
|
||||
CountCopies(CountCopies const& o) : count(o.count + 1) {}
|
||||
};
|
||||
|
||||
struct CountCopiesAllocV1 {
|
||||
typedef ex::memory_resource* allocator_type;
|
||||
allocator_type alloc;
|
||||
int count;
|
||||
CountCopiesAllocV1() : alloc(nullptr), count(0) {}
|
||||
CountCopiesAllocV1(std::allocator_arg_t, allocator_type const& a,
|
||||
CountCopiesAllocV1 const& o) : alloc(a), count(o.count + 1)
|
||||
{}
|
||||
|
||||
CountCopiesAllocV1(CountCopiesAllocV1 const& o) : count(o.count + 1) {}
|
||||
};
|
||||
|
||||
|
||||
struct CountCopiesAllocV2 {
|
||||
typedef ex::memory_resource* allocator_type;
|
||||
allocator_type alloc;
|
||||
int count;
|
||||
CountCopiesAllocV2() : alloc(nullptr), count(0) {}
|
||||
CountCopiesAllocV2(CountCopiesAllocV2 const& o, allocator_type const& a)
|
||||
: alloc(a), count(o.count + 1)
|
||||
{ }
|
||||
|
||||
CountCopiesAllocV2(CountCopiesAllocV2 const& o) : count(o.count + 1) {}
|
||||
};
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
using PMR = ex::memory_resource*;
|
||||
using PMA = ex::polymorphic_allocator<char>;
|
||||
|
||||
{
|
||||
using T = CountCopies;
|
||||
using U = CountCopiesAllocV1;
|
||||
using P = std::pair<T, U>;
|
||||
using TH = TestHarness<P>;
|
||||
|
||||
std::tuple<T> t1;
|
||||
std::tuple<U> t2;
|
||||
|
||||
TestHarness<P> h;
|
||||
h.construct(std::piecewise_construct, t1, t2);
|
||||
P const& p = *h.ptr;
|
||||
assert(p.first.count == 2);
|
||||
assert(p.second.count == 2);
|
||||
assert(p.second.alloc == h.M);
|
||||
}
|
||||
{
|
||||
using T = CountCopiesAllocV1;
|
||||
using U = CountCopiesAllocV2;
|
||||
using P = std::pair<T, U>;
|
||||
using TH = TestHarness<P>;
|
||||
|
||||
std::tuple<T> t1;
|
||||
std::tuple<U> t2;
|
||||
|
||||
TestHarness<P> h;
|
||||
h.construct(std::piecewise_construct, std::move(t1), std::move(t2));
|
||||
P const& p = *h.ptr;
|
||||
assert(p.first.count == 2);
|
||||
assert(p.first.alloc == h.M);
|
||||
assert(p.second.count == 2);
|
||||
assert(p.second.alloc == h.M);
|
||||
}
|
||||
{
|
||||
using T = CountCopiesAllocV2;
|
||||
using U = CountCopiesAllocV1;
|
||||
using P = std::pair<T, U>;
|
||||
using TH = TestHarness<P>;
|
||||
|
||||
std::tuple<T> t1;
|
||||
std::tuple<U> t2;
|
||||
|
||||
TestHarness<P> h;
|
||||
h.construct(std::piecewise_construct, std::move(t1), std::move(t2));
|
||||
P const& p = *h.ptr;
|
||||
assert(p.first.count == 2);
|
||||
assert(p.first.alloc == h.M);
|
||||
assert(p.second.count == 2);
|
||||
assert(p.second.alloc == h.M);
|
||||
}
|
||||
{
|
||||
using T = CountCopiesAllocV2;
|
||||
using U = CountCopies;
|
||||
using P = std::pair<T, U>;
|
||||
using TH = TestHarness<P>;
|
||||
|
||||
std::tuple<T> t1;
|
||||
std::tuple<U> t2;
|
||||
|
||||
TestHarness<P> h;
|
||||
h.construct(std::piecewise_construct, t1, t2);
|
||||
P const& p = *h.ptr;
|
||||
assert(p.first.count == 2);
|
||||
assert(p.first.alloc == h.M);
|
||||
assert(p.second.count == 2);
|
||||
}
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
|
||||
// <experimental/memory_resource>
|
||||
|
||||
// template <class T> class polymorphic_allocator
|
||||
|
||||
// T* polymorphic_allocator<T>::deallocate(T*, size_t size)
|
||||
|
||||
int AssertCount = 0;
|
||||
|
||||
#define _LIBCPP_ASSERT(x, m) ((x) ? (void)0 : (void)::AssertCount++)
|
||||
#define _LIBCPP_DEBUG 0
|
||||
#include <experimental/memory_resource>
|
||||
#include <type_traits>
|
||||
#include <cassert>
|
||||
|
||||
#include "test_memory_resource.hpp"
|
||||
|
||||
namespace ex = std::experimental::pmr;
|
||||
|
||||
int main()
|
||||
{
|
||||
using Alloc = ex::polymorphic_allocator<int>;
|
||||
using Traits = std::allocator_traits<Alloc>;
|
||||
NullResource R;
|
||||
Alloc a(&R);
|
||||
const std::size_t maxSize = Traits::max_size(a);
|
||||
|
||||
a.deallocate(nullptr, maxSize);
|
||||
assert(AssertCount == 0);
|
||||
a.deallocate(nullptr, maxSize + 1);
|
||||
assert(AssertCount == 1);
|
||||
}
|
@ -0,0 +1,64 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
|
||||
// <experimental/memory_resource>
|
||||
|
||||
// template <class T> class polymorphic_allocator
|
||||
|
||||
// EXTENSION
|
||||
// std::size_t polymorphic_allocator<T>::max_size() const noexcept
|
||||
|
||||
#include <experimental/memory_resource>
|
||||
#include <type_traits>
|
||||
#include <cassert>
|
||||
|
||||
#include "test_memory_resource.hpp"
|
||||
|
||||
namespace ex = std::experimental::pmr;
|
||||
|
||||
template <std::size_t S>
|
||||
std::size_t getMaxSize() {
|
||||
using T = typename std::aligned_storage<S>::type;
|
||||
static_assert(sizeof(T) == S, "Required for test");
|
||||
return ex::polymorphic_allocator<T>{}.max_size();
|
||||
}
|
||||
|
||||
template <std::size_t S, std::size_t A>
|
||||
std::size_t getMaxSize() {
|
||||
using T = typename std::aligned_storage<S, A>::type;
|
||||
static_assert(sizeof(T) == S, "Required for test");
|
||||
return ex::polymorphic_allocator<T>{}.max_size();
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
{
|
||||
using Alloc = ex::polymorphic_allocator<int>;
|
||||
using Traits = std::allocator_traits<Alloc>;
|
||||
const Alloc a;
|
||||
static_assert(std::is_same<decltype(a.max_size()), Traits::size_type>::value, "");
|
||||
static_assert(noexcept(a.max_size()), "");
|
||||
}
|
||||
{
|
||||
constexpr std::size_t Max = std::numeric_limits<std::size_t>::max();
|
||||
assert(getMaxSize<1>() == Max);
|
||||
assert(getMaxSize<2>() == Max / 2);
|
||||
assert(getMaxSize<4>() == Max / 4);
|
||||
assert(getMaxSize<8>() == Max / 8);
|
||||
assert(getMaxSize<16>() == Max / 16);
|
||||
assert(getMaxSize<32>() == Max / 32);
|
||||
assert(getMaxSize<64>() == Max / 64);
|
||||
assert(getMaxSize<1024>() == Max / 1024);
|
||||
|
||||
assert((getMaxSize<6, 2>() == Max / 6));
|
||||
assert((getMaxSize<12, 4>() == Max / 12));
|
||||
}
|
||||
}
|
@ -0,0 +1,45 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
|
||||
// <experimental/memory_resource>
|
||||
|
||||
// template <class T> class polymorphic_allocator
|
||||
|
||||
// T* polymorphic_allocator<T>::deallocate(T*, size_t size)
|
||||
|
||||
int AssertCount = 0;
|
||||
|
||||
#define _LIBCPP_ASSERT(x, m) ((x) ? (void)0 : (void)::AssertCount++)
|
||||
#define _LIBCPP_DEBUG 0
|
||||
#include <experimental/memory_resource>
|
||||
#include <type_traits>
|
||||
#include <cassert>
|
||||
|
||||
#include "test_memory_resource.hpp"
|
||||
|
||||
namespace ex = std::experimental::pmr;
|
||||
|
||||
int main()
|
||||
{
|
||||
using Alloc = NullAllocator<char>;
|
||||
using R = ex::resource_adaptor<Alloc>;
|
||||
AllocController P;
|
||||
ex::resource_adaptor<Alloc> r(Alloc{P});
|
||||
ex::memory_resource & m1 = r;
|
||||
|
||||
std::size_t maxSize = std::numeric_limits<std::size_t>::max()
|
||||
- alignof(std::max_align_t);
|
||||
|
||||
m1.deallocate(nullptr, maxSize);
|
||||
assert(AssertCount == 0);
|
||||
m1.deallocate(nullptr, maxSize + 1);
|
||||
assert(AssertCount >= 1);
|
||||
}
|
@ -0,0 +1,60 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
|
||||
// <experimental/memory_resource>
|
||||
|
||||
// memory_resource * new_delete_resource()
|
||||
|
||||
// The lifetime of the value returned by 'new_delete_resource()' should
|
||||
// never end, even very late into program termination. This test constructs
|
||||
// attempts to use 'new_delete_resource()' very late in program termination
|
||||
// to detect lifetime issues.
|
||||
|
||||
#include <experimental/memory_resource>
|
||||
#include <type_traits>
|
||||
#include <cassert>
|
||||
|
||||
namespace ex = std::experimental::pmr;
|
||||
|
||||
struct POSType {
|
||||
ex::memory_resource* res = nullptr;
|
||||
void* ptr = nullptr;
|
||||
int n = 0;
|
||||
POSType() {}
|
||||
POSType(ex::memory_resource* r, void* p, int s) : res(r), ptr(p), n(s) {}
|
||||
~POSType() {
|
||||
if (ptr) {
|
||||
if (!res) res = ex::get_default_resource();
|
||||
res->deallocate(ptr, n);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
void swap(POSType & L, POSType & R) {
|
||||
std::swap(L.res, R.res);
|
||||
std::swap(L.ptr, R.ptr);
|
||||
std::swap(L.n, R.n);
|
||||
}
|
||||
|
||||
POSType constructed_before_resources;
|
||||
POSType constructed_before_resources2;
|
||||
|
||||
// Constructs resources
|
||||
ex::memory_resource* resource = ex::get_default_resource();
|
||||
|
||||
POSType constructed_after_resources(resource, resource->allocate(1024), 1024);
|
||||
POSType constructed_after_resources2(nullptr, resource->allocate(1024), 1024);
|
||||
|
||||
int main()
|
||||
{
|
||||
swap(constructed_after_resources, constructed_before_resources);
|
||||
swap(constructed_before_resources2, constructed_after_resources2);
|
||||
}
|
@ -0,0 +1,52 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
|
||||
// <experimental/memory_resource>
|
||||
|
||||
// memory_resource * new_delete_resource()
|
||||
|
||||
// The lifetime of the value returned by 'new_delete_resource()' should
|
||||
// never end, even very late into program termination. This test constructs
|
||||
// attempts to use 'new_delete_resource()' very late in program termination
|
||||
// to detect lifetime issues.
|
||||
|
||||
#include <experimental/memory_resource>
|
||||
#include <type_traits>
|
||||
#include <cassert>
|
||||
|
||||
namespace ex = std::experimental::pmr;
|
||||
|
||||
struct POSType {
|
||||
ex::memory_resource* res = nullptr;
|
||||
void* ptr = nullptr;
|
||||
int n = 0;
|
||||
POSType() {res = ex::new_delete_resource(); ptr = res->allocate(42); n = 42; }
|
||||
POSType(ex::memory_resource* r, void* p, int s) : res(r), ptr(p), n(s) {}
|
||||
~POSType() { if (ptr) res->deallocate(ptr, n); }
|
||||
};
|
||||
|
||||
void swap(POSType & L, POSType & R) {
|
||||
std::swap(L.res, R.res);
|
||||
std::swap(L.ptr, R.ptr);
|
||||
std::swap(L.n, R.n);
|
||||
}
|
||||
|
||||
POSType constructed_before_resources;
|
||||
|
||||
// Constructs resources
|
||||
ex::memory_resource* resource = ex::new_delete_resource();
|
||||
|
||||
POSType constructed_after_resources(resource, resource->allocate(1024), 1024);
|
||||
|
||||
int main()
|
||||
{
|
||||
swap(constructed_after_resources, constructed_before_resources);
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
|
||||
// <experimental/memory_resource>
|
||||
|
||||
#include <experimental/memory_resource>
|
||||
|
||||
#ifndef _LIBCPP_VERSION
|
||||
#error _LIBCPP_VERSION not defined
|
||||
#endif
|
||||
|
||||
int main()
|
||||
{
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
|
||||
// <experimental/memory_resource>
|
||||
|
||||
// template <class T> class polymorphic_allocator
|
||||
|
||||
// polymorphic_allocator operator=(polymorphic_allocator const &) = delete
|
||||
|
||||
#include <experimental/memory_resource>
|
||||
#include <type_traits>
|
||||
#include <cassert>
|
||||
|
||||
namespace ex = std::experimental::pmr;
|
||||
|
||||
int main()
|
||||
{
|
||||
typedef ex::polymorphic_allocator<void> T;
|
||||
static_assert(std::is_copy_assignable<T>::value, "");
|
||||
static_assert(std::is_move_assignable<T>::value, "");
|
||||
}
|
@ -0,0 +1,48 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
|
||||
// <experimental/memory_resource>
|
||||
|
||||
// template <class T> class polymorphic_allocator
|
||||
|
||||
// polymorphic_allocator<T>::polymorphic_allocator(polymorphic_allocator const &);
|
||||
|
||||
#include <experimental/memory_resource>
|
||||
#include <type_traits>
|
||||
#include <cassert>
|
||||
|
||||
namespace ex = std::experimental::pmr;
|
||||
|
||||
int main()
|
||||
{
|
||||
typedef ex::polymorphic_allocator<void> A1;
|
||||
{
|
||||
static_assert(
|
||||
std::is_copy_constructible<A1>::value, ""
|
||||
);
|
||||
static_assert(
|
||||
std::is_move_constructible<A1>::value, ""
|
||||
);
|
||||
}
|
||||
// copy
|
||||
{
|
||||
A1 const a((ex::memory_resource*)42);
|
||||
A1 const a2(a);
|
||||
assert(a.resource() == a2.resource());
|
||||
}
|
||||
// move
|
||||
{
|
||||
A1 a((ex::memory_resource*)42);
|
||||
A1 a2(std::move(a));
|
||||
assert(a.resource() == a2.resource());
|
||||
assert(a2.resource() == (ex::memory_resource*)42);
|
||||
}
|
||||
}
|
@ -0,0 +1,48 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
|
||||
// <experimental/memory_resource>
|
||||
|
||||
// template <class T> class polymorphic_allocator
|
||||
|
||||
// polymorphic_allocator<T>::polymorphic_allocator() noexcept
|
||||
|
||||
#include <experimental/memory_resource>
|
||||
#include <type_traits>
|
||||
#include <cassert>
|
||||
|
||||
#include "test_memory_resource.hpp"
|
||||
|
||||
namespace ex = std::experimental::pmr;
|
||||
|
||||
int main()
|
||||
{
|
||||
{
|
||||
static_assert(
|
||||
std::is_nothrow_default_constructible<ex::polymorphic_allocator<void>>::value
|
||||
, "Must me nothrow default constructible"
|
||||
);
|
||||
}
|
||||
{
|
||||
// test that the allocator gets its resource from get_default_resource
|
||||
TestResource R1(42);
|
||||
ex::set_default_resource(&R1);
|
||||
|
||||
typedef ex::polymorphic_allocator<void> A;
|
||||
A const a;
|
||||
assert(a.resource() == &R1);
|
||||
|
||||
ex::set_default_resource(nullptr);
|
||||
A const a2;
|
||||
assert(a.resource() == &R1);
|
||||
assert(a2.resource() == ex::new_delete_resource());
|
||||
}
|
||||
}
|
@ -0,0 +1,45 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
|
||||
// <experimental/memory_resource>
|
||||
|
||||
// template <class T> class polymorphic_allocator
|
||||
|
||||
// polymorphic_allocator<T>::polymorphic_allocator(memory_resource *)
|
||||
|
||||
#include <experimental/memory_resource>
|
||||
#include <type_traits>
|
||||
#include <cassert>
|
||||
|
||||
#include "test_memory_resource.hpp"
|
||||
|
||||
namespace ex = std::experimental::pmr;
|
||||
|
||||
int main()
|
||||
{
|
||||
{
|
||||
typedef ex::polymorphic_allocator<void> A;
|
||||
static_assert(
|
||||
std::is_convertible<decltype(nullptr), A>::value
|
||||
, "Must be convertible"
|
||||
);
|
||||
static_assert(
|
||||
std::is_convertible<ex::memory_resource *, A>::value
|
||||
, "Must be convertible"
|
||||
);
|
||||
}
|
||||
{
|
||||
typedef ex::polymorphic_allocator<void> A;
|
||||
TestResource R;
|
||||
A const a(&R);
|
||||
assert(a.resource() == &R);
|
||||
}
|
||||
}
|
@ -0,0 +1,57 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
|
||||
// <experimental/memory_resource>
|
||||
|
||||
// template <class T> class polymorphic_allocator
|
||||
|
||||
// template <class U>
|
||||
// polymorphic_allocator<T>::polymorphic_allocator(polymorphic_allocator<U> const &);
|
||||
|
||||
|
||||
#include <experimental/memory_resource>
|
||||
#include <type_traits>
|
||||
#include <cassert>
|
||||
|
||||
namespace ex = std::experimental::pmr;
|
||||
|
||||
int main()
|
||||
{
|
||||
typedef ex::polymorphic_allocator<void> A1;
|
||||
typedef ex::polymorphic_allocator<char> A2;
|
||||
{ // Test that the conversion is implicit and noexcept.
|
||||
static_assert(
|
||||
std::is_convertible<A1 const &, A2>::value, ""
|
||||
);
|
||||
static_assert(
|
||||
std::is_convertible<A2 const &, A1>::value, ""
|
||||
);
|
||||
static_assert(
|
||||
std::is_nothrow_constructible<A1, A2 const &>::value, ""
|
||||
);
|
||||
static_assert(
|
||||
std::is_nothrow_constructible<A2, A1 const &>::value, ""
|
||||
);
|
||||
}
|
||||
// copy other type
|
||||
{
|
||||
A1 const a((ex::memory_resource*)42);
|
||||
A2 const a2(a);
|
||||
assert(a.resource() == a2.resource());
|
||||
assert(a2.resource() == (ex::memory_resource*)42);
|
||||
}
|
||||
{
|
||||
A1 a((ex::memory_resource*)42);
|
||||
A2 const a2(std::move(a));
|
||||
assert(a.resource() == a2.resource());
|
||||
assert(a2.resource() == (ex::memory_resource*)42);
|
||||
}
|
||||
}
|
@ -0,0 +1,133 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
|
||||
// <experimental/memory_resource>
|
||||
|
||||
// template <class T> class polymorphic_allocator;
|
||||
|
||||
// template <class T, class U>
|
||||
// bool operator==(
|
||||
// polymorphic_allocator<T> const &
|
||||
// , polymorphic_allocator<U> const &) noexcept
|
||||
|
||||
#include <experimental/memory_resource>
|
||||
#include <type_traits>
|
||||
#include <cassert>
|
||||
|
||||
#include "test_memory_resource.hpp"
|
||||
|
||||
namespace ex = std::experimental::pmr;
|
||||
|
||||
int main()
|
||||
{
|
||||
typedef ex::polymorphic_allocator<void> A1;
|
||||
typedef ex::polymorphic_allocator<int> A2;
|
||||
// check return types
|
||||
{
|
||||
A1 const a1;
|
||||
A2 const a2;
|
||||
static_assert(std::is_same<decltype(a1 == a2), bool>::value, "");
|
||||
static_assert(noexcept(a1 == a2), "");
|
||||
}
|
||||
// equal same type (different resource)
|
||||
{
|
||||
TestResource d1(1);
|
||||
TestResource d2(1);
|
||||
A1 const a1(&d1);
|
||||
A1 const a2(&d2);
|
||||
|
||||
assert(a1 == a2);
|
||||
assert(d1.checkIsEqualCalledEq(1));
|
||||
assert(d2.checkIsEqualCalledEq(0));
|
||||
|
||||
d1.reset();
|
||||
|
||||
assert(a2 == a1);
|
||||
assert(d1.checkIsEqualCalledEq(0));
|
||||
assert(d2.checkIsEqualCalledEq(1));
|
||||
}
|
||||
// equal same type (same resource)
|
||||
{
|
||||
TestResource d1;
|
||||
A1 const a1(&d1);
|
||||
A1 const a2(&d1);
|
||||
|
||||
assert(a1 == a2);
|
||||
assert(d1.checkIsEqualCalledEq(0));
|
||||
|
||||
assert(a2 == a1);
|
||||
assert(d1.checkIsEqualCalledEq(0));
|
||||
}
|
||||
// equal different type (different resource)
|
||||
{
|
||||
TestResource d1(42);
|
||||
TestResource d2(42);
|
||||
A1 const a1(&d1);
|
||||
A2 const a2(&d2);
|
||||
|
||||
assert(a1 == a2);
|
||||
assert(d1.checkIsEqualCalledEq(1));
|
||||
assert(d2.checkIsEqualCalledEq(0));
|
||||
|
||||
assert(a2 == a1);
|
||||
assert(d1.checkIsEqualCalledEq(1));
|
||||
assert(d2.checkIsEqualCalledEq(1));
|
||||
|
||||
}
|
||||
// equal different type (same resource)
|
||||
{
|
||||
TestResource d1(42);
|
||||
A1 const a1(&d1);
|
||||
A2 const a2(&d1);
|
||||
|
||||
assert(a1 == a2);
|
||||
assert(d1.checkIsEqualCalledEq(0));
|
||||
|
||||
assert(a2 == a1);
|
||||
assert(d1.checkIsEqualCalledEq(0));
|
||||
|
||||
}
|
||||
// not equal same type
|
||||
{
|
||||
TestResource d1(1);
|
||||
TestResource d2(2);
|
||||
A1 const a1(&d1);
|
||||
A1 const a2(&d2);
|
||||
|
||||
assert(!(a1 == a2));
|
||||
assert(d1.checkIsEqualCalledEq(1));
|
||||
assert(d2.checkIsEqualCalledEq(0));
|
||||
|
||||
d1.reset();
|
||||
|
||||
assert(!(a2 == a1));
|
||||
assert(d1.checkIsEqualCalledEq(0));
|
||||
assert(d2.checkIsEqualCalledEq(1));
|
||||
|
||||
}
|
||||
// not equal different types
|
||||
{
|
||||
TestResource d1;
|
||||
TestResource1 d2;
|
||||
A1 const a1(&d1);
|
||||
A2 const a2(&d2);
|
||||
|
||||
assert(!(a1 == a2));
|
||||
assert(d1.checkIsEqualCalledEq(1));
|
||||
assert(d2.checkIsEqualCalledEq(0));
|
||||
|
||||
d1.reset();
|
||||
|
||||
assert(!(a2 == a1));
|
||||
assert(d1.checkIsEqualCalledEq(0));
|
||||
assert(d2.checkIsEqualCalledEq(1));
|
||||
}
|
||||
}
|
@ -0,0 +1,104 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
|
||||
// <experimental/memory_resource>
|
||||
|
||||
// template <class T> class polymorphic_allocator;
|
||||
|
||||
// template <class T>
|
||||
// bool operator!=(
|
||||
// polymorphic_allocator<T> const &
|
||||
// , polymorphic_allocator<T> const &) noexcept
|
||||
|
||||
#include <experimental/memory_resource>
|
||||
#include <type_traits>
|
||||
#include <cassert>
|
||||
|
||||
#include "test_memory_resource.hpp"
|
||||
|
||||
namespace ex = std::experimental::pmr;
|
||||
|
||||
int main()
|
||||
{
|
||||
typedef ex::polymorphic_allocator<void> A1;
|
||||
typedef ex::polymorphic_allocator<int> A2;
|
||||
// check return types
|
||||
{
|
||||
A1 const a1;
|
||||
A2 const a2;
|
||||
static_assert(std::is_same<decltype(a1 != a2), bool>::value, "");
|
||||
static_assert(noexcept(a1 != a2), "");
|
||||
}
|
||||
// not equal same type (different resource)
|
||||
{
|
||||
TestResource d1(1);
|
||||
TestResource d2(2);
|
||||
A1 const a1(&d1);
|
||||
A1 const a2(&d2);
|
||||
|
||||
assert(a1 != a2);
|
||||
assert(d1.checkIsEqualCalledEq(1));
|
||||
assert(d2.checkIsEqualCalledEq(0));
|
||||
|
||||
d1.reset();
|
||||
|
||||
assert(a2 != a1);
|
||||
assert(d1.checkIsEqualCalledEq(0));
|
||||
assert(d2.checkIsEqualCalledEq(1));
|
||||
}
|
||||
// equal same type (same resource)
|
||||
{
|
||||
TestResource d1;
|
||||
A1 const a1(&d1);
|
||||
A1 const a2(&d1);
|
||||
|
||||
assert(!(a1 != a2));
|
||||
assert(d1.checkIsEqualCalledEq(0));
|
||||
|
||||
assert(!(a2 != a1));
|
||||
assert(d1.checkIsEqualCalledEq(0));
|
||||
}
|
||||
// equal same type
|
||||
{
|
||||
TestResource d1(1);
|
||||
TestResource d2(1);
|
||||
A1 const a1(&d1);
|
||||
A1 const a2(&d2);
|
||||
|
||||
assert(!(a1 != a2));
|
||||
assert(d1.checkIsEqualCalledEq(1));
|
||||
assert(d2.checkIsEqualCalledEq(0));
|
||||
|
||||
d1.reset();
|
||||
|
||||
assert(!(a2 != a1));
|
||||
assert(d1.checkIsEqualCalledEq(0));
|
||||
assert(d2.checkIsEqualCalledEq(1));
|
||||
|
||||
}
|
||||
// not equal different types
|
||||
{
|
||||
TestResource d1;
|
||||
TestResource1 d2;
|
||||
A1 const a1(&d1);
|
||||
A2 const a2(&d2);
|
||||
|
||||
assert(a1 != a2);
|
||||
assert(d1.checkIsEqualCalledEq(1));
|
||||
assert(d2.checkIsEqualCalledEq(0));
|
||||
|
||||
d1.reset();
|
||||
|
||||
assert(a2 != a1);
|
||||
assert(d1.checkIsEqualCalledEq(0));
|
||||
assert(d2.checkIsEqualCalledEq(1));
|
||||
}
|
||||
}
|
@ -0,0 +1,111 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
|
||||
// <experimental/memory_resource>
|
||||
|
||||
// template <class T> class polymorphic_allocator
|
||||
|
||||
// T* polymorphic_allocator<T>::allocate(size_t n)
|
||||
|
||||
#include <experimental/memory_resource>
|
||||
#include <limits>
|
||||
#include <memory>
|
||||
#include <exception>
|
||||
#include <type_traits>
|
||||
#include <cassert>
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "test_memory_resource.hpp"
|
||||
|
||||
namespace ex = std::experimental::pmr;
|
||||
|
||||
template <size_t S, size_t Align>
|
||||
void testForSizeAndAlign() {
|
||||
using T = typename std::aligned_storage<S, Align>::type;
|
||||
TestResource R;
|
||||
ex::polymorphic_allocator<T> a(&R);
|
||||
|
||||
for (int N = 1; N <= 5; ++N) {
|
||||
auto ret = a.allocate(N);
|
||||
assert(R.checkAlloc(ret, N * sizeof(T), alignof(T)));
|
||||
|
||||
a.deallocate(ret, N);
|
||||
R.reset();
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef TEST_HAS_NO_EXCEPTIONS
|
||||
template <size_t S>
|
||||
void testAllocForSizeThrows() {
|
||||
using T = typename std::aligned_storage<S>::type;
|
||||
using Alloc = ex::polymorphic_allocator<T>;
|
||||
using Traits = std::allocator_traits<Alloc>;
|
||||
NullResource R;
|
||||
Alloc a(&R);
|
||||
|
||||
// Test that allocating exactly the max size does not throw.
|
||||
size_t maxSize = Traits::max_size(a);
|
||||
try {
|
||||
a.allocate(maxSize);
|
||||
} catch (...) {
|
||||
assert(false);
|
||||
}
|
||||
|
||||
size_t sizeTypeMax = std::numeric_limits<std::size_t>::max();
|
||||
if (maxSize != sizeTypeMax)
|
||||
{
|
||||
// Test that allocating size_t(~0) throws bad alloc.
|
||||
try {
|
||||
a.allocate(sizeTypeMax);
|
||||
assert(false);
|
||||
} catch (std::exception const&) {
|
||||
}
|
||||
|
||||
// Test that allocating even one more than the max size does throw.
|
||||
size_t overSize = maxSize + 1;
|
||||
try {
|
||||
a.allocate(overSize);
|
||||
assert(false);
|
||||
} catch (std::exception const&) {
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // TEST_HAS_NO_EXCEPTIONS
|
||||
|
||||
int main()
|
||||
{
|
||||
{
|
||||
ex::polymorphic_allocator<int> a;
|
||||
static_assert(std::is_same<decltype(a.allocate(0)), int*>::value, "");
|
||||
static_assert(!noexcept(a.allocate(0)), "");
|
||||
}
|
||||
{
|
||||
constexpr std::size_t MA = alignof(std::max_align_t);
|
||||
testForSizeAndAlign<1, 1>();
|
||||
testForSizeAndAlign<1, 2>();
|
||||
testForSizeAndAlign<1, MA>();
|
||||
testForSizeAndAlign<2, 2>();
|
||||
testForSizeAndAlign<73, alignof(void*)>();
|
||||
testForSizeAndAlign<73, MA>();
|
||||
testForSizeAndAlign<13, MA>();
|
||||
}
|
||||
#ifndef TEST_HAS_NO_EXCEPTIONS
|
||||
{
|
||||
testAllocForSizeThrows<1>();
|
||||
testAllocForSizeThrows<2>();
|
||||
testAllocForSizeThrows<4>();
|
||||
testAllocForSizeThrows<8>();
|
||||
testAllocForSizeThrows<16>();
|
||||
testAllocForSizeThrows<73>();
|
||||
testAllocForSizeThrows<13>();
|
||||
}
|
||||
#endif
|
||||
}
|
@ -0,0 +1,52 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
|
||||
// <experimental/memory_resource>
|
||||
|
||||
// template <class T> class polymorphic_allocator
|
||||
|
||||
// template <class U1, class U2>
|
||||
// void polymorphic_allocator<T>::construct(pair<U1, U2>*)
|
||||
|
||||
#include <experimental/memory_resource>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
#include <tuple>
|
||||
#include <cassert>
|
||||
#include <cstdlib>
|
||||
#include "uses_alloc_types.hpp"
|
||||
|
||||
namespace ex = std::experimental::pmr;
|
||||
|
||||
int constructed = 0;
|
||||
|
||||
struct default_constructible
|
||||
{
|
||||
default_constructible() : x(42) { ++constructed; }
|
||||
int x{0};
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
// pair<default_constructible, default_constructible> as T()
|
||||
{
|
||||
typedef default_constructible T;
|
||||
typedef std::pair<T, T> P;
|
||||
typedef ex::polymorphic_allocator<void> A;
|
||||
P * ptr = (P*)std::malloc(sizeof(P));
|
||||
A a;
|
||||
a.construct(ptr);
|
||||
assert(constructed == 2);
|
||||
assert(ptr->first.x == 42);
|
||||
assert(ptr->second.x == 42);
|
||||
std::free(ptr);
|
||||
}
|
||||
}
|
@ -0,0 +1,111 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
|
||||
// <experimental/memory_resource>
|
||||
|
||||
// template <class T> class polymorphic_allocator
|
||||
|
||||
// template <class P1, class P2, class U1, class U2>
|
||||
// void polymorphic_allocator<T>::construct(pair<P1, P2>*, pair<U1, U2> const&)
|
||||
|
||||
#include <experimental/memory_resource>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
#include <tuple>
|
||||
#include <cassert>
|
||||
#include <cstdlib>
|
||||
#include "uses_alloc_types.hpp"
|
||||
|
||||
namespace ex = std::experimental::pmr;
|
||||
|
||||
|
||||
template <class UA1, class UA2, class TT, class UU>
|
||||
bool doTest(UsesAllocatorType TExpect, UsesAllocatorType UExpect,
|
||||
std::pair<TT, UU> const& p)
|
||||
{
|
||||
using P = std::pair<UA1, UA2>;
|
||||
TestResource R;
|
||||
ex::memory_resource * M = &R;
|
||||
ex::polymorphic_allocator<P> A(M);
|
||||
P * ptr = (P*)std::malloc(sizeof(P));
|
||||
P * ptr2 = (P*)std::malloc(sizeof(P));
|
||||
|
||||
// UNDER TEST //
|
||||
A.construct(ptr, p);
|
||||
|
||||
A.construct(ptr2, std::piecewise_construct,
|
||||
std::forward_as_tuple(p.first),
|
||||
std::forward_as_tuple(p.second));
|
||||
// ------- //
|
||||
|
||||
bool tres = checkConstruct<decltype((p.first))>(ptr->first, TExpect, M) &&
|
||||
checkConstructionEquiv(ptr->first, ptr2->first);
|
||||
|
||||
bool ures = checkConstruct<decltype((p.second))>(ptr->second, UExpect, M) &&
|
||||
checkConstructionEquiv(ptr->second, ptr2->second);
|
||||
|
||||
A.destroy(ptr);
|
||||
std::free(ptr);
|
||||
A.destroy(ptr2);
|
||||
std::free(ptr2);
|
||||
return tres && ures;
|
||||
|
||||
}
|
||||
|
||||
template <class Alloc, class TT, class UU>
|
||||
void test_pmr_uses_allocator(std::pair<TT, UU> const& p)
|
||||
{
|
||||
{
|
||||
using T = NotUsesAllocator<Alloc, 1>;
|
||||
using U = NotUsesAllocator<Alloc, 1>;
|
||||
assert((doTest<T, U>(UA_None, UA_None, p)));
|
||||
}
|
||||
{
|
||||
using T = UsesAllocatorV1<Alloc, 1>;
|
||||
using U = UsesAllocatorV2<Alloc, 1>;
|
||||
assert((doTest<T, U>(UA_AllocArg, UA_AllocLast, p)));
|
||||
}
|
||||
{
|
||||
using T = UsesAllocatorV2<Alloc, 1>;
|
||||
using U = UsesAllocatorV3<Alloc, 1>;
|
||||
assert((doTest<T, U>(UA_AllocLast, UA_AllocArg, p)));
|
||||
}
|
||||
{
|
||||
using T = UsesAllocatorV3<Alloc, 1>;
|
||||
using U = NotUsesAllocator<Alloc, 1>;
|
||||
assert((doTest<T, U>(UA_AllocArg, UA_None, p)));
|
||||
}
|
||||
}
|
||||
template <class Tp>
|
||||
struct Print;
|
||||
|
||||
int main()
|
||||
{
|
||||
using ERT = std::experimental::erased_type;
|
||||
using PMR = ex::memory_resource*;
|
||||
using PMA = ex::polymorphic_allocator<char>;
|
||||
{
|
||||
int x = 42;
|
||||
int y = 42;
|
||||
const std::pair<int, int&> p(x, y);
|
||||
test_pmr_uses_allocator<ERT>(p);
|
||||
test_pmr_uses_allocator<PMR>(p);
|
||||
test_pmr_uses_allocator<PMA>(p);
|
||||
}
|
||||
{
|
||||
int x = 42;
|
||||
int y = 42;
|
||||
const std::pair<int&, int&&> p(x, std::move(y));
|
||||
test_pmr_uses_allocator<ERT>(p);
|
||||
test_pmr_uses_allocator<PMR>(p);
|
||||
test_pmr_uses_allocator<PMA>(p);
|
||||
}
|
||||
}
|
@ -0,0 +1,108 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
|
||||
// <experimental/memory_resource>
|
||||
|
||||
// template <class T> class polymorphic_allocator
|
||||
|
||||
// template <class P1, class P2, class U1, class U2>
|
||||
// void polymorphic_allocator<T>::construct(pair<P1, P2>*, pair<U1, U2> &&)
|
||||
|
||||
#include <experimental/memory_resource>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
#include <tuple>
|
||||
#include <cassert>
|
||||
#include <cstdlib>
|
||||
#include "uses_alloc_types.hpp"
|
||||
|
||||
namespace ex = std::experimental::pmr;
|
||||
|
||||
|
||||
|
||||
template <class UA1, class UA2, class TT, class UU>
|
||||
bool doTest(UsesAllocatorType TExpect, UsesAllocatorType UExpect,
|
||||
std::pair<TT, UU>&& p)
|
||||
{
|
||||
using P = std::pair<UA1, UA2>;
|
||||
TestResource R;
|
||||
ex::memory_resource * M = &R;
|
||||
ex::polymorphic_allocator<P> A(M);
|
||||
P * ptr = A.allocate(2);
|
||||
P * ptr2 = ptr + 1;
|
||||
|
||||
// UNDER TEST //
|
||||
A.construct(ptr, std::move(p));
|
||||
|
||||
A.construct(ptr2, std::piecewise_construct,
|
||||
std::forward_as_tuple(std::forward<TT>(p.first)),
|
||||
std::forward_as_tuple(std::forward<UU>(p.second)));
|
||||
// ------- //
|
||||
|
||||
bool tres = checkConstruct<TT&&>(ptr->first, TExpect, M) &&
|
||||
checkConstructionEquiv(ptr->first, ptr2->first);
|
||||
|
||||
bool ures = checkConstruct<UU&&>(ptr->second, UExpect, M) &&
|
||||
checkConstructionEquiv(ptr->second, ptr2->second);
|
||||
|
||||
A.destroy(ptr);
|
||||
A.destroy(ptr2);
|
||||
A.deallocate(ptr, 2);
|
||||
return tres && ures;
|
||||
}
|
||||
|
||||
template <class Alloc, class TT, class UU>
|
||||
void test_pmr_uses_allocator(std::pair<TT, UU>&& p)
|
||||
{
|
||||
{
|
||||
using T = NotUsesAllocator<Alloc, 1>;
|
||||
using U = NotUsesAllocator<Alloc, 1>;
|
||||
assert((doTest<T, U>(UA_None, UA_None, std::move(p))));
|
||||
}
|
||||
{
|
||||
using T = UsesAllocatorV1<Alloc, 1>;
|
||||
using U = UsesAllocatorV2<Alloc, 1>;
|
||||
assert((doTest<T, U>(UA_AllocArg, UA_AllocLast, std::move(p))));
|
||||
}
|
||||
{
|
||||
using T = UsesAllocatorV2<Alloc, 1>;
|
||||
using U = UsesAllocatorV3<Alloc, 1>;
|
||||
assert((doTest<T, U>(UA_AllocLast, UA_AllocArg, std::move(p))));
|
||||
}
|
||||
{
|
||||
using T = UsesAllocatorV3<Alloc, 1>;
|
||||
using U = NotUsesAllocator<Alloc, 1>;
|
||||
assert((doTest<T, U>(UA_AllocArg, UA_None, std::move(p))));
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
using ERT = std::experimental::erased_type;
|
||||
using PMR = ex::memory_resource*;
|
||||
using PMA = ex::polymorphic_allocator<char>;
|
||||
{
|
||||
int x = 42;
|
||||
int y = 42;
|
||||
std::pair<int&, int&&> p(x, std::move(y));
|
||||
test_pmr_uses_allocator<ERT>(std::move(p));
|
||||
test_pmr_uses_allocator<PMR>(std::move(p));
|
||||
test_pmr_uses_allocator<PMA>(std::move(p));
|
||||
}
|
||||
{
|
||||
int x = 42;
|
||||
int y = 42;
|
||||
std::pair<int&&, int&> p(std::move(x), y);
|
||||
test_pmr_uses_allocator<ERT>(std::move(p));
|
||||
test_pmr_uses_allocator<PMR>(std::move(p));
|
||||
test_pmr_uses_allocator<PMA>(std::move(p));
|
||||
}
|
||||
}
|
@ -0,0 +1,109 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
|
||||
// <experimental/memory_resource>
|
||||
|
||||
// template <class T> class polymorphic_allocator
|
||||
|
||||
// template <class P1, class P2, class U1, class U2>
|
||||
// void polymorphic_allocator<T>::construct(pair<P1, P2>*, U1&&, U2&&)
|
||||
|
||||
#include <experimental/memory_resource>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
#include <tuple>
|
||||
#include <cassert>
|
||||
#include <cstdlib>
|
||||
#include "uses_alloc_types.hpp"
|
||||
|
||||
namespace ex = std::experimental::pmr;
|
||||
|
||||
|
||||
template <class UA1, class UA2, class TT, class UU>
|
||||
bool doTest(UsesAllocatorType TExpect, UsesAllocatorType UExpect,
|
||||
TT&& t, UU&& u)
|
||||
{
|
||||
using P = std::pair<UA1, UA2>;
|
||||
TestResource R;
|
||||
ex::memory_resource * M = &R;
|
||||
ex::polymorphic_allocator<P> A(M);
|
||||
P * ptr = (P*)std::malloc(sizeof(P));
|
||||
P * ptr2 = (P*)std::malloc(sizeof(P));
|
||||
|
||||
// UNDER TEST //
|
||||
A.construct(ptr, std::forward<TT>(t), std::forward<UU>(u));
|
||||
A.construct(ptr2, std::piecewise_construct,
|
||||
std::forward_as_tuple(std::forward<TT>(t)),
|
||||
std::forward_as_tuple(std::forward<UU>(u)));
|
||||
// ------- //
|
||||
|
||||
bool tres = checkConstruct<TT&&>(ptr->first, TExpect, M) &&
|
||||
checkConstructionEquiv(ptr->first, ptr2->first);
|
||||
|
||||
bool ures = checkConstruct<UU&&>(ptr->second, UExpect, M) &&
|
||||
checkConstructionEquiv(ptr->second, ptr2->second);
|
||||
|
||||
A.destroy(ptr);
|
||||
A.destroy(ptr2);
|
||||
std::free(ptr);
|
||||
std::free(ptr2);
|
||||
return tres && ures;
|
||||
}
|
||||
|
||||
template <class Alloc, class TT, class UU>
|
||||
void test_pmr_uses_allocator(TT&& t, UU&& u)
|
||||
{
|
||||
{
|
||||
using T = NotUsesAllocator<Alloc, 1>;
|
||||
using U = NotUsesAllocator<Alloc, 1>;
|
||||
assert((doTest<T, U>(UA_None, UA_None,
|
||||
std::forward<TT>(t), std::forward<UU>(u))));
|
||||
}
|
||||
{
|
||||
using T = UsesAllocatorV1<Alloc, 1>;
|
||||
using U = UsesAllocatorV2<Alloc, 1>;
|
||||
assert((doTest<T, U>(UA_AllocArg, UA_AllocLast,
|
||||
std::forward<TT>(t), std::forward<UU>(u))));
|
||||
}
|
||||
{
|
||||
using T = UsesAllocatorV2<Alloc, 1>;
|
||||
using U = UsesAllocatorV3<Alloc, 1>;
|
||||
assert((doTest<T, U>(UA_AllocLast, UA_AllocArg,
|
||||
std::forward<TT>(t), std::forward<UU>(u))));
|
||||
}
|
||||
{
|
||||
using T = UsesAllocatorV3<Alloc, 1>;
|
||||
using U = NotUsesAllocator<Alloc, 1>;
|
||||
assert((doTest<T, U>(UA_AllocArg, UA_None,
|
||||
std::forward<TT>(t), std::forward<UU>(u))));
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
using ERT = std::experimental::erased_type;
|
||||
using PMR = ex::memory_resource*;
|
||||
using PMA = ex::polymorphic_allocator<char>;
|
||||
{
|
||||
int x = 42;
|
||||
int y = 42;
|
||||
test_pmr_uses_allocator<ERT>(x, std::move(y));
|
||||
test_pmr_uses_allocator<PMR>(x, std::move(y));
|
||||
test_pmr_uses_allocator<PMA>(x, std::move(y));
|
||||
}
|
||||
{
|
||||
int x = 42;
|
||||
const int y = 42;
|
||||
test_pmr_uses_allocator<ERT>(std::move(x), y);
|
||||
test_pmr_uses_allocator<PMR>(std::move(x), y);
|
||||
test_pmr_uses_allocator<PMA>(std::move(x), y);
|
||||
}
|
||||
}
|
@ -0,0 +1,129 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
|
||||
// <experimental/memory_resource>
|
||||
|
||||
// template <class T> class polymorphic_allocator
|
||||
|
||||
// template <class U1, class U2, class ...Args1, class ...Args2>
|
||||
// void polymorphic_allocator<T>::construct(pair<U1, U2>*, piecewise_construct_t
|
||||
// tuple<Args1...>, tuple<Args2...>)
|
||||
|
||||
#include <experimental/memory_resource>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
#include <tuple>
|
||||
#include <cassert>
|
||||
#include <cstdlib>
|
||||
#include "uses_alloc_types.hpp"
|
||||
#include "test_allocator.h"
|
||||
|
||||
namespace ex = std::experimental::pmr;
|
||||
|
||||
template <class T, class U, class ...TTuple, class ...UTuple>
|
||||
bool doTest(UsesAllocatorType TExpect, UsesAllocatorType UExpect,
|
||||
std::tuple<TTuple...> ttuple, std::tuple<UTuple...> utuple)
|
||||
{
|
||||
using P = std::pair<T, U>;
|
||||
TestResource R;
|
||||
ex::memory_resource * M = &R;
|
||||
ex::polymorphic_allocator<P> A(M);
|
||||
P * ptr = A.allocate(1);
|
||||
|
||||
// UNDER TEST //
|
||||
A.construct(ptr, std::piecewise_construct, std::move(ttuple), std::move(utuple));
|
||||
// ------- //
|
||||
bool tres = checkConstruct<TTuple&&...>(ptr->first, TExpect, M);
|
||||
bool ures = checkConstruct<UTuple&&...>(ptr->second, UExpect, M);
|
||||
|
||||
A.destroy(ptr);
|
||||
A.deallocate(ptr, 1);
|
||||
return tres && ures;
|
||||
}
|
||||
|
||||
template <class Alloc, class ...TTypes, class ...UTypes>
|
||||
void test_pmr_uses_allocator(std::tuple<TTypes...> ttuple, std::tuple<UTypes...> utuple)
|
||||
{
|
||||
{
|
||||
using T = NotUsesAllocator<Alloc, sizeof...(TTypes)>;
|
||||
using U = NotUsesAllocator<Alloc, sizeof...(UTypes)>;
|
||||
assert((doTest<T, U>(UA_None, UA_None,
|
||||
std::move(ttuple), std::move(utuple))));
|
||||
}
|
||||
{
|
||||
using T = UsesAllocatorV1<Alloc, sizeof...(TTypes)>;
|
||||
using U = UsesAllocatorV2<Alloc, sizeof...(UTypes)>;
|
||||
assert((doTest<T, U>(UA_AllocArg, UA_AllocLast,
|
||||
std::move(ttuple), std::move(utuple))));
|
||||
}
|
||||
{
|
||||
using T = UsesAllocatorV2<Alloc, sizeof...(TTypes)>;
|
||||
using U = UsesAllocatorV3<Alloc, sizeof...(UTypes)>;
|
||||
assert((doTest<T, U>(UA_AllocLast, UA_AllocArg,
|
||||
std::move(ttuple), std::move(utuple))));
|
||||
}
|
||||
{
|
||||
using T = UsesAllocatorV3<Alloc, sizeof...(TTypes)>;
|
||||
using U = NotUsesAllocator<Alloc, sizeof...(UTypes)>;
|
||||
assert((doTest<T, U>(UA_AllocArg, UA_None,
|
||||
std::move(ttuple), std::move(utuple))));
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
using ERT = std::experimental::erased_type;
|
||||
using PMR = ex::memory_resource*;
|
||||
using PMA = ex::polymorphic_allocator<char>;
|
||||
{
|
||||
std::tuple<> t1;
|
||||
test_pmr_uses_allocator<ERT>(t1, t1);
|
||||
test_pmr_uses_allocator<PMR>(t1, t1);
|
||||
test_pmr_uses_allocator<PMA>(t1, t1);
|
||||
}
|
||||
{
|
||||
std::tuple<int> t1(42);
|
||||
std::tuple<> t2;
|
||||
test_pmr_uses_allocator<ERT>(t1, t2);
|
||||
test_pmr_uses_allocator<ERT>(t2, t1);
|
||||
test_pmr_uses_allocator<PMR>(t1, t2);
|
||||
test_pmr_uses_allocator<PMR>(t2, t1);
|
||||
test_pmr_uses_allocator<PMA>(t1, t2);
|
||||
test_pmr_uses_allocator<PMA>(t2, t1);
|
||||
}
|
||||
{
|
||||
std::tuple<int> t1(42);
|
||||
int x = 55;
|
||||
double dx = 42.42;
|
||||
std::tuple<int&, double&&> t2(x, std::move(dx));
|
||||
test_pmr_uses_allocator<ERT>( t1, std::move(t2));
|
||||
test_pmr_uses_allocator<ERT>(std::move(t2), t1);
|
||||
test_pmr_uses_allocator<PMR>( t1, std::move(t2));
|
||||
test_pmr_uses_allocator<PMR>(std::move(t2), t1);
|
||||
test_pmr_uses_allocator<PMA>( t1, std::move(t2));
|
||||
test_pmr_uses_allocator<PMA>(std::move(t2), t1);
|
||||
}
|
||||
{
|
||||
void* xptr = nullptr;
|
||||
long y = 4242;
|
||||
std::tuple<int, long const&, void*&> t1(42, y, xptr);
|
||||
int x = 55;
|
||||
double dx = 42.42;
|
||||
const char* s = "hello World";
|
||||
std::tuple<int&, double&&, const char*> t2(x, std::move(dx), s);
|
||||
test_pmr_uses_allocator<ERT>( t1, std::move(t2));
|
||||
test_pmr_uses_allocator<ERT>(std::move(t2), t1);
|
||||
test_pmr_uses_allocator<PMR>( t1, std::move(t2));
|
||||
test_pmr_uses_allocator<PMR>(std::move(t2), t1);
|
||||
test_pmr_uses_allocator<PMA>( t1, std::move(t2));
|
||||
test_pmr_uses_allocator<PMA>(std::move(t2), t1);
|
||||
}
|
||||
}
|
@ -0,0 +1,189 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
|
||||
// <experimental/memory_resource>
|
||||
|
||||
// template <class T> class polymorphic_allocator
|
||||
|
||||
// template <class U, class ...Args>
|
||||
// void polymorphic_allocator<T>::construct(U *, Args &&...)
|
||||
|
||||
#include <experimental/memory_resource>
|
||||
#include <type_traits>
|
||||
#include <cassert>
|
||||
#include <cstdlib>
|
||||
#include "uses_alloc_types.hpp"
|
||||
#include "test_allocator.h"
|
||||
|
||||
namespace ex = std::experimental::pmr;
|
||||
|
||||
template <class T>
|
||||
struct PMATest {
|
||||
TestResource R;
|
||||
ex::polymorphic_allocator<T> A;
|
||||
T* ptr;
|
||||
bool constructed;
|
||||
|
||||
PMATest() : A(&R), ptr(A.allocate(1)), constructed(false) {}
|
||||
|
||||
template <class ...Args>
|
||||
void construct(Args&&... args) {
|
||||
A.construct(ptr, std::forward<Args>(args)...);
|
||||
constructed = true;
|
||||
}
|
||||
|
||||
~PMATest() {
|
||||
if (constructed) A.destroy(ptr);
|
||||
A.deallocate(ptr, 1);
|
||||
}
|
||||
};
|
||||
|
||||
template <class T, class ...Args>
|
||||
bool doTest(UsesAllocatorType UAExpect, Args&&... args)
|
||||
{
|
||||
PMATest<T> TH;
|
||||
// UNDER TEST //
|
||||
TH.construct(std::forward<Args>(args)...);
|
||||
return checkConstruct<Args&&...>(*TH.ptr, UAExpect, &TH.R);
|
||||
// ------- //
|
||||
}
|
||||
|
||||
|
||||
template <class T, class ...Args>
|
||||
bool doTestUsesAllocV0(Args&&... args)
|
||||
{
|
||||
PMATest<T> TH;
|
||||
// UNDER TEST //
|
||||
TH.construct(std::forward<Args>(args)...);
|
||||
return checkConstruct<Args&&...>(*TH.ptr, UA_None);
|
||||
// -------- //
|
||||
}
|
||||
|
||||
|
||||
template <class T, class EAlloc, class ...Args>
|
||||
bool doTestUsesAllocV1(EAlloc const& ealloc, Args&&... args)
|
||||
{
|
||||
PMATest<T> TH;
|
||||
// UNDER TEST //
|
||||
TH.construct(std::allocator_arg, ealloc, std::forward<Args>(args)...);
|
||||
return checkConstruct<Args&&...>(*TH.ptr, UA_AllocArg, ealloc);
|
||||
// -------- //
|
||||
}
|
||||
|
||||
template <class T, class EAlloc, class ...Args>
|
||||
bool doTestUsesAllocV2(EAlloc const& ealloc, Args&&... args)
|
||||
{
|
||||
PMATest<T> TH;
|
||||
// UNDER TEST //
|
||||
TH.construct(std::forward<Args>(args)..., ealloc);
|
||||
return checkConstruct<Args&&...>(*TH.ptr, UA_AllocLast, ealloc);
|
||||
// -------- //
|
||||
}
|
||||
|
||||
template <class Alloc, class ...Args>
|
||||
void test_pmr_uses_alloc(Args&&... args)
|
||||
{
|
||||
TestResource R(12435);
|
||||
ex::memory_resource* M = &R;
|
||||
{
|
||||
// NotUsesAllocator provides valid signatures for each uses-allocator
|
||||
// construction but does not supply the required allocator_type typedef.
|
||||
// Test that we can call these constructors manually without
|
||||
// polymorphic_allocator interfering.
|
||||
using T = NotUsesAllocator<Alloc, sizeof...(Args)>;
|
||||
assert(doTestUsesAllocV0<T>(std::forward<Args>(args)...));
|
||||
assert((doTestUsesAllocV1<T>(M, std::forward<Args>(args)...)));
|
||||
assert((doTestUsesAllocV2<T>(M, std::forward<Args>(args)...)));
|
||||
}
|
||||
{
|
||||
// Test T(std::allocator_arg_t, Alloc const&, Args...) construction
|
||||
using T = UsesAllocatorV1<Alloc, sizeof...(Args)>;
|
||||
assert((doTest<T>(UA_AllocArg, std::forward<Args>(args)...)));
|
||||
}
|
||||
{
|
||||
// Test T(Args..., Alloc const&) construction
|
||||
using T = UsesAllocatorV2<Alloc, sizeof...(Args)>;
|
||||
assert((doTest<T>(UA_AllocLast, std::forward<Args>(args)...)));
|
||||
}
|
||||
{
|
||||
// Test that T(std::allocator_arg_t, Alloc const&, Args...) construction
|
||||
// is prefered when T(Args..., Alloc const&) is also available.
|
||||
using T = UsesAllocatorV3<Alloc, sizeof...(Args)>;
|
||||
assert((doTest<T>(UA_AllocArg, std::forward<Args>(args)...)));
|
||||
}
|
||||
}
|
||||
|
||||
// Test that polymorphic_allocator does not prevent us from manually
|
||||
// doing non-pmr uses-allocator construction.
|
||||
template <class Alloc, class AllocObj, class ...Args>
|
||||
void test_non_pmr_uses_alloc(AllocObj const& A, Args&&... args)
|
||||
{
|
||||
{
|
||||
using T = NotUsesAllocator<Alloc, sizeof...(Args)>;
|
||||
assert(doTestUsesAllocV0<T>(std::forward<Args>(args)...));
|
||||
assert((doTestUsesAllocV1<T>(A, std::forward<Args>(args)...)));
|
||||
assert((doTestUsesAllocV2<T>(A, std::forward<Args>(args)...)));
|
||||
}
|
||||
{
|
||||
using T = UsesAllocatorV1<Alloc, sizeof...(Args)>;
|
||||
assert(doTestUsesAllocV0<T>(std::forward<Args>(args)...));
|
||||
assert((doTestUsesAllocV1<T>(A, std::forward<Args>(args)...)));
|
||||
}
|
||||
{
|
||||
using T = UsesAllocatorV2<Alloc, sizeof...(Args)>;
|
||||
assert(doTestUsesAllocV0<T>(std::forward<Args>(args)...));
|
||||
assert((doTestUsesAllocV2<T>(A, std::forward<Args>(args)...)));
|
||||
}
|
||||
{
|
||||
using T = UsesAllocatorV3<Alloc, sizeof...(Args)>;
|
||||
assert(doTestUsesAllocV0<T>(std::forward<Args>(args)...));
|
||||
assert((doTestUsesAllocV1<T>(A, std::forward<Args>(args)...)));
|
||||
assert((doTestUsesAllocV2<T>(A, std::forward<Args>(args)...)));
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
using ET = std::experimental::erased_type;
|
||||
using PMR = ex::memory_resource*;
|
||||
using PMA = ex::polymorphic_allocator<void>;
|
||||
using STDA = std::allocator<char>;
|
||||
using TESTA = test_allocator<char>;
|
||||
|
||||
int value = 42;
|
||||
const int cvalue = 43;
|
||||
{
|
||||
test_pmr_uses_alloc<ET>();
|
||||
test_pmr_uses_alloc<PMR>();
|
||||
test_pmr_uses_alloc<PMA>();
|
||||
test_pmr_uses_alloc<ET>(value);
|
||||
test_pmr_uses_alloc<PMR>(value);
|
||||
test_pmr_uses_alloc<PMA>(value);
|
||||
test_pmr_uses_alloc<ET>(cvalue);
|
||||
test_pmr_uses_alloc<PMR>(cvalue);
|
||||
test_pmr_uses_alloc<PMA>(cvalue);
|
||||
test_pmr_uses_alloc<ET>(cvalue, std::move(value));
|
||||
test_pmr_uses_alloc<PMR>(cvalue, std::move(value));
|
||||
test_pmr_uses_alloc<PMA>(cvalue, std::move(value));
|
||||
}
|
||||
{
|
||||
STDA std_alloc;
|
||||
TESTA test_alloc(42);
|
||||
test_non_pmr_uses_alloc<STDA>(std_alloc);
|
||||
test_non_pmr_uses_alloc<TESTA>(test_alloc);
|
||||
test_non_pmr_uses_alloc<STDA>(std_alloc, value);
|
||||
test_non_pmr_uses_alloc<TESTA>(test_alloc, value);
|
||||
test_non_pmr_uses_alloc<STDA>(std_alloc, cvalue);
|
||||
test_non_pmr_uses_alloc<TESTA>(test_alloc, cvalue);
|
||||
test_non_pmr_uses_alloc<STDA>(std_alloc, cvalue, std::move(value));
|
||||
test_non_pmr_uses_alloc<TESTA>(test_alloc, cvalue, std::move(value));
|
||||
}
|
||||
}
|
@ -0,0 +1,61 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
|
||||
// <experimental/memory_resource>
|
||||
|
||||
// template <class T> class polymorphic_allocator
|
||||
|
||||
// T* polymorphic_allocator<T>::deallocate(T*, size_t size)
|
||||
|
||||
#include <experimental/memory_resource>
|
||||
#include <type_traits>
|
||||
#include <cassert>
|
||||
|
||||
#include "test_memory_resource.hpp"
|
||||
|
||||
namespace ex = std::experimental::pmr;
|
||||
|
||||
template <size_t S, size_t Align>
|
||||
void testForSizeAndAlign() {
|
||||
using T = typename std::aligned_storage<S, Align>::type;
|
||||
|
||||
TestResource R;
|
||||
ex::polymorphic_allocator<T> a(&R);
|
||||
|
||||
for (int N = 1; N <= 5; ++N) {
|
||||
auto ret = a.allocate(N);
|
||||
assert(R.checkAlloc(ret, N * sizeof(T), alignof(T)));
|
||||
|
||||
a.deallocate(ret, N);
|
||||
assert(R.checkDealloc(ret, N * sizeof(T), alignof(T)));
|
||||
|
||||
R.reset();
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
{
|
||||
ex::polymorphic_allocator<int> a;
|
||||
static_assert(
|
||||
std::is_same<decltype(a.deallocate(nullptr, 0)), void>::value, "");
|
||||
}
|
||||
{
|
||||
constexpr std::size_t MA = alignof(std::max_align_t);
|
||||
testForSizeAndAlign<1, 1>();
|
||||
testForSizeAndAlign<1, 2>();
|
||||
testForSizeAndAlign<1, MA>();
|
||||
testForSizeAndAlign<2, 2>();
|
||||
testForSizeAndAlign<73, alignof(void*)>();
|
||||
testForSizeAndAlign<73, MA>();
|
||||
testForSizeAndAlign<13, MA>();
|
||||
}
|
||||
}
|
@ -0,0 +1,51 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
|
||||
// <experimental/memory_resource>
|
||||
|
||||
// template <class T> class polymorphic_allocator
|
||||
|
||||
// template <class U>
|
||||
// void polymorphic_allocator<T>::destroy(U * ptr);
|
||||
|
||||
#include <experimental/memory_resource>
|
||||
#include <type_traits>
|
||||
#include <new>
|
||||
#include <cassert>
|
||||
#include <cstdlib>
|
||||
|
||||
namespace ex = std::experimental::pmr;
|
||||
|
||||
int count = 0;
|
||||
|
||||
struct destroyable
|
||||
{
|
||||
destroyable() { ++count; }
|
||||
~destroyable() { --count; }
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
typedef ex::polymorphic_allocator<double> A;
|
||||
{
|
||||
A a;
|
||||
static_assert(
|
||||
std::is_same<decltype(a.destroy((destroyable*)nullptr)), void>::value,
|
||||
"");
|
||||
}
|
||||
{
|
||||
destroyable * ptr = ::new (std::malloc(sizeof(destroyable))) destroyable();
|
||||
assert(count == 1);
|
||||
A{}.destroy(ptr);
|
||||
assert(count == 0);
|
||||
std::free(ptr);
|
||||
}
|
||||
}
|
@ -0,0 +1,56 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
|
||||
// <experimental/memory_resource>
|
||||
|
||||
// template <class T> class polymorphic_allocator
|
||||
|
||||
// memory_resource *
|
||||
// polymorphic_allocator<T>::resource() const
|
||||
|
||||
#include <experimental/memory_resource>
|
||||
#include <type_traits>
|
||||
#include <cassert>
|
||||
|
||||
namespace ex = std::experimental::pmr;
|
||||
|
||||
int main()
|
||||
{
|
||||
typedef ex::polymorphic_allocator<void> A;
|
||||
{
|
||||
A const a;
|
||||
static_assert(
|
||||
std::is_same<decltype(a.resource()), ex::memory_resource*>::value
|
||||
, ""
|
||||
);
|
||||
}
|
||||
{
|
||||
ex::memory_resource * mptr = (ex::memory_resource*)42;
|
||||
A const a(mptr);
|
||||
assert(a.resource() == mptr);
|
||||
}
|
||||
{
|
||||
A const a(nullptr);
|
||||
assert(a.resource() == nullptr);
|
||||
assert(a.resource() == nullptr);
|
||||
}
|
||||
{
|
||||
A const a;
|
||||
assert(a.resource() == ex::get_default_resource());
|
||||
}
|
||||
{
|
||||
ex::memory_resource * mptr = (ex::memory_resource*)42;
|
||||
ex::set_default_resource(mptr);
|
||||
A const a;
|
||||
assert(a.resource() == mptr);
|
||||
assert(a.resource() == ex::get_default_resource());
|
||||
}
|
||||
}
|
@ -0,0 +1,52 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
|
||||
// <experimental/memory_resource>
|
||||
|
||||
// template <class T> class polymorphic_allocator
|
||||
|
||||
// polymorphic_allocator
|
||||
// polymorphic_allocator<T>::select_on_container_copy_construction() const
|
||||
|
||||
#include <experimental/memory_resource>
|
||||
#include <type_traits>
|
||||
#include <cassert>
|
||||
|
||||
namespace ex = std::experimental::pmr;
|
||||
|
||||
int main()
|
||||
{
|
||||
typedef ex::polymorphic_allocator<void> A;
|
||||
{
|
||||
A const a;
|
||||
static_assert(
|
||||
std::is_same<decltype(a.select_on_container_copy_construction()), A>::value,
|
||||
"");
|
||||
}
|
||||
{
|
||||
ex::memory_resource * mptr = (ex::memory_resource*)42;
|
||||
A const a(mptr);
|
||||
assert(a.resource() == mptr);
|
||||
A const other = a.select_on_container_copy_construction();
|
||||
assert(other.resource() == ex::get_default_resource());
|
||||
assert(a.resource() == mptr);
|
||||
}
|
||||
{
|
||||
ex::memory_resource * mptr = (ex::memory_resource*)42;
|
||||
ex::set_default_resource(mptr);
|
||||
A const a(nullptr);
|
||||
assert(a.resource() == nullptr);
|
||||
A const other = a.select_on_container_copy_construction();
|
||||
assert(other.resource() == ex::get_default_resource());
|
||||
assert(other.resource() == mptr);
|
||||
assert(a.resource() == nullptr);
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
//===--------------------------- TODO.cpp ---------------------------------===//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
@ -7,8 +7,4 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "experimental/__config"
|
||||
|
||||
_LIBCPP_BEGIN_NAMESPACE_LFTS
|
||||
|
||||
_LIBCPP_END_NAMESPACE_LFTS
|
||||
int main () {}
|
@ -0,0 +1,10 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
int main () {}
|
@ -0,0 +1,53 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
|
||||
// <experimental/memory_resource>
|
||||
|
||||
// template <class Alloc> class resource_adaptor_imp;
|
||||
|
||||
// resource_adaptor_imp<Alloc>::resource_adaptor_imp(Alloc const &)
|
||||
|
||||
#include <experimental/memory_resource>
|
||||
#include <cassert>
|
||||
|
||||
#include "test_memory_resource.hpp"
|
||||
|
||||
namespace ex = std::experimental::pmr;
|
||||
|
||||
int main()
|
||||
{
|
||||
typedef CountingAllocator<char> AllocT;
|
||||
typedef ex::resource_adaptor<AllocT> R;
|
||||
{
|
||||
AllocController P;
|
||||
AllocT const a(P);
|
||||
R const r(a);
|
||||
assert(P.copy_constructed == 1);
|
||||
assert(P.move_constructed == 0);
|
||||
assert(r.get_allocator() == a);
|
||||
}
|
||||
{
|
||||
AllocController P;
|
||||
AllocT a(P);
|
||||
R const r(a);
|
||||
assert(P.copy_constructed == 1);
|
||||
assert(P.move_constructed == 0);
|
||||
assert(r.get_allocator() == a);
|
||||
}
|
||||
{
|
||||
AllocController P;
|
||||
AllocT const a(P);
|
||||
R const r(std::move(a));
|
||||
assert(P.copy_constructed == 1);
|
||||
assert(P.move_constructed == 0);
|
||||
assert(r.get_allocator() == a);
|
||||
}
|
||||
}
|
@ -0,0 +1,44 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
|
||||
// <experimental/memory_resource>
|
||||
|
||||
// template <class Alloc> class resource_adaptor_imp;
|
||||
|
||||
// resource_adaptor_imp<Alloc>::resource_adaptor_imp(Alloc &&)
|
||||
|
||||
#include <experimental/memory_resource>
|
||||
#include <cassert>
|
||||
|
||||
#include "test_memory_resource.hpp"
|
||||
|
||||
namespace ex = std::experimental::pmr;
|
||||
|
||||
int main()
|
||||
{
|
||||
typedef CountingAllocator<char> AllocT;
|
||||
typedef ex::resource_adaptor<AllocT> R;
|
||||
{
|
||||
AllocController P;
|
||||
AllocT a(P);
|
||||
R const r(std::move(a));
|
||||
assert(P.copy_constructed == 0);
|
||||
assert(P.move_constructed == 1);
|
||||
assert(r.get_allocator() == a);
|
||||
}
|
||||
{
|
||||
AllocController P;
|
||||
R const r(AllocT{P});
|
||||
assert(P.copy_constructed == 0);
|
||||
assert(P.move_constructed == 1);
|
||||
assert(r.get_allocator() == AllocT{P});
|
||||
}
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
|
||||
// <experimental/memory_resource>
|
||||
|
||||
// template <class Alloc> class resource_adaptor_imp;
|
||||
|
||||
// resource_adaptor_imp<Alloc>::resource_adaptor_imp() = default;
|
||||
|
||||
#include <experimental/memory_resource>
|
||||
#include <memory>
|
||||
#include <type_traits>
|
||||
#include <cassert>
|
||||
|
||||
#include "test_memory_resource.hpp"
|
||||
|
||||
namespace ex = std::experimental::pmr;
|
||||
|
||||
int main()
|
||||
{
|
||||
{
|
||||
typedef CountingAllocator<char> AllocT; // Not default constructible
|
||||
typedef ex::resource_adaptor<AllocT> R;
|
||||
static_assert(!std::is_default_constructible<R>::value, "");
|
||||
}
|
||||
{
|
||||
typedef std::allocator<char> AllocT; // Is default constructible
|
||||
typedef ex::resource_adaptor<AllocT> R;
|
||||
static_assert(std::is_default_constructible<R>::value, "");
|
||||
R r; ((void)r);
|
||||
}
|
||||
}
|
@ -0,0 +1,115 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
|
||||
// <experimental/memory_resource>
|
||||
|
||||
// template <class Alloc> class resource_adaptor_imp;
|
||||
|
||||
// void * do_allocate(size_t size, size_t align)
|
||||
// void do_deallocate(void*, size_t, size_t)
|
||||
|
||||
|
||||
#include <experimental/memory_resource>
|
||||
#include <type_traits>
|
||||
#include <memory>
|
||||
#include <exception>
|
||||
#include <cassert>
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "test_memory_resource.hpp"
|
||||
|
||||
namespace ex = std::experimental::pmr;
|
||||
|
||||
template <class Alloc>
|
||||
void check_allocate_deallocate()
|
||||
{
|
||||
typedef ex::resource_adaptor<Alloc> R1;
|
||||
const std::size_t max_align = alignof(std::max_align_t);
|
||||
|
||||
for (std::size_t s = 0; s < 5012; ++s)
|
||||
{
|
||||
for(std::size_t align_req = 1; align_req <= (max_align * 2); align_req *= 2)
|
||||
{
|
||||
const std::size_t align_exp = align_req > max_align
|
||||
? max_align : align_req;
|
||||
AllocController P;
|
||||
R1 r{Alloc(P)};
|
||||
ex::memory_resource & m1 = r;
|
||||
|
||||
void * const ret = m1.allocate(s, align_req);
|
||||
assert(P.alive == 1);
|
||||
assert(P.alloc_count == 1);
|
||||
assert(P.checkAllocAtLeast(ret, s, align_exp));
|
||||
|
||||
assert(((std::size_t)ret % align_exp) == 0);
|
||||
|
||||
m1.deallocate(ret, s, align_req);
|
||||
assert(P.alive == 0);
|
||||
assert(P.dealloc_count == 1);
|
||||
assert(P.checkDeallocMatchesAlloc());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void check_alloc_max_size() {
|
||||
using Alloc = NullAllocator<char>;
|
||||
using R1 = ex::resource_adaptor<Alloc>;
|
||||
const std::size_t max_align = alignof(std::max_align_t);
|
||||
|
||||
auto check = [=](std::size_t s, std::size_t align_req) {
|
||||
const std::size_t align_exp = align_req > max_align
|
||||
? max_align : align_req;
|
||||
AllocController P;
|
||||
R1 r{Alloc(P)};
|
||||
ex::memory_resource & m1 = r;
|
||||
|
||||
void * const ret = m1.allocate(s, align_req);
|
||||
assert(P.alive == 1);
|
||||
assert(P.alloc_count == 1);
|
||||
assert(P.checkAllocAtLeast(ret, s, align_exp));
|
||||
|
||||
m1.deallocate(ret, s, align_req);
|
||||
assert(P.alive == 0);
|
||||
assert(P.dealloc_count == 1);
|
||||
assert(P.checkDeallocMatchesAlloc());
|
||||
};
|
||||
|
||||
const std::size_t sizeTypeMax = ~0;
|
||||
const std::size_t testSizeStart = sizeTypeMax - (max_align * 3);
|
||||
const std::size_t testSizeEnd = sizeTypeMax - max_align;
|
||||
|
||||
for (std::size_t size = testSizeStart; size <= testSizeEnd; ++size) {
|
||||
for (std::size_t align=1; align <= (max_align * 2); align *= 2) {
|
||||
check(size, align);
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef TEST_HAS_NO_EXCEPTIONS
|
||||
for (std::size_t size = sizeTypeMax; size > testSizeEnd; --size) {
|
||||
AllocController P;
|
||||
R1 r{Alloc(P)};
|
||||
ex::memory_resource & m1 = r;
|
||||
|
||||
try {
|
||||
m1.allocate(size);
|
||||
assert(false);
|
||||
} catch (std::exception const&) {
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
check_allocate_deallocate<CountingAllocator<char>>();
|
||||
check_allocate_deallocate<MinAlignedAllocator<char>>();
|
||||
check_alloc_max_size();
|
||||
}
|
@ -0,0 +1,83 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
|
||||
// <experimental/memory_resource>
|
||||
|
||||
// template <class Alloc> class resource_adaptor_imp;
|
||||
|
||||
// bool do_is_equal(memory_resource const &) const noexcept;
|
||||
|
||||
#include <experimental/memory_resource>
|
||||
#include <type_traits>
|
||||
#include <memory>
|
||||
#include <cassert>
|
||||
#include "test_memory_resource.hpp"
|
||||
|
||||
using std::size_t;
|
||||
namespace ex = std::experimental::pmr;
|
||||
|
||||
int main()
|
||||
{
|
||||
|
||||
typedef CountingAllocator<char> Alloc1;
|
||||
typedef CountingAllocator<int> RAlloc1;
|
||||
typedef ex::resource_adaptor<Alloc1> R1;
|
||||
typedef ex::resource_adaptor<RAlloc1> RR1;
|
||||
static_assert(std::is_same<R1, RR1>::value, "");
|
||||
|
||||
typedef std::allocator<char> Alloc2;
|
||||
typedef ex::resource_adaptor<Alloc2> R2;
|
||||
static_assert(!std::is_same<R1, R2>::value, "");
|
||||
|
||||
// equal same type
|
||||
{
|
||||
AllocController C;
|
||||
Alloc1 a1(C);
|
||||
R1 const r1(a1);
|
||||
ex::memory_resource const & m1 = r1;
|
||||
|
||||
Alloc1 a2(C);
|
||||
R1 const r2(a2);
|
||||
ex::memory_resource const & m2 = r2;
|
||||
|
||||
assert(m1.is_equal(m2));
|
||||
assert(m2.is_equal(m1));
|
||||
}
|
||||
// not equal same type
|
||||
{
|
||||
AllocController C;
|
||||
Alloc1 a1(C);
|
||||
R1 const r1(a1);
|
||||
ex::memory_resource const & m1 = r1;
|
||||
|
||||
AllocController C2;
|
||||
Alloc1 a2(C2);
|
||||
R1 const r2(a2);
|
||||
ex::memory_resource const & m2 = r2;
|
||||
|
||||
assert(!m1.is_equal(m2));
|
||||
assert(!m2.is_equal(m1));
|
||||
}
|
||||
// different allocator types
|
||||
{
|
||||
AllocController C;
|
||||
Alloc1 a1(C);
|
||||
R1 const r1(a1);
|
||||
ex::memory_resource const & m1 = r1;
|
||||
|
||||
Alloc2 a2;
|
||||
R2 const r2(a2);
|
||||
ex::memory_resource const & m2 = r2;
|
||||
|
||||
assert(!m1.is_equal(m2));
|
||||
assert(!m2.is_equal(m1));
|
||||
}
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
|
||||
// <experimental/memory_resource>
|
||||
|
||||
// template <class Alloc> class resource_adaptor_imp;
|
||||
|
||||
#include <experimental/memory_resource>
|
||||
#include <type_traits>
|
||||
#include <memory>
|
||||
#include <cassert>
|
||||
|
||||
namespace ex = std::experimental::pmr;
|
||||
|
||||
int main()
|
||||
{
|
||||
typedef ex::resource_adaptor<std::allocator<void>> R;
|
||||
typedef ex::resource_adaptor<std::allocator<long>> R2;
|
||||
static_assert(std::is_same<R, R2>::value, "");
|
||||
{
|
||||
static_assert(std::is_base_of<ex::memory_resource, R>::value, "");
|
||||
static_assert(std::is_same<R::allocator_type, std::allocator<char>>::value, "");
|
||||
}
|
||||
{
|
||||
static_assert(std::is_default_constructible<R>::value, "");
|
||||
static_assert(std::is_copy_constructible<R>::value, "");
|
||||
static_assert(std::is_move_constructible<R>::value, "");
|
||||
static_assert(std::is_copy_assignable<R>::value, "");
|
||||
static_assert(std::is_move_assignable<R>::value, "");
|
||||
}
|
||||
}
|
@ -0,0 +1,73 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
|
||||
// <experimental/memory_resource>
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// TESTING memory_resource * get_default_resource() noexcept;
|
||||
// memory_resource * set_default_resource(memory_resource*) noexcept;
|
||||
//
|
||||
// Concerns:
|
||||
// A) 'get_default_resource()' returns a non-null memory_resource pointer.
|
||||
// B) 'get_default_resource()' returns the value set by the last call to
|
||||
// 'set_default_resource(...)' and 'new_delete_resource()' if no call
|
||||
// to 'set_default_resource(...)' has occurred.
|
||||
// C) 'set_default_resource(...)' returns the previous value of the default
|
||||
// resource.
|
||||
// D) 'set_default_resource(T* p)' for a non-null 'p' sets the default resource
|
||||
// to be 'p'.
|
||||
// E) 'set_default_resource(null)' sets the default resource to
|
||||
// 'new_delete_resource()'.
|
||||
// F) 'get_default_resource' and 'set_default_resource' are noexcept.
|
||||
|
||||
|
||||
#include <experimental/memory_resource>
|
||||
#include <cassert>
|
||||
|
||||
#include "test_memory_resource.hpp"
|
||||
|
||||
using namespace std::experimental::pmr;
|
||||
|
||||
int main() {
|
||||
TestResource R;
|
||||
{ // Test (A) and (B)
|
||||
memory_resource* p = get_default_resource();
|
||||
assert(p != nullptr);
|
||||
assert(p == new_delete_resource());
|
||||
assert(p == get_default_resource());
|
||||
}
|
||||
{ // Test (C) and (D)
|
||||
memory_resource *expect = &R;
|
||||
memory_resource *old = set_default_resource(expect);
|
||||
assert(old != nullptr);
|
||||
assert(old == new_delete_resource());
|
||||
|
||||
memory_resource *p = get_default_resource();
|
||||
assert(p != nullptr);
|
||||
assert(p == expect);
|
||||
assert(p == get_default_resource());
|
||||
}
|
||||
{ // Test (E)
|
||||
memory_resource* old = set_default_resource(nullptr);
|
||||
assert(old == &R);
|
||||
memory_resource* p = get_default_resource();
|
||||
assert(p != nullptr);
|
||||
assert(p == new_delete_resource());
|
||||
assert(p == get_default_resource());
|
||||
}
|
||||
{ // Test (F)
|
||||
static_assert(noexcept(get_default_resource()),
|
||||
"get_default_resource() must be noexcept");
|
||||
|
||||
static_assert(noexcept(set_default_resource(nullptr)),
|
||||
"set_default_resource() must be noexcept");
|
||||
}
|
||||
}
|
@ -0,0 +1,101 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
|
||||
// <experimental/memory_resource>
|
||||
|
||||
// memory_resource * new_delete_resource()
|
||||
|
||||
#include <experimental/memory_resource>
|
||||
#include <type_traits>
|
||||
#include <cassert>
|
||||
|
||||
#include "count_new.hpp"
|
||||
|
||||
namespace ex = std::experimental::pmr;
|
||||
|
||||
struct assert_on_compare : public ex::memory_resource
|
||||
{
|
||||
protected:
|
||||
virtual void * do_allocate(size_t, size_t)
|
||||
{ assert(false); }
|
||||
|
||||
virtual void do_deallocate(void *, size_t, size_t)
|
||||
{ assert(false); }
|
||||
|
||||
virtual bool do_is_equal(ex::memory_resource const &) const noexcept
|
||||
{ assert(false); }
|
||||
};
|
||||
|
||||
void test_return()
|
||||
{
|
||||
{
|
||||
static_assert(std::is_same<
|
||||
decltype(ex::new_delete_resource()), ex::memory_resource*
|
||||
>::value, "");
|
||||
}
|
||||
// assert not null
|
||||
{
|
||||
assert(ex::new_delete_resource());
|
||||
}
|
||||
// assert same return value
|
||||
{
|
||||
assert(ex::new_delete_resource() == ex::new_delete_resource());
|
||||
}
|
||||
}
|
||||
|
||||
void test_equality()
|
||||
{
|
||||
// Same object
|
||||
{
|
||||
ex::memory_resource & r1 = *ex::new_delete_resource();
|
||||
ex::memory_resource & r2 = *ex::new_delete_resource();
|
||||
// check both calls returned the same object
|
||||
assert(&r1 == &r2);
|
||||
// check for proper equality semantics
|
||||
assert(r1 == r2);
|
||||
assert(r2 == r1);
|
||||
assert(!(r1 != r2));
|
||||
assert(!(r2 != r1));
|
||||
}
|
||||
// Different types
|
||||
{
|
||||
ex::memory_resource & r1 = *ex::new_delete_resource();
|
||||
assert_on_compare c;
|
||||
ex::memory_resource & r2 = c;
|
||||
assert(r1 != r2);
|
||||
assert(!(r1 == r2));
|
||||
}
|
||||
}
|
||||
|
||||
void test_allocate_deallocate()
|
||||
{
|
||||
ex::memory_resource & r1 = *ex::new_delete_resource();
|
||||
|
||||
globalMemCounter.reset();
|
||||
|
||||
void *ret = r1.allocate(50);
|
||||
assert(ret);
|
||||
assert(globalMemCounter.checkOutstandingNewEq(1));
|
||||
assert(globalMemCounter.checkLastNewSizeEq(50));
|
||||
|
||||
r1.deallocate(ret, 1);
|
||||
assert(globalMemCounter.checkOutstandingNewEq(0));
|
||||
assert(globalMemCounter.checkDeleteCalledEq(1));
|
||||
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
static_assert(noexcept(ex::new_delete_resource()), "Must be noexcept");
|
||||
test_return();
|
||||
test_equality();
|
||||
test_allocate_deallocate();
|
||||
}
|
@ -0,0 +1,117 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
|
||||
// <experimental/memory_resource>
|
||||
|
||||
// memory_resource * null_memory_resource()
|
||||
|
||||
#include <experimental/memory_resource>
|
||||
#include <new>
|
||||
#include <type_traits>
|
||||
#include <cassert>
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "count_new.hpp"
|
||||
|
||||
namespace ex = std::experimental::pmr;
|
||||
|
||||
struct assert_on_compare : public ex::memory_resource
|
||||
{
|
||||
protected:
|
||||
virtual void * do_allocate(size_t, size_t)
|
||||
{ assert(false); }
|
||||
|
||||
virtual void do_deallocate(void *, size_t, size_t)
|
||||
{ assert(false); }
|
||||
|
||||
virtual bool do_is_equal(ex::memory_resource const &) const noexcept
|
||||
{ assert(false); }
|
||||
};
|
||||
|
||||
void test_return()
|
||||
{
|
||||
{
|
||||
static_assert(std::is_same<
|
||||
decltype(ex::null_memory_resource()), ex::memory_resource*
|
||||
>::value, "");
|
||||
}
|
||||
// Test that the returned value is not null
|
||||
{
|
||||
assert(ex::null_memory_resource());
|
||||
}
|
||||
// Test the same value is returned by repeated calls.
|
||||
{
|
||||
assert(ex::null_memory_resource() == ex::null_memory_resource());
|
||||
}
|
||||
}
|
||||
|
||||
void test_equality()
|
||||
{
|
||||
// Same object
|
||||
{
|
||||
ex::memory_resource & r1 = *ex::null_memory_resource();
|
||||
ex::memory_resource & r2 = *ex::null_memory_resource();
|
||||
// check both calls returned the same object
|
||||
assert(&r1 == &r2);
|
||||
// check for proper equality semantics
|
||||
assert(r1 == r2);
|
||||
assert(r2 == r1);
|
||||
assert(!(r1 != r2));
|
||||
assert(!(r2 != r1));
|
||||
// check the is_equal method
|
||||
assert(r1.is_equal(r2));
|
||||
assert(r2.is_equal(r1));
|
||||
}
|
||||
// Different types
|
||||
{
|
||||
ex::memory_resource & r1 = *ex::null_memory_resource();
|
||||
assert_on_compare c;
|
||||
ex::memory_resource & r2 = c;
|
||||
assert(r1 != r2);
|
||||
assert(!(r1 == r2));
|
||||
assert(!r1.is_equal(r2));
|
||||
}
|
||||
}
|
||||
|
||||
void test_allocate()
|
||||
{
|
||||
#ifndef TEST_HAS_NO_EXCEPTIONS
|
||||
DisableAllocationGuard g; // null_memory_resource shouldn't allocate.
|
||||
try {
|
||||
ex::null_memory_resource()->allocate(1);
|
||||
assert(false);
|
||||
} catch (std::bad_alloc const &) {
|
||||
// do nothing
|
||||
} catch (...) {
|
||||
assert(false);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void test_deallocate()
|
||||
{
|
||||
globalMemCounter.reset();
|
||||
|
||||
int x = 42;
|
||||
ex::null_memory_resource()->deallocate(nullptr, 0);
|
||||
ex::null_memory_resource()->deallocate(&x, 0);
|
||||
|
||||
assert(globalMemCounter.checkDeleteCalledEq(0));
|
||||
assert(globalMemCounter.checkDeleteArrayCalledEq(0));
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
test_return();
|
||||
test_equality();
|
||||
test_allocate();
|
||||
test_deallocate();
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
// -*- C++ -*-
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
int main()
|
||||
{
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
|
||||
// <experimental/memory_resource>
|
||||
|
||||
// Check that memory_resource is not constructible
|
||||
|
||||
#include <experimental/memory_resource>
|
||||
#include <type_traits>
|
||||
#include <cassert>
|
||||
|
||||
namespace ex = std::experimental::pmr;
|
||||
|
||||
int main()
|
||||
{
|
||||
ex::memory_resource m; // expected-error {{variable type 'ex::memory_resource' is an abstract class}}
|
||||
}
|
@ -0,0 +1,76 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
|
||||
// <experimental/memory_resource>
|
||||
|
||||
// bool operator==(memory_resource const &, memory_resource const &) noexcept;
|
||||
|
||||
#include <experimental/memory_resource>
|
||||
#include <type_traits>
|
||||
#include <cassert>
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "test_memory_resource.hpp"
|
||||
|
||||
namespace ex = std::experimental::pmr;
|
||||
|
||||
int main()
|
||||
{
|
||||
// check return types
|
||||
{
|
||||
ex::memory_resource const * mr1(nullptr);
|
||||
ex::memory_resource const * mr2(nullptr);
|
||||
static_assert(std::is_same<decltype(*mr1 == *mr2), bool>::value, "");
|
||||
static_assert(noexcept(*mr1 == *mr2), "");
|
||||
}
|
||||
// equal
|
||||
{
|
||||
TestResource r1(1);
|
||||
TestResource r2(1);
|
||||
ex::memory_resource const & mr1 = r1;
|
||||
ex::memory_resource const & mr2 = r2;
|
||||
|
||||
assert(mr1 == mr2);
|
||||
assert(r1.checkIsEqualCalledEq(1));
|
||||
assert(r2.checkIsEqualCalledEq(0));
|
||||
|
||||
assert(mr2 == mr1);
|
||||
assert(r1.checkIsEqualCalledEq(1));
|
||||
assert(r2.checkIsEqualCalledEq(1));
|
||||
}
|
||||
// equal same object
|
||||
{
|
||||
TestResource r1(1);
|
||||
ex::memory_resource const & mr1 = r1;
|
||||
ex::memory_resource const & mr2 = r1;
|
||||
|
||||
assert(mr1 == mr2);
|
||||
assert(r1.checkIsEqualCalledEq(0));
|
||||
|
||||
assert(mr2 == mr1);
|
||||
assert(r1.checkIsEqualCalledEq(0));
|
||||
}
|
||||
// not equal
|
||||
{
|
||||
TestResource r1(1);
|
||||
TestResource r2(2);
|
||||
ex::memory_resource const & mr1 = r1;
|
||||
ex::memory_resource const & mr2 = r2;
|
||||
|
||||
assert(!(mr1 == mr2));
|
||||
assert(r1.checkIsEqualCalledEq(1));
|
||||
assert(r2.checkIsEqualCalledEq(0));
|
||||
|
||||
assert(!(mr2 == mr1));
|
||||
assert(r1.checkIsEqualCalledEq(1));
|
||||
assert(r2.checkIsEqualCalledEq(1));
|
||||
}
|
||||
}
|
@ -0,0 +1,75 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
|
||||
// <experimental/memory_resource>
|
||||
|
||||
// bool operator!=(memory_resource const &, memory_resource const &) noexcept;
|
||||
|
||||
#include <experimental/memory_resource>
|
||||
#include <type_traits>
|
||||
#include <cassert>
|
||||
|
||||
#include "test_memory_resource.hpp"
|
||||
|
||||
namespace ex = std::experimental::pmr;
|
||||
|
||||
int main()
|
||||
{
|
||||
// check return types
|
||||
{
|
||||
ex::memory_resource const * mr1(nullptr);
|
||||
ex::memory_resource const * mr2(nullptr);
|
||||
static_assert(std::is_same<decltype(*mr1 != *mr2), bool>::value, "");
|
||||
static_assert(noexcept(*mr1 != *mr2), "");
|
||||
}
|
||||
// not equal
|
||||
{
|
||||
TestResource r1(1);
|
||||
TestResource r2(2);
|
||||
ex::memory_resource const & mr1 = r1;
|
||||
ex::memory_resource const & mr2 = r2;
|
||||
|
||||
assert(mr1 != mr2);
|
||||
assert(r1.checkIsEqualCalledEq(1));
|
||||
assert(r2.checkIsEqualCalledEq(0));
|
||||
|
||||
assert(mr2 != mr1);
|
||||
assert(r1.checkIsEqualCalledEq(1));
|
||||
assert(r2.checkIsEqualCalledEq(1));
|
||||
}
|
||||
// equal
|
||||
{
|
||||
TestResource r1(1);
|
||||
TestResource r2(1);
|
||||
ex::memory_resource const & mr1 = r1;
|
||||
ex::memory_resource const & mr2 = r2;
|
||||
|
||||
assert(!(mr1 != mr2));
|
||||
assert(r1.checkIsEqualCalledEq(1));
|
||||
assert(r2.checkIsEqualCalledEq(0));
|
||||
|
||||
assert(!(mr2 != mr1));
|
||||
assert(r1.checkIsEqualCalledEq(1));
|
||||
assert(r2.checkIsEqualCalledEq(1));
|
||||
}
|
||||
// equal same object
|
||||
{
|
||||
TestResource r1(1);
|
||||
ex::memory_resource const & mr1 = r1;
|
||||
ex::memory_resource const & mr2 = r1;
|
||||
|
||||
assert(!(mr1 != mr2));
|
||||
assert(r1.checkIsEqualCalledEq(0));
|
||||
|
||||
assert(!(mr2 != mr1));
|
||||
assert(r1.checkIsEqualCalledEq(0));
|
||||
}
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
int main () {}
|
@ -0,0 +1,27 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
|
||||
// <experimental/memory_resource>
|
||||
|
||||
// memory_resource::do_allocate(size_t, size_t); /* protected */
|
||||
// memory_resource::do_deallocate(void*, size_t, size_t); /* protected */
|
||||
// memory_resource::do_is_equal(memory_resource const&); /* protected */
|
||||
|
||||
#include <experimental/memory_resource>
|
||||
|
||||
namespace ex = std::experimental::pmr;
|
||||
|
||||
int main() {
|
||||
ex::memory_resource *m = ex::new_delete_resource();
|
||||
m->do_allocate(0, 0); // expected-error{{'do_allocate' is a protected member}}
|
||||
m->do_deallocate(nullptr, 0, 0); // expected-error{{'do_deallocate' is a protected member}}
|
||||
m->do_is_equal(*m); // expected-error{{'do_is_equal' is a protected member}}
|
||||
}
|
@ -0,0 +1,89 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// <experimental/memory_resource>
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// TESTING void * memory_resource::allocate(size_t, size_t = max_align)
|
||||
//
|
||||
// Concerns:
|
||||
// A) 'memory_resource' contains a member 'allocate' with the required
|
||||
// signature, including the default alignment parameter.
|
||||
// B) The return type of 'allocate' is 'void*'.
|
||||
// C) 'allocate' is not marked as 'noexcept'.
|
||||
// D) Invoking 'allocate' invokes 'do_allocate' with the same arguments.
|
||||
// E) If 'do_allocate' throws then 'allocate' propagates that exception.
|
||||
|
||||
#include <experimental/memory_resource>
|
||||
#include <type_traits>
|
||||
#include <cstddef>
|
||||
#include <cassert>
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "test_memory_resource.hpp"
|
||||
|
||||
using std::experimental::pmr::memory_resource;
|
||||
|
||||
int main()
|
||||
{
|
||||
TestResource R(42);
|
||||
auto& P = R.getController();
|
||||
memory_resource& M = R;
|
||||
{
|
||||
static_assert(
|
||||
std::is_same<decltype(M.allocate(0, 0)), void*>::value
|
||||
, "Must be void*"
|
||||
);
|
||||
static_assert(
|
||||
std::is_same<decltype(M.allocate(0)), void*>::value
|
||||
, "Must be void*"
|
||||
);
|
||||
}
|
||||
{
|
||||
static_assert(
|
||||
! noexcept(M.allocate(0, 0))
|
||||
, "Must not be noexcept."
|
||||
);
|
||||
static_assert(
|
||||
! noexcept(M.allocate(0))
|
||||
, "Must not be noexcept."
|
||||
);
|
||||
}
|
||||
{
|
||||
int s = 42;
|
||||
int a = 64;
|
||||
void* p = M.allocate(s, a);
|
||||
assert(P.alloc_count == 1);
|
||||
assert(P.checkAlloc(p, s, a));
|
||||
|
||||
s = 128;
|
||||
a = MaxAlignV;
|
||||
p = M.allocate(s);
|
||||
assert(P.alloc_count == 2);
|
||||
assert(P.checkAlloc(p, s, a));
|
||||
}
|
||||
#ifndef TEST_HAS_NO_EXCEPTIONS
|
||||
{
|
||||
TestResource R2;
|
||||
auto& P = R2.getController();
|
||||
P.throw_on_alloc = true;
|
||||
memory_resource& M2 = R2;
|
||||
try {
|
||||
M2.allocate(42);
|
||||
assert(false);
|
||||
} catch (TestException const&) {
|
||||
// do nothing.
|
||||
} catch (...) {
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
@ -0,0 +1,74 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// <experimental/memory_resource>
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// TESTING void * memory_resource::deallocate(void *, size_t, size_t = max_align)
|
||||
//
|
||||
// Concerns:
|
||||
// A) 'memory_resource' contains a member 'deallocate' with the required
|
||||
// signature, including the default alignment parameter.
|
||||
// B) The return type of 'deallocate' is 'void'.
|
||||
// C) 'deallocate' is not marked as 'noexcept'.
|
||||
// D) Invoking 'deallocate' invokes 'do_deallocate' with the same arguments.
|
||||
|
||||
|
||||
#include <experimental/memory_resource>
|
||||
#include <type_traits>
|
||||
#include <cstddef>
|
||||
#include <cassert>
|
||||
|
||||
#include "test_memory_resource.hpp"
|
||||
|
||||
using std::experimental::pmr::memory_resource;
|
||||
|
||||
int main()
|
||||
{
|
||||
NullResource R(42);
|
||||
auto& P = R.getController();
|
||||
memory_resource& M = R;
|
||||
{
|
||||
static_assert(
|
||||
std::is_same<decltype(M.deallocate(nullptr, 0, 0)), void>::value
|
||||
, "Must be void"
|
||||
);
|
||||
static_assert(
|
||||
std::is_same<decltype(M.deallocate(nullptr, 0)), void>::value
|
||||
, "Must be void"
|
||||
);
|
||||
}
|
||||
{
|
||||
static_assert(
|
||||
! noexcept(M.deallocate(nullptr, 0, 0))
|
||||
, "Must not be noexcept."
|
||||
);
|
||||
static_assert(
|
||||
! noexcept(M.deallocate(nullptr, 0))
|
||||
, "Must not be noexcept."
|
||||
);
|
||||
}
|
||||
{
|
||||
int s = 100;
|
||||
int a = 64;
|
||||
void* p = reinterpret_cast<void*>(640);
|
||||
M.deallocate(p, s, a);
|
||||
assert(P.dealloc_count == 1);
|
||||
assert(P.checkDealloc(p, s, a));
|
||||
|
||||
s = 128;
|
||||
a = alignof(std::max_align_t);
|
||||
p = reinterpret_cast<void*>(12800);
|
||||
M.deallocate(p, s);
|
||||
assert(P.dealloc_count == 2);
|
||||
assert(P.checkDealloc(p, s, a));
|
||||
}
|
||||
}
|
@ -0,0 +1,59 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
|
||||
// <experimental/memory_resource>
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// TESTING virtual ~memory_resource()
|
||||
//
|
||||
// Concerns:
|
||||
// A) 'memory_resource' is destructible.
|
||||
// B) The destructor is implicitly marked noexcept.
|
||||
// C) The destructor is marked virtual.
|
||||
|
||||
#include <experimental/memory_resource>
|
||||
#include <type_traits>
|
||||
#include <cassert>
|
||||
|
||||
#include "test_memory_resource.hpp"
|
||||
|
||||
using std::experimental::pmr::memory_resource;
|
||||
|
||||
int main()
|
||||
{
|
||||
static_assert(
|
||||
std::has_virtual_destructor<memory_resource>::value
|
||||
, "Must have virtual destructor"
|
||||
);
|
||||
static_assert(
|
||||
std::is_nothrow_destructible<memory_resource>::value,
|
||||
"Must be nothrow destructible"
|
||||
);
|
||||
static_assert(
|
||||
std::is_abstract<memory_resource>::value
|
||||
, "Must be abstract"
|
||||
);
|
||||
// Check that the destructor of `TestResource` is called when
|
||||
// it is deleted as a pointer to `memory_resource`
|
||||
{
|
||||
using TR = TestResource;
|
||||
memory_resource* M = new TR(42);
|
||||
assert(TR::resource_alive == 1);
|
||||
assert(TR::resource_constructed == 1);
|
||||
assert(TR::resource_destructed == 0);
|
||||
|
||||
delete M;
|
||||
|
||||
assert(TR::resource_alive == 0);
|
||||
assert(TR::resource_constructed == 1);
|
||||
assert(TR::resource_destructed == 1);
|
||||
}
|
||||
}
|
@ -0,0 +1,93 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
|
||||
// <experimental/memory_resource>
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// TESTING virtual bool is_equal(memory_resource const &) const noexcept
|
||||
//
|
||||
// Concerns:
|
||||
// A) 'memory_resource' provides a function 'is_equal' with the required
|
||||
// signature.
|
||||
// B) 'is_equal' is noexcept.
|
||||
// C) 'do_is_equal' is called using the same arguments passed to 'is_equal'
|
||||
// and the resulting value is returned.
|
||||
// D) 'do_is_equal' is called on the LHS object and not the RHS object.
|
||||
|
||||
#include <experimental/memory_resource>
|
||||
#include <type_traits>
|
||||
#include <cassert>
|
||||
#include "test_memory_resource.hpp"
|
||||
|
||||
using std::experimental::pmr::memory_resource;
|
||||
|
||||
int main()
|
||||
{
|
||||
{
|
||||
memory_resource const* r1 = nullptr;
|
||||
memory_resource const* r2 = nullptr;
|
||||
static_assert(
|
||||
noexcept(r1->is_equal(*r2))
|
||||
, "is_equal must be noexcept"
|
||||
);
|
||||
}
|
||||
{
|
||||
TestResource1 R1(1);
|
||||
auto& P1 = R1.getController();
|
||||
memory_resource const& M1 = R1;
|
||||
|
||||
TestResource2 R2(1);
|
||||
auto& P2 = R2.getController();
|
||||
memory_resource const& M2 = R2;
|
||||
|
||||
assert(M1.is_equal(M2) == false);
|
||||
assert(P1.checkIsEqualCalledEq(1));
|
||||
assert(P2.checkIsEqualCalledEq(0));
|
||||
|
||||
assert(M2.is_equal(M1) == false);
|
||||
assert(P2.checkIsEqualCalledEq(1));
|
||||
assert(P1.checkIsEqualCalledEq(1));
|
||||
}
|
||||
{
|
||||
TestResource1 R1(1);
|
||||
auto& P1 = R1.getController();
|
||||
memory_resource const& M1 = R1;
|
||||
|
||||
TestResource1 R2(2);
|
||||
auto& P2 = R2.getController();
|
||||
memory_resource const& M2 = R2;
|
||||
|
||||
assert(M1.is_equal(M2) == false);
|
||||
assert(P1.checkIsEqualCalledEq(1));
|
||||
assert(P2.checkIsEqualCalledEq(0));
|
||||
|
||||
assert(M2.is_equal(M1) == false);
|
||||
assert(P2.checkIsEqualCalledEq(1));
|
||||
assert(P1.checkIsEqualCalledEq(1));
|
||||
}
|
||||
{
|
||||
TestResource1 R1(1);
|
||||
auto& P1 = R1.getController();
|
||||
memory_resource const& M1 = R1;
|
||||
|
||||
TestResource1 R2(1);
|
||||
auto& P2 = R2.getController();
|
||||
memory_resource const& M2 = R2;
|
||||
|
||||
assert(M1.is_equal(M2) == true);
|
||||
assert(P1.checkIsEqualCalledEq(1));
|
||||
assert(P2.checkIsEqualCalledEq(0));
|
||||
|
||||
assert(M2.is_equal(M1) == true);
|
||||
assert(P2.checkIsEqualCalledEq(1));
|
||||
assert(P1.checkIsEqualCalledEq(1));
|
||||
}
|
||||
}
|
13
test/std/experimental/memory/nothing_to_do.pass.cpp
Normal file
13
test/std/experimental/memory/nothing_to_do.pass.cpp
Normal file
@ -0,0 +1,13 @@
|
||||
// -*- C++ -*-
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
int main()
|
||||
{
|
||||
}
|
506
test/support/test_memory_resource.hpp
Normal file
506
test/support/test_memory_resource.hpp
Normal file
@ -0,0 +1,506 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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 SUPPORT_TEST_MEMORY_RESOURCE_HPP
|
||||
#define SUPPORT_TEST_MEMORY_RESOURCE_HPP
|
||||
|
||||
#include <experimental/memory_resource>
|
||||
#include <memory>
|
||||
#include <type_traits>
|
||||
#include <cstddef>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <cassert>
|
||||
#include "test_macros.h"
|
||||
|
||||
struct AllocController;
|
||||
// 'AllocController' is a concrete type that instruments and controls the
|
||||
// behavior of of test allocators.
|
||||
|
||||
template <class T>
|
||||
class CountingAllocator;
|
||||
// 'CountingAllocator' is an basic implementation of the 'Allocator'
|
||||
// requirements that use the 'AllocController' interface.
|
||||
|
||||
template <class T>
|
||||
class MinAlignAllocator;
|
||||
// 'MinAlignAllocator' is an instrumented test type which implements the
|
||||
// 'Allocator' requirements. 'MinAlignAllocator' ensures that it *never*
|
||||
// returns a pointer to over-aligned storage. For example
|
||||
// 'MinAlignPointer<char>{}.allocate(...)' will never a 2-byte aligned
|
||||
// pointer.
|
||||
|
||||
template <class T>
|
||||
class NullAllocator;
|
||||
// 'NullAllocator' is an instrumented test type which implements the
|
||||
// 'Allocator' requirements except that 'allocator' and 'deallocate' are
|
||||
// nops.
|
||||
|
||||
|
||||
#define DISALLOW_COPY(Type) \
|
||||
Type(Type const&) = delete; \
|
||||
Type& operator=(Type const&) = delete
|
||||
|
||||
constexpr std::size_t MaxAlignV = alignof(std::max_align_t);
|
||||
|
||||
struct TestException {};
|
||||
|
||||
struct AllocController {
|
||||
int copy_constructed = 0;
|
||||
int move_constructed = 0;
|
||||
|
||||
int alive = 0;
|
||||
int alloc_count = 0;
|
||||
int dealloc_count = 0;
|
||||
int is_equal_count = 0;
|
||||
|
||||
std::size_t alive_size;
|
||||
std::size_t allocated_size;
|
||||
std::size_t deallocated_size;
|
||||
|
||||
std::size_t last_size = 0;
|
||||
std::size_t last_align = 0;
|
||||
void * last_pointer = 0;
|
||||
|
||||
std::size_t last_alloc_size = 0;
|
||||
std::size_t last_alloc_align = 0;
|
||||
void * last_alloc_pointer = nullptr;
|
||||
|
||||
std::size_t last_dealloc_size = 0;
|
||||
std::size_t last_dealloc_align = 0;
|
||||
void * last_dealloc_pointer = nullptr;
|
||||
|
||||
bool throw_on_alloc = false;
|
||||
|
||||
AllocController() = default;
|
||||
|
||||
void countAlloc(void* p, size_t s, size_t a) {
|
||||
++alive;
|
||||
++alloc_count;
|
||||
alive_size += s;
|
||||
allocated_size += s;
|
||||
last_pointer = last_alloc_pointer = p;
|
||||
last_size = last_alloc_size = s;
|
||||
last_align = last_alloc_align = a;
|
||||
}
|
||||
|
||||
void countDealloc(void* p, size_t s, size_t a) {
|
||||
--alive;
|
||||
++dealloc_count;
|
||||
alive_size -= s;
|
||||
deallocated_size += s;
|
||||
last_pointer = last_dealloc_pointer = p;
|
||||
last_size = last_dealloc_size = s;
|
||||
last_align = last_dealloc_align = a;
|
||||
}
|
||||
|
||||
void reset() { std::memset(this, 0, sizeof(*this)); }
|
||||
|
||||
public:
|
||||
bool checkAlloc(void* p, size_t s, size_t a) const {
|
||||
return p == last_alloc_pointer &&
|
||||
s == last_alloc_size &&
|
||||
a == last_alloc_align;
|
||||
}
|
||||
|
||||
bool checkAlloc(void* p, size_t s) const {
|
||||
return p == last_alloc_pointer &&
|
||||
s == last_alloc_size;
|
||||
}
|
||||
|
||||
bool checkAllocAtLeast(void* p, size_t s, size_t a) const {
|
||||
return p == last_alloc_pointer &&
|
||||
s <= last_alloc_size &&
|
||||
a <= last_alloc_align;
|
||||
}
|
||||
|
||||
bool checkAllocAtLeast(void* p, size_t s) const {
|
||||
return p == last_alloc_pointer &&
|
||||
s <= last_alloc_size;
|
||||
}
|
||||
|
||||
bool checkDealloc(void* p, size_t s, size_t a) const {
|
||||
return p == last_dealloc_pointer &&
|
||||
s == last_dealloc_size &&
|
||||
a == last_dealloc_align;
|
||||
}
|
||||
|
||||
bool checkDealloc(void* p, size_t s) const {
|
||||
return p == last_dealloc_pointer &&
|
||||
s == last_dealloc_size;
|
||||
}
|
||||
|
||||
bool checkDeallocMatchesAlloc() const {
|
||||
return last_dealloc_pointer == last_alloc_pointer &&
|
||||
last_dealloc_size == last_alloc_size &&
|
||||
last_dealloc_align == last_alloc_align;
|
||||
}
|
||||
|
||||
void countIsEqual() {
|
||||
++is_equal_count;
|
||||
}
|
||||
|
||||
bool checkIsEqualCalledEq(int n) const {
|
||||
return is_equal_count == n;
|
||||
}
|
||||
private:
|
||||
DISALLOW_COPY(AllocController);
|
||||
};
|
||||
|
||||
template <class T>
|
||||
class CountingAllocator
|
||||
{
|
||||
public:
|
||||
typedef T value_type;
|
||||
typedef T* pointer;
|
||||
CountingAllocator() = delete;
|
||||
explicit CountingAllocator(AllocController& PP) : P(&PP) {}
|
||||
|
||||
CountingAllocator(CountingAllocator const& other) : P(other.P) {
|
||||
P->copy_constructed += 1;
|
||||
}
|
||||
|
||||
CountingAllocator(CountingAllocator&& other) : P(other.P) {
|
||||
P->move_constructed += 1;
|
||||
}
|
||||
|
||||
template <class U>
|
||||
CountingAllocator(CountingAllocator<U> const& other) TEST_NOEXCEPT : P(other.P) {
|
||||
P->copy_constructed += 1;
|
||||
}
|
||||
|
||||
template <class U>
|
||||
CountingAllocator(CountingAllocator<U>&& other) TEST_NOEXCEPT : P(other.P) {
|
||||
P->move_constructed += 1;
|
||||
}
|
||||
|
||||
T* allocate(std::size_t n)
|
||||
{
|
||||
void* ret = ::operator new(n*sizeof(T));
|
||||
P->countAlloc(ret, n*sizeof(T), alignof(T));
|
||||
return static_cast<T*>(ret);
|
||||
}
|
||||
|
||||
void deallocate(T* p, std::size_t n)
|
||||
{
|
||||
void* vp = static_cast<void*>(p);
|
||||
P->countDealloc(vp, n*sizeof(T), alignof(T));
|
||||
::operator delete(vp);
|
||||
}
|
||||
|
||||
AllocController& getController() const { return *P; }
|
||||
|
||||
private:
|
||||
template <class Tp> friend class CountingAllocator;
|
||||
AllocController *P;
|
||||
};
|
||||
|
||||
template <class T, class U>
|
||||
inline bool operator==(CountingAllocator<T> const& x,
|
||||
CountingAllocator<U> const& y) {
|
||||
return &x.getController() == &y.getController();
|
||||
}
|
||||
|
||||
template <class T, class U>
|
||||
inline bool operator!=(CountingAllocator<T> const& x,
|
||||
CountingAllocator<U> const& y) {
|
||||
return !(x == y);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
class MinAlignedAllocator
|
||||
{
|
||||
public:
|
||||
typedef T value_type;
|
||||
typedef T* pointer;
|
||||
|
||||
MinAlignedAllocator() = delete;
|
||||
|
||||
explicit MinAlignedAllocator(AllocController& R) : P(&R) {}
|
||||
|
||||
MinAlignedAllocator(MinAlignedAllocator const& other) : P(other.P) {
|
||||
P->copy_constructed += 1;
|
||||
}
|
||||
|
||||
MinAlignedAllocator(MinAlignedAllocator&& other) : P(other.P) {
|
||||
P->move_constructed += 1;
|
||||
}
|
||||
|
||||
template <class U>
|
||||
MinAlignedAllocator(MinAlignedAllocator<U> const& other) TEST_NOEXCEPT : P(other.P) {
|
||||
P->copy_constructed += 1;
|
||||
}
|
||||
|
||||
template <class U>
|
||||
MinAlignedAllocator(MinAlignedAllocator<U>&& other) TEST_NOEXCEPT : P(other.P) {
|
||||
P->move_constructed += 1;
|
||||
}
|
||||
|
||||
T* allocate(std::size_t n) {
|
||||
char* aligned_ptr = (char*)::operator new(alloc_size(n*sizeof(T)));
|
||||
assert(is_max_aligned(aligned_ptr));
|
||||
|
||||
char* unaligned_ptr = aligned_ptr + alignof(T);
|
||||
assert(is_min_aligned(unaligned_ptr));
|
||||
|
||||
P->countAlloc(unaligned_ptr, n * sizeof(T), alignof(T));
|
||||
|
||||
return ((T*)unaligned_ptr);
|
||||
}
|
||||
|
||||
void deallocate(T* p, std::size_t n) {
|
||||
assert(is_min_aligned(p));
|
||||
|
||||
char* aligned_ptr = ((char*)p) - alignof(T);
|
||||
assert(is_max_aligned(aligned_ptr));
|
||||
|
||||
P->countDealloc(p, n*sizeof(T), alignof(T));
|
||||
|
||||
return ::operator delete(static_cast<void*>(aligned_ptr));
|
||||
}
|
||||
|
||||
AllocController& getController() const { return *P; }
|
||||
|
||||
private:
|
||||
static const std::size_t BlockSize = alignof(std::max_align_t);
|
||||
|
||||
static std::size_t alloc_size(std::size_t s) {
|
||||
std::size_t bytes = (s + BlockSize - 1) & ~(BlockSize - 1);
|
||||
bytes += BlockSize;
|
||||
assert(bytes % BlockSize == 0);
|
||||
return bytes / BlockSize;
|
||||
}
|
||||
|
||||
static bool is_max_aligned(void* p) {
|
||||
return reinterpret_cast<std::size_t>(p) % BlockSize == 0;
|
||||
}
|
||||
|
||||
static bool is_min_aligned(void* p) {
|
||||
if (alignof(T) == BlockSize) {
|
||||
return is_max_aligned(p);
|
||||
} else {
|
||||
return reinterpret_cast<std::size_t>(p) % BlockSize == alignof(T);
|
||||
}
|
||||
}
|
||||
|
||||
template <class Tp> friend class MinAlignedAllocator;
|
||||
mutable AllocController *P;
|
||||
};
|
||||
|
||||
|
||||
template <class T, class U>
|
||||
inline bool operator==(MinAlignedAllocator<T> const& x,
|
||||
MinAlignedAllocator<U> const& y) {
|
||||
return &x.getController() == &y.getController();
|
||||
}
|
||||
|
||||
template <class T, class U>
|
||||
inline bool operator!=(MinAlignedAllocator<T> const& x,
|
||||
MinAlignedAllocator<U> const& y) {
|
||||
return !(x == y);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
class NullAllocator
|
||||
{
|
||||
public:
|
||||
typedef T value_type;
|
||||
typedef T* pointer;
|
||||
NullAllocator() = delete;
|
||||
explicit NullAllocator(AllocController& PP) : P(&PP) {}
|
||||
|
||||
NullAllocator(NullAllocator const& other) : P(other.P) {
|
||||
P->copy_constructed += 1;
|
||||
}
|
||||
|
||||
NullAllocator(NullAllocator&& other) : P(other.P) {
|
||||
P->move_constructed += 1;
|
||||
}
|
||||
|
||||
template <class U>
|
||||
NullAllocator(NullAllocator<U> const& other) TEST_NOEXCEPT : P(other.P) {
|
||||
P->copy_constructed += 1;
|
||||
}
|
||||
|
||||
template <class U>
|
||||
NullAllocator(NullAllocator<U>&& other) TEST_NOEXCEPT : P(other.P) {
|
||||
P->move_constructed += 1;
|
||||
}
|
||||
|
||||
T* allocate(std::size_t n)
|
||||
{
|
||||
P->countAlloc(nullptr, n*sizeof(T), alignof(T));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void deallocate(T* p, std::size_t n)
|
||||
{
|
||||
void* vp = static_cast<void*>(p);
|
||||
P->countDealloc(vp, n*sizeof(T), alignof(T));
|
||||
}
|
||||
|
||||
AllocController& getController() const { return *P; }
|
||||
|
||||
private:
|
||||
template <class Tp> friend class NullAllocator;
|
||||
AllocController *P;
|
||||
};
|
||||
|
||||
template <class T, class U>
|
||||
inline bool operator==(NullAllocator<T> const& x,
|
||||
NullAllocator<U> const& y) {
|
||||
return &x.getController() == &y.getController();
|
||||
}
|
||||
|
||||
template <class T, class U>
|
||||
inline bool operator!=(NullAllocator<T> const& x,
|
||||
NullAllocator<U> const& y) {
|
||||
return !(x == y);
|
||||
}
|
||||
|
||||
|
||||
|
||||
template <class ProviderT, int = 0>
|
||||
class TestResourceImp : public std::experimental::pmr::memory_resource
|
||||
{
|
||||
public:
|
||||
static int resource_alive;
|
||||
static int resource_constructed;
|
||||
static int resource_destructed;
|
||||
|
||||
static void resetStatics() {
|
||||
assert(resource_alive == 0);
|
||||
resource_alive = 0;
|
||||
resource_constructed = 0;
|
||||
resource_destructed = 0;
|
||||
}
|
||||
|
||||
using memory_resource = std::experimental::pmr::memory_resource;
|
||||
using Provider = ProviderT;
|
||||
|
||||
int value;
|
||||
|
||||
explicit TestResourceImp(int val = 0) : value(val) {
|
||||
++resource_alive;
|
||||
++resource_constructed;
|
||||
}
|
||||
|
||||
~TestResourceImp() noexcept {
|
||||
--resource_alive;
|
||||
++resource_destructed;
|
||||
}
|
||||
|
||||
void reset() { C.reset(); P.reset(); }
|
||||
AllocController& getController() { return C; }
|
||||
|
||||
bool checkAlloc(void* p, std::size_t s, std::size_t a) const
|
||||
{ return C.checkAlloc(p, s, a); }
|
||||
|
||||
bool checkDealloc(void* p, std::size_t s, std::size_t a) const
|
||||
{ return C.checkDealloc(p, s, a); }
|
||||
|
||||
bool checkIsEqualCalledEq(int n) const { return C.checkIsEqualCalledEq(n); }
|
||||
|
||||
protected:
|
||||
virtual void * do_allocate(std::size_t s, std::size_t a) {
|
||||
if (C.throw_on_alloc) {
|
||||
#ifndef TEST_HAS_NO_EXCEPTIONS
|
||||
throw TestException{};
|
||||
#else
|
||||
assert(false);
|
||||
#endif
|
||||
}
|
||||
void* ret = P.allocate(s, a);
|
||||
C.countAlloc(ret, s, a);
|
||||
return ret;
|
||||
}
|
||||
|
||||
virtual void do_deallocate(void * p, std::size_t s, std::size_t a) {
|
||||
C.countDealloc(p, s, a);
|
||||
P.deallocate(p, s, a);
|
||||
}
|
||||
|
||||
virtual bool do_is_equal(memory_resource const & other) const noexcept {
|
||||
C.countIsEqual();
|
||||
TestResourceImp const * o = dynamic_cast<TestResourceImp const *>(&other);
|
||||
return o && o->value == value;
|
||||
}
|
||||
private:
|
||||
mutable AllocController C;
|
||||
mutable Provider P;
|
||||
DISALLOW_COPY(TestResourceImp);
|
||||
};
|
||||
|
||||
template <class Provider, int N>
|
||||
int TestResourceImp<Provider, N>::resource_alive = 0;
|
||||
|
||||
template <class Provider, int N>
|
||||
int TestResourceImp<Provider, N>::resource_constructed = 0;
|
||||
|
||||
template <class Provider, int N>
|
||||
int TestResourceImp<Provider, N>::resource_destructed = 0;
|
||||
|
||||
|
||||
struct NullProvider {
|
||||
NullProvider() {}
|
||||
void* allocate(size_t, size_t) { return nullptr; }
|
||||
void deallocate(void*, size_t, size_t) {}
|
||||
void reset() {}
|
||||
private:
|
||||
DISALLOW_COPY(NullProvider);
|
||||
};
|
||||
|
||||
struct NewDeleteProvider {
|
||||
NewDeleteProvider() {}
|
||||
void* allocate(size_t s, size_t) { return ::operator new(s); }
|
||||
void deallocate(void* p, size_t, size_t) { ::operator delete(p); }
|
||||
void reset() {}
|
||||
private:
|
||||
DISALLOW_COPY(NewDeleteProvider);
|
||||
};
|
||||
|
||||
template <size_t Size = 4096 * 10> // 10 pages worth of memory.
|
||||
struct BufferProvider {
|
||||
char buffer[Size];
|
||||
void* next = &buffer;
|
||||
size_t space = Size;
|
||||
|
||||
BufferProvider() {}
|
||||
|
||||
void* allocate(size_t s, size_t a) {
|
||||
void* ret = std::align(s, a, next, space);
|
||||
if (ret == nullptr) {
|
||||
#ifndef TEST_HAS_NO_EXCEPTIONS
|
||||
throw std::bad_alloc();
|
||||
#else
|
||||
assert(false);
|
||||
#endif
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void deallocate(void*, size_t, size_t) {}
|
||||
|
||||
void reset() {
|
||||
next = &buffer;
|
||||
space = Size;
|
||||
}
|
||||
private:
|
||||
DISALLOW_COPY(BufferProvider);
|
||||
};
|
||||
|
||||
using NullResource = TestResourceImp<NullProvider, 0>;
|
||||
using NewDeleteResource = TestResourceImp<NewDeleteProvider, 0>;
|
||||
using TestResource = TestResourceImp<BufferProvider<>, 0>;
|
||||
using TestResource1 = TestResourceImp<BufferProvider<>, 1>;
|
||||
using TestResource2 = TestResourceImp<BufferProvider<>, 2>;
|
||||
|
||||
|
||||
#endif /* SUPPORT_TEST_MEMORY_RESOURCE_HPP */
|
57
test/support/type_id.h
Normal file
57
test/support/type_id.h
Normal file
@ -0,0 +1,57 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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 SUPPORT_TYPE_ID_H
|
||||
#define SUPPORT_TYPE_ID_H
|
||||
|
||||
#include <functional>
|
||||
#include <cassert>
|
||||
|
||||
#include "test_macros.h"
|
||||
|
||||
#if TEST_STD_VER < 11
|
||||
#error This header requires C++11 or greater
|
||||
#endif
|
||||
|
||||
// TypeID - Represent a unique identifier for a type. TypeID allows equality
|
||||
// comparisons between different types.
|
||||
struct TypeID {
|
||||
friend bool operator==(TypeID const& LHS, TypeID const& RHS)
|
||||
{return LHS.m_id == RHS.m_id; }
|
||||
friend bool operator!=(TypeID const& LHS, TypeID const& RHS)
|
||||
{return LHS.m_id != RHS.m_id; }
|
||||
private:
|
||||
explicit constexpr TypeID(const int* xid) : m_id(xid) {}
|
||||
|
||||
TypeID(const TypeID&) = delete;
|
||||
TypeID& operator=(TypeID const&) = delete;
|
||||
|
||||
const int* const m_id;
|
||||
template <class T> friend TypeID const& makeTypeID();
|
||||
|
||||
};
|
||||
|
||||
// makeTypeID - Return the TypeID for the specified type 'T'.
|
||||
template <class T>
|
||||
inline TypeID const& makeTypeID() {
|
||||
static int dummy;
|
||||
static const TypeID id(&dummy);
|
||||
return id;
|
||||
}
|
||||
|
||||
template <class ...Args>
|
||||
struct ArgumentListID {};
|
||||
|
||||
// makeArgumentID - Create and return a unique identifier for a given set
|
||||
// of arguments.
|
||||
template <class ...Args>
|
||||
inline TypeID const& makeArgumentID() {
|
||||
return makeTypeID<ArgumentListID<Args...>>();
|
||||
}
|
||||
|
||||
#endif // SUPPORT_TYPE_ID_H
|
298
test/support/uses_alloc_types.hpp
Normal file
298
test/support/uses_alloc_types.hpp
Normal file
@ -0,0 +1,298 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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 USES_ALLOC_TYPES_HPP
|
||||
#define USES_ALLOC_TYPES_HPP
|
||||
|
||||
# include <experimental/memory_resource>
|
||||
# include <experimental/utility>
|
||||
# include <memory>
|
||||
# include <cassert>
|
||||
|
||||
#include "test_memory_resource.hpp"
|
||||
#include "type_id.h"
|
||||
|
||||
// There are two forms of uses-allocator construction:
|
||||
// (1) UA_AllocArg: 'T(allocator_arg_t, Alloc const&, Args&&...)'
|
||||
// (2) UA_AllocLast: 'T(Args&&..., Alloc const&)'
|
||||
// 'UA_None' represents non-uses allocator construction.
|
||||
enum class UsesAllocatorType {
|
||||
UA_None = 0,
|
||||
UA_AllocArg = 2,
|
||||
UA_AllocLast = 4
|
||||
};
|
||||
constexpr UsesAllocatorType UA_None = UsesAllocatorType::UA_None;
|
||||
constexpr UsesAllocatorType UA_AllocArg = UsesAllocatorType::UA_AllocArg;
|
||||
constexpr UsesAllocatorType UA_AllocLast = UsesAllocatorType::UA_AllocLast;
|
||||
|
||||
template <class Alloc, std::size_t N>
|
||||
class UsesAllocatorV1;
|
||||
// Implements form (1) of uses-allocator construction from the specified
|
||||
// 'Alloc' type and exactly 'N' additional arguments. It also provides
|
||||
// non-uses allocator construction from 'N' arguments. This test type
|
||||
// blows up when form (2) of uses-allocator is even considered.
|
||||
|
||||
template <class Alloc, std::size_t N>
|
||||
class UsesAllocatorV2;
|
||||
// Implements form (2) of uses-allocator construction from the specified
|
||||
// 'Alloc' type and exactly 'N' additional arguments. It also provides
|
||||
// non-uses allocator construction from 'N' arguments.
|
||||
|
||||
template <class Alloc, std::size_t N>
|
||||
class UsesAllocatorV3;
|
||||
// Implements both form (1) and (2) of uses-allocator construction from
|
||||
// the specified 'Alloc' type and exactly 'N' additional arguments. It also
|
||||
// provides non-uses allocator construction from 'N' arguments.
|
||||
|
||||
template <class Alloc, std::size_t>
|
||||
class NotUsesAllocator;
|
||||
// Implements both form (1) and (2) of uses-allocator construction from
|
||||
// the specified 'Alloc' type and exactly 'N' additional arguments. It also
|
||||
// provides non-uses allocator construction from 'N' arguments. However
|
||||
// 'NotUsesAllocator' never provides a 'allocator_type' typedef so it is
|
||||
// never automatically uses-allocator constructed.
|
||||
|
||||
|
||||
template <class ...ArgTypes, class TestType>
|
||||
bool checkConstruct(TestType& value, UsesAllocatorType form,
|
||||
typename TestType::CtorAlloc const& alloc)
|
||||
// Check that 'value' was constructed using the specified 'form' of
|
||||
// construction and with the specified 'ArgTypes...'. Additionally
|
||||
// check that 'value' was constructed using the specified 'alloc'.
|
||||
{
|
||||
if (form == UA_None) {
|
||||
return value.template checkConstruct<ArgTypes&&...>(form);
|
||||
} else {
|
||||
return value.template checkConstruct<ArgTypes&&...>(form, alloc);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template <class ...ArgTypes, class TestType>
|
||||
bool checkConstruct(TestType& value, UsesAllocatorType form) {
|
||||
return value.template checkConstruct<ArgTypes&&...>(form);
|
||||
}
|
||||
|
||||
template <class TestType>
|
||||
bool checkConstructionEquiv(TestType& T, TestType& U)
|
||||
// check that 'T' and 'U' where initialized in the exact same manner.
|
||||
{
|
||||
return T.checkConstructEquiv(U);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
namespace detail {
|
||||
|
||||
template <bool IsZero, size_t N, class ArgList, class ...Args>
|
||||
struct TakeNImp;
|
||||
|
||||
template <class ArgList, class ...Args>
|
||||
struct TakeNImp<true, 0, ArgList, Args...> {
|
||||
typedef ArgList type;
|
||||
};
|
||||
|
||||
template <size_t N, class ...A1, class F, class ...R>
|
||||
struct TakeNImp<false, N, ArgumentListID<A1...>, F, R...>
|
||||
: TakeNImp<N-1 == 0, N - 1, ArgumentListID<A1..., F>, R...> {};
|
||||
|
||||
template <size_t N, class ...Args>
|
||||
struct TakeNArgs : TakeNImp<N == 0, N, ArgumentListID<>, Args...> {};
|
||||
|
||||
template <class T>
|
||||
struct Identity { typedef T type; };
|
||||
|
||||
template <class T>
|
||||
using IdentityT = typename Identity<T>::type;
|
||||
|
||||
template <bool Value>
|
||||
using EnableIfB = typename std::enable_if<Value, bool>::type;
|
||||
|
||||
} // end namespace detail
|
||||
|
||||
using detail::EnableIfB;
|
||||
|
||||
struct AllocLastTag {};
|
||||
|
||||
template <class Alloc>
|
||||
struct UsesAllocatorTestBase {
|
||||
public:
|
||||
using CtorAlloc = typename std::conditional<
|
||||
std::is_same<Alloc, std::experimental::erased_type>::value,
|
||||
std::experimental::pmr::memory_resource*,
|
||||
Alloc
|
||||
>::type;
|
||||
|
||||
template <class ...ArgTypes>
|
||||
bool checkConstruct(UsesAllocatorType expectType) const {
|
||||
return expectType == constructor_called &&
|
||||
makeArgumentID<ArgTypes...>() == *args_id;
|
||||
}
|
||||
|
||||
template <class ...ArgTypes>
|
||||
bool checkConstruct(UsesAllocatorType expectType,
|
||||
CtorAlloc const& expectAlloc) const {
|
||||
return expectType == constructor_called &&
|
||||
makeArgumentID<ArgTypes...>() == *args_id &&
|
||||
expectAlloc == allocator;
|
||||
}
|
||||
|
||||
bool checkConstructEquiv(UsesAllocatorTestBase& O) const {
|
||||
return constructor_called == O.constructor_called
|
||||
&& *args_id == *O.args_id
|
||||
&& allocator == O.allocator;
|
||||
}
|
||||
|
||||
protected:
|
||||
explicit UsesAllocatorTestBase(const TypeID* aid)
|
||||
: args_id(aid), constructor_called(UA_None), allocator()
|
||||
{}
|
||||
|
||||
template <class ...Args>
|
||||
UsesAllocatorTestBase(std::allocator_arg_t, CtorAlloc const& a, Args&&...)
|
||||
: args_id(&makeArgumentID<Args&&...>()),
|
||||
constructor_called(UA_AllocArg),
|
||||
allocator(a)
|
||||
{}
|
||||
|
||||
template <class ...Args>
|
||||
UsesAllocatorTestBase(AllocLastTag, Args&&... args)
|
||||
: args_id(nullptr),
|
||||
constructor_called(UA_AllocLast)
|
||||
{
|
||||
typedef typename detail::TakeNArgs<sizeof...(Args) - 1, Args&&...>::type
|
||||
ArgIDL;
|
||||
args_id = &makeTypeID<ArgIDL>();
|
||||
getAllocatorFromPack(ArgIDL{}, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
private:
|
||||
template <class ...LArgs, class ...Args>
|
||||
void getAllocatorFromPack(ArgumentListID<LArgs...>, Args&&... args) {
|
||||
getAllocatorFromPackImp<LArgs const&...>(args...);
|
||||
}
|
||||
|
||||
template <class ...LArgs>
|
||||
void getAllocatorFromPackImp(typename detail::Identity<LArgs>::type..., CtorAlloc const& alloc) {
|
||||
allocator = alloc;
|
||||
}
|
||||
|
||||
const TypeID* args_id;
|
||||
UsesAllocatorType constructor_called = UA_None;
|
||||
CtorAlloc allocator;
|
||||
};
|
||||
|
||||
template <class Alloc, size_t Arity>
|
||||
class UsesAllocatorV1 : public UsesAllocatorTestBase<Alloc>
|
||||
{
|
||||
public:
|
||||
typedef Alloc allocator_type;
|
||||
|
||||
using Base = UsesAllocatorTestBase<Alloc>;
|
||||
using CtorAlloc = typename Base::CtorAlloc;
|
||||
|
||||
UsesAllocatorV1() : Base(&makeArgumentID<>()) {}
|
||||
|
||||
// Non-Uses Allocator Ctor
|
||||
template <class ...Args, EnableIfB<sizeof...(Args) == Arity> = false>
|
||||
UsesAllocatorV1(Args&&... args) : Base(&makeArgumentID<Args&&...>()) {};
|
||||
|
||||
// Uses Allocator Arg Ctor
|
||||
template <class ...Args>
|
||||
UsesAllocatorV1(std::allocator_arg_t tag, CtorAlloc const & a, Args&&... args)
|
||||
: Base(tag, a, std::forward<Args>(args)...)
|
||||
{ }
|
||||
|
||||
// BLOWS UP: Uses Allocator Last Ctor
|
||||
template <class _First, class ...Args, EnableIfB<sizeof...(Args) == Arity> _Dummy = false>
|
||||
constexpr UsesAllocatorV1(_First&& __first, Args&&... args)
|
||||
{
|
||||
static_assert(!std::is_same<_First, _First>::value, "");
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <class Alloc, size_t Arity>
|
||||
class UsesAllocatorV2 : public UsesAllocatorTestBase<Alloc>
|
||||
{
|
||||
public:
|
||||
typedef Alloc allocator_type;
|
||||
|
||||
using Base = UsesAllocatorTestBase<Alloc>;
|
||||
using CtorAlloc = typename Base::CtorAlloc;
|
||||
|
||||
UsesAllocatorV2() : Base(&makeArgumentID<>()) {}
|
||||
|
||||
// Non-Uses Allocator Ctor
|
||||
template <class ...Args, EnableIfB<sizeof...(Args) == Arity> = false>
|
||||
UsesAllocatorV2(Args&&... args) : Base(&makeArgumentID<Args&&...>()) {};
|
||||
|
||||
// Uses Allocator Last Ctor
|
||||
template <class ...Args, EnableIfB<sizeof...(Args) == Arity + 1> = false>
|
||||
UsesAllocatorV2(Args&&... args)
|
||||
: Base(AllocLastTag{}, std::forward<Args>(args)...)
|
||||
{}
|
||||
};
|
||||
|
||||
template <class Alloc, size_t Arity>
|
||||
class UsesAllocatorV3 : public UsesAllocatorTestBase<Alloc>
|
||||
{
|
||||
public:
|
||||
typedef Alloc allocator_type;
|
||||
|
||||
using Base = UsesAllocatorTestBase<Alloc>;
|
||||
using CtorAlloc = typename Base::CtorAlloc;
|
||||
|
||||
UsesAllocatorV3() : Base(&makeArgumentID<>()) {}
|
||||
|
||||
// Non-Uses Allocator Ctor
|
||||
template <class ...Args, EnableIfB<sizeof...(Args) == Arity> = false>
|
||||
UsesAllocatorV3(Args&&... args) : Base(&makeArgumentID<Args&&...>()) {};
|
||||
|
||||
// Uses Allocator Arg Ctor
|
||||
template <class ...Args>
|
||||
UsesAllocatorV3(std::allocator_arg_t tag, CtorAlloc const& alloc, Args&&... args)
|
||||
: Base(tag, alloc, std::forward<Args>(args)...)
|
||||
{}
|
||||
|
||||
// Uses Allocator Last Ctor
|
||||
template <class ...Args, EnableIfB<sizeof...(Args) == Arity + 1> = false>
|
||||
UsesAllocatorV3(Args&&... args)
|
||||
: Base(AllocLastTag{}, std::forward<Args>(args)...)
|
||||
{}
|
||||
};
|
||||
|
||||
template <class Alloc, size_t Arity>
|
||||
class NotUsesAllocator : public UsesAllocatorTestBase<Alloc>
|
||||
{
|
||||
public:
|
||||
// no allocator_type typedef provided
|
||||
|
||||
using Base = UsesAllocatorTestBase<Alloc>;
|
||||
using CtorAlloc = typename Base::CtorAlloc;
|
||||
|
||||
NotUsesAllocator() : Base(&makeArgumentID<>()) {}
|
||||
|
||||
// Non-Uses Allocator Ctor
|
||||
template <class ...Args, EnableIfB<sizeof...(Args) == Arity> = false>
|
||||
NotUsesAllocator(Args&&... args) : Base(&makeArgumentID<Args&&...>()) {};
|
||||
|
||||
// Uses Allocator Arg Ctor
|
||||
template <class ...Args>
|
||||
NotUsesAllocator(std::allocator_arg_t tag, CtorAlloc const& alloc, Args&&... args)
|
||||
: Base(tag, alloc, std::forward<Args>(args)...)
|
||||
{}
|
||||
|
||||
// Uses Allocator Last Ctor
|
||||
template <class ...Args, EnableIfB<sizeof...(Args) == Arity + 1> = false>
|
||||
NotUsesAllocator(Args&&... args)
|
||||
: Base(AllocLastTag{}, std::forward<Args>(args)...)
|
||||
{}
|
||||
};
|
||||
|
||||
#endif /* USES_ALLOC_TYPES_HPP */
|
Loading…
Reference in New Issue
Block a user