Commit 09a33a57 authored by Mark Santaniello's avatar Mark Santaniello Committed by Facebook GitHub Bot

Eliminate lift_void_to_char

Summary:
`std::allocator<void>::allocate` is not invocable as policy. Let folly allocators behave the same.

Switch existing sites to parameterizing the allocators over `char` instead, since `std::allocator<char>::allocate` is invocable.

Reviewed By: yfeldblum

Differential Revision: D22986960

fbshipit-source-id: ca1ff3cb1785029b6b6f59ddc4046b1b105d8bd6
parent efe2962d
......@@ -76,7 +76,8 @@ class SkipListNode {
size_t size = sizeof(SkipListNode) +
node->height_ * sizeof(std::atomic<SkipListNode*>);
node->~SkipListNode();
std::allocator_traits<NodeAlloc>::deallocate(alloc, node, size);
std::allocator_traits<NodeAlloc>::deallocate(
alloc, typename std::allocator_traits<NodeAlloc>::pointer(node), size);
}
template <typename NodeAlloc>
......
......@@ -140,7 +140,7 @@ template <
typename Comp = std::less<T>,
// All nodes are allocated using provided SysAllocator,
// it should be thread-safe.
typename NodeAlloc = SysAllocator<void>,
typename NodeAlloc = SysAllocator<char>,
int MAX_HEIGHT = 24>
class ConcurrentSkipList {
// MAX_HEIGHT needs to be at least 2 to suppress compiler
......
......@@ -373,17 +373,6 @@ std::shared_ptr<remove_cvref_t<T>> copy_to_shared_ptr(T&& t) {
return std::make_shared<remove_cvref_t<T>>(static_cast<T&&>(t));
}
namespace detail {
template <typename T>
struct lift_void_to_char {
using type = T;
};
template <>
struct lift_void_to_char<void> {
using type = char;
};
} // namespace detail
/**
* SysAllocator
*
......@@ -406,16 +395,14 @@ class SysAllocator {
constexpr SysAllocator(SysAllocator<U> const&) noexcept {}
T* allocate(size_t count) {
using lifted = typename detail::lift_void_to_char<T>::type;
auto const p = std::malloc(sizeof(lifted) * count);
auto const p = std::malloc(sizeof(T) * count);
if (!p) {
throw_exception<std::bad_alloc>();
}
return static_cast<T*>(p);
}
void deallocate(T* p, size_t count) {
using lifted = typename detail::lift_void_to_char<T>::type;
sizedFree(p, count * sizeof(lifted));
sizedFree(p, count * sizeof(T));
}
friend bool operator==(Self const&, Self const&) noexcept {
......@@ -522,9 +509,8 @@ class AlignedSysAllocator : private Align {
: Align(other.align()) {}
T* allocate(size_t count) {
using lifted = typename detail::lift_void_to_char<T>::type;
auto const a = align()() < alignof(lifted) ? alignof(lifted) : align()();
auto const p = aligned_malloc(sizeof(lifted) * count, a);
auto const a = align()() < alignof(T) ? alignof(T) : align()();
auto const p = aligned_malloc(sizeof(T) * count, a);
if (!p) {
if (FOLLY_UNLIKELY(errno != ENOMEM)) {
std::terminate();
......@@ -584,16 +570,14 @@ class CxxAllocatorAdaptor {
: inner_(other.inner_) {}
T* allocate(std::size_t n) {
using lifted = typename detail::lift_void_to_char<T>::type;
if (inner_ == nullptr) {
throw_exception<std::bad_alloc>();
}
return static_cast<T*>(inner_->allocate(sizeof(lifted) * n));
return static_cast<T*>(inner_->allocate(sizeof(T) * n));
}
void deallocate(T* p, std::size_t n) {
using lifted = typename detail::lift_void_to_char<T>::type;
assert(inner_);
inner_->deallocate(p, sizeof(lifted) * n);
inner_->deallocate(p, sizeof(T) * n);
}
friend bool operator==(Self const& a, Self const& b) noexcept {
......
......@@ -153,7 +153,8 @@ class Arena {
Arena& operator=(Arena&&) = delete;
private:
using AllocTraits = std::allocator_traits<Alloc>;
using AllocTraits =
typename std::allocator_traits<Alloc>::template rebind_traits<char>;
using BlockLink = boost::intrusive::slist_member_hook<>;
struct alignas(max_align_v) Block {
......@@ -199,7 +200,8 @@ class Arena {
void freeBlocks() {
blocks_.clear_and_dispose([this](Block* b) {
b->~Block();
AllocTraits::deallocate(alloc(), b, blockGoodAllocSize());
AllocTraits::deallocate(
alloc(), reinterpret_cast<char*>(b), blockGoodAllocSize());
});
}
......@@ -207,7 +209,7 @@ class Arena {
largeBlocks_.clear_and_dispose([this](LargeBlock* b) {
auto size = b->allocSize;
b->~LargeBlock();
AllocTraits::deallocate(alloc(), b, size);
AllocTraits::deallocate(alloc(), reinterpret_cast<char*>(b), size);
});
}
......@@ -298,8 +300,8 @@ struct ArenaAllocatorTraits {
};
template <>
struct ArenaAllocatorTraits<SysAllocator<void>> {
static size_t goodSize(const SysAllocator<void>& /* alloc */, size_t size) {
struct ArenaAllocatorTraits<SysAllocator<char>> {
static size_t goodSize(const SysAllocator<char>& /* alloc */, size_t size) {
return goodMallocSize(size);
}
};
......@@ -307,13 +309,13 @@ struct ArenaAllocatorTraits<SysAllocator<void>> {
/**
* Arena that uses the system allocator (malloc / free)
*/
class SysArena : public Arena<SysAllocator<void>> {
class SysArena : public Arena<SysAllocator<char>> {
public:
explicit SysArena(
size_t minBlockSize = kDefaultMinBlockSize,
size_t sizeLimit = kNoSizeLimit,
size_t maxAlign = kDefaultMaxAlign)
: Arena<SysAllocator<void>>({}, minBlockSize, sizeLimit, maxAlign) {}
: Arena<SysAllocator<char>>({}, minBlockSize, sizeLimit, maxAlign) {}
};
template <>
......@@ -323,7 +325,7 @@ template <typename T, typename Alloc>
using ArenaAllocator = CxxAllocatorAdaptor<T, Arena<Alloc>>;
template <typename T>
using SysArenaAllocator = ArenaAllocator<T, SysAllocator<void>>;
using SysArenaAllocator = ArenaAllocator<T, SysAllocator<char>>;
} // namespace folly
......
......@@ -52,7 +52,7 @@ struct ParanoidArenaAlloc {
return result;
}
void deallocate(void* ptr, size_t n) {
void deallocate(char* ptr, size_t n) {
EXPECT_EQ(1, allocated_.erase(ptr));
arena_.get().deallocate(ptr, n);
}
......@@ -474,7 +474,7 @@ void TestNonTrivialDeallocation(SkipListPtrType& list) {
template <typename ParentAlloc>
void NonTrivialDeallocationWithParanoid(ParentAlloc& parentAlloc) {
using ParanoidAlloc = ParanoidArenaAlloc<ParentAlloc>;
using Alloc = CxxAllocatorAdaptor<void, ParanoidAlloc>;
using Alloc = CxxAllocatorAdaptor<char, ParanoidAlloc>;
using ParanoidSkipListType =
ConcurrentSkipList<NonTrivialValue, std::less<NonTrivialValue>, Alloc>;
ParanoidAlloc paranoidAlloc(parentAlloc);
......@@ -485,13 +485,13 @@ void NonTrivialDeallocationWithParanoid(ParentAlloc& parentAlloc) {
}
TEST(ConcurrentSkipList, NonTrivialDeallocationWithParanoidSysAlloc) {
SysAllocator<void> alloc;
SysAllocator<char> alloc;
NonTrivialDeallocationWithParanoid(alloc);
}
TEST(ConcurrentSkipList, NonTrivialDeallocationWithParanoidSysArena) {
SysArena arena;
SysArenaAllocator<void> alloc(arena);
SysArenaAllocator<char> alloc(arena);
NonTrivialDeallocationWithParanoid(alloc);
}
......@@ -499,9 +499,9 @@ TEST(ConcurrentSkipList, NonTrivialDeallocationWithSysArena) {
using SysArenaSkipListType = ConcurrentSkipList<
NonTrivialValue,
std::less<NonTrivialValue>,
SysArenaAllocator<void>>;
SysArenaAllocator<char>>;
SysArena arena;
SysArenaAllocator<void> alloc(arena);
SysArenaAllocator<char> alloc(arena);
auto list = SysArenaSkipListType::createInstance(10, alloc);
TestNonTrivialDeallocation(list);
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment