summaryrefslogtreecommitdiff
path: root/absl/cleanup
diff options
context:
space:
mode:
authorGravatar Abseil Team <absl-team@google.com>2021-01-30 06:20:07 -0800
committerGravatar Derek Mauro <dmauro@google.com>2021-01-30 09:25:37 -0500
commit184d2f8364bcb05e413ec4c72cad0cf86e712d1c (patch)
treedb3f40595666712c8911161c3f34e0de439bc55f /absl/cleanup
parenta9a49560208484f1f99efdde889da6147e8722fe (diff)
Export of internal Abseil changes
-- 8c77b14bdee3f4cafb8ba520d4d050b15a949fd4 by Derek Mauro <dmauro@google.com>: Fix absl::Cleanup usage example PiperOrigin-RevId: 354702001 -- 10365da7a0aacaa0c4774a4b618a76dff328611b by CJ Johnson <johnsoncj@google.com>: Swap the order of the C++11 and C++17 interfaces for absl::Cleanup to mirror the order used in the comment example PiperOrigin-RevId: 354675180 GitOrigin-RevId: 8c77b14bdee3f4cafb8ba520d4d050b15a949fd4 Change-Id: Ia2054b725ed737ff9e557cb3d973de7c34bc51b0
Diffstat (limited to 'absl/cleanup')
-rw-r--r--absl/cleanup/cleanup.h42
-rw-r--r--absl/cleanup/cleanup_test.cc117
-rw-r--r--absl/cleanup/internal/cleanup.h2
3 files changed, 95 insertions, 66 deletions
diff --git a/absl/cleanup/cleanup.h b/absl/cleanup/cleanup.h
index eba04b33..f606b3f4 100644
--- a/absl/cleanup/cleanup.h
+++ b/absl/cleanup/cleanup.h
@@ -24,36 +24,36 @@
// ```
// void CopyGoodData(const char* input_path, const char* output_path) {
// FILE* in_file = fopen(input_path, "r");
-// FILE* out_file = fopen(output_path, "w");
-// if (in_file == nullptr || out_file == nullptr) return;
+// if (in_file == nullptr) return;
//
// // C++17 style using class template argument deduction
-// absl::Cleanup in_closer = [&in_file] { fclose(in_file); };
+// absl::Cleanup in_closer = [in_file] { fclose(in_file); };
//
-// // C++11 style using the factory function
-// auto out_closer = absl::MakeCleanup([&out_file] { fclose(out_file); });
+// FILE* out_file = fopen(output_path, "w");
+// if (out_file == nullptr) return; // `in_closer` will run
//
-// // `fclose` will be called on all exit paths by the cleanup instances
+// // C++11 style using the factory function
+// auto out_closer = absl::MakeCleanup([out_file] { fclose(out_file); });
//
// Data data;
// while (ReadData(in_file, &data)) {
// if (data.IsBad()) {
// LOG(ERROR) << "Found bad data.";
-// return; // `in_closer` and `out_closer` will call their callbacks
+// return; // `in_closer` and `out_closer` will run
// }
// SaveData(out_file, &data);
// }
-// return; // `in_closer` and `out_closer` will call their callbacks
+//
+// // `in_closer` and `out_closer` will run
// }
// ```
//
-// `std::move(cleanup).Invoke()` will execute the callback early, before
-// destruction, and prevent the callback from executing in the destructor.
+// Methods:
//
-// Alternatively, `std::move(cleanup).Cancel()` will prevent the callback from
-// ever executing at all.
+// `std::move(cleanup).Cancel()` will prevent the callback from executing.
//
-// Once a cleanup object has been `std::move(...)`-ed, it may not be used again.
+// `std::move(cleanup).Invoke()` will execute the callback early, before
+// destruction, and prevent the callback from executing in the destructor.
#ifndef ABSL_CLEANUP_CLEANUP_H_
#define ABSL_CLEANUP_CLEANUP_H_
@@ -101,6 +101,14 @@ class ABSL_MUST_USE_RESULT Cleanup {
cleanup_internal::Storage<Callback> storage_;
};
+// `absl::Cleanup c = /* callback */;`
+//
+// C++17 type deduction API for creating an instance of `absl::Cleanup`.
+#if defined(ABSL_HAVE_CLASS_TEMPLATE_ARGUMENT_DEDUCTION)
+template <typename Callback>
+Cleanup(Callback callback) -> Cleanup<cleanup_internal::Tag, Callback>;
+#endif // defined(ABSL_HAVE_CLASS_TEMPLATE_ARGUMENT_DEDUCTION)
+
// `auto c = absl::MakeCleanup(/* callback */);`
//
// C++11 type deduction API for creating an instance of `absl::Cleanup`.
@@ -115,14 +123,6 @@ absl::Cleanup<cleanup_internal::Tag, Callback> MakeCleanup(Callback callback) {
return {std::move(callback)};
}
-// `absl::Cleanup c = /* callback */;`
-//
-// C++17 type deduction API for creating an instance of `absl::Cleanup`.
-#if defined(ABSL_HAVE_CLASS_TEMPLATE_ARGUMENT_DEDUCTION)
-template <typename Callback>
-Cleanup(Callback callback) -> Cleanup<cleanup_internal::Tag, Callback>;
-#endif // defined(ABSL_HAVE_CLASS_TEMPLATE_ARGUMENT_DEDUCTION)
-
ABSL_NAMESPACE_END
} // namespace absl
diff --git a/absl/cleanup/cleanup_test.cc b/absl/cleanup/cleanup_test.cc
index 34e3bfad..792595d6 100644
--- a/absl/cleanup/cleanup_test.cc
+++ b/absl/cleanup/cleanup_test.cc
@@ -27,8 +27,8 @@ namespace {
using Tag = absl::cleanup_internal::Tag;
template <typename Type1, typename Type2>
-void AssertSameType() {
- static_assert(std::is_same<Type1, Type2>::value, "");
+constexpr bool IsSame() {
+ return (std::is_same<Type1, Type2>::value);
}
struct IdentityFactory {
@@ -88,27 +88,31 @@ template <typename>
struct CleanupTest : public ::testing::Test {};
TYPED_TEST_SUITE(CleanupTest, CleanupTestParams);
-bool function_pointer_called = false;
-void FunctionPointerFunction() { function_pointer_called = true; }
+bool fn_ptr_called = false;
+void FnPtrFunction() { fn_ptr_called = true; }
TYPED_TEST(CleanupTest, FactoryProducesCorrectType) {
{
auto callback = TypeParam::AsCallback([] {});
auto cleanup = absl::MakeCleanup(std::move(callback));
- AssertSameType<absl::Cleanup<Tag, decltype(callback)>, decltype(cleanup)>();
+ static_assert(
+ IsSame<absl::Cleanup<Tag, decltype(callback)>, decltype(cleanup)>(),
+ "");
}
{
- auto cleanup = absl::MakeCleanup(&FunctionPointerFunction);
+ auto cleanup = absl::MakeCleanup(&FnPtrFunction);
- AssertSameType<absl::Cleanup<Tag, void (*)()>, decltype(cleanup)>();
+ static_assert(IsSame<absl::Cleanup<Tag, void (*)()>, decltype(cleanup)>(),
+ "");
}
{
- auto cleanup = absl::MakeCleanup(FunctionPointerFunction);
+ auto cleanup = absl::MakeCleanup(FnPtrFunction);
- AssertSameType<absl::Cleanup<Tag, void (*)()>, decltype(cleanup)>();
+ static_assert(IsSame<absl::Cleanup<Tag, void (*)()>, decltype(cleanup)>(),
+ "");
}
}
@@ -118,19 +122,23 @@ TYPED_TEST(CleanupTest, CTADProducesCorrectType) {
auto callback = TypeParam::AsCallback([] {});
absl::Cleanup cleanup = std::move(callback);
- AssertSameType<absl::Cleanup<Tag, decltype(callback)>, decltype(cleanup)>();
+ static_assert(
+ IsSame<absl::Cleanup<Tag, decltype(callback)>, decltype(cleanup)>(),
+ "");
}
{
- absl::Cleanup cleanup = &FunctionPointerFunction;
+ absl::Cleanup cleanup = &FnPtrFunction;
- AssertSameType<absl::Cleanup<Tag, void (*)()>, decltype(cleanup)>();
+ static_assert(IsSame<absl::Cleanup<Tag, void (*)()>, decltype(cleanup)>(),
+ "");
}
{
- absl::Cleanup cleanup = FunctionPointerFunction;
+ absl::Cleanup cleanup = FnPtrFunction;
- AssertSameType<absl::Cleanup<Tag, void (*)()>, decltype(cleanup)>();
+ static_assert(IsSame<absl::Cleanup<Tag, void (*)()>, decltype(cleanup)>(),
+ "");
}
}
@@ -140,7 +148,8 @@ TYPED_TEST(CleanupTest, FactoryAndCTADProduceSameType) {
auto factory_cleanup = absl::MakeCleanup(callback);
absl::Cleanup deduction_cleanup = callback;
- AssertSameType<decltype(factory_cleanup), decltype(deduction_cleanup)>();
+ static_assert(
+ IsSame<decltype(factory_cleanup), decltype(deduction_cleanup)>(), "");
}
{
@@ -148,7 +157,8 @@ TYPED_TEST(CleanupTest, FactoryAndCTADProduceSameType) {
absl::MakeCleanup(FunctorClassFactory::AsCallback([] {}));
absl::Cleanup deduction_cleanup = FunctorClassFactory::AsCallback([] {});
- AssertSameType<decltype(factory_cleanup), decltype(deduction_cleanup)>();
+ static_assert(
+ IsSame<decltype(factory_cleanup), decltype(deduction_cleanup)>(), "");
}
{
@@ -156,21 +166,24 @@ TYPED_TEST(CleanupTest, FactoryAndCTADProduceSameType) {
absl::MakeCleanup(StdFunctionFactory::AsCallback([] {}));
absl::Cleanup deduction_cleanup = StdFunctionFactory::AsCallback([] {});
- AssertSameType<decltype(factory_cleanup), decltype(deduction_cleanup)>();
+ static_assert(
+ IsSame<decltype(factory_cleanup), decltype(deduction_cleanup)>(), "");
}
{
- auto factory_cleanup = absl::MakeCleanup(&FunctionPointerFunction);
- absl::Cleanup deduction_cleanup = &FunctionPointerFunction;
+ auto factory_cleanup = absl::MakeCleanup(&FnPtrFunction);
+ absl::Cleanup deduction_cleanup = &FnPtrFunction;
- AssertSameType<decltype(factory_cleanup), decltype(deduction_cleanup)>();
+ static_assert(
+ IsSame<decltype(factory_cleanup), decltype(deduction_cleanup)>(), "");
}
{
- auto factory_cleanup = absl::MakeCleanup(FunctionPointerFunction);
- absl::Cleanup deduction_cleanup = FunctionPointerFunction;
+ auto factory_cleanup = absl::MakeCleanup(FnPtrFunction);
+ absl::Cleanup deduction_cleanup = FnPtrFunction;
- AssertSameType<decltype(factory_cleanup), decltype(deduction_cleanup)>();
+ static_assert(
+ IsSame<decltype(factory_cleanup), decltype(deduction_cleanup)>(), "");
}
}
#endif // defined(ABSL_HAVE_CLASS_TEMPLATE_ARGUMENT_DEDUCTION)
@@ -179,62 +192,76 @@ TYPED_TEST(CleanupTest, BasicUsage) {
bool called = false;
{
- EXPECT_FALSE(called);
-
auto cleanup =
absl::MakeCleanup(TypeParam::AsCallback([&called] { called = true; }));
-
- EXPECT_FALSE(called);
+ EXPECT_FALSE(called); // Constructor shouldn't invoke the callback
}
- EXPECT_TRUE(called);
+ EXPECT_TRUE(called); // Destructor should invoke the callback
}
TYPED_TEST(CleanupTest, BasicUsageWithFunctionPointer) {
- function_pointer_called = false;
+ fn_ptr_called = false;
{
- EXPECT_FALSE(function_pointer_called);
-
- auto cleanup =
- absl::MakeCleanup(TypeParam::AsCallback(&FunctionPointerFunction));
-
- EXPECT_FALSE(function_pointer_called);
+ auto cleanup = absl::MakeCleanup(TypeParam::AsCallback(&FnPtrFunction));
+ EXPECT_FALSE(fn_ptr_called); // Constructor shouldn't invoke the callback
}
- EXPECT_TRUE(function_pointer_called);
+ EXPECT_TRUE(fn_ptr_called); // Destructor should invoke the callback
}
TYPED_TEST(CleanupTest, Cancel) {
bool called = false;
{
- EXPECT_FALSE(called);
-
auto cleanup =
absl::MakeCleanup(TypeParam::AsCallback([&called] { called = true; }));
- std::move(cleanup).Cancel();
+ EXPECT_FALSE(called); // Constructor shouldn't invoke the callback
- EXPECT_FALSE(called);
+ std::move(cleanup).Cancel();
+ EXPECT_FALSE(called); // Cancel shouldn't invoke the callback
}
- EXPECT_FALSE(called);
+ EXPECT_FALSE(called); // Destructor shouldn't invoke the callback
}
TYPED_TEST(CleanupTest, Invoke) {
bool called = false;
{
- EXPECT_FALSE(called);
-
auto cleanup =
absl::MakeCleanup(TypeParam::AsCallback([&called] { called = true; }));
+ EXPECT_FALSE(called); // Constructor shouldn't invoke the callback
+
std::move(cleanup).Invoke();
+ EXPECT_TRUE(called); // Invoke should invoke the callback
+
+ called = false; // Reset tracker before destructor runs
+ }
+
+ EXPECT_FALSE(called); // Destructor shouldn't invoke the callback
+}
+
+TYPED_TEST(CleanupTest, Move) {
+ bool called = false;
+
+ {
+ auto moved_from_cleanup =
+ absl::MakeCleanup(TypeParam::AsCallback([&called] { called = true; }));
+ EXPECT_FALSE(called); // Constructor shouldn't invoke the callback
+
+ {
+ auto moved_to_cleanup = std::move(moved_from_cleanup);
+ EXPECT_FALSE(called); // Move shouldn't invoke the callback
+ }
+
+ EXPECT_TRUE(called); // Destructor should invoke the callback
- EXPECT_TRUE(called);
+ called = false; // Reset tracker before destructor runs
}
- EXPECT_TRUE(called);
+ EXPECT_FALSE(called); // Destructor shouldn't invoke the callback
}
} // namespace
diff --git a/absl/cleanup/internal/cleanup.h b/absl/cleanup/internal/cleanup.h
index a126ff30..8fbca5bd 100644
--- a/absl/cleanup/internal/cleanup.h
+++ b/absl/cleanup/internal/cleanup.h
@@ -43,6 +43,8 @@ constexpr bool ReturnsVoid() {
template <typename Callback>
class Storage {
public:
+ Storage() = delete;
+
explicit Storage(Callback callback)
: engaged_(true), callback_(std::move(callback)) {}