aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMax Kellermann <max@duempel.org>2012-01-21 10:47:13 +0100
committerMax Kellermann <max@duempel.org>2012-01-21 10:51:53 +0100
commita46712809363d7cb5337d3aca67e2d06c515ad85 (patch)
tree5b30f0f045efebb6d39e812a750f01e953478210
parentabf41eb85ceac2776a4449e5cc58b6804e8b6298 (diff)
db_lock: new unified lock for songvec and dirvec
-rw-r--r--Makefile.am1
-rw-r--r--src/db_lock.c23
-rw-r--r--src/db_lock.h55
-rw-r--r--src/dirvec.c46
-rw-r--r--src/dirvec.h4
-rw-r--r--src/main.c6
-rw-r--r--src/songvec.c46
7 files changed, 111 insertions, 70 deletions
diff --git a/Makefile.am b/Makefile.am
index 19a25079..63193132 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -248,6 +248,7 @@ src_mpd_SOURCES = \
src/directory_save.c \
src/database.c \
src/db_error.h \
+ src/db_lock.c src/db_lock.h \
src/db_save.c src/db_save.h \
src/db_print.c src/db_print.h \
src/db_plugin.h \
diff --git a/src/db_lock.c b/src/db_lock.c
new file mode 100644
index 00000000..3aaba4dc
--- /dev/null
+++ b/src/db_lock.c
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2003-2011 The Music Player Daemon Project
+ * http://www.musicpd.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "config.h"
+#include "db_lock.h"
+
+GStaticMutex db_mutex = G_STATIC_MUTEX_INIT;
diff --git a/src/db_lock.h b/src/db_lock.h
new file mode 100644
index 00000000..1e557b98
--- /dev/null
+++ b/src/db_lock.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2003-2011 The Music Player Daemon Project
+ * http://www.musicpd.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+/** \file
+ *
+ * Support for locking data structures from the database, for safe
+ * multi-threading.
+ */
+
+#ifndef MPD_DB_LOCK_H
+#define MPD_DB_LOCK_H
+
+#include "check.h"
+
+#include <glib.h>
+#include <assert.h>
+
+extern GStaticMutex db_mutex;
+
+/**
+ * Obtain the global database lock. This is needed before
+ * dereferencing a #song or #directory. It is not recursive.
+ */
+static inline void
+db_lock(void)
+{
+ g_static_mutex_lock(&db_mutex);
+}
+
+/**
+ * Release the global database lock.
+ */
+static inline void
+db_unlock(void)
+{
+ g_static_mutex_unlock(&db_mutex);
+}
+
+#endif
diff --git a/src/dirvec.c b/src/dirvec.c
index 3df08e9a..fa6b7b5f 100644
--- a/src/dirvec.c
+++ b/src/dirvec.c
@@ -20,6 +20,7 @@
#include "config.h"
#include "dirvec.h"
#include "directory.h"
+#include "db_lock.h"
#include <glib.h>
@@ -27,8 +28,6 @@
#include <string.h>
#include <stdlib.h>
-static GMutex *nr_lock = NULL;
-
static size_t dv_size(const struct dirvec *dv)
{
return dv->nr * sizeof(struct directory *);
@@ -42,24 +41,11 @@ static int dirvec_cmp(const void *d1, const void *d2)
return g_utf8_collate(a->path, b->path);
}
-void dirvec_init(void)
-{
- g_assert(nr_lock == NULL);
- nr_lock = g_mutex_new();
-}
-
-void dirvec_deinit(void)
-{
- g_assert(nr_lock != NULL);
- g_mutex_free(nr_lock);
- nr_lock = NULL;
-}
-
void dirvec_sort(struct dirvec *dv)
{
- g_mutex_lock(nr_lock);
+ db_lock();
qsort(dv->base, dv->nr, sizeof(struct directory *), dirvec_cmp);
- g_mutex_unlock(nr_lock);
+ db_unlock();
}
struct directory *dirvec_find(const struct dirvec *dv, const char *path)
@@ -70,13 +56,13 @@ struct directory *dirvec_find(const struct dirvec *dv, const char *path)
base = g_path_get_basename(path);
- g_mutex_lock(nr_lock);
+ db_lock();
for (i = dv->nr; --i >= 0; )
if (!strcmp(directory_get_name(dv->base[i]), base)) {
ret = dv->base[i];
break;
}
- g_mutex_unlock(nr_lock);
+ db_unlock();
g_free(base);
return ret;
@@ -86,13 +72,13 @@ int dirvec_delete(struct dirvec *dv, struct directory *del)
{
size_t i;
- g_mutex_lock(nr_lock);
+ db_lock();
for (i = 0; i < dv->nr; ++i) {
if (dv->base[i] != del)
continue;
/* we _don't_ call directory_free() here */
if (!--dv->nr) {
- g_mutex_unlock(nr_lock);
+ db_unlock();
g_free(dv->base);
dv->base = NULL;
return i;
@@ -103,25 +89,25 @@ int dirvec_delete(struct dirvec *dv, struct directory *del)
}
break;
}
- g_mutex_unlock(nr_lock);
+ db_unlock();
return i;
}
void dirvec_add(struct dirvec *dv, struct directory *add)
{
- g_mutex_lock(nr_lock);
+ db_lock();
++dv->nr;
dv->base = g_realloc(dv->base, dv_size(dv));
dv->base[dv->nr - 1] = add;
- g_mutex_unlock(nr_lock);
+ db_unlock();
}
void dirvec_destroy(struct dirvec *dv)
{
- g_mutex_lock(nr_lock);
+ db_lock();
dv->nr = 0;
- g_mutex_unlock(nr_lock);
+ db_unlock();
if (dv->base) {
g_free(dv->base);
dv->base = NULL;
@@ -134,20 +120,20 @@ int dirvec_for_each(const struct dirvec *dv,
size_t i;
size_t prev_nr;
- g_mutex_lock(nr_lock);
+ db_lock();
for (i = 0; i < dv->nr; ) {
struct directory *dir = dv->base[i];
assert(dir);
prev_nr = dv->nr;
- g_mutex_unlock(nr_lock);
+ db_unlock();
if (fn(dir, arg) < 0)
return -1;
- g_mutex_lock(nr_lock); /* dv->nr may change in fn() */
+ db_lock(); /* dv->nr may change in fn() */
if (prev_nr == dv->nr)
++i;
}
- g_mutex_unlock(nr_lock);
+ db_unlock();
return 0;
}
diff --git a/src/dirvec.h b/src/dirvec.h
index a15510ab..b9d730a1 100644
--- a/src/dirvec.h
+++ b/src/dirvec.h
@@ -27,10 +27,6 @@ struct dirvec {
size_t nr;
};
-void dirvec_init(void);
-
-void dirvec_deinit(void);
-
void dirvec_sort(struct dirvec *dv);
struct directory *dirvec_find(const struct dirvec *dv, const char *path);
diff --git a/src/main.c b/src/main.c
index 68f19f15..f7e7ba77 100644
--- a/src/main.c
+++ b/src/main.c
@@ -54,8 +54,6 @@
#include "dbUtils.h"
#include "zeroconf.h"
#include "event_pipe.h"
-#include "dirvec.h"
-#include "songvec.h"
#include "tag_pool.h"
#include "mpd_error.h"
@@ -346,8 +344,6 @@ int mpd_main(int argc, char *argv[])
io_thread_init();
winsock_init();
idle_init();
- dirvec_init();
- songvec_init();
tag_pool_init();
config_global_init();
@@ -534,8 +530,6 @@ int mpd_main(int argc, char *argv[])
#endif
config_global_finish();
tag_pool_deinit();
- songvec_deinit();
- dirvec_deinit();
idle_deinit();
stats_global_finish();
io_thread_deinit();
diff --git a/src/songvec.c b/src/songvec.c
index 7d5a7a47..9c7b3084 100644
--- a/src/songvec.c
+++ b/src/songvec.c
@@ -21,6 +21,7 @@
#include "songvec.h"
#include "song.h"
#include "tag.h"
+#include "db_lock.h"
#include <glib.h>
@@ -28,8 +29,6 @@
#include <string.h>
#include <stdlib.h>
-static GMutex *nr_lock = NULL;
-
static const char *
tag_get_value_checked(const struct tag *tag, enum tag_type type)
{
@@ -119,24 +118,11 @@ static size_t sv_size(const struct songvec *sv)
return sv->nr * sizeof(struct song *);
}
-void songvec_init(void)
-{
- g_assert(nr_lock == NULL);
- nr_lock = g_mutex_new();
-}
-
-void songvec_deinit(void)
-{
- g_assert(nr_lock != NULL);
- g_mutex_free(nr_lock);
- nr_lock = NULL;
-}
-
void songvec_sort(struct songvec *sv)
{
- g_mutex_lock(nr_lock);
+ db_lock();
qsort(sv->base, sv->nr, sizeof(struct song *), songvec_cmp);
- g_mutex_unlock(nr_lock);
+ db_unlock();
}
struct song *
@@ -145,14 +131,14 @@ songvec_find(const struct songvec *sv, const char *uri)
int i;
struct song *ret = NULL;
- g_mutex_lock(nr_lock);
+ db_lock();
for (i = sv->nr; --i >= 0; ) {
if (strcmp(sv->base[i]->uri, uri))
continue;
ret = sv->base[i];
break;
}
- g_mutex_unlock(nr_lock);
+ db_unlock();
return ret;
}
@@ -161,7 +147,7 @@ songvec_delete(struct songvec *sv, const struct song *del)
{
size_t i;
- g_mutex_lock(nr_lock);
+ db_lock();
for (i = 0; i < sv->nr; ++i) {
if (sv->base[i] != del)
continue;
@@ -174,10 +160,10 @@ songvec_delete(struct songvec *sv, const struct song *del)
(sv->nr - i) * sizeof(struct song *));
sv->base = g_realloc(sv->base, sv_size(sv));
}
- g_mutex_unlock(nr_lock);
+ db_unlock();
return i;
}
- g_mutex_unlock(nr_lock);
+ db_unlock();
return -1; /* not found */
}
@@ -185,18 +171,18 @@ songvec_delete(struct songvec *sv, const struct song *del)
void
songvec_add(struct songvec *sv, struct song *add)
{
- g_mutex_lock(nr_lock);
+ db_lock();
++sv->nr;
sv->base = g_realloc(sv->base, sv_size(sv));
sv->base[sv->nr - 1] = add;
- g_mutex_unlock(nr_lock);
+ db_unlock();
}
void songvec_destroy(struct songvec *sv)
{
- g_mutex_lock(nr_lock);
+ db_lock();
sv->nr = 0;
- g_mutex_unlock(nr_lock);
+ db_unlock();
g_free(sv->base);
sv->base = NULL;
@@ -209,7 +195,7 @@ songvec_for_each(const struct songvec *sv,
size_t i;
size_t prev_nr;
- g_mutex_lock(nr_lock);
+ db_lock();
for (i = 0; i < sv->nr; ) {
struct song *song = sv->base[i];
@@ -217,14 +203,14 @@ songvec_for_each(const struct songvec *sv,
assert(*song->uri);
prev_nr = sv->nr;
- g_mutex_unlock(nr_lock); /* fn() may block */
+ db_unlock(); /* fn() may block */
if (fn(song, arg) < 0)
return -1;
- g_mutex_lock(nr_lock); /* sv->nr may change in fn() */
+ db_lock(); /* sv->nr may change in fn() */
if (prev_nr == sv->nr)
++i;
}
- g_mutex_unlock(nr_lock);
+ db_unlock();
return 0;
}