| Line | Branch | Exec | Source |
|---|---|---|---|
| 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 | 1172929 | void *av_refstruct_alloc_ext(size_t size, unsigned flags, void *opaque, | |
| 95 | void (*free_cb)(AVRefStructOpaque opaque, void *obj)) | ||
| 96 | { | ||
| 97 | 1172929 | 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 | 15989 | void *av_refstruct_allocz(size_t size) | |
| 106 | { | ||
| 107 | 15989 | 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 | 47448 | 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 | 47448 | 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 | 92511 | static inline void av_refstruct_pool_uninit(AVRefStructPool **poolp) | |
| 293 | { | ||
| 294 | 92511 | av_refstruct_unref(poolp); | |
| 295 | 92511 | } | |
| 296 | |||
| 297 | #endif /* AVUTIL_REFSTRUCT_H */ | ||
| 298 |