PipeWire 1.6.8

Loading...
Searching...
No Matches
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 <errno.h>
35#include <unistd.h>
36
37#define spa_steal_fd(fd) spa_exchange((fd), -1)
38
39#define spa_clear_fd(fd) \
40__extension__ ({ \
41 int _old_value = spa_steal_fd(fd), _res = 0; \
42 if (_old_value >= 0) \
43 _res = close(_old_value); \
44 _res; \
45})
46
47/* ========================================================================== */
48
49#ifdef __has_attribute
50#if __has_attribute(__cleanup__)
51#define spa_cleanup(func) __attribute__((__cleanup__(func)))
52#endif
53#endif
54
55#ifdef spa_cleanup
56
57#define SPA_DEFINE_AUTO_CLEANUP(name, type, ...) \
58 typedef __typeof__(type) _spa_auto_cleanup_type_ ## name; \
59 static inline void _spa_auto_cleanup_func_ ## name (__typeof__(type) *thing) \
60{ \
61 int _save_errno = errno; \
62 __VA_ARGS__ \
63 errno = _save_errno; \
64}
65
66#define spa_auto(name) \
67 spa_cleanup(_spa_auto_cleanup_func_ ## name) \
68 _spa_auto_cleanup_type_ ## name
69
70#define SPA_DEFINE_AUTOPTR_CLEANUP(name, type, ...) \
71 typedef __typeof__(type) * _spa_autoptr_cleanup_type_ ## name; \
72 static inline void _spa_autoptr_cleanup_func_ ## name (__typeof__(type) **thing) \
73{ \
74 int _save_errno = errno; \
75 __VA_ARGS__ \
76 errno = _save_errno; \
77}
78
79#define spa_autoptr(name) \
80 spa_cleanup(_spa_autoptr_cleanup_func_ ## name) \
81 _spa_autoptr_cleanup_type_ ## name
82
83/* ========================================================================== */
84
85#include <stdlib.h>
86
87 static inline void _spa_autofree_cleanup_func(void *p)
88{
89 int save_errno = errno;
90 free(*(void **) p);
91 errno = save_errno;
92}
93#define spa_autofree spa_cleanup(_spa_autofree_cleanup_func)
94
95/* ========================================================================== */
96
97 static inline void _spa_autoclose_cleanup_func(int *fd)
98{
99 int save_errno = errno;
100 spa_clear_fd(*fd);
101 errno = save_errno;
102}
103#define spa_autoclose spa_cleanup(_spa_autoclose_cleanup_func)
104
105/* ========================================================================== */
106
107#include <stdio.h>
108
109SPA_DEFINE_AUTOPTR_CLEANUP(FILE, FILE, {
110 spa_clear_ptr(*thing, fclose);
111})
112
113/* ========================================================================== */
114
115#include <dirent.h>
116
117SPA_DEFINE_AUTOPTR_CLEANUP(DIR, DIR, {
118 spa_clear_ptr(*thing, closedir);
119})
120
121#else
122
123#define SPA_DEFINE_AUTO_CLEANUP(name, type, ...)
124#define SPA_DEFINE_AUTOPTR_CLEANUP(name, type, ...)
125
126#endif
127
128#endif /* SPA_UTILS_CLEANUP_H */