diff options
author | wm4 <wm4@nowhere> | 2013-07-28 00:10:47 +0200 |
---|---|---|
committer | wm4 <wm4@nowhere> | 2013-07-28 18:56:49 +0200 |
commit | a9a6cf3b6c26eb21bd628c61e53c62fa7e565dbd (patch) | |
tree | c9d7a7cfb18324e9aeb032a7644ed2031ed33ac1 /video | |
parent | 0293eac84adbc34beb5d8d0bc34360d607aac79f (diff) | |
download | mpv-a9a6cf3b6c26eb21bd628c61e53c62fa7e565dbd.tar.bz2 mpv-a9a6cf3b6c26eb21bd628c61e53c62fa7e565dbd.tar.xz |
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.
Diffstat (limited to 'video')
-rw-r--r-- | video/mp_image.c | 30 |
1 files changed, 27 insertions, 3 deletions
diff --git a/video/mp_image.c b/video/mp_image.c index 26b8998197..0013c132fa 100644 --- a/video/mp_image.c +++ b/video/mp_image.c @@ -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 |