summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLouis Burda <quent.burda@gmail.com>2023-01-12 02:31:51 +0100
committerLouis Burda <quent.burda@gmail.com>2023-01-12 02:31:51 +0100
commit83f8cf7c4e8cc8cb1695aeb7e60ea9f87a94392d (patch)
treed90622f3c0374f8a3e8da7b802a999cdc4cca2f1
parent44070fb5518e2b54748d58da5a5c61f476ef8700 (diff)
downloadtmus-track-arena.tar.gz
tmus-track-arena.zip
Add libvec backend for allocationtrack-arena
Having one large arena as the memory backing is not feasible, since each realloc all track link pointers could be invalidated
-rw-r--r--.gitmodules3
-rw-r--r--Makefile10
m---------lib/libvec0
-rw-r--r--src/cmd.c4
-rw-r--r--src/data.c102
-rw-r--r--src/data.h12
-rw-r--r--src/tui.c4
7 files changed, 82 insertions, 53 deletions
diff --git a/.gitmodules b/.gitmodules
index 7130a80..ef274bc 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -1,3 +1,6 @@
[submodule "lib/liblist"]
path = lib/liblist
url = git@sinitax.com:sinitax/liblist
+[submodule "lib/libvec"]
+ path = lib/libvec
+ url = git@sinitax.com:sinitax/libvec
diff --git a/Makefile b/Makefile
index 5f03e65..57aeed4 100644
--- a/Makefile
+++ b/Makefile
@@ -1,5 +1,6 @@
CFLAGS = -I src -g $(shell pkg-config --cflags glib-2.0 dbus-1)
-CFLAGS += -I lib/liblist/include -Wunused-variable -Wmissing-prototypes
+CFLAGS += -I lib/liblist/include -I lib/libvec/include
+CFLAGS += -Wunused-variable -Wunused-function -Wmissing-prototypes
LDLIBS = -lcurses $(shell pkg-config --libs glib-2.0 dbus-1)
DEPFLAGS = -MT $@ -MMD -MP -MF build/$*.d
@@ -8,7 +9,6 @@ ifeq "$(PROF)" "YES"
endif
BACKEND ?= mplay
-
ifeq "$(BACKEND)" "mpd"
LDLIBS += -lmpdclient
endif
@@ -18,6 +18,7 @@ OBJS = $(SRCS:src/%.c=build/%.o) build/player_$(BACKEND).o
DEPS = $(OBJS:%.o=%.d)
LIBLIST_A = lib/liblist/build/liblist.a
+LIBVEC_A = lib/libvec/build/libvec.a
PREFIX ?= /usr/local
BINDIR ?= /bin
@@ -43,7 +44,10 @@ include $(DEPS)
$(LIBLIST_A):
make -C lib/liblist build/liblist.a
-tmus: $(OBJS) $(LIBLIST_A)
+$(LIBVEC_A):
+ make -C lib/libvec build/libvec.a
+
+tmus: $(OBJS) $(LIBLIST_A) $(LIBVEC_A)
$(CC) -o tmus $^ $(CFLAGS) $(LDLIBS)
install: tmus
diff --git a/lib/libvec b/lib/libvec
new file mode 160000
+Subproject 75a9d022cfa82ecbd91e0a37d5cb677e36cae86
diff --git a/src/cmd.c b/src/cmd.c
index 6d23f06..0be59ab 100644
--- a/src/cmd.c
+++ b/src/cmd.c
@@ -85,7 +85,7 @@ cmd_move(const char *name)
if (player.track == track)
player.track = new;
- if (!track_rm(track, true))
+ if (!track_rm(track, true, true))
ERROR("Failed to move track");
return true;
@@ -255,7 +255,7 @@ cmd_rm_tag(const char *name)
CMD_ERROR("No such tag");
}
- if (!tag_rm(tag, true))
+ if (!tag_rm(tag, true, true))
CMD_ERROR("Failed to remove tag");
return true;
diff --git a/src/data.c b/src/data.c
index 9d8f24a..d188eb6 100644
--- a/src/data.c
+++ b/src/data.c
@@ -2,6 +2,7 @@
#include "player.h"
#include "list.h"
+#include "vec.h"
#include "log.h"
#include "tui.h"
@@ -15,31 +16,23 @@
const char *datadir;
+struct vec track_arena;
+
struct list tracks; /* struct track (link) */
struct list tags; /* struct track (link) */
struct list tags_sel; /* struct tag (link_sel) */
bool playlist_outdated;
-static int get_fid(const char *path);
-
static struct tag *tag_alloc(const char *path, const char *fname);
static void tag_free(struct tag *tag);
static struct track *track_alloc(const char *path, const char *fname);
-static void track_free(struct track *t);
-static int track_name_compare(struct link *a, struct link *b);
+static void track_free(struct track *t, bool free_underlying);
static void tracks_load(struct tag *tag);
static void tracks_save(struct tag *tag);
-int
-get_fid(const char *path)
-{
- struct stat st;
- return stat(path, &st) ? -1 : st.st_ino;
-}
-
struct tag *
tag_alloc(const char *path, const char *fname)
{
@@ -50,7 +43,9 @@ tag_alloc(const char *path, const char *fname)
tag->fpath = aprintf("%s/%s", path, fname);
tag->name = astrdup(fname);
+
tag->index_dirty = false;
+
tag->link = LINK_EMPTY;
tag->link_sel = LINK_EMPTY;
list_init(&tag->tracks);
@@ -72,12 +67,13 @@ track_alloc(const char *dir, const char *fname)
{
struct track *track;
- track = malloc(sizeof(struct track));
- if (!track) err(1, "malloc");
-
+ track = vec_alloc_slot(&track_arena);
track->fpath = aprintf("%s/%s", dir, fname);
track->name = astrdup(fname);
track->tag = NULL;
+
+ track->pending = false;
+
track->link = LINK_EMPTY;
track->link_pl = LINK_EMPTY;
track->link_tt = LINK_EMPTY;
@@ -88,22 +84,12 @@ track_alloc(const char *dir, const char *fname)
}
void
-track_free(struct track *t)
+track_free(struct track *track, bool free_underlying)
{
- free(t->fpath);
- free(t->name);
- free(t);
-}
-
-int
-track_name_compare(struct link *a, struct link *b)
-{
- struct track *ta, *tb;
-
- ta = UPCAST(a, struct track, link);
- tb = UPCAST(b, struct track, link);
-
- return strcmp(ta->name, tb->name);
+ free(track->fpath);
+ free(track->name);
+ if (free_underlying)
+ vec_free_slot(&track_arena, track);
}
void
@@ -312,7 +298,7 @@ index_update(struct tag *tag)
bool
tracks_update(struct tag *tag)
{
- struct link *link;
+ struct link *link, *next;
struct track *track;
struct dirent *ent;
DIR *dir;
@@ -320,10 +306,9 @@ tracks_update(struct tag *tag)
dir = opendir(tag->fpath);
if (!dir) return false;
- while (!list_empty(&tag->tracks)) {
- link = list_pop_front(&tag->tracks);
+ for (LIST_ITER(&tag->tracks, link)) {
track = UPCAST(link, struct track, link_tt);
- track_rm(track, false);
+ track->pending = true;
}
while ((ent = readdir(dir))) {
@@ -336,7 +321,21 @@ tracks_update(struct tag *tag)
if (!strchr(ent->d_name + 1, '.'))
continue;
- track_add(tag, ent->d_name);
+ track = track_find(tag, ent->d_name);
+ if (track) {
+ track->pending = false;
+ } else {
+ track_add(tag, ent->d_name);
+ }
+ }
+
+ link = &tag->tracks.head;
+ while (LIST_INNER(link)) {
+ track = UPCAST(link, struct track, link_tt);
+ next = link->next;
+ if (track->pending)
+ track_rm(track, false, true);
+ link = next;
}
tag->index_dirty = false;
@@ -415,7 +414,7 @@ tag_find(const char *name)
}
bool
-tag_rm(struct tag *tag, bool sync_fs)
+tag_rm(struct tag *tag, bool sync_fs, bool free_track)
{
struct link *link;
struct track *track;
@@ -424,7 +423,7 @@ tag_rm(struct tag *tag, bool sync_fs)
while (!list_empty(&tag->tracks)) {
link = list_pop_front(&tag->tracks);
track = UPCAST(link, struct track, link_tt);
- if (!track_rm(track, sync_fs))
+ if (!track_rm(track, sync_fs, free_track))
return false;
}
@@ -480,13 +479,13 @@ track_add(struct tag *tag, const char *fname)
track = track_alloc(tag->fpath, fname);
track->tag = tag;
- /* insert track into sorted tracks list */
+ /* insert track into combined list */
list_push_back(&tracks, &track->link);
/* add to tag's tracks list */
list_push_back(&tag->tracks, &track->link_tt);
- /* if track's tag is selected, update playlist */
+ /* add new track to current playlist */
if (link_inuse(&tag->link_sel))
playlist_outdated = true;
@@ -495,8 +494,23 @@ track_add(struct tag *tag, const char *fname)
return track;
}
+struct track *
+track_find(struct tag *tag, const char *name)
+{
+ struct link *link;
+ struct track *track;
+
+ for (LIST_ITER(&tag->tracks, link)) {
+ track = UPCAST(link, struct track, link_tt);
+ if (!strcmp(track->name, name))
+ return track;
+ }
+
+ return NULL;
+}
+
bool
-track_rm(struct track *track, bool sync_fs)
+track_rm(struct track *track, bool sync_fs, bool free_underlying)
{
if (sync_fs && !rm_file(track->fpath))
return false;
@@ -520,7 +534,7 @@ track_rm(struct track *track, bool sync_fs)
if (player.track == track)
player.track = NULL;
- track_free(track);
+ track_free(track, free_underlying);
return true;
}
@@ -600,9 +614,7 @@ release_lock(const char *datadir)
bool status;
lockpath = aprintf("%s/.lock", datadir);
-
status = rm_file(lockpath);
-
free(lockpath);
return status;
@@ -617,6 +629,8 @@ data_load(void)
char *path;
DIR *dir;
+ vec_init(&track_arena, sizeof(struct track), 256);
+
list_init(&tracks);
list_init(&tags);
list_init(&tags_sel);
@@ -679,7 +693,9 @@ data_free(void)
while (!list_empty(&tags)) {
link = list_pop_front(&tags);
tag = UPCAST(link, struct tag, link);
- tag_rm(tag, false);
+ tag_rm(tag, false, false);
}
+
+ vec_deinit(&track_arena);
}
diff --git a/src/data.h b/src/data.h
index 75561d8..fd10561 100644
--- a/src/data.h
+++ b/src/data.h
@@ -7,7 +7,8 @@
struct tag {
char *name, *fpath;
struct list tracks;
- bool index_dirty;
+
+ bool index_dirty; /* index file needs updating */
struct link link; /* tags list */
struct link link_sel; /* selected tags list */
@@ -17,6 +18,8 @@ struct track {
char *name, *fpath;
struct tag *tag;
+ bool pending; /* pending deletion */
+
struct link link; /* tracks list */
struct link link_pl; /* player playlist */
struct link link_tt; /* tag tracks list */
@@ -43,11 +46,12 @@ void playlist_update(void);
struct tag *tag_add(const char *fname);
struct tag *tag_find(const char *name);
-bool tag_rm(struct tag *tag, bool sync_fs);
+bool tag_rm(struct tag *tag, bool sync_fs, bool free_track);
bool tag_rename(struct tag *tag, const char *name);
struct track *track_add(struct tag *tag, const char *fname);
-bool track_rm(struct track *track, bool sync_fs);
+struct track *track_find(struct tag *tag, const char *name);
+bool track_rm(struct track *track, bool sync_fs, bool free_track);
bool track_rename(struct track *track, const char *name);
bool acquire_lock(const char *path);
@@ -57,6 +61,8 @@ void data_load(void);
void data_save(void);
void data_free(void);
+extern struct vec track_arena;
+
extern const char *datadir;
extern struct list tracks; /* struct track (link) */
diff --git a/src/tui.c b/src/tui.c
index 5f03316..708c7cc 100644
--- a/src/tui.c
+++ b/src/tui.c
@@ -375,7 +375,7 @@ delete_selected_tag(void)
link = list_at(&tags, tag_nav.sel);
if (!link) return;
tag = UPCAST(link, struct tag, link);
- tag_rm(tag, true);
+ tag_rm(tag, true, true);
}
bool
@@ -550,7 +550,7 @@ delete_selected_track(void)
if (!link) return false;
track = tracks_vis_track(link);
- if (!track_rm(track, true))
+ if (!track_rm(track, true, true))
CMD_SET_STATUS("Failed to remove track");
return true;