*
*****************************************************************************/
struct picture_gc_sys_t {
+ picture_pool_t *pool;
+
/* Saved release */
void (*destroy)(picture_t *);
void *destroy_sys;
int picture_count;
picture_t **picture;
bool *picture_reserved;
+
+ unsigned refs;
+ vlc_mutex_t lock;
};
-static void Destroy(picture_t *);
static int Lock(picture_t *);
static void Unlock(picture_t *);
+static void Release(picture_pool_t *pool)
+{
+ bool destroy;
+
+ vlc_mutex_lock(&pool->lock);
+ assert(pool->refs > 0);
+ destroy = !--pool->refs;
+ vlc_mutex_unlock(&pool->lock);
+
+ if (!destroy)
+ return;
+
+ vlc_mutex_destroy(&pool->lock);
+ free(pool->picture_reserved);
+ free(pool->picture);
+ free(pool);
+}
+
+static void DestroyPicture(picture_t *picture)
+{
+ picture_gc_sys_t *gc_sys = picture->gc.p_sys;
+ picture_pool_t *pool = gc_sys->pool;
+
+ Unlock(picture);
+
+ if (!atomic_load(&gc_sys->zombie))
+ return;
+
+ /* Picture from an already destroyed pool */
+ picture->gc.pf_destroy = gc_sys->destroy;
+ picture->gc.p_sys = gc_sys->destroy_sys;
+ free(gc_sys);
+
+ picture->gc.pf_destroy(picture);
+ Release(pool);
+}
+
static picture_pool_t *Create(picture_pool_t *master, int picture_count)
{
picture_pool_t *pool = calloc(1, sizeof(*pool));
free(pool);
return NULL;
}
+ pool->refs = 1;
+ vlc_mutex_init(&pool->lock);
return pool;
}
picture_gc_sys_t *gc_sys = malloc(sizeof(*gc_sys));
if (unlikely(gc_sys == NULL))
abort();
+ gc_sys->pool = pool;
gc_sys->destroy = picture->gc.pf_destroy;
gc_sys->destroy_sys = picture->gc.p_sys;
gc_sys->lock = cfg->lock;
/* Override the garbage collector */
assert(atomic_load(&picture->gc.refcount) == 1);
atomic_init(&picture->gc.refcount, 0);
- picture->gc.pf_destroy = Destroy;
+ picture->gc.pf_destroy = DestroyPicture;
picture->gc.p_sys = gc_sys;
/* */
pool->picture[i] = picture;
pool->picture_reserved[i] = false;
+ pool->refs++;
}
return pool;
picture_Release(picture);
}
}
- free(pool->picture_reserved);
- free(pool->picture);
- free(pool);
+ Release(pool);
}
picture_t *picture_pool_Get(picture_pool_t *pool)
return pool->picture_count;
}
-static void Destroy(picture_t *picture)
-{
- picture_gc_sys_t *gc_sys = picture->gc.p_sys;
-
- Unlock(picture);
-
- if (atomic_load(&gc_sys->zombie))
- { /* Picture from an already destroyed pool */
- picture->gc.pf_destroy = gc_sys->destroy;
- picture->gc.p_sys = gc_sys->destroy_sys;
- free(gc_sys);
-
- picture->gc.pf_destroy(picture);
- }
-}
-
static int Lock(picture_t *picture)
{
picture_gc_sys_t *gc_sys = picture->gc.p_sys;