summaryrefslogtreecommitdiffstats
path: root/video
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2013-07-28 00:10:47 +0200
committerwm4 <wm4@nowhere>2013-07-28 18:56:49 +0200
commita9a6cf3b6c26eb21bd628c61e53c62fa7e565dbd (patch)
treec9d7a7cfb18324e9aeb032a7644ed2031ed33ac1 /video
parent0293eac84adbc34beb5d8d0bc34360d607aac79f (diff)
downloadmpv-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.c30
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