From: Jordan DeLong Date: Sun, 2 Jun 2013 03:55:24 +0000 (-0700) Subject: Make folly::allocator_delete take advantage of EBO X-Git-Tag: v0.22.0~952 X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=79345bbc341c43e41ce9314193dae8674e3eb89c;p=folly.git Make folly::allocator_delete take advantage of EBO Summary: It wasn't. Test Plan: I have a case using this that now passes a static_assert that it's the same size as the default_deleter version. I didn't add a static_assert in folly's tests because right now is_simple_allocator>::value is true (I think because the tested members come from a base class), which breaks easy test cases. Reviewed By: andrei.alexandrescu@fb.com FB internal diff: D833142 --- diff --git a/folly/Memory.h b/folly/Memory.h index 6ce239f4..3be3d78f 100644 --- a/folly/Memory.h +++ b/folly/Memory.h @@ -42,15 +42,21 @@ std::unique_ptr make_unique(Args&&... args) { return std::unique_ptr(new T(std::forward(args)...)); } -/** - * Wrap a SimpleAllocator into a STL-compliant allocator. +/* + * StlAllocator wraps a SimpleAllocator into a STL-compliant + * allocator, maintaining an instance pointer to the simple allocator + * object. The underlying SimpleAllocator object must outlive all + * instances of StlAllocator using it. + * + * A SimpleAllocator must provide two methods: * - * The SimpleAllocator must provide two methods: * void* allocate(size_t size); * void deallocate(void* ptr); - * which, respectively, allocate a block of size bytes (aligned to the maximum - * alignment required on your system), throwing std::bad_alloc if the - * allocation can't be satisfied, and free a previously allocated block. + * + * which, respectively, allocate a block of size bytes (aligned to the + * maximum alignment required on your system), throwing std::bad_alloc + * if the allocation can't be satisfied, and free a previously + * allocated block. * * Note that the following allocator resembles the standard allocator * quite well: @@ -67,11 +73,15 @@ std::unique_ptr make_unique(Args&&... args) { * } * }; * + * But note that if you pass StlAllocator to a + * standard container it will be larger due to the contained state + * pointer. + * * author: Tudor Bosman */ // This would be so much simpler with std::allocator_traits, but gcc 4.6.2 -// doesn't support it +// doesn't support it. template class StlAllocator; template class StlAllocator { @@ -177,54 +187,49 @@ class StlAllocator { */ template typename Allocator::template rebind::other rebind_allocator( - Allocator const &allocator + Allocator const& allocator ) { return typename Allocator::template rebind::other(allocator); } /* - * Helper classes/functions for creating a unique_ptr using a custom allocator + * Helper classes/functions for creating a unique_ptr using a custom + * allocator. * * @author: Marcelo Juchem */ -// A deleter implementation based on std::default_delete, -// which uses a custom allocator to free memory +// Derives from the allocator to take advantage of the empty base +// optimization when possible. template -class allocator_delete { +class allocator_delete + : private std::remove_reference::type +{ typedef typename std::remove_reference::type allocator_type; public: allocator_delete() = default; - explicit allocator_delete(const allocator_type& allocator): - allocator_(allocator) + explicit allocator_delete(const allocator_type& allocator) + : allocator_type(allocator) {} - explicit allocator_delete(allocator_type&& allocator): - allocator_(std::move(allocator)) + explicit allocator_delete(allocator_type&& allocator) + : allocator_type(std::move(allocator)) {} template - allocator_delete(const allocator_delete& other): - allocator_(other.get_allocator()) + allocator_delete(const allocator_delete& other) + : allocator_type(other.get_allocator()) {} - allocator_type& get_allocator() const { - return allocator_; - } + allocator_type& get_allocator() const { return *this; } void operator()(typename allocator_type::pointer p) const { - if (!p) { - return; - } - - allocator_.destroy(p); - allocator_.deallocate(p, 1); + if (!p) return; + const_cast(this)->destroy(p); + const_cast(this)->deallocate(p, 1); } - -private: - mutable allocator_type allocator_; }; template diff --git a/folly/test/ArenaSmartPtrTest.cpp b/folly/test/ArenaSmartPtrTest.cpp index 54b8262a..0881d706 100644 --- a/folly/test/ArenaSmartPtrTest.cpp +++ b/folly/test/ArenaSmartPtrTest.cpp @@ -25,6 +25,11 @@ using namespace folly; +static_assert( + is_simple_allocator::value, + "SysArena should be a simple allocator" +); + struct global_counter { global_counter(): count_(0) {}