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

Default constructible folly::SysArenaAllocator

Summary:
Adjust `CxxAllocatorAdaptor` such that it becomes default constructible.  This makes `SysArenaAllocator` default constructible too, which makes it much easier to use.

A default-constructed `SysArenaAllocator` is not useful at all.  Any attempt to allocate just throws `std::bad_alloc`.  But it makes it possible to at least compile code like this:

```
using MyAlloc = SysArenaAllocator<char>;
struct Foo {
   Foo() = default;  // BOOM
   Foo(MyAlloc &a) : v(a) {};
   vector<int, MyAlloc> v;
}
```

Reviewed By: yfeldblum

Differential Revision: D21967640

fbshipit-source-id: 5b74c6db14d75364b374cad71d0069b17769e5d6
parent d72d1b57
......@@ -562,7 +562,7 @@ class CxxAllocatorAdaptor {
template <typename U, typename UAlloc>
friend class CxxAllocatorAdaptor;
std::reference_wrapper<Inner> ref_;
Inner* inner_ = nullptr;
public:
using value_type = T;
......@@ -571,28 +571,34 @@ class CxxAllocatorAdaptor {
using propagate_on_container_move_assignment = std::true_type;
using propagate_on_container_swap = std::true_type;
constexpr explicit CxxAllocatorAdaptor(Inner& ref) : ref_(ref) {}
constexpr explicit CxxAllocatorAdaptor() = default;
constexpr explicit CxxAllocatorAdaptor(Inner& ref) : inner_(&ref) {}
constexpr CxxAllocatorAdaptor(CxxAllocatorAdaptor const&) = default;
template <typename U, std::enable_if_t<!std::is_same<U, T>::value, int> = 0>
constexpr CxxAllocatorAdaptor(CxxAllocatorAdaptor<U, Inner> const& other)
: ref_(other.ref_) {}
: inner_(other.inner_) {}
T* allocate(std::size_t n) {
using lifted = typename detail::lift_void_to_char<T>::type;
return static_cast<T*>(ref_.get().allocate(sizeof(lifted) * n));
if (inner_ == nullptr) {
throw_exception<std::bad_alloc>();
}
return static_cast<T*>(inner_->allocate(sizeof(lifted) * n));
}
void deallocate(T* p, std::size_t n) {
using lifted = typename detail::lift_void_to_char<T>::type;
ref_.get().deallocate(p, sizeof(lifted) * n);
assert(inner_);
inner_->deallocate(p, sizeof(lifted) * n);
}
friend bool operator==(Self const& a, Self const& b) noexcept {
return std::addressof(a.ref_.get()) == std::addressof(b.ref_.get());
return a.inner_ == b.inner_;
}
friend bool operator!=(Self const& a, Self const& b) noexcept {
return std::addressof(a.ref_.get()) != std::addressof(b.ref_.get());
return a.inner_ != b.inner_;
}
};
......
......@@ -147,6 +147,24 @@ TEST(Arena, Vector) {
}
}
TEST(Arena, DefaultConstructible) {
std::vector<size_t, SysArenaAllocator<size_t>> vec;
EXPECT_THROW(vec.push_back(42), std::bad_alloc);
}
TEST(Arena, Compare) {
SysArena arena1;
SysArenaAllocator<size_t> alloc1(arena1);
SysArenaAllocator<size_t> alloc2(arena1);
EXPECT_EQ(alloc1, alloc2);
SysArena arena2;
SysArenaAllocator<size_t> alloc3(arena2);
EXPECT_NE(alloc1, alloc3);
}
TEST(Arena, SizeLimit) {
static const size_t requestedBlockSize = sizeof(size_t);
static const size_t maxSize = 10 * requestedBlockSize;
......
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