Merge remote-tracking branches 'merge-requests/6' and 'merge-requests/7'
authorKlaus Ethgen <Klaus@Ethgen.de>
Sun, 20 Jul 2014 12:57:40 +0000 (13:57 +0100)
committerKlaus Ethgen <Klaus@Ethgen.de>
Sun, 20 Jul 2014 12:57:40 +0000 (13:57 +0100)
* 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

1  2  3 
src/filedata.c

diff --cc 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.
++  * <p />
++  * 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);
                }
   }