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