Allow android::base::ScopeGuard in STL containers This change lets android::base::ScopeGuard be useful in STL containers (e.g. std::vector<android::base::ScopeGuard<std::function<void()>>>). It also provides perfect forwarding for android::base::make_scope_guard. Bug: 34764308 Test: libbase_test Change-Id: I7d1e5494b0f0695763cff0700efdb9ec18ae85c8 Merged-In: I7d1e5494b0f0695763cff0700efdb9ec18ae85c8 (cherry picked from commit b77035b89a3e95358a1aac9e28cd61c8b256e7ae)
diff --git a/include/android-base/scopeguard.h b/include/android-base/scopeguard.h index abcf4bc..c314e02 100644 --- a/include/android-base/scopeguard.h +++ b/include/android-base/scopeguard.h
@@ -17,20 +17,27 @@ #ifndef ANDROID_BASE_SCOPEGUARD_H #define ANDROID_BASE_SCOPEGUARD_H -#include <utility> // for std::move +#include <utility> // for std::move, std::forward namespace android { namespace base { +// ScopeGuard ensures that the specified functor is executed no matter how the +// current scope exits. template <typename F> class ScopeGuard { public: - ScopeGuard(F f) : f_(f), active_(true) {} + ScopeGuard(F&& f) : f_(std::forward<F>(f)), active_(true) {} ScopeGuard(ScopeGuard&& that) : f_(std::move(that.f_)), active_(that.active_) { that.active_ = false; } + template <typename Functor> + ScopeGuard(ScopeGuard<Functor>&& that) : f_(std::move(that.f_)), active_(that.active_) { + that.active_ = false; + } + ~ScopeGuard() { if (active_) f_(); } @@ -45,13 +52,16 @@ bool active() const { return active_; } private: + template <typename Functor> + friend class ScopeGuard; + F f_; bool active_; }; -template <typename T> -ScopeGuard<T> make_scope_guard(T f) { - return ScopeGuard<T>(f); +template <typename F> +ScopeGuard<F> make_scope_guard(F&& f) { + return ScopeGuard<F>(std::forward<F>(f)); } } // namespace base
diff --git a/scopeguard_test.cpp b/scopeguard_test.cpp index e11154a..9236d7b 100644 --- a/scopeguard_test.cpp +++ b/scopeguard_test.cpp
@@ -17,6 +17,7 @@ #include "android-base/scopeguard.h" #include <utility> +#include <vector> #include <gtest/gtest.h> @@ -44,3 +45,15 @@ EXPECT_FALSE(scopeguard.active()); ASSERT_FALSE(guarded_var); } + +TEST(scopeguard, vector) { + int guarded_var = 0; + { + std::vector<android::base::ScopeGuard<std::function<void()>>> scopeguards; + scopeguards.emplace_back(android::base::make_scope_guard( + std::bind([](int& guarded_var) { guarded_var++; }, std::ref(guarded_var)))); + scopeguards.emplace_back(android::base::make_scope_guard( + std::bind([](int& guarded_var) { guarded_var++; }, std::ref(guarded_var)))); + } + ASSERT_EQ(guarded_var, 2); +}