diff --git a/wpiutil/.styleguide b/wpiutil/.styleguide index 0b08cf4318..68288c9383 100644 --- a/wpiutil/.styleguide +++ b/wpiutil/.styleguide @@ -5,6 +5,7 @@ cppHeaderFileInclude { \.inl$ math$ numbers$ + scope$ } cppSrcFileInclude { diff --git a/wpiutil/src/main/native/include/wpi/scope b/wpiutil/src/main/native/include/wpi/scope new file mode 100644 index 0000000000..e25badb617 --- /dev/null +++ b/wpiutil/src/main/native/include/wpi/scope @@ -0,0 +1,37 @@ +// Copyright (c) FIRST and other WPILib contributors. +// Open Source Software; you can modify and/or share it under the terms of +// the WPILib BSD license file in the root directory of this project. + +#pragma once + +#include + +namespace wpi { + +template +class scope_exit { + public: + explicit scope_exit(F&& f) noexcept : m_f{std::forward(f)} {} + + ~scope_exit() { + if (m_active) { + m_f(); + } + } + + scope_exit(scope_exit&& rhs) noexcept + : m_f{std::move(rhs.m_f)}, m_active{rhs.m_active} { + rhs.release(); + } + + scope_exit(const scope_exit&) = delete; + scope_exit& operator=(const scope_exit&) = delete; + + void release() noexcept { m_active = false; } + + private: + F m_f; + bool m_active = true; +}; + +} // namespace wpi diff --git a/wpiutil/src/test/native/cpp/ScopeExitTest.cpp b/wpiutil/src/test/native/cpp/ScopeExitTest.cpp new file mode 100644 index 0000000000..9cecb1cac0 --- /dev/null +++ b/wpiutil/src/test/native/cpp/ScopeExitTest.cpp @@ -0,0 +1,36 @@ +// Copyright (c) FIRST and other WPILib contributors. +// Open Source Software; you can modify and/or share it under the terms of +// the WPILib BSD license file in the root directory of this project. + +#include "gtest/gtest.h" +#include "wpi/scope" + +TEST(ScopeExitTest, ScopeExit) { + int exitCount = 0; + + { + wpi::scope_exit exit{[&] { ++exitCount; }}; + + EXPECT_EQ(0, exitCount); + } + + EXPECT_EQ(1, exitCount); +} + +TEST(ScopeExitTest, Release) { + int exitCount = 0; + + { + wpi::scope_exit exit1{[&] { ++exitCount; }}; + wpi::scope_exit exit2 = std::move(exit1); + wpi::scope_exit exit3 = std::move(exit1); + EXPECT_EQ(0, exitCount); + } + EXPECT_EQ(1, exitCount); + + { + wpi::scope_exit exit{[&] { ++exitCount; }}; + exit.release(); + } + EXPECT_EQ(1, exitCount); +}