1*6881a400Schristos /* Copyright (C) 2019-2023 Free Software Foundation, Inc. 27d62b00eSchristos 37d62b00eSchristos This file is part of GDB. 47d62b00eSchristos 57d62b00eSchristos This program is free software; you can redistribute it and/or modify 67d62b00eSchristos it under the terms of the GNU General Public License as published by 77d62b00eSchristos the Free Software Foundation; either version 3 of the License, or 87d62b00eSchristos (at your option) any later version. 97d62b00eSchristos 107d62b00eSchristos This program is distributed in the hope that it will be useful, 117d62b00eSchristos but WITHOUT ANY WARRANTY; without even the implied warranty of 127d62b00eSchristos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 137d62b00eSchristos GNU General Public License for more details. 147d62b00eSchristos 157d62b00eSchristos You should have received a copy of the GNU General Public License 167d62b00eSchristos along with this program. If not, see <http://www.gnu.org/licenses/>. */ 177d62b00eSchristos 187d62b00eSchristos #ifndef COMMON_FORWARD_SCOPE_EXIT_H 197d62b00eSchristos #define COMMON_FORWARD_SCOPE_EXIT_H 207d62b00eSchristos 217d62b00eSchristos #include "gdbsupport/scope-exit.h" 227d62b00eSchristos #include <functional> 237d62b00eSchristos 247d62b00eSchristos /* A forward_scope_exit is like scope_exit, but instead of giving it a 257d62b00eSchristos callable, you instead specialize it for a given cleanup function, 267d62b00eSchristos and the generated class automatically has a constructor with the 277d62b00eSchristos same interface as the cleanup function. forward_scope_exit 287d62b00eSchristos captures the arguments passed to the ctor, and in turn passes those 297d62b00eSchristos as arguments to the wrapped cleanup function, when it is called at 307d62b00eSchristos scope exit time, from within the forward_scope_exit dtor. The 317d62b00eSchristos forward_scope_exit class can take any number of arguments, and is 327d62b00eSchristos cancelable if needed. 337d62b00eSchristos 347d62b00eSchristos This allows usage like this: 357d62b00eSchristos 367d62b00eSchristos void 377d62b00eSchristos delete_longjmp_breakpoint (int arg) 387d62b00eSchristos { 397d62b00eSchristos // Blah, blah, blah... 407d62b00eSchristos } 417d62b00eSchristos 427d62b00eSchristos using longjmp_breakpoint_cleanup 437d62b00eSchristos = FORWARD_SCOPE_EXIT (delete_longjmp_breakpoint); 447d62b00eSchristos 457d62b00eSchristos This above created a new cleanup class `longjmp_breakpoint_cleanup` 467d62b00eSchristos than can then be used like this: 477d62b00eSchristos 487d62b00eSchristos longjmp_breakpoint_cleanup obj (thread); 497d62b00eSchristos 507d62b00eSchristos // Blah, blah, blah... 517d62b00eSchristos 527d62b00eSchristos obj.release (); // Optional cancel if needed. 537d62b00eSchristos 547d62b00eSchristos forward_scope_exit is also handy when you would need to wrap a 557d62b00eSchristos scope_exit in a gdb::optional: 567d62b00eSchristos 577d62b00eSchristos gdb::optional<longjmp_breakpoint_cleanup> cleanup; 587d62b00eSchristos if (some condition) 597d62b00eSchristos cleanup.emplace (thread); 607d62b00eSchristos ... 617d62b00eSchristos if (cleanup) 627d62b00eSchristos cleanup->release (); 637d62b00eSchristos 647d62b00eSchristos since with scope exit, you would have to know the scope_exit's 657d62b00eSchristos callable template type when you create the gdb::optional: 667d62b00eSchristos 677d62b00eSchristos gdb:optional<scope_exit<what goes here?>> 687d62b00eSchristos 697d62b00eSchristos The "forward" naming fits both purposes shown above -- the class 707d62b00eSchristos "forwards" ctor arguments to the wrapped cleanup function at scope 717d62b00eSchristos exit time, and can also be used to "forward declare" 727d62b00eSchristos scope_exit-like objects. */ 737d62b00eSchristos 747d62b00eSchristos namespace detail 757d62b00eSchristos { 767d62b00eSchristos 777d62b00eSchristos /* Function and Signature are passed in the same type, in order to 787d62b00eSchristos extract Function's arguments' types in the specialization below. 797d62b00eSchristos Those are used to generate the constructor. */ 807d62b00eSchristos 817d62b00eSchristos template<typename Function, Function *function, typename Signature> 827d62b00eSchristos struct forward_scope_exit; 837d62b00eSchristos 847d62b00eSchristos template<typename Function, Function *function, 857d62b00eSchristos typename Res, typename... Args> 867d62b00eSchristos class forward_scope_exit<Function, function, Res (Args...)> 877d62b00eSchristos : public scope_exit_base<forward_scope_exit<Function, 887d62b00eSchristos function, 897d62b00eSchristos Res (Args...)>> 907d62b00eSchristos { 917d62b00eSchristos /* For access to on_exit(). */ 927d62b00eSchristos friend scope_exit_base<forward_scope_exit<Function, 937d62b00eSchristos function, 947d62b00eSchristos Res (Args...)>>; 957d62b00eSchristos 967d62b00eSchristos public: 977d62b00eSchristos explicit forward_scope_exit (Args ...args) 987d62b00eSchristos : m_bind_function (function, args...) 997d62b00eSchristos { 1007d62b00eSchristos /* Nothing. */ 1017d62b00eSchristos } 1027d62b00eSchristos 1037d62b00eSchristos private: 1047d62b00eSchristos void on_exit () 1057d62b00eSchristos { 1067d62b00eSchristos m_bind_function (); 1077d62b00eSchristos } 1087d62b00eSchristos 1097d62b00eSchristos /* The function and the arguments passed to the ctor, all packed in 1107d62b00eSchristos a std::bind. */ 1117d62b00eSchristos decltype (std::bind (function, std::declval<Args> ()...)) 1127d62b00eSchristos m_bind_function; 1137d62b00eSchristos }; 1147d62b00eSchristos 1157d62b00eSchristos } /* namespace detail */ 1167d62b00eSchristos 1177d62b00eSchristos /* This is the "public" entry point. It's a macro to avoid having to 1187d62b00eSchristos name FUNC more than once. */ 1197d62b00eSchristos 1207d62b00eSchristos #define FORWARD_SCOPE_EXIT(FUNC) \ 1217d62b00eSchristos detail::forward_scope_exit<decltype (FUNC), FUNC, decltype (FUNC)> 1227d62b00eSchristos 1237d62b00eSchristos #endif /* COMMON_FORWARD_SCOPE_EXIT_H */ 124