Loading base/include/android-base/scopeguard.h +15 −5 Original line number Original line Diff line number Diff line Loading @@ -17,20 +17,27 @@ #ifndef ANDROID_BASE_SCOPEGUARD_H #ifndef ANDROID_BASE_SCOPEGUARD_H #define ANDROID_BASE_SCOPEGUARD_H #define ANDROID_BASE_SCOPEGUARD_H #include <utility> // for std::move #include <utility> // for std::move, std::forward namespace android { namespace android { namespace base { namespace base { // ScopeGuard ensures that the specified functor is executed no matter how the // current scope exits. template <typename F> template <typename F> class ScopeGuard { class ScopeGuard { public: 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_) { ScopeGuard(ScopeGuard&& that) : f_(std::move(that.f_)), active_(that.active_) { that.active_ = false; that.active_ = false; } } template <typename Functor> ScopeGuard(ScopeGuard<Functor>&& that) : f_(std::move(that.f_)), active_(that.active_) { that.active_ = false; } ~ScopeGuard() { ~ScopeGuard() { if (active_) f_(); if (active_) f_(); } } Loading @@ -45,13 +52,16 @@ class ScopeGuard { bool active() const { return active_; } bool active() const { return active_; } private: private: template <typename Functor> friend class ScopeGuard; F f_; F f_; bool active_; bool active_; }; }; template <typename T> template <typename F> ScopeGuard<T> make_scope_guard(T f) { ScopeGuard<F> make_scope_guard(F&& f) { return ScopeGuard<T>(f); return ScopeGuard<F>(std::forward<F>(f)); } } } // namespace base } // namespace base Loading base/scopeguard_test.cpp +13 −0 Original line number Original line Diff line number Diff line Loading @@ -17,6 +17,7 @@ #include "android-base/scopeguard.h" #include "android-base/scopeguard.h" #include <utility> #include <utility> #include <vector> #include <gtest/gtest.h> #include <gtest/gtest.h> Loading Loading @@ -44,3 +45,15 @@ TEST(scopeguard, moved) { EXPECT_FALSE(scopeguard.active()); EXPECT_FALSE(scopeguard.active()); ASSERT_FALSE(guarded_var); 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); } Loading
base/include/android-base/scopeguard.h +15 −5 Original line number Original line Diff line number Diff line Loading @@ -17,20 +17,27 @@ #ifndef ANDROID_BASE_SCOPEGUARD_H #ifndef ANDROID_BASE_SCOPEGUARD_H #define ANDROID_BASE_SCOPEGUARD_H #define ANDROID_BASE_SCOPEGUARD_H #include <utility> // for std::move #include <utility> // for std::move, std::forward namespace android { namespace android { namespace base { namespace base { // ScopeGuard ensures that the specified functor is executed no matter how the // current scope exits. template <typename F> template <typename F> class ScopeGuard { class ScopeGuard { public: 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_) { ScopeGuard(ScopeGuard&& that) : f_(std::move(that.f_)), active_(that.active_) { that.active_ = false; that.active_ = false; } } template <typename Functor> ScopeGuard(ScopeGuard<Functor>&& that) : f_(std::move(that.f_)), active_(that.active_) { that.active_ = false; } ~ScopeGuard() { ~ScopeGuard() { if (active_) f_(); if (active_) f_(); } } Loading @@ -45,13 +52,16 @@ class ScopeGuard { bool active() const { return active_; } bool active() const { return active_; } private: private: template <typename Functor> friend class ScopeGuard; F f_; F f_; bool active_; bool active_; }; }; template <typename T> template <typename F> ScopeGuard<T> make_scope_guard(T f) { ScopeGuard<F> make_scope_guard(F&& f) { return ScopeGuard<T>(f); return ScopeGuard<F>(std::forward<F>(f)); } } } // namespace base } // namespace base Loading
base/scopeguard_test.cpp +13 −0 Original line number Original line Diff line number Diff line Loading @@ -17,6 +17,7 @@ #include "android-base/scopeguard.h" #include "android-base/scopeguard.h" #include <utility> #include <utility> #include <vector> #include <gtest/gtest.h> #include <gtest/gtest.h> Loading Loading @@ -44,3 +45,15 @@ TEST(scopeguard, moved) { EXPECT_FALSE(scopeguard.active()); EXPECT_FALSE(scopeguard.active()); ASSERT_FALSE(guarded_var); 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); }