PipeWire  1.0.0
cleanup.h
1 /* Simple Plugin API */
2 /* SPDX-FileCopyrightText: Copyright © 2023 PipeWire authors */
3 /* SPDX-License-Identifier: MIT */
4 
5 #ifndef SPA_UTILS_CLEANUP_H
6 #define SPA_UTILS_CLEANUP_H
7 
8 #define spa_exchange(var, new_value) \
9 __extension__ ({ \
10  __typeof__(var) *_ptr = &(var); \
11  __typeof__(var) _old_value = *_ptr; \
12  *_ptr = (new_value); \
13  _old_value; \
14 })
15 
16 /* ========================================================================== */
17 
18 #if __GNUC__ >= 10 || defined(__clang__)
19 #define spa_steal_ptr(ptr) ((__typeof__(*(ptr)) *) spa_exchange((ptr), NULL))
20 #else
21 #define spa_steal_ptr(ptr) spa_exchange((ptr), NULL)
22 #endif
23 
24 #define spa_clear_ptr(ptr, destructor) \
25 __extension__ ({ \
26  __typeof__(ptr) _old_value = spa_steal_ptr(ptr); \
27  if (_old_value) \
28  destructor(_old_value); \
29  (void) 0; \
30 })
31 
32 /* ========================================================================== */
33 
34 #include <unistd.h>
35 
36 #define spa_steal_fd(fd) spa_exchange((fd), -1)
37 
38 #define spa_clear_fd(fd) \
39 __extension__ ({ \
40  int _old_value = spa_steal_fd(fd), _res = 0; \
41  if (_old_value >= 0) \
42  _res = close(_old_value); \
43  _res; \
44 })
45 
46 /* ========================================================================== */
47 
48 #if defined(__has_attribute) && __has_attribute(__cleanup__)
49 
50 #define spa_cleanup(func) __attribute__((__cleanup__(func)))
51 
52 #define SPA_DEFINE_AUTO_CLEANUP(name, type, ...) \
53 typedef __typeof__(type) _spa_auto_cleanup_type_ ## name; \
54 static inline void _spa_auto_cleanup_func_ ## name (__typeof__(type) *thing) \
55 { \
56  __VA_ARGS__ \
57 }
58 
59 #define spa_auto(name) \
60  spa_cleanup(_spa_auto_cleanup_func_ ## name) \
61  _spa_auto_cleanup_type_ ## name
62 
63 #define SPA_DEFINE_AUTOPTR_CLEANUP(name, type, ...) \
64 typedef __typeof__(type) * _spa_autoptr_cleanup_type_ ## name; \
65 static inline void _spa_autoptr_cleanup_func_ ## name (__typeof__(type) **thing) \
66 { \
67  __VA_ARGS__ \
68 }
69 
70 #define spa_autoptr(name) \
71  spa_cleanup(_spa_autoptr_cleanup_func_ ## name) \
72  _spa_autoptr_cleanup_type_ ## name
73 
74 /* ========================================================================== */
75 
76 #include <stdlib.h>
77 
78 static inline void _spa_autofree_cleanup_func(void *p)
79 {
80  free(*(void **) p);
81 }
82 #define spa_autofree spa_cleanup(_spa_autofree_cleanup_func)
83 
84 /* ========================================================================== */
85 
86 static inline void _spa_autoclose_cleanup_func(int *fd)
87 {
88  spa_clear_fd(*fd);
89 }
90 #define spa_autoclose spa_cleanup(_spa_autoclose_cleanup_func)
91 
92 /* ========================================================================== */
93 
94 #include <stdio.h>
95 
96 SPA_DEFINE_AUTOPTR_CLEANUP(FILE, FILE, {
97  spa_clear_ptr(*thing, fclose);
98 })
99 
100 /* ========================================================================== */
101 
102 #include <dirent.h>
103 
104 SPA_DEFINE_AUTOPTR_CLEANUP(DIR, DIR, {
105  spa_clear_ptr(*thing, closedir);
106 })
107 
108 #else
109 
110 #define SPA_DEFINE_AUTO_CLEANUP(name, type, ...)
111 #define SPA_DEFINE_AUTOPTR_CLEANUP(name, type, ...)
112 
113 #endif
114 
115 #endif /* SPA_UTILS_CLEANUP_H */