Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
stenzek
GitHub Repository: stenzek/duckstation
Path: blob/master/dep/ffmpeg/include/libavcodec/refstruct.h
5196 views
1
/*
2
* This file is part of FFmpeg.
3
*
4
* FFmpeg is free software; you can redistribute it and/or
5
* modify it under the terms of the GNU Lesser General Public
6
* License as published by the Free Software Foundation; either
7
* version 2.1 of the License, or (at your option) any later version.
8
*
9
* FFmpeg is distributed in the hope that it will be useful,
10
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12
* Lesser General Public License for more details.
13
*
14
* You should have received a copy of the GNU Lesser General Public
15
* License along with FFmpeg; if not, write to the Free Software
16
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17
*/
18
19
#ifndef AVUTIL_REFSTRUCT_H
20
#define AVUTIL_REFSTRUCT_H
21
22
#include <stddef.h>
23
24
/**
25
* RefStruct is an API for creating reference-counted objects
26
* with minimal overhead. The API is designed for objects,
27
* not buffers like the AVBuffer API. The main differences
28
* to the AVBuffer API are as follows:
29
*
30
* - It uses void* instead of uint8_t* as its base type due to
31
* its focus on objects.
32
* - There are no equivalents of AVBuffer and AVBufferRef.
33
* E.g. there is no way to get the usable size of the object:
34
* The user is supposed to know what is at the other end of
35
* the pointer. It also avoids one level of indirection.
36
* - Custom allocators are not supported. This allows to simplify
37
* the implementation and reduce the amount of allocations.
38
* - It also has the advantage that the user's free callback need
39
* only free the resources owned by the object, but not the
40
* object itself.
41
* - Because referencing (and replacing) an object managed by the
42
* RefStruct API does not involve allocations, they can not fail
43
* and therefore need not be checked.
44
*
45
* @note Referencing and unreferencing the buffers is thread-safe and thus
46
* may be done from multiple threads simultaneously without any need for
47
* additional locking.
48
*/
49
50
/**
51
* This union is used for all opaque parameters in this API to spare the user
52
* to cast const away in case the opaque to use is const-qualified.
53
*
54
* The functions provided by this API with an AVRefStructOpaque come in pairs
55
* named foo_c and foo. The foo function accepts void* as opaque and is just
56
* a wrapper around the foo_c function; "_c" means "(potentially) const".
57
*/
58
typedef union {
59
void *nc;
60
const void *c;
61
} AVRefStructOpaque;
62
63
/**
64
* If this flag is set in av_refstruct_alloc_ext_c(), the object will not
65
* be initially zeroed.
66
*/
67
#define AV_REFSTRUCT_FLAG_NO_ZEROING (1 << 0)
68
69
/**
70
* Allocate a refcounted object of usable size `size` managed via
71
* the RefStruct API.
72
*
73
* By default (in the absence of flags to the contrary),
74
* the returned object is initially zeroed.
75
*
76
* @param size Desired usable size of the returned object.
77
* @param flags A bitwise combination of AV_REFSTRUCT_FLAG_* flags.
78
* @param opaque A pointer that will be passed to the free_cb callback.
79
* @param free_cb A callback for freeing this object's content
80
* when its reference count reaches zero;
81
* it must not free the object itself.
82
* @return A pointer to an object of the desired size or NULL on failure.
83
*/
84
void *av_refstruct_alloc_ext_c(size_t size, unsigned flags, AVRefStructOpaque opaque,
85
void (*free_cb)(AVRefStructOpaque opaque, void *obj));
86
87
/**
88
* A wrapper around av_refstruct_alloc_ext_c() for the common case
89
* of a non-const qualified opaque.
90
*
91
* @see av_refstruct_alloc_ext_c()
92
*/
93
static inline
94
void *av_refstruct_alloc_ext(size_t size, unsigned flags, void *opaque,
95
void (*free_cb)(AVRefStructOpaque opaque, void *obj))
96
{
97
return av_refstruct_alloc_ext_c(size, flags, (AVRefStructOpaque){.nc = opaque},
98
free_cb);
99
}
100
101
/**
102
* Equivalent to av_refstruct_alloc_ext(size, 0, NULL, NULL)
103
*/
104
static inline
105
void *av_refstruct_allocz(size_t size)
106
{
107
return av_refstruct_alloc_ext(size, 0, NULL, NULL);
108
}
109
110
/**
111
* Decrement the reference count of the underlying object and automatically
112
* free the object if there are no more references to it.
113
*
114
* `*objp == NULL` is legal and a no-op.
115
*
116
* @param objp Pointer to a pointer that is either NULL or points to an object
117
* managed via this API. `*objp` is set to NULL on return.
118
*/
119
void av_refstruct_unref(void *objp);
120
121
/**
122
* Create a new reference to an object managed via this API,
123
* i.e. increment the reference count of the underlying object
124
* and return obj.
125
* @return a pointer equal to obj.
126
*/
127
void *av_refstruct_ref(void *obj);
128
129
/**
130
* Analog of av_refstruct_ref(), but for constant objects.
131
* @see av_refstruct_ref()
132
*/
133
const void *av_refstruct_ref_c(const void *obj);
134
135
/**
136
* Ensure `*dstp` refers to the same object as src.
137
*
138
* If `*dstp` is already equal to src, do nothing. Otherwise unreference `*dstp`
139
* and replace it with a new reference to src in case `src != NULL` (this
140
* involves incrementing the reference count of src's underlying object) or
141
* with NULL otherwise.
142
*
143
* @param dstp Pointer to a pointer that is either NULL or points to an object
144
* managed via this API.
145
* @param src A pointer to an object managed via this API or NULL.
146
*/
147
void av_refstruct_replace(void *dstp, const void *src);
148
149
/**
150
* Check whether the reference count of an object managed
151
* via this API is 1.
152
*
153
* @param obj A pointer to an object managed via this API.
154
* @return 1 if the reference count of obj is 1; 0 otherwise.
155
*/
156
int av_refstruct_exclusive(const void *obj);
157
158
/**
159
* AVRefStructPool is an API for a thread-safe pool of objects managed
160
* via the RefStruct API.
161
*
162
* Frequently allocating and freeing large or complicated objects may be slow
163
* and wasteful. This API is meant to solve this in cases when the caller
164
* needs a set of interchangeable objects.
165
*
166
* At the beginning, the user must call allocate the pool via
167
* av_refstruct_pool_alloc() or its analogue av_refstruct_pool_alloc_ext().
168
* Then whenever an object is needed, call av_refstruct_pool_get() to
169
* get a new or reused object from the pool. This new object works in all
170
* aspects the same way as the ones created by av_refstruct_alloc_ext().
171
* However, when the last reference to this object is unreferenced, it is
172
* (optionally) reset and returned to the pool instead of being freed and
173
* will be reused for subsequent av_refstruct_pool_get() calls.
174
*
175
* When the caller is done with the pool and no longer needs to create any new
176
* objects, av_refstruct_pool_uninit() must be called to mark the pool as
177
* freeable. Then entries returned to the pool will then be freed.
178
* Once all the entries are freed, the pool will automatically be freed.
179
*
180
* Allocating and releasing objects with this API is thread-safe as long as
181
* the user-supplied callbacks (if provided) are thread-safe.
182
*/
183
184
/**
185
* The buffer pool. This structure is opaque and not meant to be accessed
186
* directly. It is allocated with the allocators below and freed with
187
* av_refstruct_pool_uninit().
188
*/
189
typedef struct AVRefStructPool AVRefStructPool;
190
191
/**
192
* If this flag is not set, every object in the pool will be zeroed before
193
* the init callback is called or before it is turned over to the user
194
* for the first time if no init callback has been provided.
195
*/
196
#define AV_REFSTRUCT_POOL_FLAG_NO_ZEROING AV_REFSTRUCT_FLAG_NO_ZEROING
197
/**
198
* If this flag is set and both init_cb and reset_cb callbacks are provided,
199
* then reset_cb will be called if init_cb fails.
200
* The object passed to reset_cb will be in the state left by init_cb.
201
*/
202
#define AV_REFSTRUCT_POOL_FLAG_RESET_ON_INIT_ERROR (1 << 16)
203
/**
204
* If this flag is set and both init_cb and free_entry_cb callbacks are
205
* provided, then free_cb will be called if init_cb fails.
206
*
207
* It will be called after reset_cb in case reset_cb and the
208
* AV_REFSTRUCT_POOL_FLAG_RESET_ON_INIT_ERROR flag are also set.
209
*
210
* The object passed to free_cb will be in the state left by
211
* the callbacks applied earlier (init_cb potentially followed by reset_cb).
212
*/
213
#define AV_REFSTRUCT_POOL_FLAG_FREE_ON_INIT_ERROR (1 << 17)
214
/**
215
* If this flag is set, the entries will be zeroed before
216
* being returned to the user (after the init or reset callbacks
217
* have been called (if provided)). Furthermore, to avoid zeroing twice
218
* it also makes the pool behave as if the AV_REFSTRUCT_POOL_FLAG_NO_ZEROING
219
* flag had been provided.
220
*/
221
#define AV_REFSTRUCT_POOL_FLAG_ZERO_EVERY_TIME (1 << 18)
222
223
/**
224
* Equivalent to av_refstruct_pool_alloc(size, flags, NULL, NULL, NULL, NULL, NULL)
225
*/
226
AVRefStructPool *av_refstruct_pool_alloc(size_t size, unsigned flags);
227
228
/**
229
* Allocate an AVRefStructPool, potentially using complex callbacks.
230
*
231
* @param size size of the entries of the pool
232
* @param flags a bitwise combination of AV_REFSTRUCT_POOL_FLAG_* flags
233
* @param opaque A pointer that will be passed to the callbacks below.
234
* @param init A callback that will be called directly after a new entry
235
* has been allocated. obj has already been zeroed unless
236
* the AV_REFSTRUCT_POOL_FLAG_NO_ZEROING flag is in use.
237
* @param reset A callback that will be called after an entry has been
238
* returned to the pool and before it is reused.
239
* @param free_entry A callback that will be called when an entry is freed
240
* after the pool has been marked as to be uninitialized.
241
* @param free A callback that will be called when the pool itself is
242
* freed (after the last entry has been returned and freed).
243
*/
244
AVRefStructPool *av_refstruct_pool_alloc_ext_c(size_t size, unsigned flags,
245
AVRefStructOpaque opaque,
246
int (*init_cb)(AVRefStructOpaque opaque, void *obj),
247
void (*reset_cb)(AVRefStructOpaque opaque, void *obj),
248
void (*free_entry_cb)(AVRefStructOpaque opaque, void *obj),
249
void (*free_cb)(AVRefStructOpaque opaque));
250
251
/**
252
* A wrapper around av_refstruct_pool_alloc_ext_c() for the common case
253
* of a non-const qualified opaque.
254
*
255
* @see av_refstruct_pool_alloc_ext_c()
256
*/
257
static inline
258
AVRefStructPool *av_refstruct_pool_alloc_ext(size_t size, unsigned flags,
259
void *opaque,
260
int (*init_cb)(AVRefStructOpaque opaque, void *obj),
261
void (*reset_cb)(AVRefStructOpaque opaque, void *obj),
262
void (*free_entry_cb)(AVRefStructOpaque opaque, void *obj),
263
void (*free_cb)(AVRefStructOpaque opaque))
264
{
265
return av_refstruct_pool_alloc_ext_c(size, flags, (AVRefStructOpaque){.nc = opaque},
266
init_cb, reset_cb, free_entry_cb, free_cb);
267
}
268
269
/**
270
* Get an object from the pool, reusing an old one from the pool when
271
* available.
272
*
273
* Every call to this function must happen before av_refstruct_pool_uninit().
274
* Otherwise undefined behaviour may occur.
275
*
276
* @param pool the pool from which to get the object
277
* @return a reference to the object on success, NULL on error.
278
*/
279
void *av_refstruct_pool_get(AVRefStructPool *pool);
280
281
/**
282
* Mark the pool as being available for freeing. It will actually be freed
283
* only once all the allocated buffers associated with the pool are released.
284
* Thus it is safe to call this function while some of the allocated buffers
285
* are still in use.
286
*
287
* It is illegal to try to get a new entry after this function has been called.
288
*
289
* @param poolp pointer to a pointer to either NULL or a pool to be freed.
290
* `*poolp` will be set to NULL.
291
*/
292
static inline void av_refstruct_pool_uninit(AVRefStructPool **poolp)
293
{
294
av_refstruct_unref(poolp);
295
}
296
297
#endif /* AVUTIL_REFSTRUCT_H */
298
299