diff options
Diffstat (limited to 'gdb/common/scope-exit.h')
-rw-r--r-- | gdb/common/scope-exit.h | 186 |
1 files changed, 0 insertions, 186 deletions
diff --git a/gdb/common/scope-exit.h b/gdb/common/scope-exit.h deleted file mode 100644 index 8cdbec3..0000000 --- a/gdb/common/scope-exit.h +++ /dev/null @@ -1,186 +0,0 @@ -/* Copyright (C) 2019 Free Software Foundation, Inc. - - This file is part of GDB. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. */ - -#ifndef COMMON_SCOPE_EXIT_H -#define COMMON_SCOPE_EXIT_H - -#include <functional> -#include <type_traits> -#include "common/preprocessor.h" - -/* scope_exit is a general-purpose scope guard that calls its exit - function at the end of the current scope. A scope_exit may be - canceled by calling the "release" method. The API is modeled on - P0052R5 - Generic Scope Guard and RAII Wrapper for the Standard - Library, which is itself based on Andrej Alexandrescu's - ScopeGuard/SCOPE_EXIT. - - There are two forms available: - - - The "make_scope_exit" form allows canceling the scope guard. Use - it like this: - - auto cleanup = make_scope_exit ( <function, function object, lambda> ); - ... - cleanup.release (); // cancel - - - If you don't need to cancel the guard, you can use the SCOPE_EXIT - macro, like this: - - SCOPE_EXIT - { - // any code you like here. - } - - See also forward_scope_exit. -*/ - -/* CRTP base class for cancelable scope_exit-like classes. Implements - the common call-custom-function-from-dtor functionality. Classes - that inherit this implement the on_exit() method, which is called - from scope_exit_base's dtor. */ - -template <typename CRTP> -class scope_exit_base -{ -public: - scope_exit_base () = default; - - ~scope_exit_base () - { - if (!m_released) - { - auto *self = static_cast<CRTP *> (this); - self->on_exit (); - } - } - - /* This is needed for make_scope_exit because copy elision isn't - guaranteed until C++17. An optimizing compiler will usually skip - calling this, but it must exist. */ - scope_exit_base (const scope_exit_base &other) - : m_released (other.m_released) - { - other.m_released = true; - } - - void operator= (const scope_exit_base &) = delete; - - /* If this is called, then the wrapped function will not be called - on destruction. */ - void release () noexcept - { - m_released = true; - } - -private: - - /* True if released. Mutable because of the copy ctor hack - above. */ - mutable bool m_released = false; -}; - -/* The scope_exit class. */ - -template<typename EF> -class scope_exit : public scope_exit_base<scope_exit<EF>> -{ - /* For access to on_exit(). */ - friend scope_exit_base<scope_exit<EF>>; - -public: - - template<typename EFP, - typename = gdb::Requires<std::is_constructible<EF, EFP>>> - scope_exit (EFP &&f) - try : m_exit_function ((!std::is_lvalue_reference<EFP>::value - && std::is_nothrow_constructible<EF, EFP>::value) - ? std::move (f) - : f) - { - } - catch (...) - { - /* "If the initialization of exit_function throws an exception, - calls f()." */ - f (); - } - - template<typename EFP, - typename = gdb::Requires<std::is_constructible<EF, EFP>>> - scope_exit (scope_exit &&rhs) - noexcept (std::is_nothrow_move_constructible<EF>::value - || std::is_nothrow_copy_constructible<EF>::value) - : m_exit_function (std::is_nothrow_constructible<EFP>::value - ? std::move (rhs) - : rhs) - { - rhs.release (); - } - - /* This is needed for make_scope_exit because copy elision isn't - guaranteed until C++17. An optimizing compiler will usually skip - calling this, but it must exist. */ - scope_exit (const scope_exit &other) - : scope_exit_base<scope_exit<EF>> (other), - m_exit_function (other.m_exit_function) - { - } - - void operator= (const scope_exit &) = delete; - void operator= (scope_exit &&) = delete; - -private: - void on_exit () - { - m_exit_function (); - } - - /* The function to call on scope exit. */ - EF m_exit_function; -}; - -template <typename EF> -scope_exit<typename std::decay<EF>::type> -make_scope_exit (EF &&f) -{ - return scope_exit<typename std::decay<EF>::type> (std::forward<EF> (f)); -} - -namespace detail -{ - -enum class scope_exit_lhs {}; - -template<typename EF> -scope_exit<typename std::decay<EF>::type> -operator+ (scope_exit_lhs, EF &&rhs) -{ - return scope_exit<typename std::decay<EF>::type> (std::forward<EF> (rhs)); -} - -} - -/* Register a block of code to run on scope exit. Note that the local - context is captured by reference, which means you should be careful - to avoid inadvertently changing a captured local's value before the - scope exit runs. */ - -#define SCOPE_EXIT \ - auto CONCAT(scope_exit_, __LINE__) = ::detail::scope_exit_lhs () + [&] () - -#endif /* COMMON_SCOPE_EXIT_H */ |