[llvm] r323442 - Give scope_exit helper correct move semantics

Sam McCall via llvm-commits llvm-commits at lists.llvm.org
Thu Jan 25 08:55:48 PST 2018


Author: sammccall
Date: Thu Jan 25 08:55:48 2018
New Revision: 323442

URL: http://llvm.org/viewvc/llvm-project?rev=323442&view=rev
Log:
Give scope_exit helper correct move semantics

Modified:
    llvm/trunk/include/llvm/ADT/ScopeExit.h
    llvm/trunk/unittests/ADT/ScopeExitTest.cpp

Modified: llvm/trunk/include/llvm/ADT/ScopeExit.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ADT/ScopeExit.h?rev=323442&r1=323441&r2=323442&view=diff
==============================================================================
--- llvm/trunk/include/llvm/ADT/ScopeExit.h (original)
+++ llvm/trunk/include/llvm/ADT/ScopeExit.h Thu Jan 25 08:55:48 2018
@@ -25,14 +25,26 @@ namespace detail {
 
 template <typename Callable> class scope_exit {
   Callable ExitFunction;
+  bool Engaged = true; // False once moved-from or release()d.
 
 public:
   template <typename Fp>
   explicit scope_exit(Fp &&F) : ExitFunction(std::forward<Fp>(F)) {}
 
-  scope_exit(scope_exit &&Rhs) : ExitFunction(std::move(Rhs.ExitFunction)) {}
+  scope_exit(scope_exit &&Rhs)
+      : ExitFunction(std::move(Rhs.ExitFunction)), Engaged(Rhs.Engaged) {
+    Rhs.release();
+  }
+  scope_exit(const scope_exit &) = delete;
+  scope_exit &operator=(scope_exit &&) = delete;
+  scope_exit &operator=(const scope_exit &) = delete;
 
-  ~scope_exit() { ExitFunction(); }
+  void release() { Engaged = false; }
+
+  ~scope_exit() {
+    if (Engaged)
+      ExitFunction();
+  }
 };
 
 } // end namespace detail

Modified: llvm/trunk/unittests/ADT/ScopeExitTest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/ADT/ScopeExitTest.cpp?rev=323442&r1=323441&r2=323442&view=diff
==============================================================================
--- llvm/trunk/unittests/ADT/ScopeExitTest.cpp (original)
+++ llvm/trunk/unittests/ADT/ScopeExitTest.cpp Thu Jan 25 08:55:48 2018
@@ -29,4 +29,21 @@ TEST(ScopeExitTest, Basic) {
   EXPECT_TRUE(Called);
 }
 
+TEST(ScopeExitTest, Release) {
+  int Count = 0;
+  auto Increment = [&] { ++Count; };
+  {
+    auto G = make_scope_exit(Increment);
+    auto H = std::move(G);
+    auto I = std::move(G);
+    EXPECT_EQ(0, Count);
+  }
+  EXPECT_EQ(1, Count);
+  {
+    auto G = make_scope_exit(Increment);
+    G.release();
+  }
+  EXPECT_EQ(1, Count);
+}
+
 } // end anonymous namespace




More information about the llvm-commits mailing list