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:
Eric Fiselier 2016-05-07 01:04:55 +00:00
parent 70487694ba
commit 257fd699fd
55 changed files with 4712 additions and 6 deletions

View File

@ -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

View File

@ -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 } } }

View 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 */

View 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 */

View 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

View File

@ -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);
}
}

View File

@ -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);
}

View File

@ -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));
}
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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()
{
}

View File

@ -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, "");
}

View File

@ -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);
}
}

View File

@ -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());
}
}

View File

@ -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);
}
}

View 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.
//
//===----------------------------------------------------------------------===//
// 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);
}
}

View File

@ -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));
}
}

View File

@ -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));
}
}

View File

@ -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
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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));
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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));
}
}

View File

@ -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>();
}
}

View File

@ -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);
}
}

View File

@ -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());
}
}

View File

@ -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);
}
}

View File

@ -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 () {}

View File

@ -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 () {}

View File

@ -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);
}
}

View File

@ -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});
}
}

View File

@ -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);
}
}

View File

@ -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();
}

View File

@ -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));
}
}

View File

@ -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, "");
}
}

View File

@ -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");
}
}

View File

@ -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();
}

View File

@ -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();
}

View 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()
{
}

View File

@ -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}}
}

View File

@ -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));
}
}

View File

@ -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));
}
}

View File

@ -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 () {}

View File

@ -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}}
}

View File

@ -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
}

View File

@ -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));
}
}

View File

@ -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);
}
}

View File

@ -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));
}
}

View 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()
{
}

View 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
View 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

View 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 */