diff options
| author | Louis Burda <quent.burda@gmail.com> | 2023-01-12 02:31:51 +0100 |
|---|---|---|
| committer | Louis Burda <quent.burda@gmail.com> | 2023-01-12 02:31:51 +0100 |
| commit | 83f8cf7c4e8cc8cb1695aeb7e60ea9f87a94392d (patch) | |
| tree | d90622f3c0374f8a3e8da7b802a999cdc4cca2f1 | |
| parent | 44070fb5518e2b54748d58da5a5c61f476ef8700 (diff) | |
| download | tmus-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-- | .gitmodules | 3 | ||||
| -rw-r--r-- | Makefile | 10 | ||||
| m--------- | lib/libvec | 0 | ||||
| -rw-r--r-- | src/cmd.c | 4 | ||||
| -rw-r--r-- | src/data.c | 102 | ||||
| -rw-r--r-- | src/data.h | 12 | ||||
| -rw-r--r-- | src/tui.c | 4 |
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 @@ -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 @@ -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; @@ -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); } @@ -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) */ @@ -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; |
