123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123 |
- /* 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 */
|