Index: include/experimental/__config =================================================================== --- include/experimental/__config +++ include/experimental/__config @@ -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 } } } Index: include/experimental/__memory =================================================================== --- /dev/null +++ include/experimental/__memory @@ -0,0 +1,39 @@ +// -*- 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 + +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +#pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_LFTS + +inline _LIBCPP_INLINE_VISIBILITY +size_t __is_power2(size_t __bc) +{ + return __bc == 1 || __bc == 2 || (__bc && !(__bc & (__bc - 1))); +} + +inline _LIBCPP_INLINE_VISIBILITY +size_t __alignment_offset(void * __p, size_t __a) _NOEXCEPT +{ + static_assert(sizeof(size_t) == sizeof(void*), "must be same"); + return (__a - reinterpret_cast(__p)) & (__a - 1); +} + +_LIBCPP_END_NAMESPACE_LFTS + +#endif /* _LIBCPP_EXPERIMENTAL___MEMORY */ Index: include/experimental/memory_resource =================================================================== --- /dev/null +++ include/experimental/memory_resource @@ -0,0 +1,148 @@ +// -*- 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 polymorphic_allocator; + + template + bool operator==(const polymorphic_allocator& a, + const polymorphic_allocator& b) noexcept; + template + bool operator!=(const polymorphic_allocator& a, + const polymorphic_allocator& b) noexcept; + + // The name resource_adaptor_imp is for exposition only. + template class resource_adaptor_imp; + + template + using resource_adaptor = resource_adaptor_imp< + allocator_traits::rebind_alloc>; + + // 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 +#include +#include +#include + +#include <__debug> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +#pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_LFTS_PMR + +// 8.5, memory.resource +class _LIBCPP_TYPE_VIS_ONLY memory_resource +{ + static const size_t __max_align = + alignment_of::value; + +// 8.5.2, memory.resource.public +public: + virtual ~memory_resource(); + + _LIBCPP_INLINE_VISIBILITY + void* allocate(size_t __bytes, size_t __align = __max_align) { + _LIBCPP_ASSERT(__align != 0, "can't be zero"); + _LIBCPP_ASSERT(__is_power2(__align), "alignment must be power of two"); + void * const __ret = do_allocate(__bytes, __align); + _LIBCPP_ASSERT( + __alignment_offset(__ret, __max_align < __align ? __max_align : __align) == 0 + , "Incorrect alignment"); + return __ret; + } + + _LIBCPP_INLINE_VISIBILITY + void deallocate(void * __p, size_t __bytes, size_t __align = __max_align) { + _LIBCPP_ASSERT(__is_power2(__align), "alignment must be power of two"); + _LIBCPP_ASSERT( + __alignment_offset(__p, __max_align < __align ? __max_align : __align) == 0 + , "Incorrect alignment"); + 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 __bytes, size_t __align) = 0; + virtual void do_deallocate(void * __p, size_t __bytes, size_t __align) = 0; + virtual bool do_is_equal(memory_resource const & __other) 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*) _NOEXCEPT; + +_LIBCPP_END_NAMESPACE_LFTS_PMR + +#endif /* _LIBCPP_EXPERIMENTAL_MEMORY_RESOURCE */ Index: src/memory_resource.cpp =================================================================== --- /dev/null +++ src/memory_resource.cpp @@ -0,0 +1,127 @@ +//===------------------------ 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" +#include "limits" +#include "cstdlib" + +#include "support/atomic_support.h" + +_LIBCPP_BEGIN_NAMESPACE_LFTS_PMR + +//////////////////////////////////////////////////////////////////////////////// +memory_resource::~memory_resource() +{ +} + +//////////////////////////////////////////////////////////////////////////////// +class _LIBCPP_HIDDEN __new_delete_memory_resource_imp + : public memory_resource +{ +public: + ~__new_delete_memory_resource_imp(); +protected: + virtual void* do_allocate(size_t __size, size_t __align); + virtual void do_deallocate(void * __p, size_t __size, size_t __align); + virtual bool do_is_equal(memory_resource const & __other) const _NOEXCEPT; +}; + +__new_delete_memory_resource_imp::~__new_delete_memory_resource_imp() +{ +} + +void * __new_delete_memory_resource_imp::do_allocate(size_t s, size_t) +{ + return ::operator new(s); +} + +void __new_delete_memory_resource_imp::do_deallocate(void * p, size_t, size_t) +{ + return ::operator delete(p); +} + +bool __new_delete_memory_resource_imp::do_is_equal( + memory_resource const & other) const _NOEXCEPT +{ + return this == + dynamic_cast<__new_delete_memory_resource_imp const *>(&other); +} + +//////////////////////////////////////////////////////////////////////////////// + class _LIBCPP_HIDDEN __null_memory_resource_imp + : public memory_resource +{ +public: + ~__null_memory_resource_imp(); +protected: + virtual void* do_allocate(size_t, size_t); + virtual void do_deallocate(void *, size_t, size_t); + virtual bool do_is_equal(memory_resource const & __other) const _NOEXCEPT; +}; + +__null_memory_resource_imp::~__null_memory_resource_imp() +{ +} + +void* __null_memory_resource_imp::do_allocate(size_t, size_t) +{ +#ifndef _LIBCPP_NO_EXCEPTIONS + throw bad_alloc(); +#else + abort(); +#endif +} + +void __null_memory_resource_imp::do_deallocate(void *, size_t, size_t) +{ +} + +bool __null_memory_resource_imp::do_is_equal( + memory_resource const & __other) const _NOEXCEPT +{ + return &__other == static_cast(this); +} +/////////////////////////////////////////////////////////////////////////////// + +_ALIGNAS_TYPE(__new_delete_memory_resource_imp) +static char __nd_res_buf[sizeof(__new_delete_memory_resource_imp)]; + +_ALIGNAS_TYPE(__null_memory_resource_imp) +static char __null_res_buf[sizeof(__null_memory_resource_imp)]; + +memory_resource * new_delete_resource() _NOEXCEPT { + static memory_resource* resource = + ::new ((void*)&__nd_res_buf) __new_delete_memory_resource_imp(); + return resource; +} + +memory_resource * null_memory_resource() _NOEXCEPT { + static memory_resource* resource = + ::new ((void*)&__null_res_buf) __null_memory_resource_imp(); + return resource; +} + +/////////////////////////////////////////////////////////////////////////////// +static memory_resource** __default_resource() { + static memory_resource* ptr = new_delete_resource() ; + return &ptr; +} + +memory_resource* get_default_resource() _NOEXCEPT +{ + return __libcpp_atomic_load(__default_resource(), _AO_Aquire); +} + +memory_resource * set_default_resource(memory_resource * new_res) _NOEXCEPT +{ + new_res = new_res ? new_res : new_delete_resource(); + return __libcpp_atomic_exchange(__default_resource(), new_res, _AO_Acq_Rel); +} + +_LIBCPP_END_NAMESPACE_LFTS_PMR Index: src/support/atomic_support.h =================================================================== --- src/support/atomic_support.h +++ src/support/atomic_support.h @@ -31,8 +31,8 @@ namespace { -#if defined(_LIBCPP_HAS_ATOMIC_BUILTINS) && !defined(_LIBCPP_HAS_NO_THREADS) - +//#if defined(_LIBCPP_HAS_ATOMIC_BUILTINS) && !defined(_LIBCPP_HAS_NO_THREADS) +#if 1 enum __libcpp_atomic_order { _AO_Relaxed = __ATOMIC_RELAXED, _AO_Consume = __ATOMIC_CONSUME, @@ -73,6 +73,13 @@ return __atomic_add_fetch(__val, __a, __order); } +template +inline _LIBCPP_INLINE_VISIBILITY +_ValueType __libcpp_atomic_exchange(_ValueType* __val, _ValueType2 __new, int __order = _AO_Seq) +{ + return __atomic_exchange_n(__val, __new, __order); +}; + template inline _LIBCPP_INLINE_VISIBILITY bool __libcpp_atomic_compare_exchange(_ValueType* __val, @@ -119,6 +126,15 @@ return *__val += __a; } +template +inline _LIBCPP_INLINE_VISIBILITY +_ValueType __libcpp_atomic_exchange(_ValueType* __val, _ValueType2 __new, int = 0) +{ + _ValueType __tmp = *__val; + *__val = __new; + return __tmp; +}; + template inline _LIBCPP_INLINE_VISIBILITY bool __libcpp_atomic_compare_exchange(_ValueType* __val, Index: test/libcxx/experimental/memory/memory.resource.synop/version.pass.cpp =================================================================== --- /dev/null +++ test/libcxx/experimental/memory/memory.resource.synop/version.pass.cpp @@ -0,0 +1,20 @@ +//===----------------------------------------------------------------------===// +// +// 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 + +#ifndef _LIBCPP_VERSION +#error _LIBCPP_VERSION not defined +#endif + +int main() +{ +} Index: test/std/algorithms/alg.sorting/alg.heap.operations/make.heap/make_heap_comp.pass.cpp =================================================================== --- test/std/algorithms/alg.sorting/alg.heap.operations/make.heap/make_heap_comp.pass.cpp +++ test/std/algorithms/alg.sorting/alg.heap.operations/make.heap/make_heap_comp.pass.cpp @@ -42,6 +42,7 @@ std::make_heap(ia, ia+N, std::greater()); assert(std::is_heap(ia, ia+N, std::greater())); } + } // Ascending { Index: test/std/experimental/memory/memory.resource.global/default_resource.pass.cpp =================================================================== --- /dev/null +++ test/std/experimental/memory/memory.resource.global/default_resource.pass.cpp @@ -0,0 +1,106 @@ +//===----------------------------------------------------------------------===// +// +// 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 + +//----------------------------------------------------------------------------- +// 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. +// +// Plan: +// 1) Check concerns A and B in the following manner. +// +// 1a) Create a pointer 'p' from the return value of 'get_default_resource()'. +// Check that 'p' is not null and is the same as 'new_delete_resource()'. +// 1b) Call 'get_default_resource()' again and check that it returns a pointer +// that is equal to 'p' +// +// 2) Check concerns A, B, C and D in the following manner: +// +// 2a) Create a TestResource 't' that derives from memory resource. +// 2b) Call 'set_default_resource(&t)' and check that the returned +// value is the same as 'new_delete_resource()'. +// 2c) Create a pointer 'p' from the return valeu of 'get_default_resource()' +// Check that 'p == &t'. +// 2d) Call 'get_default_resource()' again and check that the same value +// is returned. +// +// 3) Check concerns A, B, C and E in the following manner: +// +// 3a) Call 'set_default_resource(nullptr)' and check that the returned +// value is the same as 't' from 2a. +// 3b) Create a pointer 'p' from the return value of 'get_default_resource()' +// and check that 'p' is the same as 'new_delete_resource()'. +// 3c) Call 'get_default_resource()' again and check that the same value +// is returned. +// +// 4) Check concern F by calling 'get_default_resource()' and +// 'set_default_resource()' in a noexcept expression and assert +// that the expression is noexcept. + +#include +#include + +#include "test_memory_resource.hpp" + +using namespace std::experimental::pmr; + +int main() { + TestResource R; + { // Test Part 1 + memory_resource* p = get_default_resource(); + assert(p != nullptr); + assert(p == new_delete_resource()); + assert(p == get_default_resource()); + } + { // Test Part 2 + 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 Part 3 + 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 Part 4 + 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" + ); + } +} Index: test/std/experimental/memory/memory.resource.global/new_delete_resource.pass.cpp =================================================================== --- /dev/null +++ test/std/experimental/memory/memory.resource.global/new_delete_resource.pass.cpp @@ -0,0 +1,90 @@ +//===----------------------------------------------------------------------===// +// +// 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 + +//----------------------------------------------------------------------------- +// TESTING memory_resource * new_delete_resource() noexcept +// +// Concerns: +// A) 'new_delete_memory_resource()' returns a non-null pointer to a 'memory_resource' 'M'. +// B) 'new_delete_memory_resource()' always returns the same pointer. +// C) 'M.allocate(s, a)' calls '::operator new(s)' and returns that pointer. +// D) 'M.deallocate(p, s, a)' calls '::operator delete(p)'. +// E) 'M' only compares equal to itself. 'M.is_equal(Other)' will not invoke +// 'Other.is_equal(M)'. +// F) 'new_delete_resource()' is marked as 'noexcept'. +// +// Plan: +// 1) Check concerns A, B and E by getting two pointers 'p1' and 'p2' from +// calling 'new_deletee_memory_resource()' twice. Check that these pointers +// have the same address and are not null. +// +// 2) Check concerns C and D by performing an allocation and deallocation with +// 'M'. Use 'globalMemCounter' to check that 'new' and 'delete' were invoked +// by those operations with the correct arguments. +// +// 3) Check concern E by comparing 'M' to other 'memory_resource' objects +// with different base classes. Check that 'M.is_equal(Other)' is always +// false and it does not invoke 'Other.is_equal(M)'. +// +// 4) Check concern F by calling 'new_delete_resource()' in a noexcept expression +// and check that the expression returns true. + +#include +#include + +#include "test_memory_resource.hpp" +#include "count_new.hpp" + +using namespace std::experimental::pmr; + +int main() +{ + { // Plan Part 1 + memory_resource* p1 = new_delete_resource(); + assert(p1 != nullptr); + assert(p1->is_equal(*p1)); + + memory_resource* p2 = new_delete_resource(); + assert(p2 != nullptr); + assert(p1 == p2); + assert(p1->is_equal(*p2)); + assert(p2->is_equal(*p1)); + } + { // Plan part 2 + MemCounter& G = globalMemCounter; + memory_resource& M = *new_delete_resource(); + void* p = M.allocate(1024); + assert(p != nullptr); + assert(G.checkOutstandingNewEq(1)); + assert(G.checkLastNewSizeEq(1024)); + + M.deallocate(p, 1024); + assert(G.checkOutstandingNewEq(0)); + assert(G.checkDeleteCalledEq(1)); + } + { // Plan part 3 + memory_resource const& M = *new_delete_resource(); + TestResource R; + auto& P = R.getProvider(); + memory_resource const& O = R; + + assert(M.is_equal(O) == false); + assert(P.checkIsEqualCalledEq(0)); + } + { // Plan Part 4 + static_assert( + noexcept(new_delete_resource()) + , "new_delete_resource() must be noexcept" + ); + } +} Index: test/std/experimental/memory/memory.resource.global/null_memory_resource.pass.cpp =================================================================== --- /dev/null +++ test/std/experimental/memory/memory.resource.global/null_memory_resource.pass.cpp @@ -0,0 +1,114 @@ +//===----------------------------------------------------------------------===// +// +// 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 + +//----------------------------------------------------------------------------- +// TESTING memory_resource * null_memory_resource() noexcept +// +// Concerns: +// A) 'null_memory_resource()' returns a non-null pointer to a 'memory_resource' 'M'. +// B) 'null_memory_resource()' always returns the same pointer. +// C) 'M.allocate(...)' always throws bad_alloc. +// D) 'M.deallocate(...)' does nothing. +// E) 'M' only compares equal to itself. 'M.is_equal(Other)' will not invoke +// 'Other.is_equal(M)'. +// F) 'null_memory_resource()' is marked noexcept. +// +// Plan: +// 1) Check concerns A, B and E by getting two pointers 'p1' and 'p2' from +// calling 'null_memory_resource()' twice. Check that these pointers +// have the same address and are not null. +// +// 2) Check concern C by calling 'M.alloc(...)' for a couple of different +// sizes and alignments. Check that 'bad_alloc' is always thrown. +// +// 3) Check concern D by calling 'M.deallocate(...)' for various pointers, +// sizes and alignment. Make sure nothing happens (???) +// +// 4) Check concern E by comparing 'M' to other 'memory_resource' objects +// with different base classes. Check that 'M.is_equal(Other)' is always +// false and it does not invoke 'Other.is_equal(M)'. +// +// 5) Check concern F by calling 'null_memory_resource()' inside a noexcept +// expression and check that the expression returns true. + +#include +#include + +#include "test_memory_resource.hpp" + +using namespace std::experimental::pmr; + +void checkThrows(memory_resource& M, size_t size, size_t align) { + try { + M.allocate(size, align); + assert(false); + } catch (std::bad_alloc const&) { + // do nothing + } catch (...) { + assert(false); + } + try { + M.allocate(size); + assert(false); + } catch (std::bad_alloc const&) { + // do nothing + } catch (...) { + assert(false); + } +} + +int main() +{ + { // Plan Part 1 + memory_resource* p1 = null_memory_resource(); + assert(p1 != nullptr); + assert(p1->is_equal(*p1)); + + memory_resource* p2 = null_memory_resource(); + assert(p2 != nullptr); + assert(p1 == p2); + assert(p1->is_equal(*p2)); + assert(p2->is_equal(*p1)); + } + { // Plan part 2 + memory_resource& M = *null_memory_resource(); + checkThrows(M, 100, 16); + checkThrows(M, 0, 0); + checkThrows(M, (size_t)-1, (size_t)-1); + } + { // Plan part 3 + memory_resource& M = *null_memory_resource(); + // Test zero values. + M.deallocate(nullptr, 0, 0); + M.deallocate(reinterpret_cast(42), 0, 0); + M.deallocate(nullptr, 100, 16); + M.deallocate(reinterpret_cast(42), 100, 16); + M.deallocate(nullptr, (size_t)-1, (size_t)-1); + M.deallocate(reinterpret_cast(42), (size_t)-1, (size_t)-1); + } + { // Plan part 4 + memory_resource const& M = *null_memory_resource(); + TestResource R; + auto& P = R.getProvider(); + memory_resource const& O = R; + + assert(M.is_equal(O) == false); + assert(P.checkIsEqualCalledEq(0)); + } + { // Plan part 5 + static_assert( + noexcept(null_memory_resource()) + , "null_memory_resource() must be noexcept" + ); + } +} Index: test/std/experimental/memory/memory.resource.synop/nothing_to_do.pass.cpp =================================================================== --- /dev/null +++ test/std/experimental/memory/memory.resource.synop/nothing_to_do.pass.cpp @@ -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() +{ +} Index: test/std/experimental/memory/memory.resource/construct.fail.cpp =================================================================== --- /dev/null +++ test/std/experimental/memory/memory.resource/construct.fail.cpp @@ -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. +// +//===----------------------------------------------------------------------===// + +// + +// Check that memory_resource is not constructible because it is a abstract +// class. + +#include + +namespace ex = std::experimental::pmr; + +int main() +{ + ex::memory_resource m; // expected-error {{variable type 'ex::memory_resource' is an abstract class}} + // expected-note@experimental/memory_resource:* {{unimplemented pure virtual method 'do_allocate' in 'memory_resource'}} + // expected-note@experimental/memory_resource:* {{unimplemented pure virtual method 'do_deallocate' in 'memory_resource'}} + // expected-note@experimental/memory_resource:* {{unimplemented pure virtual method 'do_is_equal' in 'memory_resource'}} +} Index: test/std/experimental/memory/memory.resource/memory.resource.eq/equality.pass.cpp =================================================================== --- /dev/null +++ test/std/experimental/memory/memory.resource/memory.resource.eq/equality.pass.cpp @@ -0,0 +1,126 @@ +//===----------------------------------------------------------------------===// +// +// 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 + +//------------------------------------------------------------------------------ +// TESTING bool operator==(memory_resource const&, memory_resource const&) noexcept; +// bool operator!=(memory_resource const&, memory_resource const&) noexcept; +// +// Concerns: +// A) The equality operators are properly marked noexcept. +// B) The equality operators do not call `is_equal` if '&LHS == &RHS'. +// C) The equality operators call 'LHS.is_equal(RHS)' if '&LHS != &RHS'. +// +// Plan: +// 1) Check concern A by calling the equality operators within a noexcept +// expression. Assert that the operators are marked noexcept. +// +// 2) Check concern B by calling the equality operators with the same object +// on both sides. Assert that the objects are "equal" and that 'is_equal' +// is never called. +// +// 3) Check concern C by calling the equality operators with different and +// UNEQUAL objects on either side. Assert that 'is_equal' is called on the +// LHS object and not the RHS object. Assert that the objects don't compare equal. +// +// 4) Check concern C by calling the equality operators with different and +// EQUAL objects on either side. Assert that 'is_equal' is called on the +// LHS object and not the RHS object. Assert that the objects compare equal. + + +#include +#include +#include + +#include "test_memory_resource.hpp" + +using std::experimental::pmr::memory_resource; + +int main() +{ + // Plan Part 1 + { + memory_resource const* r1 = nullptr; + memory_resource const* r2 = nullptr; + static_assert( + noexcept(*r1 == *r2) + , "operator==(...) must be noexcept" + ); + static_assert( + noexcept(*r1 != *r2) + , "operator!=(...) must be noexcept" + ); + } + // Plan Part 2 + { + TestResource1 R1(1); + auto& P1 = R1.getProvider(); + memory_resource const& M1 = R1; + memory_resource const& M2 = R1; + + assert(M1 == M2); + assert((M1 != M2) == false); + assert(P1.checkIsEqualCalledEq(0)); + } + // Plan Part 3 + { + TestResource1 R1(1); + auto& P1 = R1.getProvider(); + memory_resource const& M1 = R1; + + TestResource1 R2(2); + auto& P2 = R2.getProvider(); + memory_resource const& M2 = R2; + + assert((M1 == M2) == false); + assert(P1.checkIsEqualCalledEq(1)); + assert(P2.checkIsEqualCalledEq(0)); + + assert(M1 != M2); + assert(P1.checkIsEqualCalledEq(2)); + assert(P2.checkIsEqualCalledEq(0)); + + assert((M2 == M1) == false); + assert(P1.checkIsEqualCalledEq(2)); + assert(P2.checkIsEqualCalledEq(1)); + + assert(M2 != M1); + assert(P1.checkIsEqualCalledEq(2)); + assert(P2.checkIsEqualCalledEq(2)); + } + // Plan Part 4 + { + TestResource1 R1(1); + auto& P1 = R1.getProvider(); + memory_resource const& M1 = R1; + + TestResource1 R2(1); + auto& P2 = R2.getProvider(); + memory_resource const& M2 = R2; + + assert(M1 == M2); + assert(P1.checkIsEqualCalledEq(1)); + assert(P2.checkIsEqualCalledEq(0)); + + assert((M1 != M2) == false); + assert(P1.checkIsEqualCalledEq(2)); + assert(P2.checkIsEqualCalledEq(0)); + + assert(M2 == M1); + assert(P1.checkIsEqualCalledEq(2)); + assert(P2.checkIsEqualCalledEq(1)); + + assert((M2 != M1) == false); + assert(P1.checkIsEqualCalledEq(2)); + assert(P2.checkIsEqualCalledEq(2)); + } +} Index: test/std/experimental/memory/memory.resource/memory.resource.overview/nothing_to_do.pass.cpp =================================================================== --- /dev/null +++ test/std/experimental/memory/memory.resource/memory.resource.overview/nothing_to_do.pass.cpp @@ -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 () {} Index: test/std/experimental/memory/memory.resource/memory.resource.priv/tested_elsewhere.pass.cpp =================================================================== --- /dev/null +++ test/std/experimental/memory/memory.resource/memory.resource.priv/tested_elsewhere.pass.cpp @@ -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 () {} Index: test/std/experimental/memory/memory.resource/memory.resource.public/allocate.pass.cpp =================================================================== --- /dev/null +++ test/std/experimental/memory/memory.resource/memory.resource.public/allocate.pass.cpp @@ -0,0 +1,107 @@ +//===----------------------------------------------------------------------===// +// +// 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 + +//------------------------------------------------------------------------------ +// 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. +// +// Plan: +// 1) Check concerns A and B by calling 'allocate' within a decltype expression +// and check that the return type is 'void*'. +// +// 2) Check concerns A and C by calling 'allocate' within a noexcept expression +// and check that the expression is not noexcept. +// +// 3) Check concern A and C by creating a pointer, 'res', of type +// 'memory_resource' which points to an instance of 'TestResource'. +// +// 3a) Allocate memory of size 's' and alignment 'a' using 'res.allocate(s, a)' +// and store it into a pointer 'p'. Check that 'TestResource::do_allocate' +// was called with 's' and 'a' and that it returned 'p'. +// +// 3c) Allocate memory of size 's' using 'res->allocate(s)' without +// specifying alignment and store it into pointer 'p'. Check that +// 'TestResource::do_allocate' was called with 's' and +// the max alignment and returned 'p'. +// +// 4) Check concern E by creating a 'memory_resource' pointer 'p1' which points +// to an object of type 'AllocThrowsResource'. Call 'p1->allocate(...)' and +// check that the expected exception is thrown through 'allocate'. + + +#include +#include +#include + +#include "test_memory_resource.hpp" + +using std::experimental::pmr::memory_resource; + +int main() +{ + TestResource R(42); + auto& P = R.getProvider(); + memory_resource& M = R; + { + static_assert( + std::is_same::value + , "Must be void*" + ); + static_assert( + std::is_same::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)); + } + { + AllocThrowsResource R2; + memory_resource& M2 = R2; + try { + M2.allocate(42); + assert(false); + } catch (TestException const&) { + // do nothing. + } catch (...) { + assert(false); + } + } +} Index: test/std/experimental/memory/memory.resource/memory.resource.public/deallocate.pass.cpp =================================================================== --- /dev/null +++ test/std/experimental/memory/memory.resource/memory.resource.public/deallocate.pass.cpp @@ -0,0 +1,90 @@ +//===----------------------------------------------------------------------===// +// +// 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 + +//------------------------------------------------------------------------------ +// 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. +// +// Plan: +// 1) Check concerns A and B by calling 'deallocate' within a decltype expression +// and check that the return type is 'void'. +// +// 2) Check concerns A and C by calling 'deallocate' within a noexcept expression +// and check that the expression is not noexcept. +// +// 3) Check concern A and C by creating a pointer, 'res', of type +// 'memory_resource' which points to an instance of 'TestResource'. +// +// 3a) Call 'res->deallocate(p, s, a)' for some 'p', 's' and 'a'. Check that +// 'NullResource::do_deallocate' was called with the same arguments. +// +// 3b) Call 'res->deallocate(p, s)' for some 'p' and 's'. Check that +// 'NullResource::do_deallocate' was called with the same arguments +// and an alignment of 'MaxAlignV' + + +#include +#include +#include + +#include "test_memory_resource.hpp" + +using std::experimental::pmr::memory_resource; + +int main() +{ + NullResource R(42); + auto& P = R.getProvider(); + memory_resource& M = R; + { + static_assert( + std::is_same::value + , "Must be void" + ); + static_assert( + std::is_same::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(640); + M.deallocate(p, s, a); + assert(P.dealloc_count == 1); + assert(P.checkDealloc(p, s, a)); + + s = 128; + a = MaxAlignV; + p = reinterpret_cast(12800); + M.deallocate(p, s); + assert(P.dealloc_count == 2); + assert(P.checkDealloc(p, s, a)); + } +} Index: test/std/experimental/memory/memory.resource/memory.resource.public/dtor.pass.cpp =================================================================== --- /dev/null +++ test/std/experimental/memory/memory.resource/memory.resource.public/dtor.pass.cpp @@ -0,0 +1,68 @@ +//===----------------------------------------------------------------------===// +// +// 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 + +//------------------------------------------------------------------------------ +// TESTING virtual ~memory_resource() +// +// Concerns: +// A) 'memory_resource' is destructible. +// B) The destructor is implicitly marked noexcept. +// C) The destructor is marked virtual. +// +// Plan: +// 1) Use type traits to check concerns A, B and C. +// +// 2) To check concerns A and C at runtime dynamically create an object of +// a type that is derived from 'memory_resource'. Then delete that object +// using a pointer to 'memory_resource' and ensure that the derived classes +// destructor was invoked. + + +#include +#include +#include + +#include "test_memory_resource.hpp" + +using std::experimental::pmr::memory_resource; + +int main() +{ + static_assert( + std::has_virtual_destructor::value + , "Must have virtual destructor" + ); + static_assert( + std::is_nothrow_destructible::value, + "Must be nothrow destructible" + ); + static_assert( + std::is_abstract::value + , "Must be abstract" + ); + // Check that the destructor of `TestResource` is called when + // it is deleted as a pointer to `memory_resource` + { + using RT = TestResource; + memory_resource* M = new RT(42); + assert(RT::resource_alive == 1); + assert(RT::resource_constructed == 1); + assert(RT::resource_destructed == 0); + + delete M; + + assert(RT::resource_alive == 0); + assert(RT::resource_constructed == 1); + assert(RT::resource_destructed == 1); + } +} Index: test/std/experimental/memory/memory.resource/memory.resource.public/is_equal.pass.cpp =================================================================== --- /dev/null +++ test/std/experimental/memory/memory.resource/memory.resource.public/is_equal.pass.cpp @@ -0,0 +1,119 @@ +//===----------------------------------------------------------------------===// +// +// 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 + +//------------------------------------------------------------------------------ +// 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. +// +// Plan: +// 1) Check A and B by calling 'is_equal' within a noexcept expression and +// asserting that the expression is noexcept. +// +// 2) For two different types 'T1' and 'T2' that derive from 'memory_resource' +// create objects of those types 't1' and 't2'. Create 'memory_resource' +// pointers, 'p1' and 'p2' from 't1' and 't2'. +// +// 2a) Check that 'p1.is_equal(p2)' returns false and calls only 'p1.do_is_equal(p2)'. +// Check that 'p2.is_equal(p1)' returns false and calls only 'p2.do_is_equal(p1)'. +// +// 3) For a type 'T' that derives from 'memory_resource' create objects 't1' +// and 't2' with different values so that they will not compare equal. +// Create 'memory_resource' pointers 'p1' and 'p2' from 't1' and 't2'. +// +// 3a) Check that 'p1.is_equal(p2)' returns false and calls only 'p1.do_is_equal(p2)'. +// Check that 'p2.is_equal(p1)' returns false and calls only 'p2.do_is_equal(p1)'. +// +// 4) For a type 'T' that derives from 'memory_resource' create objects 't1' +// and 't2' with the same values so that they will compare equal. +// Create 'memory_resource' pointers 'p1' and 'p2' from 't1' and 't2'. +// +// 4a) Check that 'p1.is_equal(p2)' returns true and calls only 'p1.do_is_equal(p2)'. +// Check that 'p2.is_equal(p1)' returns true and calls only 'p2.do_is_equal(p1)'. + + +#include +#include +#include +#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.getProvider(); + memory_resource const& M1 = R1; + + TestResource2 R2(1); + auto& P2 = R2.getProvider(); + 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.getProvider(); + memory_resource const& M1 = R1; + + TestResource1 R2(2); + auto& P2 = R2.getProvider(); + 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.getProvider(); + memory_resource const& M1 = R1; + + TestResource1 R2(1); + auto& P2 = R2.getProvider(); + 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)); + } +} Index: test/support/test_memory_resource.hpp =================================================================== --- /dev/null +++ test/support/test_memory_resource.hpp @@ -0,0 +1,296 @@ +//===----------------------------------------------------------------------===// +// +// 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 +#include +#include +#include +#include +#include + +#define DISALLOW_COPY(Type) \ + Type(Type const&) = delete; \ + Type& operator=(Type const&) = delete + +constexpr size_t MaxAlignV = std::alignment_of::value; + +struct ResourceCounter { + 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; + + ResourceCounter() {} + + 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; + } + + bool checkAlloc(void* p, size_t s, size_t a = MaxAlignV) const { + return p == last_alloc_pointer && + s == last_alloc_size && + a == last_alloc_align; + } + + 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; + } + + bool checkDealloc(void* p, size_t s, size_t a = MaxAlignV) const { + return p == last_dealloc_pointer && + s == last_dealloc_size && + a == last_dealloc_align; + } + + void countIsEqual() { + ++is_equal_count; + } + + bool checkIsEqualCalledEq(int n) const { + return is_equal_count == n; + } + + void reset() { + std::memset(this, 0, sizeof(*this)); + } + +private: + DISALLOW_COPY(ResourceCounter); +}; + +struct NullProvider : ResourceCounter { + + NullProvider() {} + + void* allocate(size_t s, size_t a) { + countAlloc(nullptr, s, a); + return nullptr; + } + + void deallocate(void* p, size_t s, size_t a) { + countDealloc(p, s, a); + } + + void reset() { + ResourceCounter::reset(); + } + +private: + DISALLOW_COPY(NullProvider); +}; + +struct MallocProvider : ResourceCounter { + + MallocProvider() {} + + void* allocate(size_t s, size_t a) { + void* p = std::malloc(s); + countAlloc(p, s, a); + return p; + } + + void deallocate(void* p, size_t s, size_t a) { + countDealloc(p, s, a); + std::free(p); + } + + void reset() { + ResourceCounter::reset(); + } +private: + DISALLOW_COPY(MallocProvider); +}; + +struct NewDeleteProvider : ResourceCounter { + NewDeleteProvider() {} + + void* allocate(size_t s, size_t a) { + void* p = ::operator new(s); + countAlloc(p, s, a); + return p; + } + + void deallocate(void* p, size_t s, size_t a) { + countDealloc(p, s, a); + ::operator delete(p); + } + + void reset() { + ResourceCounter::reset(); + } +private: + DISALLOW_COPY(NewDeleteProvider); +}; + +template // 10 pages worth of memory. +struct BufferProvider : ResourceCounter { + 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); + countAlloc(ret, s, a); + if (ret == nullptr) throw std::bad_alloc(); + return ret; + } + + void deallocate(void* p, size_t s, size_t a) { + countDealloc(p, s, a); + } + + void reset() { + next = &buffer; + space = Size; + ResourceCounter::reset(); + } +private: + DISALLOW_COPY(BufferProvider); +}; + +struct TestException {}; + +struct AllocThrowsProvider : ResourceCounter { + + AllocThrowsProvider() {} + + void* allocate(size_t s, size_t a) { + throw TestException(); + } + + void deallocate(void* p, size_t s, size_t a) { + countDealloc(p, s, a); + } + + void reset() { + ResourceCounter::reset(); + } + +private: + DISALLOW_COPY(AllocThrowsProvider); +}; + +template +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() { P.reset(); } + Provider& getProvider() { return P; } + +protected: + virtual void * do_allocate(std::size_t s, std::size_t a) { + return P.allocate(s, a); + } + + virtual void do_deallocate(void * p, std::size_t s, std::size_t a) { + P.deallocate(p, s, a); + } + + virtual bool do_is_equal(memory_resource const & other) const noexcept { + P.countIsEqual(); + TestResourceImp const * o = dynamic_cast(&other); + return o && o->value == value; + } +private: + mutable Provider P; + DISALLOW_COPY(TestResourceImp); +}; + +template +int TestResourceImp::resource_alive = 0; + +template +int TestResourceImp::resource_constructed = 0; + +template +int TestResourceImp::resource_destructed = 0; + +using NullResource = TestResourceImp; +using NullResource1 = TestResourceImp; +using NullResource2 = TestResourceImp; + +using MallocResource = TestResourceImp; +using MallocResource1 = TestResourceImp; +using MallocResource2 = TestResourceImp; + +using NewDeleteResource = TestResourceImp; +using NewDeleteResource1 = TestResourceImp; +using NewDeleteResource2 = TestResourceImp; + +using BufferResource = TestResourceImp, 0>; +using BufferResource1 = TestResourceImp, 1>; +using BufferResource2 = TestResourceImp, 2>; + +using TestResource = BufferResource; +using TestResource1 = BufferResource1; +using TestResource2 = BufferResource2; + +using AllocThrowsResource = TestResourceImp; + + +#endif /* SUPPORT_TEST_MEMORY_RESOURCE_HPP */