From b29d023b350b6eaec52bc0b7b58fb6b2c9b0ad95 Mon Sep 17 00:00:00 2001 From: Yedidya Feldblum Date: Fri, 5 Feb 2016 12:27:56 -0800 Subject: [PATCH] ConditionallyExistent Summary: [Folly] `ConditionallyExistent`. For when we need extra member fields in dbg builds, but want to save the space in opt builds. Or other situations along similar lines, but with perhaps another the statically-known condition. Conditional compilation can have some nasty side-effects. Best to avoid it. Let the compiler see everything, rather than having the preprocessor ruin our day. Let the optimizer remove code that will never be called, after the compiler has seen it. Let us have a single AST in our source file, not one AST for dbg and one for opt, or other statically-known conditions. Reviewed By: andriigrynenko Differential Revision: D2879397 fb-gh-sync-id: d631141a984eebd46674f27a40a97f670eb33f54 --- folly/ConditionallyExistent.h | 62 ++++++++++++++++++++++++ folly/Makefile.am | 1 + folly/Portability.h | 9 ++++ folly/test/ConditionallyExistentTest.cpp | 43 ++++++++++++++++ folly/test/Makefile.am | 4 ++ 5 files changed, 119 insertions(+) create mode 100644 folly/ConditionallyExistent.h create mode 100644 folly/test/ConditionallyExistentTest.cpp diff --git a/folly/ConditionallyExistent.h b/folly/ConditionallyExistent.h new file mode 100644 index 00000000..c40dff1b --- /dev/null +++ b/folly/ConditionallyExistent.h @@ -0,0 +1,62 @@ +/* + * Copyright 2016 Facebook, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include +#include + +namespace folly { + +template +class ConditionallyExistent; + +template +class ConditionallyExistent { + public: + static constexpr bool present() { return false; } + explicit ConditionallyExistent(const T&) {} + explicit ConditionallyExistent(T&&) {} + ConditionallyExistent(const ConditionallyExistent&) = delete; + ConditionallyExistent(ConditionallyExistent&&) = delete; + ConditionallyExistent& operator=(const ConditionallyExistent&) = delete; + ConditionallyExistent& operator=(ConditionallyExistent&&) = delete; + template + void with(const F&&) {} +}; + +template +class ConditionallyExistent { + public: + static constexpr bool present() { return true; } + explicit ConditionallyExistent(const T& v) : value_(v) {} + explicit ConditionallyExistent(T&& v) : value_(std::move(v)) {} + ConditionallyExistent(const ConditionallyExistent&) = delete; + ConditionallyExistent(ConditionallyExistent&&) = delete; + ConditionallyExistent& operator=(const ConditionallyExistent&) = delete; + ConditionallyExistent& operator=(ConditionallyExistent&&) = delete; + template + void with(F&& f) { + f(value_); + } + + private: + T value_; +}; + +template +using ExistentIfDebug = ConditionallyExistent; +} diff --git a/folly/Makefile.am b/folly/Makefile.am index 1cf59337..1440a07b 100644 --- a/folly/Makefile.am +++ b/folly/Makefile.am @@ -263,6 +263,7 @@ nobase_follyinclude_HEADERS = \ PicoSpinLock.h \ Portability.h \ portability/Syscall.h \ + ConditionallyExistent.h \ Preprocessor.h \ ProducerConsumerQueue.h \ Random.h \ diff --git a/folly/Portability.h b/folly/Portability.h index 5054afd8..b1faa45c 100644 --- a/folly/Portability.h +++ b/folly/Portability.h @@ -334,6 +334,15 @@ typedef SSIZE_T ssize_t; #endif +// Debug +namespace folly { +#ifdef NDEBUG +constexpr auto kIsDebug = false; +#else +constexpr auto kIsDebug = true; +#endif +} + // Endianness namespace folly { #ifdef _MSC_VER diff --git a/folly/test/ConditionallyExistentTest.cpp b/folly/test/ConditionallyExistentTest.cpp new file mode 100644 index 00000000..b198e005 --- /dev/null +++ b/folly/test/ConditionallyExistentTest.cpp @@ -0,0 +1,43 @@ +/* + * Copyright 2016 Facebook, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include + +using namespace std; +using namespace folly; + +namespace { + +class ConditionallyExistentTest : public testing::Test {}; +} + +TEST_F(ConditionallyExistentTest, WhenConditionFalse) { + folly::ConditionallyExistent foobar("hello world"); + EXPECT_FALSE(foobar.present()); + bool called = false; + foobar.with([&](const string&) { called = true; }); + EXPECT_FALSE(called); +} + +TEST_F(ConditionallyExistentTest, WhenConditionTrue) { + folly::ConditionallyExistent foobar("hello world"); + EXPECT_TRUE(foobar.present()); + bool called = false; + foobar.with([&](const string&) { called = true; }); + EXPECT_TRUE(called); +} diff --git a/folly/test/Makefile.am b/folly/test/Makefile.am index 641c98cb..8c305dd7 100644 --- a/folly/test/Makefile.am +++ b/folly/test/Makefile.am @@ -159,6 +159,10 @@ string_test_SOURCES = StringTest.cpp string_test_LDADD = libfollytestmain.la TESTS += string_test +conditionally_existent_test_SOURCES = ConditionallyExistent.cpp +conditionally_existent_test_LDADD = libfollytestmain.la +TESTS += conditionally_existent_test + producer_consumer_queue_test_SOURCES = ProducerConsumerQueueTest.cpp producer_consumer_queue_test_LDADD = libfollytestmain.la TESTS += producer_consumer_queue_test -- 2.34.1