aboutsummaryrefslogtreecommitdiffstats
path: root/libavcodec/refstruct.h
blob: 8b0723a982e066c4a62db07879ebada616df8e03 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
/*
 * This file is part of FFmpeg.
 *
 * FFmpeg is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * FFmpeg is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with FFmpeg; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 */

#ifndef AVCODEC_REFSTRUCT_H
#define AVCODEC_REFSTRUCT_H

#include <stddef.h>

/**
 * RefStruct is an API for creating reference-counted objects
 * with minimal overhead. The API is designed for objects,
 * not buffers like the AVBuffer API. The main differences
 * to the AVBuffer API are as follows:
 *
 * - It uses void* instead of uint8_t* as its base type due to
 *   its focus on objects.
 * - There are no equivalents of AVBuffer and AVBufferRef.
 *   E.g. there is no way to get the usable size of the object:
 *   The user is supposed to know what is at the other end of
 *   the pointer. It also avoids one level of indirection.
 * - Custom allocators are not supported. This allows to simplify
 *   the implementation and reduce the amount of allocations.
 * - It also has the advantage that the user's free callback need
 *   only free the resources owned by the object, but not the
 *   object itself.
 * - Because referencing (and replacing) an object managed by the
 *   RefStruct API does not involve allocations, they can not fail
 *   and therefore need not be checked.
 *
 * @note Referencing and unreferencing the buffers is thread-safe and thus
 * may be done from multiple threads simultaneously without any need for
 * additional locking.
 */

/**
 * This union is used for all opaque parameters in this API to spare the user
 * to cast const away in case the opaque to use is const-qualified.
 *
 * The functions provided by this API with an FFRefStructOpaque come in pairs
 * named foo_c and foo. The foo function accepts void* as opaque and is just
 * a wrapper around the foo_c function; "_c" means "(potentially) const".
 */
typedef union {
    void *nc;
    const void *c;
} FFRefStructOpaque;

/**
 * If this flag is set in ff_refstruct_alloc_ext_c(), the object will not
 * be initially zeroed.
 */
#define FF_REFSTRUCT_FLAG_NO_ZEROING (1 << 0)

/**
 * Allocate a refcounted object of usable size `size` managed via
 * the RefStruct API.
 *
 * By default (in the absence of flags to the contrary),
 * the returned object is initially zeroed.
 *
 * @param size    Desired usable size of the returned object.
 * @param flags   A bitwise combination of FF_REFSTRUCT_FLAG_* flags.
 * @param opaque  A pointer that will be passed to the free_cb callback.
 * @param free_cb A callback for freeing this object's content
 *                when its reference count reaches zero;
 *                it must not free the object itself.
 * @return A pointer to an object of the desired size or NULL on failure.
 */
void *ff_refstruct_alloc_ext_c(size_t size, unsigned flags, FFRefStructOpaque opaque,
                               void (*free_cb)(FFRefStructOpaque opaque, void *obj));

/**
 * A wrapper around ff_refstruct_alloc_ext_c() for the common case
 * of a non-const qualified opaque.
 *
 * @see ff_refstruct_alloc_ext_c()
 */
static inline
void *ff_refstruct_alloc_ext(size_t size, unsigned flags, void *opaque,
                             void (*free_cb)(FFRefStructOpaque opaque, void *obj))
{
    return ff_refstruct_alloc_ext_c(size, flags, (FFRefStructOpaque){.nc = opaque},
                                    free_cb);
}

/**
 * Equivalent to ff_refstruct_alloc_ext(size, 0, NULL, NULL)
 */
static inline
void *ff_refstruct_allocz(size_t size)
{
    return ff_refstruct_alloc_ext(size, 0, NULL, NULL);
}

/**
 * Decrement the reference count of the underlying object and automatically
 * free the object if there are no more references to it.
 *
 * `*objp == NULL` is legal and a no-op.
 *
 * @param objp Pointer to a pointer that is either NULL or points to an object
 *             managed via this API. `*objp` is set to NULL on return.
 */
void ff_refstruct_unref(void *objp);

/**
 * Create a new reference to an object managed via this API,
 * i.e. increment the reference count of the underlying object
 * and return obj.
 * @return a pointer equal to obj.
 */
void *ff_refstruct_ref(void *obj);

/**
 * Analog of ff_refstruct_ref(), but for constant objects.
 * @see ff_refstruct_ref()
 */
const void *ff_refstruct_ref_c(const void *obj);

/**
 * Ensure `*dstp` refers to the same object as src.
 *
 * If `*dstp` is already equal to src, do nothing. Otherwise unreference `*dstp`
 * and replace it with a new reference to src in case `src != NULL` (this
 * involves incrementing the reference count of src's underlying object) or
 * with NULL otherwise.
 *
 * @param dstp Pointer to a pointer that is either NULL or points to an object
 *             managed via this API.
 * @param src  A pointer to an object managed via this API or NULL.
 */
void ff_refstruct_replace(void *dstp, const void *src);

/**
 * Check whether the reference count of an object managed
 * via this API is 1.
 *
 * @param obj A pointer to an object managed via this API.
 * @return 1 if the reference count of obj is 1; 0 otherwise.
 */
int ff_refstruct_exclusive(const void *obj);

#endif /* AVCODEC_REFSTRUCT_H */