Mercurial > geeqie.yaz
annotate src/filecache.c @ 1024:c92e5a5c3bfa
Add a Save button to Preferences dialog, which allow to save options to file without quitting the application.
author | zas_ |
---|---|
date | Sun, 31 Aug 2008 12:29:49 +0000 |
parents | 6ca2c5fd7b13 |
children | 1646720364cf |
rev | line source |
---|---|
844 | 1 /* |
2 * Geeqie | |
3 * Copyright (C) 2008 The Geeqie Team | |
4 * | |
5 * Author: Vladimir Nadvornik | |
6 * | |
7 * This software is released under the GNU General Public License (GNU GPL). | |
8 * Please read the included file COPYING for more information. | |
9 * This software comes with no warranty of any kind, use at your own risk! | |
10 */ | |
11 | |
12 | |
13 #include "main.h" | |
14 #include "filecache.h" | |
15 | |
873
bd3bdceb1230
Optimize file_cache_get() by only moving element to front if needed
zas_
parents:
855
diff
changeset
|
16 /* Set to TRUE to add file cache dumps to the debug output */ |
bd3bdceb1230
Optimize file_cache_get() by only moving element to front if needed
zas_
parents:
855
diff
changeset
|
17 const gboolean debug_file_cache = FALSE; |
bd3bdceb1230
Optimize file_cache_get() by only moving element to front if needed
zas_
parents:
855
diff
changeset
|
18 |
844 | 19 /* this implements a simple LRU algorithm */ |
20 | |
21 struct _FileCacheData { | |
22 FileCacheReleaseFunc release; | |
23 GList *list; | |
24 gulong max_size; | |
25 gulong size; | |
26 }; | |
27 | |
847 | 28 typedef struct _FileCacheEntry FileCacheEntry; |
29 struct _FileCacheEntry { | |
30 FileData *fd; | |
31 gulong size; | |
32 }; | |
33 | |
888 | 34 static void file_cache_notify_cb(FileData *fd, NotifyType type, gpointer data); |
35 | |
844 | 36 FileCacheData *file_cache_new(FileCacheReleaseFunc release, gulong max_size) |
37 { | |
38 FileCacheData *fc = g_new(FileCacheData, 1); | |
39 fc->release = release; | |
40 fc->list = NULL; | |
41 fc->max_size = max_size; | |
42 fc->size = 0; | |
888 | 43 |
44 file_data_register_notify_func(file_cache_notify_cb, fc, NOTIFY_PRIORITY_HIGH); | |
45 | |
844 | 46 return fc; |
47 } | |
48 | |
873
bd3bdceb1230
Optimize file_cache_get() by only moving element to front if needed
zas_
parents:
855
diff
changeset
|
49 gboolean file_cache_get(FileCacheData *fc, FileData *fd) |
844 | 50 { |
51 GList *work; | |
855 | 52 |
873
bd3bdceb1230
Optimize file_cache_get() by only moving element to front if needed
zas_
parents:
855
diff
changeset
|
53 g_assert(fc && fd); |
bd3bdceb1230
Optimize file_cache_get() by only moving element to front if needed
zas_
parents:
855
diff
changeset
|
54 |
bd3bdceb1230
Optimize file_cache_get() by only moving element to front if needed
zas_
parents:
855
diff
changeset
|
55 work = fc->list; |
bd3bdceb1230
Optimize file_cache_get() by only moving element to front if needed
zas_
parents:
855
diff
changeset
|
56 while (work) |
844 | 57 { |
873
bd3bdceb1230
Optimize file_cache_get() by only moving element to front if needed
zas_
parents:
855
diff
changeset
|
58 FileCacheEntry *fce = work->data; |
bd3bdceb1230
Optimize file_cache_get() by only moving element to front if needed
zas_
parents:
855
diff
changeset
|
59 if (fce->fd == fd) |
bd3bdceb1230
Optimize file_cache_get() by only moving element to front if needed
zas_
parents:
855
diff
changeset
|
60 { |
bd3bdceb1230
Optimize file_cache_get() by only moving element to front if needed
zas_
parents:
855
diff
changeset
|
61 /* entry exists */ |
bd3bdceb1230
Optimize file_cache_get() by only moving element to front if needed
zas_
parents:
855
diff
changeset
|
62 DEBUG_1("cache hit: fc=%p %s", fc, fd->path); |
bd3bdceb1230
Optimize file_cache_get() by only moving element to front if needed
zas_
parents:
855
diff
changeset
|
63 if (work == fc->list) return TRUE; /* already at the beginning */ |
bd3bdceb1230
Optimize file_cache_get() by only moving element to front if needed
zas_
parents:
855
diff
changeset
|
64 /* move it to the beginning */ |
bd3bdceb1230
Optimize file_cache_get() by only moving element to front if needed
zas_
parents:
855
diff
changeset
|
65 DEBUG_1("cache move to front: fc=%p %s", fc, fd->path); |
bd3bdceb1230
Optimize file_cache_get() by only moving element to front if needed
zas_
parents:
855
diff
changeset
|
66 fc->list = g_list_remove_link(fc->list, work); |
bd3bdceb1230
Optimize file_cache_get() by only moving element to front if needed
zas_
parents:
855
diff
changeset
|
67 fc->list = g_list_concat(work, fc->list); |
888 | 68 |
891 | 69 if (file_data_check_changed_files(fd)) /* this will eventually remove changed files from cache via file_cache_notify_cb */ |
70 return FALSE; | |
888 | 71 |
873
bd3bdceb1230
Optimize file_cache_get() by only moving element to front if needed
zas_
parents:
855
diff
changeset
|
72 if (debug_file_cache) file_cache_dump(fc); |
bd3bdceb1230
Optimize file_cache_get() by only moving element to front if needed
zas_
parents:
855
diff
changeset
|
73 return TRUE; |
bd3bdceb1230
Optimize file_cache_get() by only moving element to front if needed
zas_
parents:
855
diff
changeset
|
74 } |
bd3bdceb1230
Optimize file_cache_get() by only moving element to front if needed
zas_
parents:
855
diff
changeset
|
75 work = work->next; |
844 | 76 } |
873
bd3bdceb1230
Optimize file_cache_get() by only moving element to front if needed
zas_
parents:
855
diff
changeset
|
77 DEBUG_1("cache miss: fc=%p %s", fc, fd->path); |
844 | 78 return FALSE; |
79 } | |
80 | |
847 | 81 void file_cache_set_size(FileCacheData *fc, gulong size) |
82 { | |
83 GList *work; | |
84 FileCacheEntry *last_fe; | |
873
bd3bdceb1230
Optimize file_cache_get() by only moving element to front if needed
zas_
parents:
855
diff
changeset
|
85 |
bd3bdceb1230
Optimize file_cache_get() by only moving element to front if needed
zas_
parents:
855
diff
changeset
|
86 if (debug_file_cache) file_cache_dump(fc); |
bd3bdceb1230
Optimize file_cache_get() by only moving element to front if needed
zas_
parents:
855
diff
changeset
|
87 |
847 | 88 work = g_list_last(fc->list); |
89 while (fc->size > size && work) | |
90 { | |
91 GList *prev; | |
92 last_fe = work->data; | |
995 | 93 prev = work->prev; |
847 | 94 fc->list = g_list_delete_link(fc->list, work); |
95 work = prev; | |
96 | |
888 | 97 DEBUG_1("file changed - cache remove: fc=%p %s", fc, last_fe->fd->path); |
847 | 98 fc->size -= last_fe->size; |
99 fc->release(last_fe->fd); | |
100 file_data_unref(last_fe->fd); | |
101 g_free(last_fe); | |
102 } | |
103 } | |
104 | |
844 | 105 void file_cache_put(FileCacheData *fc, FileData *fd, gulong size) |
106 { | |
847 | 107 FileCacheEntry *fe; |
855 | 108 |
873
bd3bdceb1230
Optimize file_cache_get() by only moving element to front if needed
zas_
parents:
855
diff
changeset
|
109 if (file_cache_get(fc, fd)) return; |
844 | 110 |
873
bd3bdceb1230
Optimize file_cache_get() by only moving element to front if needed
zas_
parents:
855
diff
changeset
|
111 DEBUG_1("cache add: fc=%p %s", fc, fd->path); |
847 | 112 fe = g_new(FileCacheEntry, 1); |
113 fe->fd = file_data_ref(fd); | |
114 fe->size = size; | |
115 fc->list = g_list_prepend(fc->list, fe); | |
116 fc->size += size; | |
844 | 117 |
847 | 118 file_cache_set_size(fc, fc->max_size); |
119 } | |
120 | |
121 gulong file_cache_get_max_size(FileCacheData *fc) | |
122 { | |
123 return fc->max_size; | |
124 } | |
125 | |
126 gulong file_cache_get_size(FileCacheData *fc) | |
127 { | |
128 return fc->size; | |
129 } | |
130 | |
131 void file_cache_set_max_size(FileCacheData *fc, gulong size) | |
132 { | |
133 fc->max_size = size; | |
134 file_cache_set_size(fc, fc->max_size); | |
844 | 135 } |
846 | 136 |
888 | 137 static void file_cache_remove_fd(FileCacheData *fc, FileData *fd) |
138 { | |
139 GList *work; | |
140 FileCacheEntry *fe; | |
141 | |
142 if (debug_file_cache) file_cache_dump(fc); | |
143 | |
144 work = fc->list; | |
145 while (work) | |
146 { | |
147 GList *current = work; | |
148 fe = work->data; | |
995 | 149 work = work->next; |
888 | 150 |
151 if (fe->fd == fd) | |
152 { | |
153 fc->list = g_list_delete_link(fc->list, current); | |
154 | |
155 DEBUG_1("cache remove: fc=%p %s", fc, fe->fd->path); | |
156 fc->size -= fe->size; | |
157 fc->release(fe->fd); | |
158 file_data_unref(fe->fd); | |
159 g_free(fe); | |
160 } | |
161 } | |
162 } | |
163 | |
846 | 164 void file_cache_dump(FileCacheData *fc) |
165 { | |
166 GList *work; | |
167 work = fc->list; | |
873
bd3bdceb1230
Optimize file_cache_get() by only moving element to front if needed
zas_
parents:
855
diff
changeset
|
168 guint n = 0; |
bd3bdceb1230
Optimize file_cache_get() by only moving element to front if needed
zas_
parents:
855
diff
changeset
|
169 DEBUG_1("cache dump: fc=%p max size:%ld size:%ld", fc, fc->max_size, fc->size); |
847 | 170 |
855 | 171 while (work) |
846 | 172 { |
847 | 173 FileCacheEntry *fe = work->data; |
846 | 174 work = work->next; |
873
bd3bdceb1230
Optimize file_cache_get() by only moving element to front if needed
zas_
parents:
855
diff
changeset
|
175 DEBUG_1("cache entry: fc=%p [%lu] %s %ld", fc, ++n, fe->fd->path, fe->size); |
846 | 176 } |
177 } | |
888 | 178 |
179 static void file_cache_notify_cb(FileData *fd, NotifyType type, gpointer data) | |
180 { | |
181 FileCacheData *fc = data; | |
182 | |
183 if (type == NOTIFY_TYPE_REREAD) | |
184 { | |
185 file_cache_remove_fd(fc, fd); | |
186 } | |
893 | 187 } |