diff --git a/orc-rt/include/CMakeLists.txt b/orc-rt/include/CMakeLists.txt index 67fe060c4b25b..c3295b3c781bf 100644 --- a/orc-rt/include/CMakeLists.txt +++ b/orc-rt/include/CMakeLists.txt @@ -13,6 +13,7 @@ set(ORC_RT_HEADERS orc-rt/MemoryFlags.h orc-rt/RTTI.h orc-rt/WrapperFunction.h + orc-rt/ScopeExit.h orc-rt/SimplePackedSerialization.h orc-rt/SPSWrapperFunction.h orc-rt/bind.h diff --git a/orc-rt/include/orc-rt/ScopeExit.h b/orc-rt/include/orc-rt/ScopeExit.h new file mode 100644 index 0000000000000..e73ca187ddc74 --- /dev/null +++ b/orc-rt/include/orc-rt/ScopeExit.h @@ -0,0 +1,53 @@ +//===---------- ScopeExit.h - Execute code at scope exit --------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// make_scope_exit and related APIs. +// +//===----------------------------------------------------------------------===// + +#ifndef ORC_RT_SCOPEEXIT_H +#define ORC_RT_SCOPEEXIT_H + +#include +#include + +namespace orc_rt { +namespace detail { + +template class ScopeExitRunner { +public: + ScopeExitRunner(Fn &&F) : F(F) {} + ScopeExitRunner(const ScopeExitRunner &) = delete; + ScopeExitRunner &operator=(const ScopeExitRunner &) = delete; + ScopeExitRunner(ScopeExitRunner &&) = delete; + ScopeExitRunner &operator=(ScopeExitRunner &&) = delete; + ~ScopeExitRunner() { + if (Engaged) + F(); + } + void release() { Engaged = false; } + +private: + Fn F; + bool Engaged = true; +}; + +} // namespace detail + +/// Creates an object that runs the given function object upon destruction. +/// Calling the object's release method prior to destruction will prevent the +/// function object from running. +template +[[nodiscard]] detail::ScopeExitRunner> +make_scope_exit(Fn &&F) { + return detail::ScopeExitRunner>(std::forward(F)); +} + +} // namespace orc_rt + +#endif // ORC_RT_SCOPEEXIT_H diff --git a/orc-rt/unittests/CMakeLists.txt b/orc-rt/unittests/CMakeLists.txt index 7bf53ca9826e2..4ebc5277a5f15 100644 --- a/orc-rt/unittests/CMakeLists.txt +++ b/orc-rt/unittests/CMakeLists.txt @@ -21,6 +21,7 @@ add_orc_rt_unittest(CoreTests MathTest.cpp MemoryFlagsTest.cpp RTTITest.cpp + ScopeExitTest.cpp SimplePackedSerializationTest.cpp SPSWrapperFunctionTest.cpp WrapperFunctionBufferTest.cpp diff --git a/orc-rt/unittests/ScopeExitTest.cpp b/orc-rt/unittests/ScopeExitTest.cpp new file mode 100644 index 0000000000000..bbd517d79793b --- /dev/null +++ b/orc-rt/unittests/ScopeExitTest.cpp @@ -0,0 +1,39 @@ +//===- ScopeExitTest.cpp --------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// Tests for orc-rt's ScopeExit.h APIs. +// +//===----------------------------------------------------------------------===// + +#include "orc-rt/ScopeExit.h" +#include "gtest/gtest.h" + +using namespace orc_rt; + +TEST(ScopeExitTest, Noop) { + auto _ = make_scope_exit([]() {}); +} + +TEST(ScopeExitTest, OnScopeExit) { + bool ScopeExitRun = false; + { + auto _ = make_scope_exit([&]() { ScopeExitRun = true; }); + EXPECT_FALSE(ScopeExitRun); + } + EXPECT_TRUE(ScopeExitRun); +} + +TEST(ScopeExitTest, Release) { + bool ScopeExitRun = false; + { + auto OnExit = make_scope_exit([&]() { ScopeExitRun = true; }); + EXPECT_FALSE(ScopeExitRun); + OnExit.release(); + } + EXPECT_FALSE(ScopeExitRun); +}