diff options
author | Pedro Alves <palves@redhat.com> | 2019-01-23 18:58:29 +0000 |
---|---|---|
committer | Pedro Alves <palves@redhat.com> | 2019-01-23 19:03:20 +0000 |
commit | 5b9b3e53a68f4568dc0b6907e34e763a6c3dd145 (patch) | |
tree | 88330e51c94cb494319813787fe23e42abeee4b1 /gdb | |
parent | 54b65c9b51ec80ef5812dde1a508ce171eeb8ce6 (diff) | |
download | gdb-5b9b3e53a68f4568dc0b6907e34e763a6c3dd145.zip gdb-5b9b3e53a68f4568dc0b6907e34e763a6c3dd145.tar.gz gdb-5b9b3e53a68f4568dc0b6907e34e763a6c3dd145.tar.bz2 |
Introduce forward_scope_exit
This adds a template that can be used to automatically instantiate
scope_exit-like types that wrap some cleanup function. The
instantiated type has a ctor that has the same interface as the
wrapped function. While the "magic" is just straight C++11, the
intended use is via the FORWARD_SCOPE_EXIT macro, which is a minimal
macro that avoids spelling out the wrapped function name more than
once:
void some_function (int foo, object *bar);
using some_function_fce = FORWARD_SCOPE_EXIT (some_function);
some_function_fce cleanup (some_int, some_obj_ptr);
The above runs:
some_function (some_int, some_obj_ptr);
at scope exit.
This is mainly useful as opposed to a simpler SCOPE_EXIT when you need
to:
- cancel the scope_exit, in which case you need the object's name
- wrap the scope_exit in a gdb::optional, in which case you need the
scope_exit's type in advance.
More details in the code comments.
gdb/ChangeLog:
2019-01-23 Pedro Alves <palves@redhat.com>
Andrew Burgess <andrew.burgess@embecosm.com>
* common/forward-scope-exit.h: New file.
Diffstat (limited to 'gdb')
-rw-r--r-- | gdb/ChangeLog | 5 | ||||
-rw-r--r-- | gdb/common/forward-scope-exit.h | 123 |
2 files changed, 128 insertions, 0 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 996ca18..dff515d 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,5 +1,10 @@ 2019-01-23 Pedro Alves <palves@redhat.com> Andrew Burgess <andrew.burgess@embecosm.com> + + * common/forward-scope-exit.h: New file. + +2019-01-23 Pedro Alves <palves@redhat.com> + Andrew Burgess <andrew.burgess@embecosm.com> Tom Tromey <tom@tromey.com> * common/scope-exit.h: New file. diff --git a/gdb/common/forward-scope-exit.h b/gdb/common/forward-scope-exit.h new file mode 100644 index 0000000..8d63915 --- /dev/null +++ b/gdb/common/forward-scope-exit.h @@ -0,0 +1,123 @@ +/* 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_FORWARD_SCOPE_EXIT_H +#define COMMON_FORWARD_SCOPE_EXIT_H + +#include "common/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 (std::bind (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 */ |