Add translations for various sub-directories
[binutils-gdb.git] / gdbsupport / scope-exit.h
blobc0aadd9cb6698c0761f8b0aa1235570a96fcf42e
1 /* Copyright (C) 2019-2024 Free Software Foundation, Inc.
3 This file is part of GDB.
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>. */
18 #ifndef GDBSUPPORT_SCOPE_EXIT_H
19 #define GDBSUPPORT_SCOPE_EXIT_H
21 #include <functional>
22 #include <type_traits>
23 #include "gdbsupport/preprocessor.h"
25 /* scope_exit is a general-purpose scope guard that calls its exit
26 function at the end of the current scope. A scope_exit may be
27 canceled by calling the "release" method. The API is modeled on
28 P0052R5 - Generic Scope Guard and RAII Wrapper for the Standard
29 Library, which is itself based on Andrej Alexandrescu's
30 ScopeGuard/SCOPE_EXIT.
32 There are two forms available:
34 - The "make_scope_exit" form allows canceling the scope guard. Use
35 it like this:
37 auto cleanup = make_scope_exit ( <function, function object, lambda> );
38 ...
39 cleanup.release (); // cancel
41 - If you don't need to cancel the guard, you can use the SCOPE_EXIT
42 macro, like this:
44 SCOPE_EXIT
46 // any code you like here.
49 See also forward_scope_exit.
52 /* CRTP base class for cancelable scope_exit-like classes. Implements
53 the common call-custom-function-from-dtor functionality. Classes
54 that inherit this implement the on_exit() method, which is called
55 from scope_exit_base's dtor. */
57 template <typename CRTP>
58 class scope_exit_base
60 public:
61 scope_exit_base () = default;
63 ~scope_exit_base ()
65 if (!m_released)
67 auto *self = static_cast<CRTP *> (this);
68 self->on_exit ();
72 DISABLE_COPY_AND_ASSIGN (scope_exit_base);
74 /* If this is called, then the wrapped function will not be called
75 on destruction. */
76 void release () noexcept
78 m_released = true;
81 private:
83 /* True if released. Mutable because of the copy ctor hack
84 above. */
85 mutable bool m_released = false;
88 /* The scope_exit class. */
90 template<typename EF>
91 class scope_exit : public scope_exit_base<scope_exit<EF>>
93 /* For access to on_exit(). */
94 friend scope_exit_base<scope_exit<EF>>;
96 public:
98 template<typename EFP,
99 typename = gdb::Requires<std::is_constructible<EF, EFP>>>
100 scope_exit (EFP &&f)
101 try : m_exit_function ((!std::is_lvalue_reference<EFP>::value
102 && std::is_nothrow_constructible<EF, EFP>::value)
103 ? std::move (f)
104 : f)
107 catch (...)
109 /* "If the initialization of exit_function throws an exception,
110 calls f()." */
111 f ();
112 /* "throws: Nothing, unless the initialization of exit_function
113 throws." */
114 throw;
117 template<typename EFP,
118 typename = gdb::Requires<std::is_constructible<EF, EFP>>>
119 scope_exit (scope_exit &&rhs)
120 noexcept (std::is_nothrow_move_constructible<EF>::value
121 || std::is_nothrow_copy_constructible<EF>::value)
122 : m_exit_function (std::is_nothrow_constructible<EFP>::value
123 ? std::move (rhs)
124 : rhs)
126 rhs.release ();
129 DISABLE_COPY_AND_ASSIGN (scope_exit);
130 void operator= (scope_exit &&) = delete;
132 private:
133 void on_exit ()
135 m_exit_function ();
138 /* The function to call on scope exit. */
139 EF m_exit_function;
142 template <typename EF>
143 scope_exit<typename std::decay<EF>::type>
144 make_scope_exit (EF &&f)
146 return scope_exit<typename std::decay<EF>::type> (std::forward<EF> (f));
149 namespace detail
152 enum class scope_exit_lhs {};
154 template<typename EF>
155 scope_exit<typename std::decay<EF>::type>
156 operator+ (scope_exit_lhs, EF &&rhs)
158 return scope_exit<typename std::decay<EF>::type> (std::forward<EF> (rhs));
163 /* Register a block of code to run on scope exit. Note that the local
164 context is captured by reference, which means you should be careful
165 to avoid inadvertently changing a captured local's value before the
166 scope exit runs. */
168 #define SCOPE_EXIT \
169 auto CONCAT(scope_exit_, __LINE__) = ::detail::scope_exit_lhs () + [&] ()
171 #endif /* GDBSUPPORT_SCOPE_EXIT_H */