mp_image: make reference counting thread-safe

This hasn't been done yet, because pthreads is still an optional
dependency, so this is a bit annoying. Now doing it anyway, because
maybe we will need this capability in the future.

We keep it as simple as possible. We (probably) don't need anything
more sophisticated, and keeping it simple avoids introducing weird
bugs. So, no atomic instructions, no fine grained locks, no cleverness.
This commit is contained in:
wm4 2013-07-28 00:10:47 +02:00
parent 0293eac84a
commit a9a6cf3b6c
1 changed files with 27 additions and 3 deletions

View File

@ -36,6 +36,16 @@
#include "memcpy_pic.h"
#include "fmt-conversion.h"
#if HAVE_PTHREADS
#include <pthread.h>
static pthread_mutex_t refcount_mutex = PTHREAD_MUTEX_INITIALIZER;
#define refcount_lock() pthread_mutex_lock(&refcount_mutex)
#define refcount_unlock() pthread_mutex_unlock(&refcount_mutex)
#else
#define refcount_lock() 0
#define refcount_unlock() 0
#endif
struct m_refcount {
void *arg;
// free() is called if refcount reaches 0.
@ -70,18 +80,27 @@ static struct m_refcount *m_refcount_new(void)
static void m_refcount_ref(struct m_refcount *ref)
{
refcount_lock();
ref->refcount++;
refcount_unlock();
if (ref->ext_ref)
ref->ext_ref(ref->arg);
}
static void m_refcount_unref(struct m_refcount *ref)
{
assert(ref->refcount > 0);
if (ref->ext_unref)
ref->ext_unref(ref->arg);
bool dead;
refcount_lock();
assert(ref->refcount > 0);
ref->refcount--;
if (ref->refcount == 0) {
dead = ref->refcount == 0;
refcount_unlock();
if (dead) {
if (ref->free)
ref->free(ref->arg);
talloc_free(ref);
@ -90,7 +109,12 @@ static void m_refcount_unref(struct m_refcount *ref)
static bool m_refcount_is_unique(struct m_refcount *ref)
{
if (ref->refcount > 1)
bool nonunique;
refcount_lock();
nonunique = ref->refcount > 1;
refcount_unlock();
if (nonunique)
return false;
if (ref->ext_is_unique)
return ref->ext_is_unique(ref->arg); // referenced only by us