From: Klaus Ethgen Date: Sun, 20 Jul 2014 12:57:40 +0000 (+0100) Subject: Merge remote-tracking branches 'merge-requests/6' and 'merge-requests/7' X-Git-Tag: v1.2~1 X-Git-Url: http://geeqie.org/cgi-bin/gitweb.cgi?p=geeqie.git;a=commitdiff_plain;h=d6c33614c45e38845a0bcfd702e38e18d5dcec0b Merge remote-tracking branches 'merge-requests/6' and 'merge-requests/7' * merge-requests/6: Bug 3594998: make lirc initialization quieter * merge-requests/7: Add filedata counting to watch for filedata leaks Use FileData locks to avoid expensive reloads with marks enabled Add "lock" functionality to keep FileDatas in memory --- d6c33614c45e38845a0bcfd702e38e18d5dcec0b diff --cc src/filedata.c index 9c2ac8c2,e0d70f00,95f74d64..c99f3a91 --- a/src/filedata.c +++ b/src/filedata.c @@@@ -566,41 -566,41 -631,72 +631,72 @@@@ void file_data_unref(FileData *fd fd->ref--; #ifdef DEBUG_FILEDATA -- DEBUG_2("file_data_unref fd=%p (%d): '%s' @ %s:%d", fd, fd->ref, fd->path, file, line); ++ DEBUG_2("file_data_unref fd=%p (%d:%d): '%s' @ %s:%d", fd, fd->ref, fd->locked, fd->path, ++ file, line); #else -- DEBUG_2("file_data_unref fd=%p (%d): '%s'", fd, fd->ref, fd->path); ++ DEBUG_2("file_data_unref fd=%p (%d:%d): '%s'", fd, fd->ref, fd->locked, fd->path); #endif -- if (fd->ref == 0) -- { -- GList *work; -- FileData *parent = fd->parent ? fd->parent : fd; -- if (parent->ref > 0) return; ++ // Free FileData if it's no longer ref'd ++ file_data_consider_free(fd); ++ } + - work = parent->sidecar_files; - while (work) - { - FileData *sfd = work->data; - if (sfd->ref > 0) return; - work = work->next; - } ++ /** ++ * \brief Lock the FileData in memory. ++ * ++ * This allows the caller to prevent a FileData from being freed, even after its refcount is zero. ++ * This is intended to be used in cases where a FileData _should_ stay in memory as an optimization, ++ * even if the code would continue to function properly even if the FileData were freed. Code that ++ * _requires_ the FileData to remain in memory should continue to use file_data_(un)ref. ++ *

++ * Note: This differs from file_data_ref in that the behavior is reentrant -- after N calls to ++ * file_data_lock, a single call to file_data_unlock will unlock the FileData. ++ */ ++ void file_data_lock(FileData *fd) ++ { ++ if (fd == NULL) return; ++ if (fd->magick != FD_MAGICK) DEBUG_0("fd magick mismatch fd=%p", fd); - work = parent->sidecar_files; - while (work) - { - FileData *sfd = work->data; - if (sfd->ref > 0) return; - work = work->next; - } - /* none of parent/children is referenced, we can free everything */ ++ g_assert(fd->magick == FD_MAGICK); ++ fd->locked = TRUE; - /* none of parent/children is referenced, we can free everything */ - DEBUG_2("file_data_unref: deleting '%s', parent '%s'", fd->path, fd->parent ? parent->path : "-"); ++ DEBUG_2("file_data_ref fd=%p (%d): '%s'", fd, fd->ref, fd->path); ++ } - DEBUG_2("file_data_unref: deleting '%s', parent '%s'", fd->path, fd->parent ? parent->path : "-"); - work = parent->sidecar_files; - while (work) - { - FileData *sfd = work->data; - file_data_free(sfd); - work = work->next; - } ++ /** ++ * \brief Reset the maintain-FileData-in-memory lock ++ * ++ * This again allows the FileData to be freed when its refcount drops to zero. Automatically frees ++ * the FileData if its refcount is already zero (which will happen if the lock is the only thing ++ * keeping it from being freed. ++ */ ++ void file_data_unlock(FileData *fd) ++ { ++ if (fd == NULL) return; ++ if (fd->magick != FD_MAGICK) DEBUG_0("fd magick mismatch fd=%p", fd); - work = parent->sidecar_files; - while (work) - { - FileData *sfd = work->data; - file_data_free(sfd); - work = work->next; - } - g_list_free(parent->sidecar_files); - parent->sidecar_files = NULL; ++ g_assert(fd->magick == FD_MAGICK); ++ fd->locked = FALSE; + - file_data_free(parent); ++ // Free FileData if it's no longer ref'd ++ file_data_consider_free(fd); ++ } + - g_list_free(parent->sidecar_files); - parent->sidecar_files = NULL; ++ /** ++ * \brief Lock all of the FileDatas in the provided list ++ * ++ * \see file_data_lock(FileData) ++ */ ++ void file_data_lock_list(GList *list) ++ { ++ GList *work; + - file_data_free(parent); ++ work = list; ++ while (work) ++ { ++ FileData *fd = work->data; ++ work = work->next; ++ file_data_lock(fd); } }