diff options
author | Martin Braun <martin.braun@ettus.com> | 2019-03-27 17:32:09 -0700 |
---|---|---|
committer | Martin Braun <martin.braun@ettus.com> | 2019-04-01 23:39:35 -0500 |
commit | beb1f3c207bcf1ebc6ca1e83f1940bd91c867d9a (patch) | |
tree | 00c6c956c74a778cf98733d820f09f422a0f2765 | |
parent | 87109484600083a6c74d6c5ae1c1a7e8398261b9 (diff) | |
download | uhd-beb1f3c207bcf1ebc6ca1e83f1940bd91c867d9a.tar.gz uhd-beb1f3c207bcf1ebc6ca1e83f1940bd91c867d9a.tar.bz2 uhd-beb1f3c207bcf1ebc6ca1e83f1940bd91c867d9a.zip |
utils: Add scope_exit object
This is a utility for RAII-style operations. An object that will run
code when a scope is left.
Also includes unit tests.
-rw-r--r-- | host/include/uhd/utils/CMakeLists.txt | 1 | ||||
-rw-r--r-- | host/include/uhd/utils/scope_exit.hpp | 55 | ||||
-rw-r--r-- | host/tests/CMakeLists.txt | 1 | ||||
-rw-r--r-- | host/tests/scope_exit_test.cpp | 45 |
4 files changed, 102 insertions, 0 deletions
diff --git a/host/include/uhd/utils/CMakeLists.txt b/host/include/uhd/utils/CMakeLists.txt index dc70b9f03..767e56c44 100644 --- a/host/include/uhd/utils/CMakeLists.txt +++ b/host/include/uhd/utils/CMakeLists.txt @@ -26,6 +26,7 @@ UHD_INSTALL(FILES platform.hpp safe_call.hpp safe_main.hpp + scope_exit.hpp static.hpp tasks.hpp thread_priority.hpp diff --git a/host/include/uhd/utils/scope_exit.hpp b/host/include/uhd/utils/scope_exit.hpp new file mode 100644 index 000000000..953e5e47d --- /dev/null +++ b/host/include/uhd/utils/scope_exit.hpp @@ -0,0 +1,55 @@ +// +// Copyright 2019 Ettus Research, a National Instruments Brand +// +// SPDX-License-Identifier: GPL-3.0-or-later +// + +#ifndef INCLUDED_UHD_SCOPE_EXIT_HPP +#define INCLUDED_UHD_SCOPE_EXIT_HPP + +#include <functional> +#include <memory> + +namespace uhd { namespace utils { + +/*! A class that will execute a function on its destruction + * + * Similar to Boost.ScopeExit. A useful tool for RAII-style operations. + * + * Note: The creation of the object can be costly if converting the exit + * callback to exit_cb_t incurs copying overhead. Keep this in mind when using + * this object in a high-performance path. + */ +class scope_exit +{ +public: + using uptr = std::unique_ptr<scope_exit>; + using exit_cb_t = std::function<void(void)>; + + // \param exit_b The function object ("exit callback") that gets executed + // in the destructor + static uptr make(exit_cb_t&& exit_cb) + { + // When we have C++14, use make_unique instead (TODO) + return uptr(new scope_exit(std::forward<exit_cb_t>(exit_cb))); + } + + ~scope_exit() + { + _exit_cb(); + } + +private: + scope_exit(std::function<void(void)>&& exit_cb) + : _exit_cb(std::forward<std::function<void(void)>>(exit_cb)) + { + // nop + } + + std::function<void(void)> _exit_cb; +}; + +}} /* namespace uhd::rfnoc */ + +#endif /* INCLUDED_UHD_SCOPE_EXIT_HPP */ + diff --git a/host/tests/CMakeLists.txt b/host/tests/CMakeLists.txt index 8a67e3f85..33fbcdbf9 100644 --- a/host/tests/CMakeLists.txt +++ b/host/tests/CMakeLists.txt @@ -39,6 +39,7 @@ set(test_sources narrow_cast_test.cpp property_test.cpp ranges_test.cpp + scope_exit_test.cpp sid_t_test.cpp sensors_test.cpp soft_reg_test.cpp diff --git a/host/tests/scope_exit_test.cpp b/host/tests/scope_exit_test.cpp new file mode 100644 index 000000000..7c05613a8 --- /dev/null +++ b/host/tests/scope_exit_test.cpp @@ -0,0 +1,45 @@ +// +// Copyright 2019 Ettus Research, a National Instruments Brand +// +// SPDX-License-Identifier: GPL-3.0-or-later +// + +#include <uhd/utils/scope_exit.hpp> +#include <boost/test/unit_test.hpp> +#include <iostream> + +BOOST_AUTO_TEST_CASE(test_scope_exit) +{ + bool flag = false; + { + auto flag_setter = uhd::utils::scope_exit::make([&flag]() { flag = true; }); + BOOST_CHECK(!flag); + } + BOOST_CHECK(flag); +} + +BOOST_AUTO_TEST_CASE(test_scope_exit_function_object) +{ + bool flag = false; + std::function<void(void)> resetter = [&flag]() { flag = true; }; + + { + auto flag_setter = uhd::utils::scope_exit::make(std::move(resetter)); + BOOST_CHECK(!flag); + } + BOOST_CHECK(flag); +} + +BOOST_AUTO_TEST_CASE(test_scope_exit_function_named_lambda) +{ + bool flag = false; + auto resetter = [&flag]() { flag = true; }; + + { + // Note: Does not require std::move() + auto flag_setter = uhd::utils::scope_exit::make(resetter); + BOOST_CHECK(!flag); + } + BOOST_CHECK(flag); +} + |