Commit 8f22c4e3 authored by Yedidya Feldblum's avatar Yedidya Feldblum Committed by Facebook Github Bot

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
parent e3974815
...@@ -16,10 +16,9 @@ ...@@ -16,10 +16,9 @@
#pragma once #pragma once
#include <cassert>
#include <type_traits>
#include <utility> #include <utility>
#include <glog/logging.h>
#include <folly/Likely.h>
#include <folly/Portability.h>
namespace folly { namespace folly {
...@@ -60,10 +59,13 @@ template <typename T> ...@@ -60,10 +59,13 @@ template <typename T>
class Indestructible final { class Indestructible final {
public: 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( explicit constexpr Indestructible(Args&&... args) noexcept(
std::is_nothrow_constructible<T, Args&&...>::value) std::is_nothrow_constructible<T, Args&&...>::value)
: storage_(std::forward<Args>(args)...), inited_(true) {} : storage_(std::forward<Args>(args)...) {}
~Indestructible() = default; ~Indestructible() = default;
...@@ -73,12 +75,12 @@ class Indestructible final { ...@@ -73,12 +75,12 @@ class Indestructible final {
Indestructible(Indestructible&& other) noexcept( Indestructible(Indestructible&& other) noexcept(
std::is_nothrow_move_constructible<T>::value) std::is_nothrow_move_constructible<T>::value)
: storage_(std::move(other.storage_.value)) { : storage_(std::move(other.storage_.value)) {
other.inited_ = false; other.erased_ = true;
} }
Indestructible& operator=(Indestructible&& other) noexcept( Indestructible& operator=(Indestructible&& other) noexcept(
std::is_nothrow_move_assignable<T>::value) { std::is_nothrow_move_assignable<T>::value) {
storage_.value = std::move(other.storage_.value); storage_.value = std::move(other.storage_.value);
other.inited_ = false; other.erased_ = true;
} }
T* get() { T* get() {
...@@ -96,26 +98,25 @@ class Indestructible final { ...@@ -96,26 +98,25 @@ class Indestructible final {
private: private:
void check() const { void check() const {
if (UNLIKELY(!inited_)) { assert(!erased_);
fail();
}
}
[[noreturn]] FOLLY_NOINLINE static void fail() {
LOG(FATAL) << "Indestructible is not initialized";
} }
union Storage { union Storage {
T value; 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) explicit constexpr Storage(Args&&... args)
: value(std::forward<Args>(args)...) {} : value(std::forward<Args>(args)...) {}
~Storage() {} ~Storage() {}
}; };
Storage storage_; Storage storage_{};
bool inited_{false}; bool erased_{false};
}; };
} }
...@@ -8,6 +8,7 @@ ACLOCAL_AMFLAGS = -I m4 ...@@ -8,6 +8,7 @@ ACLOCAL_AMFLAGS = -I m4
CLEANFILES = CLEANFILES =
noinst_PROGRAMS = generate_fingerprint_tables noinst_PROGRAMS = generate_fingerprint_tables
generate_fingerprint_tables_SOURCES = build/GenerateFingerprintTables.cpp generate_fingerprint_tables_SOURCES = build/GenerateFingerprintTables.cpp
generate_fingerprint_tables_LDADD = libfollybase.la generate_fingerprint_tables_LDADD = libfollybase.la
......
...@@ -75,6 +75,12 @@ TEST_F(IndestructibleTest, no_destruction) { ...@@ -75,6 +75,12 @@ TEST_F(IndestructibleTest, no_destruction) {
EXPECT_EQ(1, state); 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) { TEST_F(IndestructibleTest, move) {
int state = 0; int state = 0;
int value = 0; int value = 0;
...@@ -102,3 +108,14 @@ TEST_F(IndestructibleTest, move) { ...@@ -102,3 +108,14 @@ TEST_F(IndestructibleTest, move) {
EXPECT_EQ(1, state); EXPECT_EQ(1, state);
EXPECT_EQ(2, moves); 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));
}
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