5#ifndef SPA_UTILS_CLEANUP_H
6#define SPA_UTILS_CLEANUP_H
8#if !defined(__has_attribute) || !__has_attribute(__cleanup__)
9#error "attribute `cleanup` is required"
12#define spa_cleanup(func) __attribute__((__cleanup__(func)))
14#define SPA_DEFINE_AUTO_CLEANUP(name, type, ...) \
15typedef __typeof__(type) _spa_auto_cleanup_type_ ## name; \
16static inline void _spa_auto_cleanup_func_ ## name (__typeof__(type) *thing) \
21#define spa_auto(name) \
22 spa_cleanup(_spa_auto_cleanup_func_ ## name) \
23 _spa_auto_cleanup_type_ ## name
25#define SPA_DEFINE_AUTOPTR_CLEANUP(name, type, ...) \
26typedef __typeof__(type) * _spa_autoptr_cleanup_type_ ## name; \
27static inline void _spa_autoptr_cleanup_func_ ## name (__typeof__(type) **thing) \
32#define spa_autoptr(name) \
33 spa_cleanup(_spa_autoptr_cleanup_func_ ## name) \
34 _spa_autoptr_cleanup_type_ ## name
36#define spa_exchange(var, new_value) \
38 __typeof__(var) _old_value = (var); \
39 (var) = (new_value); \
43#if __GNUC__ > 10 || defined(__clang__)
44#define spa_steal_ptr(ptr) ((__typeof__(*(ptr)) *) spa_exchange((ptr), NULL))
46#define spa_steal_ptr(ptr) ((__typeof__(ptr)) spa_exchange((ptr), NULL))
49#define spa_steal_fd(fd) spa_exchange((fd), -1)
56#if __GNUC__ > 10 || defined(__clang__)
57#define spa_clear_ptr(ptr, destructor) \
59 __typeof__(*(ptr)) *_old_value = spa_steal_ptr(ptr); \
61 destructor(_old_value); \
65#define spa_clear_ptr(ptr, destructor) \
67 __typeof__(ptr) _old_value = spa_steal_ptr(ptr); \
69 destructor(_old_value); \
74static inline void _spa_autofree_cleanup_func(
void *p)
78#define spa_autofree spa_cleanup(_spa_autofree_cleanup_func)
84#define spa_clear_fd(fd) \
86 int _old_value = spa_steal_fd(fd), _res = 0; \
87 if (_old_value >= 0) \
88 _res = close(_old_value); \
92static inline void _spa_autoclose_cleanup_func(
int *fd)
96#define spa_autoclose spa_cleanup(_spa_autoclose_cleanup_func)
102SPA_DEFINE_AUTOPTR_CLEANUP(FILE, FILE, {
103 spa_clear_ptr(*thing, fclose);
110SPA_DEFINE_AUTOPTR_CLEANUP(DIR, DIR, {
111 spa_clear_ptr(*thing, closedir);