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 #include <stdatomic.h>
20 #include <stdint.h>
21 #include <string.h>
22
24
31
32 #ifndef REFSTRUCT_CHECKED
33 #ifndef ASSERT_LEVEL
34 #define ASSERT_LEVEL 0
35 #endif
36 #define REFSTRUCT_CHECKED (ASSERT_LEVEL >= 1)
37 #endif
38
39 #if REFSTRUCT_CHECKED
40 #define ff_assert(cond) av_assert0(cond)
41 #else
42 #define ff_assert(cond) ((void)0)
43 #endif
44
45 #define REFSTRUCT_COOKIE AV_NE((uint64_t)MKBETAG('R', 'e', 'f', 'S') << 32 | MKBETAG('t', 'r', 'u', 'c'), \
46 MKTAG('R', 'e', 'f', 'S') | (uint64_t)MKTAG('t', 'r', 'u', 'c') << 32)
47
48 #ifndef _MSC_VER
49 #define REFCOUNT_OFFSET FFALIGN(sizeof(RefCount), FFMAX(ALIGN_64, _Alignof(max_align_t)))
50 #else
51 #define REFCOUNT_OFFSET FFALIGN(sizeof(RefCount), ALIGN_64)
52 #endif
53
55 /**
56 * An uintptr_t is big enough to hold the address of every reference,
57 * so no overflow can happen when incrementing the refcount as long as
58 * the user does not throw away references.
59 */
64
65 #if REFSTRUCT_CHECKED
66 uint64_t cookie;
67 #endif
69
71 {
75 }
76
78 {
82 }
83
85 {
87 }
88
91 {
94 ref->free_cb = free_cb;
96
97 #if REFSTRUCT_CHECKED
99 #endif
100 }
101
104 {
105 void *buf, *obj;
106
110 if (!buf)
115 memset(obj, 0,
size);
116
117 return obj;
118 }
119
121 {
122 void *obj;
124
125 memcpy(&obj, objp, sizeof(obj));
126 if (!obj)
127 return;
128 memcpy(objp, &(
void *){
NULL },
sizeof(obj));
129
133 ref->free_cb(
ref->opaque, obj);
135 }
136
137 return;
138 }
139
141 {
143
145
146 return obj;
147 }
148
150 {
151 /* Casting const away here is fine, as it is only supposed
152 * to apply to the user's data and not our bookkeeping data. */
154
156
157 return obj;
158 }
159
161 {
163 memcpy(&
dst, dstp,
sizeof(
dst));
164
166 return;
170 memcpy(dstp, &
dst,
sizeof(
dst));
171 }
172 }
173
175 {
177 /* Casting const away here is safe, because it is a load.
178 * It is necessary because atomic_load_explicit() does not
179 * accept const atomics in C11 (see also N1807). */
181 }
182
190
194
195 /** The number of outstanding entries not in available_entries. */
197 /**
198 * This is a linked list of available entries;
199 * the RefCount's opaque pointer is used as next pointer
200 * for available entries.
201 * While the entries are in use, the opaque is a pointer
202 * to the corresponding AVRefStructPool.
203 */
206 };
207
209 {
214 }
215
217 {
221 }
222
224 {
227
233 }
235
238
241 }
242
244 {
246
248 }
249
251 {
253
254 memcpy(datap, &(
void *){
NULL },
sizeof(
void*));
255
262 ref->opaque.nc = pool;
264 }
266
277 if (err < 0) {
283 return err;
284 }
285 }
286 }
288
291
292 memcpy(datap, &
ret,
sizeof(
ret));
293
294 return 0;
295 }
296
298 {
302 }
303
304 /**
305 * Hint: The content of pool_unref() and refstruct_pool_uninit()
306 * could currently be merged; they are only separate functions
307 * in case we would ever introduce weak references.
308 */
310 {
314 }
315
317 {
320
327
329 void *next =
entry->opaque.nc;
332 }
333 }
334
336 {
338 }
339
346 {
349 int err;
350
351 if (!pool)
354
361 #define COMMON_FLAGS AV_REFSTRUCT_POOL_FLAG_NO_ZEROING
363 // Filter out nonsense combinations to avoid checks later.
369
371 // We will zero the buffer before every use, so zeroing
372 // upon allocating the buffer is unnecessary.
374 }
375
377
379 if (err) {
380 // Don't call av_refstruct_uninit() on pool, as it hasn't been properly
381 // set up and is just a POD right now.
384 }
385 return pool;
386 }