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