| 338 | } |
| 339 | |
| 340 | AVRefStructPool *av_refstruct_pool_alloc_ext_c(size_t size, unsigned flags, |
| 341 | AVRefStructOpaque opaque, |
| 342 | int (*init_cb)(AVRefStructOpaque opaque, void *obj), |
| 343 | void (*reset_cb)(AVRefStructOpaque opaque, void *obj), |
| 344 | void (*free_entry_cb)(AVRefStructOpaque opaque, void *obj), |
| 345 | void (*free_cb)(AVRefStructOpaque opaque)) |
| 346 | { |
| 347 | AVRefStructPool *pool = av_refstruct_alloc_ext(sizeof(*pool), 0, NULL, |
| 348 | refstruct_pool_uninit); |
| 349 | int err; |
| 350 | |
| 351 | if (!pool) |
| 352 | return NULL; |
| 353 | get_refcount(pool)->free = pool_unref; |
| 354 | |
| 355 | pool->size = size; |
| 356 | pool->opaque = opaque; |
| 357 | pool->init_cb = init_cb; |
| 358 | pool->reset_cb = reset_cb; |
| 359 | pool->free_entry_cb = free_entry_cb; |
| 360 | pool->free_cb = free_cb; |
| 361 | #define COMMON_FLAGS AV_REFSTRUCT_POOL_FLAG_NO_ZEROING |
| 362 | pool->entry_flags = flags & COMMON_FLAGS; |
| 363 | // Filter out nonsense combinations to avoid checks later. |
| 364 | if (!pool->reset_cb) |
| 365 | flags &= ~AV_REFSTRUCT_POOL_FLAG_RESET_ON_INIT_ERROR; |
| 366 | if (!pool->free_entry_cb) |
| 367 | flags &= ~AV_REFSTRUCT_POOL_FLAG_FREE_ON_INIT_ERROR; |
| 368 | pool->pool_flags = flags; |
| 369 | |
| 370 | if (flags & AV_REFSTRUCT_POOL_FLAG_ZERO_EVERY_TIME) { |
| 371 | // We will zero the buffer before every use, so zeroing |
| 372 | // upon allocating the buffer is unnecessary. |
| 373 | pool->entry_flags |= AV_REFSTRUCT_FLAG_NO_ZEROING; |
| 374 | } |
| 375 | |
| 376 | atomic_init(&pool->refcount, 1); |
| 377 | |
| 378 | err = ff_mutex_init(&pool->mutex, NULL); |
| 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. |
| 382 | av_free(get_refcount(pool)); |
| 383 | return NULL; |
| 384 | } |
| 385 | return pool; |
| 386 | } |
no test coverage detected