xref: /netbsd-src/external/gpl3/gdb/dist/gdbsupport/forward-scope-exit.h (revision 5ba1f45f2a09259cc846f20c7c5501604d633c90)
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