kviewshell
DjVuFileCache.cpp
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057 #ifdef HAVE_CONFIG_H
00058 # include "config.h"
00059 #endif
00060 #if NEED_GNUG_PRAGMAS
00061 # pragma implementation
00062 #endif
00063
00064 #include "DjVuFileCache.h"
00065 #include "debug.h"
00066
00067 #include <stdlib.h>
00068
00069
00070 #ifdef HAVE_NAMESPACES
00071 namespace DJVU {
00072 # ifdef NOT_DEFINED // Just to fool emacs c++ mode
00073 }
00074 #endif
00075 #endif
00076
00077
00078 DjVuFileCache::~DjVuFileCache(void) {}
00079
00080 int
00081 DjVuFileCache::Item::qsort_func(const void * el1, const void * el2)
00082 {
00083 const Item * item1=*(Item **) el1;
00084 const Item * item2=*(Item **) el2;
00085 time_t time1=item1->get_time();
00086 time_t time2=item2->get_time();
00087 return time1<time2 ? -1 : time1>time2 ? 1 : 0;
00088 }
00089
00090 void
00091 DjVuFileCache::set_max_size(int xmax_size)
00092 {
00093 DEBUG_MSG("DjVuFileCache::set_max_size(): resizing to " << xmax_size << "\n");
00094 DEBUG_MAKE_INDENT(3);
00095
00096 GCriticalSectionLock lock(&class_lock);
00097
00098 max_size=xmax_size;
00099 cur_size=calculate_size();
00100
00101 if (max_size>=0) clear_to_size(enabled ? max_size : 0);
00102 }
00103
00104 void
00105 DjVuFileCache::enable(bool en)
00106 {
00107 enabled=en;
00108 set_max_size(max_size);
00109 }
00110
00111 void
00112 DjVuFileCache::add_file(const GP<DjVuFile> & file)
00113 {
00114 DEBUG_MSG("DjVuFileCache::add_file(): trying to add a new item\n");
00115 DEBUG_MAKE_INDENT(3);
00116
00117 GCriticalSectionLock lock(&class_lock);
00118
00119
00120 GPosition pos;
00121 for(pos=list;pos;++pos)
00122 if (list[pos]->get_file()==file) break;
00123
00124 if (pos) list[pos]->refresh();
00125 else
00126 {
00127
00128 int _max_size=enabled ? max_size : 0;
00129 if (max_size<0) _max_size=max_size;
00130
00131 int add_size=file->get_memory_usage();
00132
00133 if (_max_size>=0 && add_size>_max_size)
00134 {
00135 DEBUG_MSG("but this item is way too large => doing nothing\n");
00136 return;
00137 }
00138
00139 if (_max_size>=0) clear_to_size(_max_size-add_size);
00140
00141 list.append(new Item(file));
00142 cur_size+=add_size;
00143 file_added(file);
00144 }
00145 }
00146
00147 void
00148 DjVuFileCache::clear_to_size(int size)
00149 {
00150 DEBUG_MSG("DjVuFileCache::clear_to_size(): dropping cache size to " << size << "\n");
00151 DEBUG_MAKE_INDENT(3);
00152
00153 GCriticalSectionLock lock(&class_lock);
00154
00155 if (size==0)
00156 {
00157 list.empty();
00158 cur_size=0;
00159 } else
00160 if (list.size()>20)
00161 {
00162
00163
00164 GTArray<void *> item_arr(list.size()-1);
00165 GPosition pos;
00166 int i;
00167 for(pos=list, i=0;pos;++pos, i++)
00168 {
00169 GP<Item> item=list[pos];
00170 item->list_pos=pos;
00171 item_arr[i]=item;
00172 }
00173
00174 qsort(&item_arr[0], item_arr.size(), sizeof(item_arr[0]), Item::qsort_func);
00175
00176 for(i=0;i<item_arr.size() && cur_size>(int) size;i++)
00177 {
00178 Item * item=(Item *) item_arr[i];
00179 cur_size-=item->get_size();
00180 GP<DjVuFile> file=item->file;
00181 list.del(item->list_pos);
00182 file_cleared(file);
00183 if (cur_size<=0) cur_size=calculate_size();
00184 }
00185 } else
00186 {
00187
00188 while(cur_size>(int) size)
00189 {
00190 if (!list.size())
00191 {
00192
00193 cur_size=0;
00194 break;
00195 }
00196
00197
00198 GPosition oldest_pos=list;
00199 GPosition pos=list;
00200 for(++pos;pos;++pos)
00201 if (list[pos]->get_time()<list[oldest_pos]->get_time())
00202 oldest_pos=pos;
00203 cur_size-=list[oldest_pos]->get_size();
00204 GP<DjVuFile> file=list[oldest_pos]->file;
00205 list.del(oldest_pos);
00206 file_cleared(file);
00207
00208
00209
00210 if (cur_size<=0) cur_size=calculate_size();
00211 }
00212 }
00213
00214 DEBUG_MSG("done: current cache size=" << cur_size << "\n");
00215 }
00216
00217 int
00218 DjVuFileCache::calculate_size(void)
00219 {
00220 GCriticalSectionLock lock(&class_lock);
00221
00222 int size=0;
00223 for(GPosition pos=list;pos;++pos)
00224 size+=list[pos]->get_size();
00225 return size;
00226 }
00227
00228 void
00229 DjVuFileCache::del_file(const DjVuFile * file)
00230 {
00231 DEBUG_MSG("DjVuFileCache::del_file(): Removing an item from cache\n");
00232 DEBUG_MAKE_INDENT(3);
00233
00234 GCriticalSectionLock lock(&class_lock);
00235
00236 for(GPosition pos=list;pos;++pos)
00237 if (list[pos]->get_file()==file)
00238 {
00239 GP<DjVuFile> file=list[pos]->get_file();
00240 cur_size-=list[pos]->get_size();
00241 list.del(pos);
00242 file_deleted(file);
00243 break;
00244 }
00245 if (cur_size<0) cur_size=calculate_size();
00246 DEBUG_MSG("current cache size=" << cur_size << "\n");
00247 }
00248
00249 GPList<DjVuFileCache::Item>
00250 DjVuFileCache::get_items(void)
00251 {
00252 GCriticalSectionLock lock(&class_lock);
00253
00254 return list;
00255 }
00256
00257 void
00258 DjVuFileCache::file_added(const GP<DjVuFile> &) {}
00259
00260 void
00261 DjVuFileCache::file_deleted(const GP<DjVuFile> &) {}
00262
00263 void
00264 DjVuFileCache::file_cleared(const GP<DjVuFile> &) {}
00265
00266 #ifdef HAVE_NAMESPACES
00267 }
00268 # ifndef NOT_USING_DJVU_NAMESPACE
00269 using namespace DJVU;
00270 # endif
00271 #endif
00272