aboutsummaryrefslogtreecommitdiffstats
path: root/src/songvec.c
diff options
context:
space:
mode:
authorEric Wong <normalperson@yhbt.net>2008-10-12 05:28:25 -0700
committerEric Wong <normalperson@yhbt.net>2008-10-12 05:29:27 -0700
commit7278e3b2ee49a853b01dc6532bd7067a264f235d (patch)
tree28e83de310f0c58df226e253a82b0d43ff784497 /src/songvec.c
parentc87ce02575e0a9d5ac3e50938688187ea28ad400 (diff)
parentc7579ca2d8422f0172537e1ca7d1bd46edfc4f9d (diff)
downloadmpd-7278e3b2ee49a853b01dc6532bd7067a264f235d.tar.gz
mpd-7278e3b2ee49a853b01dc6532bd7067a264f235d.tar.xz
mpd-7278e3b2ee49a853b01dc6532bd7067a264f235d.zip
Merge branch 'ew/directory'
* ew/directory: (21 commits) update: fix multiple deletes from *vec iterators directory: children leave parents before being free()ed directory: always maintain sorted properties vectors update: simplify the serialized_delete usage a bit update: remove delete_each_song and clear_directory directory: directory_free kills all that it contains update: serialize directory deletions update: serialize song_free in main thread dirvec: introduce locking for all iterators dirvec: use dirvec_for_each where it makes sense dirvec: add dirvec_for_each iterator songvec: avoid holding nr_lock during free(3) update: allow music_root updates to be queued update: validate in command.c and fix small memory leak directory: rename isRootDirectory => path_is_music_root Avoid calling isRootDirectory when we have a directory object directory: make music_root global and avoid runtime initialization directory: use mpd_sizeof_str_flex_array for path, too tag_item: avoid wasting space when struct is unpackable song: use mpd_sizeof_str_flex_array for song.url ... [ew: fixed up merge errors with myself when isRootDirectory went away]
Diffstat (limited to 'src/songvec.c')
-rw-r--r--src/songvec.c29
1 files changed, 16 insertions, 13 deletions
diff --git a/src/songvec.c b/src/songvec.c
index ce04a4373..19433a222 100644
--- a/src/songvec.c
+++ b/src/songvec.c
@@ -17,13 +17,6 @@ static size_t sv_size(struct songvec *sv)
return sv->nr * sizeof(struct mpd_song *);
}
-void songvec_sort(struct songvec *sv)
-{
- pthread_mutex_lock(&nr_lock);
- qsort(sv->base, sv->nr, sizeof(struct mpd_song *), songvec_cmp);
- pthread_mutex_unlock(&nr_lock);
-}
-
struct mpd_song *songvec_find(const struct songvec *sv, const char *url)
{
int i;
@@ -48,10 +41,12 @@ int songvec_delete(struct songvec *sv, const struct mpd_song *del)
for (i = sv->nr; --i >= 0; ) {
if (sv->base[i] != del)
continue;
- /* we _don't_ call freeSong() here */
+ /* we _don't_ call song_free() here */
if (!--sv->nr) {
+ pthread_mutex_unlock(&nr_lock);
free(sv->base);
sv->base = NULL;
+ return i;
} else {
memmove(&sv->base[i], &sv->base[i + 1],
(sv->nr - i + 1) * sizeof(struct mpd_song *));
@@ -66,40 +61,48 @@ int songvec_delete(struct songvec *sv, const struct mpd_song *del)
void songvec_add(struct songvec *sv, struct mpd_song *add)
{
+ size_t old_nr;
+
pthread_mutex_lock(&nr_lock);
- ++sv->nr;
+ old_nr = sv->nr++;
sv->base = xrealloc(sv->base, sv_size(sv));
- sv->base[sv->nr - 1] = add;
+ sv->base[old_nr] = add;
+ if (old_nr && songvec_cmp(&sv->base[old_nr - 1], &add) >= 0)
+ qsort(sv->base, sv->nr, sizeof(struct mpd_song *), songvec_cmp);
pthread_mutex_unlock(&nr_lock);
}
void songvec_destroy(struct songvec *sv)
{
pthread_mutex_lock(&nr_lock);
+ sv->nr = 0;
+ pthread_mutex_unlock(&nr_lock);
if (sv->base) {
free(sv->base);
sv->base = NULL;
}
- sv->nr = 0;
- pthread_mutex_unlock(&nr_lock);
}
int songvec_for_each(const struct songvec *sv,
int (*fn)(struct mpd_song *, void *), void *arg)
{
size_t i;
+ size_t prev_nr;
pthread_mutex_lock(&nr_lock);
- for (i = 0; i < sv->nr; ++i) {
+ for (i = 0; i < sv->nr; ) {
struct mpd_song *song = sv->base[i];
assert(song);
assert(*song->url);
+ prev_nr = sv->nr;
pthread_mutex_unlock(&nr_lock); /* fn() may block */
if (fn(song, arg) < 0)
return -1;
pthread_mutex_lock(&nr_lock); /* sv->nr may change in fn() */
+ if (prev_nr == sv->nr)
+ ++i;
}
pthread_mutex_unlock(&nr_lock);