Commit | Line | Data |
---|---|---|
5b9b3e53 PA |
1 | /* Copyright (C) 2019 Free Software Foundation, Inc. |
2 | ||
3 | This file is part of GDB. | |
4 | ||
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. | |
9 | ||
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. | |
14 | ||
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/>. */ | |
17 | ||
18 | #ifndef COMMON_FORWARD_SCOPE_EXIT_H | |
19 | #define COMMON_FORWARD_SCOPE_EXIT_H | |
20 | ||
268a13a5 | 21 | #include "gdbsupport/scope-exit.h" |
5b9b3e53 PA |
22 | #include <functional> |
23 | ||
24 | /* A forward_scope_exit is like scope_exit, but instead of giving it a | |
25 | callable, you instead specialize it for a given cleanup function, | |
26 | and the generated class automatically has a constructor with the | |
27 | same interface as the cleanup function. forward_scope_exit | |
28 | captures the arguments passed to the ctor, and in turn passes those | |
29 | as arguments to the wrapped cleanup function, when it is called at | |
30 | scope exit time, from within the forward_scope_exit dtor. The | |
31 | forward_scope_exit class can take any number of arguments, and is | |
32 | cancelable if needed. | |
33 | ||
34 | This allows usage like this: | |
35 | ||
36 | void | |
37 | delete_longjmp_breakpoint (int arg) | |
38 | { | |
39 | // Blah, blah, blah... | |
40 | } | |
41 | ||
42 | using longjmp_breakpoint_cleanup | |
43 | = FORWARD_SCOPE_EXIT (delete_longjmp_breakpoint); | |
44 | ||
45 | This above created a new cleanup class `longjmp_breakpoint_cleanup` | |
46 | than can then be used like this: | |
47 | ||
48 | longjmp_breakpoint_cleanup obj (thread); | |
49 | ||
50 | // Blah, blah, blah... | |
51 | ||
52 | obj.release (); // Optional cancel if needed. | |
53 | ||
54 | forward_scope_exit is also handy when you would need to wrap a | |
55 | scope_exit in a gdb::optional: | |
56 | ||
57 | gdb::optional<longjmp_breakpoint_cleanup> cleanup; | |
58 | if (some condition) | |
59 | cleanup.emplace (thread); | |
60 | ... | |
61 | if (cleanup) | |
62 | cleanup->release (); | |
63 | ||
64 | since with scope exit, you would have to know the scope_exit's | |
65 | callable template type when you create the gdb::optional: | |
66 | ||
67 | gdb:optional<scope_exit<what goes here?>> | |
68 | ||
69 | The "forward" naming fits both purposes shown above -- the class | |
70 | "forwards" ctor arguments to the wrapped cleanup function at scope | |
71 | exit time, and can also be used to "forward declare" | |
72 | scope_exit-like objects. */ | |
73 | ||
74 | namespace detail | |
75 | { | |
76 | ||
77 | /* Function and Signature are passed in the same type, in order to | |
78 | extract Function's arguments' types in the specialization below. | |
79 | Those are used to generate the constructor. */ | |
80 | ||
81 | template<typename Function, Function *function, typename Signature> | |
82 | struct forward_scope_exit; | |
83 | ||
84 | template<typename Function, Function *function, | |
85 | typename Res, typename... Args> | |
86 | class forward_scope_exit<Function, function, Res (Args...)> | |
87 | : public scope_exit_base<forward_scope_exit<Function, | |
88 | function, | |
89 | Res (Args...)>> | |
90 | { | |
91 | /* For access to on_exit(). */ | |
92 | friend scope_exit_base<forward_scope_exit<Function, | |
93 | function, | |
94 | Res (Args...)>>; | |
95 | ||
96 | public: | |
97 | explicit forward_scope_exit (Args ...args) | |
3046d67a | 98 | : m_bind_function (function, args...) |
5b9b3e53 PA |
99 | { |
100 | /* Nothing. */ | |
101 | } | |
102 | ||
103 | private: | |
104 | void on_exit () | |
105 | { | |
106 | m_bind_function (); | |
107 | } | |
108 | ||
109 | /* The function and the arguments passed to the ctor, all packed in | |
110 | a std::bind. */ | |
111 | decltype (std::bind (function, std::declval<Args> ()...)) | |
112 | m_bind_function; | |
113 | }; | |
114 | ||
115 | } /* namespace detail */ | |
116 | ||
117 | /* This is the "public" entry point. It's a macro to avoid having to | |
118 | name FUNC more than once. */ | |
119 | ||
120 | #define FORWARD_SCOPE_EXIT(FUNC) \ | |
121 | detail::forward_scope_exit<decltype (FUNC), FUNC, decltype (FUNC)> | |
122 | ||
123 | #endif /* COMMON_FORWARD_SCOPE_EXIT_H */ |