Zephyr API Documentation 4.4.99
A Scalable Open Source RTOS
Loading...
Searching...
No Matches
cleanup.h
Go to the documentation of this file.
1
5
6#ifndef ZEPHYR_INCLUDE_CLEANUP_H_
7#define ZEPHYR_INCLUDE_CLEANUP_H_
8
9#include <zephyr/toolchain.h>
10
15
21
22#if defined(CONFIG_SCOPE_CLEANUP_HELPERS) || defined(__DOXYGEN__)
23
85#define SCOPE_VAR_DEFINE(_name, _type, _exit_fn, _init_fn, ...) \
86 static inline void __maybe_unused cleanup_##_name##_exit(_type *p) \
87 { \
88 _type _T = *p; \
89 _exit_fn; \
90 } \
91 static inline _type __maybe_unused cleanup_##_name##_init(__VA_ARGS__) \
92 { \
93 _type t = _init_fn; \
94 return t; \
95 } \
96 typedef _type cleanup_##_name##_t
97
118#define SCOPE_GUARD_DEFINE(_name, _type, _lock, _unlock) \
119 SCOPE_VAR_DEFINE( \
120 guard_##_name, _type, if (_T != NULL) { _unlock; }, ({ \
121 _lock; \
122 _T; \
123 }), \
124 _type _T)
125
150#define SCOPE_COND_GUARD_DEFINE(_name, _type, _try_lock, _unlock) \
151 SCOPE_VAR_DEFINE(guard_##_name, _type, if (_T != NULL) { _unlock; }, \
152 ((_try_lock) ? _T : NULL), _type _T)
153
155
156#define Z_SCOPE_DEFER_DEFINE_VOID(_func) \
157 SCOPE_VAR_DEFINE(defer_##_func, void *, (void)_T; (void)_func(), NULL, void)
158
159#define Z_DEFER_CTX_ARG(idx, t) t arg##idx;
160#define Z_DEFER_FUNC_ARG(idx, t) t arg##idx
161#define Z_DEFER_INIT_ARG(idx, _) .arg##idx = arg##idx
162#define Z_DEFER_EXIT_ARG(idx, _) _T.arg##idx
163#define Z_COMMA ,
164
165#define Z_SCOPE_DEFER_DEFINE_N(_func, ...) \
166 struct defer_##_func##_ctx { \
167 FOR_EACH_IDX(Z_DEFER_CTX_ARG, (), __VA_ARGS__) \
168 }; \
169 SCOPE_VAR_DEFINE(defer_##_func, struct defer_##_func##_ctx, \
170 (void)_func(FOR_EACH_IDX(Z_DEFER_EXIT_ARG, (Z_COMMA), __VA_ARGS__)), \
171 {FOR_EACH_IDX(Z_DEFER_INIT_ARG, (Z_COMMA), __VA_ARGS__)}, \
172 FOR_EACH_IDX(Z_DEFER_FUNC_ARG, (Z_COMMA), __VA_ARGS__))
173
175
192#define SCOPE_DEFER_DEFINE(_func, ...) \
193 COND_CODE_0(NUM_VA_ARGS(__VA_ARGS__), \
194 (Z_SCOPE_DEFER_DEFINE_VOID(_func)), \
195 (Z_SCOPE_DEFER_DEFINE_N(_func, __VA_ARGS__)))
196
198
204#define Z_UNIQUE_ID(_prefix) _CONCAT(_CONCAT(Z_UNIQUE_ID_, _prefix), __COUNTER__)
205
206/*
207 * Block-scope wrapper for @ref scoped_guard. A single-iteration nested for-loop ties the
208 * lifetime of the guard variable (_g) - and thus its cleanup/release - to the brace body
209 * that follows. The body is guarded on _g != NULL so that a conditional guard whose
210 * acquisition fails skips the body instead of running it without the lock held.
211 * For an unconditional guard _g is always non-NULL.
212 */
213#define Z_SCOPED_GUARD(_name, _g, _done, ...) \
214 for (int _done = 0; _done == 0; _done = 1) \
215 for (scope_var(guard_##_name, _g)(__VA_ARGS__); _done == 0 && _g != NULL; \
216 _done = 1)
217
218/*
219 * Block-scope wrapper for @ref scoped_cond_guard. Like Z_SCOPED_GUARD but the guard
220 * variable is named (_g) so the body can be guarded on whether the lock was acquired:
221 * when acquisition fails _g is NULL, _fail runs and the body is skipped.
222 */
223#define Z_SCOPED_COND_GUARD(_name, _g, _done, _fail, ...) \
224 for (int _done = 0; _done == 0; _done = 1) \
225 for (scope_var(guard_##_name, _g)(__VA_ARGS__); _done == 0; _done = 1) \
226 if (_g == NULL) { \
227 _fail; \
228 } else
229
231
251#define scope_var(_name, _var) \
252 cleanup_##_name##_t _var __cleanup(cleanup_##_name##_exit) = cleanup_##_name##_init
253
276#define scope_var_init(_name, _var, _init_expr) \
277 cleanup_##_name##_t _var __cleanup(cleanup_##_name##_exit) = (_init_expr)
278
292#define scope_guard(_name) scope_var(guard_##_name, Z_UNIQUE_ID(guard))
293
325#define scoped_guard(_name, ...) \
326 Z_SCOPED_GUARD(_name, Z_UNIQUE_ID(scoped_g), Z_UNIQUE_ID(scoped_done), __VA_ARGS__)
327
354#define scoped_cond_guard(_name, _fail, ...) \
355 Z_SCOPED_COND_GUARD(_name, Z_UNIQUE_ID(scoped_g), Z_UNIQUE_ID(scoped_done), _fail, \
356 __VA_ARGS__)
357
371#define scope_defer(_name) scope_var(defer_##_name, Z_UNIQUE_ID(defer))
372
376
377#endif /* defined(CONFIG_SCOPE_CLEANUP_HELPERS) || defined(__DOXYGEN__) */
378
379#endif /* ZEPHYR_INCLUDE_CLEANUP_H_ */
Macros to abstract toolchain specific capabilities.