upd: [pmr] helper trait for allocator

This commit is contained in:
mutouyun 2022-11-14 21:32:00 +08:00
parent efe1fe61dd
commit a392b88787
6 changed files with 49 additions and 9 deletions

View File

@ -31,7 +31,7 @@
LIBIMP_NAMESPACE_BEG_ LIBIMP_NAMESPACE_BEG_
namespace detail { namespace detail {
/// @brief helper trait for span /// @brief Helper trait for span.
template <typename From, typename To> template <typename From, typename To>
using array_convertible = std::is_convertible<From(*)[], To(*)[]>; using array_convertible = std::is_convertible<From(*)[], To(*)[]>;

View File

@ -6,10 +6,37 @@
*/ */
#pragma once #pragma once
#include <type_traits>
#include "libimp/export.h"
#include "libpmr/def.h" #include "libpmr/def.h"
#include "libpmr/memory_resource.h" #include "libpmr/memory_resource.h"
LIBPMR_NAMESPACE_BEG_ LIBPMR_NAMESPACE_BEG_
namespace detail {
/// @brief Helper trait for allocator.
template <typename T, typename = void>
struct has_allocate : std::false_type {};
template <typename T>
struct has_allocate<T,
typename std::enable_if<std::is_convertible<
decltype(std::declval<T &>().allocate(std::declval<std::size_t>())), void *
>::value>::type> : std::true_type {};
template <typename T, typename = void>
struct has_deallocate : std::false_type {};
template <typename T>
struct has_deallocate<T,
decltype(std::declval<T &>().deallocate(std::declval<void *>(),
std::declval<std::size_t>()))
> : std::true_type {};
} // namespace detail
/** /**
* @brief An allocator which exhibits different allocation behavior * @brief An allocator which exhibits different allocation behavior
@ -23,6 +50,8 @@ LIBPMR_NAMESPACE_BEG_
* @see https://en.cppreference.com/w/cpp/memory/memory_resource * @see https://en.cppreference.com/w/cpp/memory/memory_resource
* https://en.cppreference.com/w/cpp/memory/polymorphic_allocator * https://en.cppreference.com/w/cpp/memory/polymorphic_allocator
*/ */
class LIBIMP_EXPORT allocator {
};
LIBPMR_NAMESPACE_END_ LIBPMR_NAMESPACE_END_

View File

@ -6,7 +6,7 @@
*/ */
#pragma once #pragma once
#include <cstddef> // std::size_t #include <cstddef> // std::size_t, std::max_align_t
#include "libimp/export.h" #include "libimp/export.h"
#include "libpmr/def.h" #include "libpmr/def.h"
@ -24,11 +24,11 @@ public:
/// @brief Allocates storage with a size of at least bytes bytes, aligned to the specified alignment. /// @brief Allocates storage with a size of at least bytes bytes, aligned to the specified alignment.
/// @remark Returns nullptr if storage of the requested size and alignment cannot be obtained. /// @remark Returns nullptr if storage of the requested size and alignment cannot be obtained.
/// @see https://en.cppreference.com/w/cpp/memory/memory_resource/do_allocate /// @see https://en.cppreference.com/w/cpp/memory/memory_resource/do_allocate
void *do_allocate(std::size_t bytes, std::size_t alignment) noexcept; void *allocate(std::size_t bytes, std::size_t alignment = alignof(std::max_align_t)) noexcept;
/// @brief Deallocates the storage pointed to by p. /// @brief Deallocates the storage pointed to by p.
/// @see https://en.cppreference.com/w/cpp/memory/memory_resource/deallocate /// @see https://en.cppreference.com/w/cpp/memory/memory_resource/deallocate
void do_deallocate(void* p, std::size_t bytes, std::size_t alignment) noexcept; void deallocate(void *p, std::size_t bytes, std::size_t alignment = alignof(std::max_align_t)) noexcept;
}; };
LIBPMR_NAMESPACE_END_ LIBPMR_NAMESPACE_END_

View File

@ -1,6 +1,5 @@
#include <cstdlib> // std::aligned_alloc #include <cstdlib> // std::aligned_alloc
#include <cstddef> // std::max_align_t
#include <exception> #include <exception>
#include "libimp/detect_plat.h" #include "libimp/detect_plat.h"
@ -37,7 +36,7 @@ bool verify_args(::LIBIMP_::log::gripper &log, std::size_t bytes, std::size_t al
* *
* @return void * - nullptr if storage of the requested size and alignment cannot be obtained. * @return void * - nullptr if storage of the requested size and alignment cannot be obtained.
*/ */
void *new_delete_resource::do_allocate(std::size_t bytes, std::size_t alignment) noexcept { void *new_delete_resource::allocate(std::size_t bytes, std::size_t alignment) noexcept {
LIBIMP_LOG_(); LIBIMP_LOG_();
if (!verify_args(log, bytes, alignment)) { if (!verify_args(log, bytes, alignment)) {
return nullptr; return nullptr;
@ -83,7 +82,7 @@ void *new_delete_resource::do_allocate(std::size_t bytes, std::size_t alignment)
* *
* @param p must have been returned by a prior call to new_delete_resource::do_allocate(bytes, alignment). * @param p must have been returned by a prior call to new_delete_resource::do_allocate(bytes, alignment).
*/ */
void new_delete_resource::do_deallocate(void* p, std::size_t bytes, std::size_t alignment) noexcept { void new_delete_resource::deallocate(void *p, std::size_t bytes, std::size_t alignment) noexcept {
LIBIMP_LOG_(); LIBIMP_LOG_();
if (p == nullptr) { if (p == nullptr) {
return; return;

View File

@ -1,7 +1,19 @@
#include <vector>
#include <memory_resource>
#include "gtest/gtest.h" #include "gtest/gtest.h"
#include "libpmr/allocator.h" #include "libpmr/allocator.h"
TEST(allocator, detail) {
EXPECT_FALSE(pmr::detail::has_allocate<void>::value);
EXPECT_FALSE(pmr::detail::has_allocate<int>::value);
EXPECT_FALSE(pmr::detail::has_allocate<std::vector<int>>::value);
EXPECT_TRUE (pmr::detail::has_allocate<std::allocator<int>>::value);
EXPECT_TRUE (pmr::detail::has_allocate<std::pmr::memory_resource>::value);
EXPECT_TRUE (pmr::detail::has_allocate<std::pmr::polymorphic_allocator<int>>::value);
}
TEST(allocator, construct) { TEST(allocator, construct) {
} }

View File

@ -9,13 +9,13 @@ namespace {
template <typename T> template <typename T>
void *test_mr(T &&mr, std::size_t bytes, std::size_t alignment) { void *test_mr(T &&mr, std::size_t bytes, std::size_t alignment) {
auto p = std::forward<T>(mr).do_allocate(bytes, alignment); auto p = std::forward<T>(mr).allocate(bytes, alignment);
if (alignment == 0) { if (alignment == 0) {
EXPECT_EQ(p, nullptr); EXPECT_EQ(p, nullptr);
} else if (p != nullptr) { } else if (p != nullptr) {
EXPECT_EQ((std::size_t)p % alignment, 0); EXPECT_EQ((std::size_t)p % alignment, 0);
} }
std::forward<T>(mr).do_deallocate(p, bytes, alignment); std::forward<T>(mr).deallocate(p, bytes, alignment);
return p; return p;
} }