Commit | Line | Data |
---|---|---|
d58b8198 MW |
1 | .\" -*-nroff-*- |
2 | .TH control 3 "28 April 2023" "Straylight/Edgeware" "FINALLY macro package" | |
3 | .SH NAME | |
4 | FINALLY \- defer execution until scope exit | |
5 | .SH SYNOPSIS | |
6 | .nf | |
7 | .B "#include <finally.h>" | |
8 | ||
9 | .BI FINALLY( stmt ); | |
10 | .BI FINALLY_TAGGED( tag ", " stmt ); | |
11 | .fi | |
12 | . | |
13 | .SH DESCRIPTION | |
14 | . | |
15 | .SS "General usage of FINALLY" | |
16 | The | |
17 | .B FINALLY | |
18 | macro arranges that the statement | |
19 | .I stmt | |
20 | should be executed when control leaves the immediately enclosing scope, | |
21 | whether this is by just running off the end, or by explicit control | |
22 | flow, e.g., | |
23 | .BR return , | |
24 | .BR goto , | |
25 | .BR break, | |
26 | or | |
27 | .BR continue . | |
28 | If a scope contains multiple | |
29 | .B FINALLY | |
30 | calls, then the statements are executed in reverse order. | |
31 | .PP | |
32 | In particular, if the macro call is placed at top-level within a | |
33 | function body, then | |
34 | .I stmt | |
35 | is executed when the function returns, either as a result of a | |
36 | .B return | |
37 | statement, or by running off the end of the function body. | |
38 | .PP | |
39 | With GNU-like compilers, you can arrange for the statement to be | |
40 | executed when control escapes the scope as the result of a C++ exception | |
41 | by setting the | |
42 | .B \-fexceptions | |
43 | compiler flag. | |
44 | .PP | |
45 | The statement will | |
46 | .I not | |
47 | be executed if control leaves the scope as a result of | |
48 | .BR longjmp (3) | |
49 | or similar. It also won't be executed if control `leaves' as a result | |
50 | of a call to | |
51 | .BR exit (3) | |
52 | or similar; but that's almost certainly what you want. | |
53 | .PP | |
54 | The | |
55 | .B FINALLY | |
56 | macro's expansion is syntactically one or more declarations. In C89 | |
57 | code, therefore, it must appear at the head of a block, before any | |
58 | statements. In C99 or later, it may appear anywhere in a block. | |
59 | However, because it may expand to more than one declaration, it is not | |
60 | suitable for use in a | |
61 | .B for | |
62 | statement. | |
63 | . | |
64 | .SS "Macros and FINALLY_TAGGED" | |
65 | At most one use of | |
66 | .B FINALLY | |
67 | can occur on any given line of source code. In particular, this | |
68 | rule forbids macros which expand into more than one use of | |
69 | .BR FINALLY , | |
70 | since the macro expansions will cause them all to be credited to the | |
71 | line holding the original expansion site. To avoid trouble, macro | |
72 | authors should use | |
73 | .B FINALLY_TAGGED | |
74 | instead. Each use of | |
75 | .B FINALLY_TAGGED | |
76 | on the same source line must have a distinct | |
77 | .I tag | |
78 | argument, which may be any identifier. | |
79 | . | |
80 | .SS "Nonlocal transfers, and thread and process exits" | |
81 | The statement will | |
82 | .I not | |
83 | be executed if control leaves the scope as a result of | |
84 | .BR longjmp (3) | |
85 | or similar. It also won't be executed if control `leaves' as a result | |
86 | of a call to | |
87 | .BR exit (3), | |
88 | .BR pthread_exit (3), | |
89 | .BR thrd_exit (3), | |
90 | or similar. | |
91 | .PP | |
92 | You didn't want | |
93 | .B FINALLY | |
94 | blocks to run at | |
95 | .BR exit (3) | |
96 | time. Almost all uses of | |
97 | .B FINALLY | |
98 | are to release process-local resources such as memory, file descriptors | |
99 | or locks, or something else similar. The kernel will release these by | |
100 | itself when the process exits, because leaking resources when processes | |
101 | crash would just be too awful to consider. All you'd achieve by | |
102 | carefully freeing memory prior to | |
103 | .BR exit (3) | |
104 | would be to waste time. | |
105 | . | |
106 | .SS "Setup and configuration" | |
107 | The | |
108 | .B FINALLY | |
109 | macro uses compiler-specific techniques. Not only does it need | |
110 | different implementations on different compilers, but it may require | |
111 | unusual compiler options and runtime support libraries to work. | |
112 | .PP | |
113 | Firstly, the | |
114 | .B <finally.h> | |
115 | header can work portably under C++11 or later, using RAII and lambdas: | |
116 | idiomatic C++ doesn't benefit much from this, but the facility is there | |
117 | anyway. If the header detects that such a compiler is in use (the macro | |
118 | .B __cplusplus | |
119 | is defined to a value greater than or equal to 201103), then it will use | |
120 | the C++-specific implementation. | |
121 | .PP | |
122 | Otherwise, the header checks the value of | |
123 | .BR FINALLY_CONFIG_FLAVOUR : | |
124 | it should be one of the following options. | |
125 | .TP | |
126 | .B NIL | |
127 | No support. An error is reported (using | |
128 | .BR #error ). | |
129 | .TP | |
130 | .B GCC_NESTED_FUNCTIONS | |
131 | Use the GNU C Compiler's support for nested functions and the | |
132 | .B cleanup | |
133 | function attribute. Note that this use of nested functions does not | |
134 | involve the use of trampolines, and does not require an executable | |
135 | stack. (This is verified as part of the package tests.) | |
31ac64c4 MW |
136 | .TP |
137 | .B CLANG_BLOCKS | |
138 | Use the LLVM Clang compiler's support for `blocks' and the | |
139 | .B cleanup | |
140 | function attribute. Depending on the environment, this may require the | |
141 | .B \-fblocks | |
142 | compiler option, and linking against the | |
143 | .B \-lBlocksRuntime | |
144 | library. | |
145 | .IP | |
146 | Support is only partial. When the statement is executed on exit from | |
147 | its scope, it sees the variable values that were current when the | |
148 | .B FINALLY | |
149 | declaration was processed, and not any changes since. As a result of | |
150 | this bug, the | |
151 | .B <finally.h> | |
152 | header will fail unless the macro | |
153 | .B FINALLY_TOLERATE_BUG_CAPTURE_COPIES | |
154 | is defined to a nonzero value, and will set | |
155 | .B FINALLY_BUG_CAPTURE_COPIES | |
156 | for your program to act on. | |
d58b8198 MW |
157 | .PP |
158 | If | |
159 | .B FINALLY_CONFIG_FLAVOUR | |
160 | is not set, then | |
161 | .B <finally.h> | |
162 | guesses one of these flavours based on the compiler version and other | |
163 | predefined macros. This guess may be wrong, and things may not work | |
164 | anyway because necessary compiler options or libraries aren't available. | |
165 | .PP | |
166 | The best way to set everything up correctly is to use the provided | |
167 | .B FINALLY_CHECK | |
168 | Autoconf macro. It will define | |
169 | .B FINALLY_CONFIG_FLAVOUR | |
170 | to a suitable value, and also report necessary compiler flags and | |
171 | libraries in the | |
172 | .B FINALLY_CFLAGS | |
173 | and | |
174 | .B FINALLY_LIBS | |
175 | makefile variables. See the | |
176 | .B finally.m4 | |
177 | file's internal documentation for the details. | |
178 | . | |
179 | .SH BUGS | |
180 | The selection of supported compilers is extremely limited. | |
31ac64c4 MW |
181 | .PP |
182 | Clang doesn't work properly because its `blocks' capture a copy of the | |
183 | outer scope's variables, rather than closing over them properly. | |
d58b8198 MW |
184 | . |
185 | .SH AUTHOR | |
186 | Mark Wooding, <mdw@distorted.org.uk> |