| /* Copyright (C) 2019-2021 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_FORWARD_SCOPE_EXIT_H | |
| #define COMMON_FORWARD_SCOPE_EXIT_H | |
| #include "gdbsupport/scope-exit.h" | |
| #include <functional> | |
| /* A forward_scope_exit is like scope_exit, but instead of giving it a | |
| callable, you instead specialize it for a given cleanup function, | |
| and the generated class automatically has a constructor with the | |
| same interface as the cleanup function. forward_scope_exit | |
| captures the arguments passed to the ctor, and in turn passes those | |
| as arguments to the wrapped cleanup function, when it is called at | |
| scope exit time, from within the forward_scope_exit dtor. The | |
| forward_scope_exit class can take any number of arguments, and is | |
| cancelable if needed. | |
| This allows usage like this: | |
| void | |
| delete_longjmp_breakpoint (int arg) | |
| { | |
| // Blah, blah, blah... | |
| } | |
| using longjmp_breakpoint_cleanup | |
| = FORWARD_SCOPE_EXIT (delete_longjmp_breakpoint); | |
| This above created a new cleanup class `longjmp_breakpoint_cleanup` | |
| than can then be used like this: | |
| longjmp_breakpoint_cleanup obj (thread); | |
| // Blah, blah, blah... | |
| obj.release (); // Optional cancel if needed. | |
| forward_scope_exit is also handy when you would need to wrap a | |
| scope_exit in a gdb::optional: | |
| gdb::optional<longjmp_breakpoint_cleanup> cleanup; | |
| if (some condition) | |
| cleanup.emplace (thread); | |
| ... | |
| if (cleanup) | |
| cleanup->release (); | |
| since with scope exit, you would have to know the scope_exit's | |
| callable template type when you create the gdb::optional: | |
| gdb:optional<scope_exit<what goes here?>> | |
| The "forward" naming fits both purposes shown above -- the class | |
| "forwards" ctor arguments to the wrapped cleanup function at scope | |
| exit time, and can also be used to "forward declare" | |
| scope_exit-like objects. */ | |
| namespace detail | |
| { | |
| /* Function and Signature are passed in the same type, in order to | |
| extract Function's arguments' types in the specialization below. | |
| Those are used to generate the constructor. */ | |
| template<typename Function, Function *function, typename Signature> | |
| struct forward_scope_exit; | |
| template<typename Function, Function *function, | |
| typename Res, typename... Args> | |
| class forward_scope_exit<Function, function, Res (Args...)> | |
| : public scope_exit_base<forward_scope_exit<Function, | |
| function, | |
| Res (Args...)>> | |
| { | |
| /* For access to on_exit(). */ | |
| friend scope_exit_base<forward_scope_exit<Function, | |
| function, | |
| Res (Args...)>>; | |
| public: | |
| explicit forward_scope_exit (Args ...args) | |
| : m_bind_function (function, args...) | |
| { | |
| /* Nothing. */ | |
| } | |
| private: | |
| void on_exit () | |
| { | |
| m_bind_function (); | |
| } | |
| /* The function and the arguments passed to the ctor, all packed in | |
| a std::bind. */ | |
| decltype (std::bind (function, std::declval<Args> ()...)) | |
| m_bind_function; | |
| }; | |
| } /* namespace detail */ | |
| /* This is the "public" entry point. It's a macro to avoid having to | |
| name FUNC more than once. */ | |
| #define FORWARD_SCOPE_EXIT(FUNC) \ | |
| detail::forward_scope_exit<decltype (FUNC), FUNC, decltype (FUNC)> | |
| #endif /* COMMON_FORWARD_SCOPE_EXIT_H */ |