PipeWire 0.3.80
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#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, ...) \
15typedef __typeof__(type) _spa_auto_cleanup_type_ ## name; \
16static 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, ...) \
26typedef __typeof__(type) * _spa_autoptr_cleanup_type_ ## name; \
27static 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) *_ptr = &(var); \
39 __typeof__(var) _old_value = *_ptr; \
40 *_ptr = (new_value); \
41 _old_value; \
42})
43
44#if __GNUC__ >= 10 || defined(__clang__)
45#define spa_steal_ptr(ptr) ((__typeof__(*(ptr)) *) spa_exchange((ptr), NULL))
46#else
47#define spa_steal_ptr(ptr) spa_exchange((ptr), NULL)
48#endif
49
50#define spa_steal_fd(fd) spa_exchange((fd), -1)
51
52/* ========================================================================== */
53
54#include <stdlib.h>
55
56#define spa_clear_ptr(ptr, destructor) \
57__extension__ ({ \
58 __typeof__(ptr) _old_value = spa_steal_ptr(ptr); \
59 if (_old_value) \
60 destructor(_old_value); \
61 (void) 0; \
62})
63
64static inline void _spa_autofree_cleanup_func(void *p)
65{
66 free(*(void **) p);
67}
68#define spa_autofree spa_cleanup(_spa_autofree_cleanup_func)
69
70/* ========================================================================== */
71
72#include <unistd.h>
73
74#define spa_clear_fd(fd) \
75__extension__ ({ \
76 int _old_value = spa_steal_fd(fd), _res = 0; \
77 if (_old_value >= 0) \
78 _res = close(_old_value); \
79 _res; \
80})
81
82static inline void _spa_autoclose_cleanup_func(int *fd)
83{
84 spa_clear_fd(*fd);
85}
86#define spa_autoclose spa_cleanup(_spa_autoclose_cleanup_func)
87
88/* ========================================================================== */
89
90#include <stdio.h>
91
92SPA_DEFINE_AUTOPTR_CLEANUP(FILE, FILE, {
93 spa_clear_ptr(*thing, fclose);
94})
95
96/* ========================================================================== */
97
98#include <dirent.h>
99
100SPA_DEFINE_AUTOPTR_CLEANUP(DIR, DIR, {
101 spa_clear_ptr(*thing, closedir);
102})
103
104#endif /* SPA_UTILS_CLEANUP_H */