From: Pedro Alves Date: Wed, 23 Jan 2019 18:58:29 +0000 (+0000) Subject: Introduce forward_scope_exit X-Git-Url: http://git.efficios.com/?a=commitdiff_plain;h=5b9b3e53a68f4568dc0b6907e34e763a6c3dd145;p=deliverable%2Fbinutils-gdb.git 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 Andrew Burgess * common/forward-scope-exit.h: New file. --- diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 996ca18e14..dff515d8ce 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,8 @@ +2019-01-23 Pedro Alves + Andrew Burgess + + * common/forward-scope-exit.h: New file. + 2019-01-23 Pedro Alves Andrew Burgess Tom Tromey diff --git a/gdb/common/forward-scope-exit.h b/gdb/common/forward-scope-exit.h new file mode 100644 index 0000000000..8d639151a4 --- /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 . */ + +#ifndef COMMON_FORWARD_SCOPE_EXIT_H +#define COMMON_FORWARD_SCOPE_EXIT_H + +#include "common/scope-exit.h" +#include + +/* 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 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> + + 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 +struct forward_scope_exit; + +template +class forward_scope_exit + : public scope_exit_base> +{ + /* For access to on_exit(). */ + friend scope_exit_base>; + +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 ()...)) + 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 + +#endif /* COMMON_FORWARD_SCOPE_EXIT_H */