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 #ifndef QCACHE_H
00043 #define QCACHE_H
00044
00045 #include <QtCore/qhash.h>
00046
00047 QT_BEGIN_HEADER
00048
00049 QT_BEGIN_NAMESPACE
00050
00051 QT_MODULE(Core)
00052
00053 template <class Key, class T>
00054 class QCache
00055 {
00056 struct Node {
00057 inline Node() : keyPtr(0) {}
00058 inline Node(T *data, int cost)
00059 : keyPtr(0), t(data), c(cost), p(0), n(0) {}
00060 const Key *keyPtr; T *t; int c; Node *p,*n;
00061 };
00062 Node *f, *l;
00063 QHash<Key, Node> hash;
00064 void *unused;
00065 int mx, total;
00066
00067 inline void unlink(Node &n) {
00068 if (n.p) n.p->n = n.n;
00069 if (n.n) n.n->p = n.p;
00070 if (l == &n) l = n.p;
00071 if (f == &n) f = n.n;
00072 total -= n.c;
00073 T *obj = n.t;
00074 hash.remove(*n.keyPtr);
00075 delete obj;
00076 }
00077 inline T *relink(const Key &key) {
00078 typename QHash<Key, Node>::iterator i = hash.find(key);
00079 if (typename QHash<Key, Node>::const_iterator(i) == hash.constEnd())
00080 return 0;
00081
00082 Node &n = *i;
00083 if (f != &n) {
00084 if (n.p) n.p->n = n.n;
00085 if (n.n) n.n->p = n.p;
00086 if (l == &n) l = n.p;
00087 n.p = 0;
00088 n.n = f;
00089 f->p = &n;
00090 f = &n;
00091 }
00092 return n.t;
00093 }
00094
00095 Q_DISABLE_COPY(QCache)
00096
00097 public:
00098 inline explicit QCache(int maxCost = 100);
00099 #ifdef QT3_SUPPORT
00100 inline QT3_SUPPORT_CONSTRUCTOR QCache(int maxCost, int )
00101 : f(0), l(0), mx(maxCost), total(0) {}
00102 #endif
00103 inline ~QCache() { clear(); }
00104
00105 inline int maxCost() const { return mx; }
00106 void setMaxCost(int m);
00107 inline int totalCost() const { return total; }
00108
00109 inline int size() const { return hash.size(); }
00110 inline int count() const { return hash.size(); }
00111 inline bool isEmpty() const { return hash.isEmpty(); }
00112 inline QList<Key> keys() const { return hash.keys(); }
00113
00114 void clear();
00115
00116 bool insert(const Key &key, T *object, int cost = 1);
00117 T *object(const Key &key) const;
00118 inline bool contains(const Key &key) const { return hash.contains(key); }
00119 T *operator[](const Key &key) const;
00120
00121 bool remove(const Key &key);
00122 T *take(const Key &key);
00123
00124 private:
00125 void trim(int m);
00126
00127 #ifdef QT3_SUPPORT
00128 inline QT3_SUPPORT T *find(const Key &key) const { return object(key); }
00129 #endif
00130
00131 };
00132
00133 template <class Key, class T>
00134 inline QCache<Key, T>::QCache(int amaxCost)
00135 : f(0), l(0), unused(0), mx(amaxCost), total(0) {}
00136
00137 template <class Key, class T>
00138 inline void QCache<Key,T>::clear()
00139 { while (f) { delete f->t; f = f->n; }
00140 hash.clear(); l = 0; total = 0; }
00141
00142 template <class Key, class T>
00143 inline void QCache<Key,T>::setMaxCost(int m)
00144 { mx = m; trim(mx); }
00145
00146 template <class Key, class T>
00147 inline T *QCache<Key,T>::object(const Key &key) const
00148 { return const_cast<QCache<Key,T>*>(this)->relink(key); }
00149
00150 template <class Key, class T>
00151 inline T *QCache<Key,T>::operator[](const Key &key) const
00152 { return object(key); }
00153
00154 template <class Key, class T>
00155 inline bool QCache<Key,T>::remove(const Key &key)
00156 {
00157 typename QHash<Key, Node>::iterator i = hash.find(key);
00158 if (typename QHash<Key, Node>::const_iterator(i) == hash.constEnd()) {
00159 return false;
00160 } else {
00161 unlink(*i);
00162 return true;
00163 }
00164 }
00165
00166 template <class Key, class T>
00167 inline T *QCache<Key,T>::take(const Key &key)
00168 {
00169 typename QHash<Key, Node>::iterator i = hash.find(key);
00170 if (i == hash.end())
00171 return 0;
00172
00173 Node &n = *i;
00174 T *t = n.t;
00175 n.t = 0;
00176 unlink(n);
00177 return t;
00178 }
00179
00180 template <class Key, class T>
00181 bool QCache<Key,T>::insert(const Key &akey, T *aobject, int acost)
00182 {
00183 remove(akey);
00184 if (acost > mx) {
00185 delete aobject;
00186 return false;
00187 }
00188 trim(mx - acost);
00189 Node sn(aobject, acost);
00190 typename QHash<Key, Node>::iterator i = hash.insert(akey, sn);
00191 total += acost;
00192 Node *n = &i.value();
00193 n->keyPtr = &i.key();
00194 if (f) f->p = n;
00195 n->n = f;
00196 f = n;
00197 if (!l) l = f;
00198 return true;
00199 }
00200
00201 template <class Key, class T>
00202 void QCache<Key,T>::trim(int m)
00203 {
00204 Node *n = l;
00205 while (n && total > m) {
00206 Node *u = n;
00207 n = n->p;
00208 if (qIsDetached(*u->t))
00209 unlink(*u);
00210 }
00211 }
00212
00213 QT_END_NAMESPACE
00214
00215 QT_END_HEADER
00216
00217 #endif // QCACHE_H