diff options
-rw-r--r-- | Makefile.am | 1 | ||||
-rw-r--r-- | src/db_lock.c | 23 | ||||
-rw-r--r-- | src/db_lock.h | 55 | ||||
-rw-r--r-- | src/dirvec.c | 46 | ||||
-rw-r--r-- | src/dirvec.h | 4 | ||||
-rw-r--r-- | src/main.c | 6 | ||||
-rw-r--r-- | src/songvec.c | 46 |
7 files changed, 111 insertions, 70 deletions
diff --git a/Makefile.am b/Makefile.am index 19a25079f..631931325 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 000000000..3aaba4dc2 --- /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 000000000..1e557b985 --- /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 3df08e9ab..fa6b7b5f6 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 a15510ab2..b9d730a17 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 68f19f153..f7e7ba778 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 7d5a7a474..9c7b30845 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; } |