EricWF updated this revision to Diff 30304.
EricWF added a comment.
I changed the lifetime of the global resources. The global resources are no
longer destroyed during program termination. This should prevent issues where
other static destructors require memory resources.
http://reviews.llvm.org/D11397
Files:
include/experimental/__config
include/experimental/__memory
include/experimental/memory_resource
src/memory_resource.cpp
src/support/atomic_support.h
test/libcxx/experimental/memory/memory.resource.synop/version.pass.cpp
test/std/algorithms/alg.sorting/alg.heap.operations/make.heap/make_heap_comp.pass.cpp
test/std/experimental/memory/memory.resource.global/default_resource.pass.cpp
test/std/experimental/memory/memory.resource.global/new_delete_resource.pass.cpp
test/std/experimental/memory/memory.resource.global/null_memory_resource.pass.cpp
test/std/experimental/memory/memory.resource.synop/nothing_to_do.pass.cpp
test/std/experimental/memory/memory.resource/construct.fail.cpp
test/std/experimental/memory/memory.resource/memory.resource.eq/equality.pass.cpp
test/std/experimental/memory/memory.resource/memory.resource.overview/nothing_to_do.pass.cpp
test/std/experimental/memory/memory.resource/memory.resource.priv/tested_elsewhere.pass.cpp
test/std/experimental/memory/memory.resource/memory.resource.public/allocate.pass.cpp
test/std/experimental/memory/memory.resource/memory.resource.public/deallocate.pass.cpp
test/std/experimental/memory/memory.resource/memory.resource.public/dtor.pass.cpp
test/std/experimental/memory/memory.resource/memory.resource.public/is_equal.pass.cpp
test/support/test_memory_resource.hpp
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 <experimental/memory_resource>
+#include <memory>
+#include <type_traits>
+#include <cstddef>
+#include <cstdlib>
+#include <cstring>
+
+#define DISALLOW_COPY(Type) \
+ Type(Type const&) = delete; \
+ Type& operator=(Type const&) = delete
+
+constexpr size_t MaxAlignV = std::alignment_of<std::max_align_t>::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 <size_t Size = 4096 * 10> // 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 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() { 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<TestResourceImp const *>(&other);
+ return o && o->value == value;
+ }
+private:
+ 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;
+
+using NullResource = TestResourceImp<NullProvider, 0>;
+using NullResource1 = TestResourceImp<NullProvider, 1>;
+using NullResource2 = TestResourceImp<NullProvider, 2>;
+
+using MallocResource = TestResourceImp<MallocProvider, 0>;
+using MallocResource1 = TestResourceImp<MallocProvider, 1>;
+using MallocResource2 = TestResourceImp<MallocProvider, 2>;
+
+using NewDeleteResource = TestResourceImp<NewDeleteProvider, 0>;
+using NewDeleteResource1 = TestResourceImp<NewDeleteProvider, 1>;
+using NewDeleteResource2 = TestResourceImp<NewDeleteProvider, 2>;
+
+using BufferResource = TestResourceImp<BufferProvider<>, 0>;
+using BufferResource1 = TestResourceImp<BufferProvider<>, 1>;
+using BufferResource2 = TestResourceImp<BufferProvider<>, 2>;
+
+using TestResource = BufferResource;
+using TestResource1 = BufferResource1;
+using TestResource2 = BufferResource2;
+
+using AllocThrowsResource = TestResourceImp<AllocThrowsProvider, 0>;
+
+
+#endif /* SUPPORT_TEST_MEMORY_RESOURCE_HPP */
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.
+//
+//===----------------------------------------------------------------------===//
+
+// <experimental/memory_resource>
+
+// 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 <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.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/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.
+//
+//===----------------------------------------------------------------------===//
+
+// <experimental/memory_resource>
+
+// 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 <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 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/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.
+//
+//===----------------------------------------------------------------------===//
+
+// <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.
+//
+// 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 <experimental/memory_resource>
+#include <type_traits>
+#include <cassert>
+
+#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<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 = MaxAlignV;
+ p = reinterpret_cast<void*>(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/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.
+//
+//===----------------------------------------------------------------------===//
+
+// <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.
+//
+// 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 <experimental/memory_resource>
+#include <type_traits>
+#include <cassert>
+
+#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<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));
+ }
+ {
+ 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.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.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.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.
+//
+//===----------------------------------------------------------------------===//
+
+// <experimental/memory_resource>
+
+// 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 <experimental/memory_resource>
+#include <type_traits>
+#include <cassert>
+
+#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/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.
+//
+//===----------------------------------------------------------------------===//
+
+// <experimental/memory_resource>
+
+// Check that memory_resource is not constructible because it is a abstract
+// class.
+
+#include <experimental/memory_resource>
+
+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.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.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.
+//
+//===----------------------------------------------------------------------===//
+
+// <experimental/memory_resource>
+
+// 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 <experimental/memory_resource>
+#include <cassert>
+
+#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<void*>(42), 0, 0);
+ M.deallocate(nullptr, 100, 16);
+ M.deallocate(reinterpret_cast<void*>(42), 100, 16);
+ M.deallocate(nullptr, (size_t)-1, (size_t)-1);
+ M.deallocate(reinterpret_cast<void*>(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.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.
+//
+//===----------------------------------------------------------------------===//
+
+// <experimental/memory_resource>
+
+// 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 <experimental/memory_resource>
+#include <cassert>
+
+#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/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.
+//
+//===----------------------------------------------------------------------===//
+
+// <experimental/memory_resource>
+
+// 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 <experimental/memory_resource>
+#include <cassert>
+
+#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/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<int>());
assert(std::is_heap(ia, ia+N, std::greater<int>()));
}
+ }
// Ascending
{
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.
+//
+//===----------------------------------------------------------------------===//
+
+// <experimental/memory_resource>
+
+#include <experimental/memory_resource>
+
+#ifndef _LIBCPP_VERSION
+#error _LIBCPP_VERSION not defined
+#endif
+
+int main()
+{
+}
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 <class _ValueType, class _ValueType2>
+inline _LIBCPP_INLINE_VISIBILITY
+_ValueType __libcpp_atomic_exchange(_ValueType* __val, _ValueType2 __new, int __order = _AO_Seq)
+{
+ return __atomic_exchange_n(__val, __new, __order);
+};
+
template <class _ValueType>
inline _LIBCPP_INLINE_VISIBILITY
bool __libcpp_atomic_compare_exchange(_ValueType* __val,
@@ -119,6 +126,15 @@
return *__val += __a;
}
+template <class _ValueType, class _ValueType2>
+inline _LIBCPP_INLINE_VISIBILITY
+_ValueType __libcpp_atomic_exchange(_ValueType* __val, _ValueType2 __new, int = 0)
+{
+ _ValueType __tmp = *__val;
+ *__val = __new;
+ return __tmp;
+};
+
template <class _ValueType>
inline _LIBCPP_INLINE_VISIBILITY
bool __libcpp_atomic_compare_exchange(_ValueType* __val,
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<memory_resource const *>(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: 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 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 <new>
+#include <cstddef>
+
+#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<max_align_t>::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: 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 <experimental/__config>
+
+#include <cstddef>
+
+#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<size_t>(__p)) & (__a - 1);
+}
+
+_LIBCPP_END_NAMESPACE_LFTS
+
+#endif /* _LIBCPP_EXPERIMENTAL___MEMORY */
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 } } }
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits