1*5ba1f45fSchristos /* Copyright (C) 2019-2024 Free Software Foundation, Inc. 28dffb485Schristos 38dffb485Schristos This file is part of GDB. 48dffb485Schristos 58dffb485Schristos This program is free software; you can redistribute it and/or modify 68dffb485Schristos it under the terms of the GNU General Public License as published by 78dffb485Schristos the Free Software Foundation; either version 3 of the License, or 88dffb485Schristos (at your option) any later version. 98dffb485Schristos 108dffb485Schristos This program is distributed in the hope that it will be useful, 118dffb485Schristos but WITHOUT ANY WARRANTY; without even the implied warranty of 128dffb485Schristos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 138dffb485Schristos GNU General Public License for more details. 148dffb485Schristos 158dffb485Schristos You should have received a copy of the GNU General Public License 168dffb485Schristos along with this program. If not, see <http://www.gnu.org/licenses/>. */ 178dffb485Schristos 188dffb485Schristos #ifndef COMMON_FORWARD_SCOPE_EXIT_H 198dffb485Schristos #define COMMON_FORWARD_SCOPE_EXIT_H 208dffb485Schristos 218dffb485Schristos #include "gdbsupport/scope-exit.h" 228dffb485Schristos #include <functional> 238dffb485Schristos 248dffb485Schristos /* A forward_scope_exit is like scope_exit, but instead of giving it a 258dffb485Schristos callable, you instead specialize it for a given cleanup function, 268dffb485Schristos and the generated class automatically has a constructor with the 278dffb485Schristos same interface as the cleanup function. forward_scope_exit 288dffb485Schristos captures the arguments passed to the ctor, and in turn passes those 298dffb485Schristos as arguments to the wrapped cleanup function, when it is called at 308dffb485Schristos scope exit time, from within the forward_scope_exit dtor. The 318dffb485Schristos forward_scope_exit class can take any number of arguments, and is 328dffb485Schristos cancelable if needed. 338dffb485Schristos 348dffb485Schristos This allows usage like this: 358dffb485Schristos 368dffb485Schristos void 378dffb485Schristos delete_longjmp_breakpoint (int arg) 388dffb485Schristos { 398dffb485Schristos // Blah, blah, blah... 408dffb485Schristos } 418dffb485Schristos 428dffb485Schristos using longjmp_breakpoint_cleanup 438dffb485Schristos = FORWARD_SCOPE_EXIT (delete_longjmp_breakpoint); 448dffb485Schristos 458dffb485Schristos This above created a new cleanup class `longjmp_breakpoint_cleanup` 468dffb485Schristos than can then be used like this: 478dffb485Schristos 488dffb485Schristos longjmp_breakpoint_cleanup obj (thread); 498dffb485Schristos 508dffb485Schristos // Blah, blah, blah... 518dffb485Schristos 528dffb485Schristos obj.release (); // Optional cancel if needed. 538dffb485Schristos 548dffb485Schristos forward_scope_exit is also handy when you would need to wrap a 55*5ba1f45fSchristos scope_exit in a std::optional: 568dffb485Schristos 57*5ba1f45fSchristos std::optional<longjmp_breakpoint_cleanup> cleanup; 588dffb485Schristos if (some condition) 598dffb485Schristos cleanup.emplace (thread); 608dffb485Schristos ... 618dffb485Schristos if (cleanup) 628dffb485Schristos cleanup->release (); 638dffb485Schristos 648dffb485Schristos since with scope exit, you would have to know the scope_exit's 65*5ba1f45fSchristos callable template type when you create the std::optional: 668dffb485Schristos 678dffb485Schristos gdb:optional<scope_exit<what goes here?>> 688dffb485Schristos 698dffb485Schristos The "forward" naming fits both purposes shown above -- the class 708dffb485Schristos "forwards" ctor arguments to the wrapped cleanup function at scope 718dffb485Schristos exit time, and can also be used to "forward declare" 728dffb485Schristos scope_exit-like objects. */ 738dffb485Schristos 748dffb485Schristos namespace detail 758dffb485Schristos { 768dffb485Schristos 778dffb485Schristos /* Function and Signature are passed in the same type, in order to 788dffb485Schristos extract Function's arguments' types in the specialization below. 798dffb485Schristos Those are used to generate the constructor. */ 808dffb485Schristos 818dffb485Schristos template<typename Function, Function *function, typename Signature> 828dffb485Schristos struct forward_scope_exit; 838dffb485Schristos 848dffb485Schristos template<typename Function, Function *function, 858dffb485Schristos typename Res, typename... Args> 868dffb485Schristos class forward_scope_exit<Function, function, Res (Args...)> 878dffb485Schristos : public scope_exit_base<forward_scope_exit<Function, 888dffb485Schristos function, 898dffb485Schristos Res (Args...)>> 908dffb485Schristos { 918dffb485Schristos /* For access to on_exit(). */ 928dffb485Schristos friend scope_exit_base<forward_scope_exit<Function, 938dffb485Schristos function, 948dffb485Schristos Res (Args...)>>; 958dffb485Schristos 968dffb485Schristos public: 978dffb485Schristos explicit forward_scope_exit (Args ...args) 988dffb485Schristos : m_bind_function (function, args...) 998dffb485Schristos { 1008dffb485Schristos /* Nothing. */ 1018dffb485Schristos } 1028dffb485Schristos 1038dffb485Schristos private: 1048dffb485Schristos void on_exit () 1058dffb485Schristos { 1068dffb485Schristos m_bind_function (); 1078dffb485Schristos } 1088dffb485Schristos 1098dffb485Schristos /* The function and the arguments passed to the ctor, all packed in 1108dffb485Schristos a std::bind. */ 1118dffb485Schristos decltype (std::bind (function, std::declval<Args> ()...)) 1128dffb485Schristos m_bind_function; 1138dffb485Schristos }; 1148dffb485Schristos 1158dffb485Schristos } /* namespace detail */ 1168dffb485Schristos 1178dffb485Schristos /* This is the "public" entry point. It's a macro to avoid having to 1188dffb485Schristos name FUNC more than once. */ 1198dffb485Schristos 1208dffb485Schristos #define FORWARD_SCOPE_EXIT(FUNC) \ 1218dffb485Schristos detail::forward_scope_exit<decltype (FUNC), FUNC, decltype (FUNC)> 1228dffb485Schristos 1238dffb485Schristos #endif /* COMMON_FORWARD_SCOPE_EXIT_H */ 124