|  | /* Copyright (C) 2019-2022 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 */ |