From: Yedidya Feldblum <yfeldblum@fb.com> Date: Sat, 7 Jan 2017 06:40:09 +0000 (-0800) Subject: Remove <glog/logging.h> from folly/Indestructible.h X-Git-Tag: v2017.03.06.00~123 X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=8f22c4e3ae765fa8b631c07ffa90dc4ba1aff279;p=folly.git Remove <glog/logging.h> from folly/Indestructible.h Summary: [Folly] Remove `<glog/logging.h>` from `folly/Indestructible.h`. This makes the header much lighter. And abort on invalid access (the use-case for `glog`) only in `!defined(NDEBUG)` mode. Anti-Pattern Combined Mega-Diff Description: * Add non-`explicit` default ctor. * Disable ctor explicitly when underlying ctor would fail to compile. Not sure how useful it would be, but it makes type-traits work correctly for whatever that is worth. * Switch boolean flag to `erased_{false}` so that it is zero-initializable, because that's better. Reviewed By: ericniebler Differential Revision: D4380469 fbshipit-source-id: a39cb7470f7ee678fa722778da587409f468d985 --- diff --git a/folly/Indestructible.h b/folly/Indestructible.h index 686bbce3..285d9ed6 100644 --- a/folly/Indestructible.h +++ b/folly/Indestructible.h @@ -16,10 +16,9 @@ #pragma once +#include <cassert> +#include <type_traits> #include <utility> -#include <glog/logging.h> -#include <folly/Likely.h> -#include <folly/Portability.h> namespace folly { @@ -60,10 +59,13 @@ template <typename T> class Indestructible final { public: - template <typename... Args> + template <typename S = T, typename = decltype(S())> + constexpr Indestructible() noexcept(noexcept(T())) {} + + template <typename... Args, typename = decltype(T(std::declval<Args&&>()...))> explicit constexpr Indestructible(Args&&... args) noexcept( std::is_nothrow_constructible<T, Args&&...>::value) - : storage_(std::forward<Args>(args)...), inited_(true) {} + : storage_(std::forward<Args>(args)...) {} ~Indestructible() = default; @@ -73,12 +75,12 @@ class Indestructible final { Indestructible(Indestructible&& other) noexcept( std::is_nothrow_move_constructible<T>::value) : storage_(std::move(other.storage_.value)) { - other.inited_ = false; + other.erased_ = true; } Indestructible& operator=(Indestructible&& other) noexcept( std::is_nothrow_move_assignable<T>::value) { storage_.value = std::move(other.storage_.value); - other.inited_ = false; + other.erased_ = true; } T* get() { @@ -96,26 +98,25 @@ class Indestructible final { private: void check() const { - if (UNLIKELY(!inited_)) { - fail(); - } - } - - [[noreturn]] FOLLY_NOINLINE static void fail() { - LOG(FATAL) << "Indestructible is not initialized"; + assert(!erased_); } union Storage { T value; - template <typename... Args> + template <typename S = T, typename = decltype(S())> + constexpr Storage() noexcept(noexcept(T())) : value() {} + + template < + typename... Args, + typename = decltype(T(std::declval<Args&&>()...))> explicit constexpr Storage(Args&&... args) : value(std::forward<Args>(args)...) {} ~Storage() {} }; - Storage storage_; - bool inited_{false}; + Storage storage_{}; + bool erased_{false}; }; } diff --git a/folly/Makefile.am b/folly/Makefile.am index dd6e6bc0..2fc98c82 100644 --- a/folly/Makefile.am +++ b/folly/Makefile.am @@ -8,6 +8,7 @@ ACLOCAL_AMFLAGS = -I m4 CLEANFILES = + noinst_PROGRAMS = generate_fingerprint_tables generate_fingerprint_tables_SOURCES = build/GenerateFingerprintTables.cpp generate_fingerprint_tables_LDADD = libfollybase.la diff --git a/folly/test/IndestructibleTest.cpp b/folly/test/IndestructibleTest.cpp index e01a2ba6..b5ca9656 100644 --- a/folly/test/IndestructibleTest.cpp +++ b/folly/test/IndestructibleTest.cpp @@ -75,6 +75,12 @@ TEST_F(IndestructibleTest, no_destruction) { EXPECT_EQ(1, state); } +TEST_F(IndestructibleTest, empty) { + static const Indestructible<map<string, int>> data; + auto& m = *data; + EXPECT_EQ(0, m.size()); +} + TEST_F(IndestructibleTest, move) { int state = 0; int value = 0; @@ -102,3 +108,14 @@ TEST_F(IndestructibleTest, move) { EXPECT_EQ(1, state); EXPECT_EQ(2, moves); } + +TEST_F(IndestructibleTest, disabled_default_ctor) { + EXPECT_TRUE((std::is_constructible<Indestructible<int>>::value)) << "sanity"; + + struct Foo { + Foo(int) {} + }; + EXPECT_FALSE((std::is_constructible<Indestructible<Foo>>::value)); + EXPECT_FALSE((std::is_constructible<Indestructible<Foo>, Magic>::value)); + EXPECT_TRUE((std::is_constructible<Indestructible<Foo>, int>::value)); +}