[PATCH] D22796: [ADT] Add make_scope_exit().

Justin Bogner via llvm-commits llvm-commits at lists.llvm.org
Mon Aug 1 14:25:45 PDT 2016


Tim Shen via llvm-commits <llvm-commits at lists.llvm.org> writes:
> timshen created this revision.
> timshen added a reviewer: chandlerc.
> timshen added a subscriber: llvm-commits.
>
> make_scope_exit() is described in C++ proposal p0052r2, which uses
> RAII to do cleanup works at scope exit.

Do you need this for something in particular? We don't usually add
utilities until we need them.

> https://reviews.llvm.org/D22796
>
> Files:
>   include/llvm/ADT/ScopeExit.h
>   unittests/ADT/CMakeLists.txt
>   unittests/ADT/ScopeExitTest.cpp
>
> Index: unittests/ADT/ScopeExitTest.cpp
> ===================================================================
> --- /dev/null
> +++ unittests/ADT/ScopeExitTest.cpp
> @@ -0,0 +1,45 @@
> +//===- llvm/unittest/ADT/ScopeExit.cpp - Scope exit unit tests --*- C++ -*-===//
> +//
> +//                     The LLVM Compiler Infrastructure
> +//
> +// This file is distributed under the University of Illinois Open Source
> +// License. See LICENSE.TXT for details.
> +//
> +//===----------------------------------------------------------------------===//
> +
> +#include "llvm/ADT/ScopeExit.h"
> +#include "gtest/gtest.h"
> +
> +#include <functional>
> +#include <vector>
> +
> +using namespace llvm;
> +
> +namespace {
> +
> +TEST(ScopeExitTest, Copy) {
> +  std::vector<int> v;
> +  const auto f = [&](int counter) {
> +    return [&v, counter] { v.push_back(counter); };
> +  };
> +  {
> +    auto g1 = make_scope_exit(f(0));
> +    { auto g2 = make_scope_exit(f(1)); }
> +    auto g3 = make_scope_exit(f(2));
> +    EXPECT_EQ((std::vector<int>{1}), v);
> +  }
> +  EXPECT_EQ((std::vector<int>{1, 2, 0}), v);
> +}
> +
> +TEST(ScopeExitTest, Move) {
> +  bool succ = false;
> +  std::function<void()> f([&succ] { succ = true; });
> +  ASSERT_TRUE(static_cast<bool>(f));
> +  {
> +    auto g4 = make_scope_exit(std::move(f));
> +    EXPECT_FALSE(f);
> +    EXPECT_FALSE(succ);
> +  }
> +  EXPECT_TRUE(succ);
> +}
> +}
> Index: unittests/ADT/CMakeLists.txt
> ===================================================================
> --- unittests/ADT/CMakeLists.txt
> +++ unittests/ADT/CMakeLists.txt
> @@ -34,6 +34,7 @@
>    PriorityWorklistTest.cpp
>    RangeAdapterTest.cpp
>    SCCIteratorTest.cpp
> +  ScopeExitTest.cpp
>    SequenceTest.cpp
>    SetVectorTest.cpp
>    SmallPtrSetTest.cpp
> Index: include/llvm/ADT/ScopeExit.h
> ===================================================================
> --- /dev/null
> +++ include/llvm/ADT/ScopeExit.h
> @@ -0,0 +1,54 @@
> +//===- llvm/ADT/ScopeExit.h - Execute code at scope exit --------*- C++ -*-===//
> +//
> +//                     The LLVM Compiler Infrastructure
> +//
> +// This file is distributed under the University of Illinois Open Source
> +// License. See LICENSE.TXT for details.
> +//
> +//===----------------------------------------------------------------------===//
> +//
> +// This file defines the make_scope_exit function.

It's probably worth mentioning briefly what the function does here.

> +//
> +//===----------------------------------------------------------------------===//
> +
> +#ifndef LLVM_ADT_SCOPE_EXIT_H
> +#define LLVM_ADT_SCOPE_EXIT_H
> +
> +#include "llvm/Support/Compiler.h"
> +
> +#include <type_traits>
> +#include <utility>
> +
> +namespace llvm {
> +namespace detail {
> +
> +template <typename Callable> class scope_exit {
> +  Callable ExitFunction;
> +
> +public:
> +  scope_exit() = delete;
> +
> +  template <typename Fp>
> +  explicit scope_exit(Fp &&F) : ExitFunction(std::forward<Fp>(F)) {}
> +
> +  ~scope_exit() { ExitFunction(); }
> +};
> +
> +} // detail

I think "end namespace detail" is more common.

> +
> +// Keeps the callable object that is passed in, and execute it at the
> +// destruction of the returned object (usually at the scope exit where the
> +// returned object is kept).
> +//
> +// Interface is specified by p0052r2.
> +template <typename Callable>
> +LLVM_ATTRIBUTE_UNUSED_RESULT
> +detail::scope_exit<typename std::decay<Callable>::type>
> +make_scope_exit(Callable &&F) {
> +  return detail::scope_exit<typename std::decay<Callable>::type>(
> +      std::forward<Callable>(F));
> +}
> +
> +} // llvm
> +
> +#endif
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits


More information about the llvm-commits mailing list