Skip to content

Commit

Permalink
[libc++] Add the C++17 <memory_resource> header (mono-patch)
Browse files Browse the repository at this point in the history
This patch is the rebase and squash of three earlier patches.
It supersedes all three of them.

- D47111: experimental monotonic_buffer_resource.
- D47358: experimental pool resources.
- D47360: Copy std::experimental::pmr to std::pmr.

The significant difference between this patch and the-sum-of-those-three
is that this patch does not add `std::experimental::pmr::monotonic_buffer_resource`
and so on. This patch simply adds the C++17 standard facilities, and
leaves the `std::experimental` namespace entirely alone.

Differential Revision: https://reviews.llvm.org/D89057
  • Loading branch information
Arthur O'Dwyer authored and ldionne committed Oct 11, 2022
1 parent defe7c0 commit 243da90
Show file tree
Hide file tree
Showing 131 changed files with 7,447 additions and 341 deletions.
2 changes: 1 addition & 1 deletion libcxx/docs/FeatureTestMacroTable.rst
Expand Up @@ -126,7 +126,7 @@ Status
------------------------------------------------- -----------------
``__cpp_lib_math_special_functions`` *unimplemented*
------------------------------------------------- -----------------
``__cpp_lib_memory_resource`` *unimplemented*
``__cpp_lib_memory_resource`` ``201603L``
------------------------------------------------- -----------------
``__cpp_lib_node_extract`` ``201606L``
------------------------------------------------- -----------------
Expand Down
1 change: 1 addition & 0 deletions libcxx/docs/ReleaseNotes.rst
Expand Up @@ -48,6 +48,7 @@ Improvements and New Features
- Declarations of ``std::c8rtomb()`` and ``std::mbrtoc8()`` from P0482R6 are
now provided when implementations in the global namespace are provided by
the C library.
- Implemented ``<memory_resource>`` header from C++17

Deprecations and Removals
-------------------------
Expand Down
7 changes: 7 additions & 0 deletions libcxx/include/CMakeLists.txt
Expand Up @@ -414,6 +414,12 @@ set(files
__memory/uses_allocator.h
__memory/uses_allocator_construction.h
__memory/voidify.h
__memory_resource/memory_resource.h
__memory_resource/monotonic_buffer_resource.h
__memory_resource/polymorphic_allocator.h
__memory_resource/pool_options.h
__memory_resource/synchronized_pool_resource.h
__memory_resource/unsynchronized_pool_resource.h
__mutex_base
__node_handle
__numeric/accumulate.h
Expand Down Expand Up @@ -776,6 +782,7 @@ set(files
map
math.h
memory
memory_resource
mutex
new
numbers
Expand Down
78 changes: 78 additions & 0 deletions libcxx/include/__memory_resource/memory_resource.h
@@ -0,0 +1,78 @@
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#ifndef _LIBCPP___MEMORY_RESOURCE_MEMORY_RESOURCE_H
#define _LIBCPP___MEMORY_RESOURCE_MEMORY_RESOURCE_H

#include <__config>
#include <cstddef>

#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
#endif

#if _LIBCPP_STD_VER > 14

_LIBCPP_BEGIN_NAMESPACE_STD

namespace pmr {

// [mem.res.class]

_LIBCPP_DIAGNOSTIC_PUSH
_LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wweak-vtables") // TODO: move destructor into the dylib
class _LIBCPP_TYPE_VIS memory_resource {
static const size_t __max_align = alignof(max_align_t);

public:
virtual ~memory_resource() = default;

_LIBCPP_HIDE_FROM_ABI void* allocate(size_t __bytes, size_t __align = __max_align) {
return do_allocate(__bytes, __align);
}

_LIBCPP_HIDE_FROM_ABI void deallocate(void* __p, size_t __bytes, size_t __align = __max_align) {
do_deallocate(__p, __bytes, __align);
}

_LIBCPP_HIDE_FROM_ABI bool is_equal(const memory_resource& __other) const noexcept { return do_is_equal(__other); }

private:
virtual void* do_allocate(size_t, size_t) = 0;
virtual void do_deallocate(void*, size_t, size_t) = 0;
virtual bool do_is_equal(memory_resource const&) const noexcept = 0;
};
_LIBCPP_DIAGNOSTIC_POP

// [mem.res.eq]

inline _LIBCPP_HIDE_FROM_ABI bool operator==(const memory_resource& __lhs, const memory_resource& __rhs) noexcept {
return &__lhs == &__rhs || __lhs.is_equal(__rhs);
}

inline _LIBCPP_HIDE_FROM_ABI bool operator!=(const memory_resource& __lhs, const memory_resource& __rhs) noexcept {
return !(__lhs == __rhs);
}

// [mem.res.global]

_LIBCPP_FUNC_VIS memory_resource* get_default_resource() noexcept;

_LIBCPP_FUNC_VIS memory_resource* set_default_resource(memory_resource*) noexcept;

_LIBCPP_FUNC_VIS memory_resource* new_delete_resource() noexcept;

_LIBCPP_FUNC_VIS memory_resource* null_memory_resource() noexcept;

} // namespace pmr

_LIBCPP_END_NAMESPACE_STD

#endif // _LIBCPP_STD_VER > 14

#endif // _LIBCPP___MEMORY_RESOURCE_MEMORY_RESOURCE_H
119 changes: 119 additions & 0 deletions libcxx/include/__memory_resource/monotonic_buffer_resource.h
@@ -0,0 +1,119 @@
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#ifndef _LIBCPP___MEMORY_RESOURCE_MONOTONIC_BUFFER_RESOURCE_H
#define _LIBCPP___MEMORY_RESOURCE_MONOTONIC_BUFFER_RESOURCE_H

#include <__config>
#include <__memory/addressof.h>
#include <__memory_resource/memory_resource.h>
#include <cstddef>

#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
#endif

#if _LIBCPP_STD_VER > 14

_LIBCPP_BEGIN_NAMESPACE_STD

namespace pmr {

// [mem.res.monotonic.buffer]

class _LIBCPP_TYPE_VIS monotonic_buffer_resource : public memory_resource {
static const size_t __default_buffer_capacity = 1024;
static const size_t __default_buffer_alignment = 16;

struct __chunk_footer {
__chunk_footer* __next_;
char* __start_;
char* __cur_;
size_t __align_;
size_t __allocation_size() { return (reinterpret_cast<char*>(this) - __start_) + sizeof(*this); }
void* __try_allocate_from_chunk(size_t, size_t);
};

struct __initial_descriptor {
char* __start_;
char* __cur_;
union {
char* __end_;
size_t __size_;
};
void* __try_allocate_from_chunk(size_t, size_t);
};

public:
_LIBCPP_HIDE_FROM_ABI monotonic_buffer_resource()
: monotonic_buffer_resource(nullptr, __default_buffer_capacity, get_default_resource()) {}

_LIBCPP_HIDE_FROM_ABI explicit monotonic_buffer_resource(size_t __initial_size)
: monotonic_buffer_resource(nullptr, __initial_size, get_default_resource()) {}

_LIBCPP_HIDE_FROM_ABI monotonic_buffer_resource(void* __buffer, size_t __buffer_size)
: monotonic_buffer_resource(__buffer, __buffer_size, get_default_resource()) {}

_LIBCPP_HIDE_FROM_ABI explicit monotonic_buffer_resource(memory_resource* __upstream)
: monotonic_buffer_resource(nullptr, __default_buffer_capacity, __upstream) {}

_LIBCPP_HIDE_FROM_ABI monotonic_buffer_resource(size_t __initial_size, memory_resource* __upstream)
: monotonic_buffer_resource(nullptr, __initial_size, __upstream) {}

_LIBCPP_HIDE_FROM_ABI monotonic_buffer_resource(void* __buffer, size_t __buffer_size, memory_resource* __upstream)
: __res_(__upstream) {
__initial_.__start_ = static_cast<char*>(__buffer);
if (__buffer != nullptr) {
__initial_.__cur_ = static_cast<char*>(__buffer);
__initial_.__end_ = static_cast<char*>(__buffer) + __buffer_size;
} else {
__initial_.__cur_ = nullptr;
__initial_.__size_ = __buffer_size;
}
__chunks_ = nullptr;
}

monotonic_buffer_resource(const monotonic_buffer_resource&) = delete;

_LIBCPP_HIDE_FROM_ABI ~monotonic_buffer_resource() override { release(); }

monotonic_buffer_resource& operator=(const monotonic_buffer_resource&) = delete;

_LIBCPP_HIDE_FROM_ABI void release() {
__initial_.__cur_ = __initial_.__start_;
while (__chunks_ != nullptr) {
__chunk_footer* __next = __chunks_->__next_;
__res_->deallocate(__chunks_->__start_, __chunks_->__allocation_size(), __chunks_->__align_);
__chunks_ = __next;
}
}

_LIBCPP_HIDE_FROM_ABI memory_resource* upstream_resource() const { return __res_; }

protected:
void* do_allocate(size_t __bytes, size_t __alignment) override; // key function

_LIBCPP_HIDE_FROM_ABI void do_deallocate(void*, size_t, size_t) override {}

_LIBCPP_HIDE_FROM_ABI bool do_is_equal(const memory_resource& __other) const _NOEXCEPT override {
return this == std::addressof(__other);
}

private:
__initial_descriptor __initial_;
__chunk_footer* __chunks_;
memory_resource* __res_;
};

} // namespace pmr

_LIBCPP_END_NAMESPACE_STD

#endif // _LIBCPP_STD_VER > 14

#endif // _LIBCPP___MEMORY_RESOURCE_MONOTONIC_BUFFER_RESOURCE_H

0 comments on commit 243da90

Please sign in to comment.