From 64afe23528483a49eaa561d12c6440b1352531bd Mon Sep 17 00:00:00 2001 From: Tim Shen Date: Wed, 10 Aug 2016 17:52:09 +0000 Subject: [PATCH] [ADT] Add make_scope_exit(). Summary: make_scope_exit() is described in C++ proposal p0052r2, which uses RAII to do cleanup works at scope exit. Reviewers: chandlerc Subscribers: llvm-commits Differential Revision: https://reviews.llvm.org/D22796 llvm-svn: 278251 --- llvm/include/llvm/ADT/ScopeExit.h | 55 ++++++++++++++++++++++++++++++++++++ llvm/unittests/ADT/CMakeLists.txt | 1 + llvm/unittests/ADT/ScopeExitTest.cpp | 32 +++++++++++++++++++++ 3 files changed, 88 insertions(+) create mode 100644 llvm/include/llvm/ADT/ScopeExit.h create mode 100644 llvm/unittests/ADT/ScopeExitTest.cpp diff --git a/llvm/include/llvm/ADT/ScopeExit.h b/llvm/include/llvm/ADT/ScopeExit.h new file mode 100644 index 0000000..497e80b --- /dev/null +++ b/llvm/include/llvm/ADT/ScopeExit.h @@ -0,0 +1,55 @@ +//===- 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, which executes user-defined +// cleanup logic at scope exit. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_SCOPE_EXIT_H +#define LLVM_ADT_SCOPE_EXIT_H + +#include "llvm/Support/Compiler.h" + +#include +#include + +namespace llvm { +namespace detail { + +template class LLVM_ATTRIBUTE_UNUSED_RESULT scope_exit { + Callable ExitFunction; + +public: + template + explicit scope_exit(Fp &&F) : ExitFunction(std::forward(F)) {} + + scope_exit(const scope_exit &) = default; + scope_exit(scope_exit &&) = default; + + ~scope_exit() { ExitFunction(); } +}; + +} // end namespace detail + +// 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 +detail::scope_exit::type> +make_scope_exit(Callable &&F) { + return detail::scope_exit::type>( + std::forward(F)); +} + +} // end namespace llvm + +#endif diff --git a/llvm/unittests/ADT/CMakeLists.txt b/llvm/unittests/ADT/CMakeLists.txt index ca1644b..83d6eb5 100644 --- a/llvm/unittests/ADT/CMakeLists.txt +++ b/llvm/unittests/ADT/CMakeLists.txt @@ -34,6 +34,7 @@ set(ADTSources PriorityWorklistTest.cpp RangeAdapterTest.cpp SCCIteratorTest.cpp + ScopeExitTest.cpp SequenceTest.cpp SetVectorTest.cpp SmallPtrSetTest.cpp diff --git a/llvm/unittests/ADT/ScopeExitTest.cpp b/llvm/unittests/ADT/ScopeExitTest.cpp new file mode 100644 index 0000000..301942c --- /dev/null +++ b/llvm/unittests/ADT/ScopeExitTest.cpp @@ -0,0 +1,32 @@ +//===- 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" + +using namespace llvm; + +namespace { + +TEST(ScopeExitTest, Basic) { + struct Callable { + bool &Called; + Callable(bool &Called) : Called(Called) {} + Callable(Callable &&RHS) : Called(RHS.Called) {} + void operator()() { Called = true; } + }; + bool Called = false; + { + auto g = make_scope_exit(Callable(Called)); + EXPECT_FALSE(Called); + } + EXPECT_TRUE(Called); +} + +} // end anonymous namespace -- 2.7.4