template <class Key, class T>
class QCache
{
- struct Node {
- inline Node() : keyPtr(Q_NULLPTR) {}
- inline Node(T *data, int cost)
- : keyPtr(Q_NULLPTR), t(data), c(cost), p(Q_NULLPTR), n(Q_NULLPTR) {}
- const Key *keyPtr; T *t; int c; Node *p,*n;
- };
- Node *f, *l;
- QHash<Key, Node> hash;
- int mx, total;
-
- inline void unlink(Node &n) {
- if (n.p) n.p->n = n.n;
- if (n.n) n.n->p = n.p;
- if (l == &n) l = n.p;
- if (f == &n) f = n.n;
- total -= n.c;
- T *obj = n.t;
- hash.remove(*n.keyPtr);
- delete obj;
- }
- inline T *relink(const Key &key) {
- typename QHash<Key, Node>::iterator i = hash.find(key);
- if (typename QHash<Key, Node>::const_iterator(i) == hash.constEnd())
- return Q_NULLPTR;
-
- Node &n = *i;
- if (f != &n) {
- if (n.p) n.p->n = n.n;
- if (n.n) n.n->p = n.p;
- if (l == &n) l = n.p;
- n.p = 0;
- n.n = f;
- f->p = &n;
- f = &n;
- }
- return n.t;
- }
+ QHash<Key, T*> hash;
+ int mx;
Q_DISABLE_COPY(QCache)
inline ~QCache() { clear(); }
inline int maxCost() const { return mx; }
- void setMaxCost(int m);
- inline int totalCost() const { return total; }
+ inline void setMaxCost(int m);
inline int size() const { return hash.size(); }
inline int count() const { return hash.size(); }
inline bool isEmpty() const { return hash.isEmpty(); }
inline QList<Key> keys() const { return hash.keys(); }
+ inline void clear() { hash.clear(); }
- void clear();
-
- bool insert(const Key &key, T *object, int cost = 1);
- T *object(const Key &key) const;
+ inline bool insert(const Key &key, T *object, int cost = 1);
+ inline T *object(const Key &key) const { return hash.value(key, Q_NULLPTR); }
inline bool contains(const Key &key) const { return hash.contains(key); }
- T *operator[](const Key &key) const;
-
- bool remove(const Key &key);
- T *take(const Key &key);
-
-private:
- void trim(int m);
-
+ inline T *operator[](const Key &key) const;
+ inline bool remove(const Key &key);
+ inline T *take(const Key &key);
};
template <class Key, class T>
inline QCache<Key, T>::QCache(int amaxCost)
- : f(Q_NULLPTR), l(Q_NULLPTR), mx(amaxCost), total(0) {}
-
-template <class Key, class T>
-inline void QCache<Key,T>::clear()
-{ while (f) { delete f->t; f = f->n; }
- hash.clear(); l = Q_NULLPTR; total = 0; }
+ : mx(amaxCost)
+{ hash.reserve(amaxCost); }
template <class Key, class T>
inline void QCache<Key,T>::setMaxCost(int m)
-{ mx = m; trim(mx); }
-
-template <class Key, class T>
-inline T *QCache<Key,T>::object(const Key &key) const
-{ return const_cast<QCache<Key,T>*>(this)->relink(key); }
+{
+ mx = m;
+ hash.clear();
+ hash.reserve(m);
+}
template <class Key, class T>
inline T *QCache<Key,T>::operator[](const Key &key) const
template <class Key, class T>
inline bool QCache<Key,T>::remove(const Key &key)
-{
- typename QHash<Key, Node>::iterator i = hash.find(key);
- if (typename QHash<Key, Node>::const_iterator(i) == hash.constEnd()) {
- return false;
- } else {
- unlink(*i);
- return true;
- }
-}
+{ return hash.remove(key) != 0; }
template <class Key, class T>
inline T *QCache<Key,T>::take(const Key &key)
{
- typename QHash<Key, Node>::iterator i = hash.find(key);
- if (i == hash.end())
+ if (!hash.contains(key))
return Q_NULLPTR;
-
- Node &n = *i;
- T *t = n.t;
- n.t = Q_NULLPTR;
- unlink(n);
- return t;
+ return hash.take(key);
}
template <class Key, class T>
-bool QCache<Key,T>::insert(const Key &akey, T *aobject, int acost)
+inline bool QCache<Key,T>::insert(const Key &akey, T *aobject, int acost)
{
- remove(akey);
if (acost > mx) {
delete aobject;
return false;
+ } else if (hash.size() >= mx) {
+ hash.erase(hash.begin());
}
- trim(mx - acost);
- Node sn(aobject, acost);
- typename QHash<Key, Node>::iterator i = hash.insert(akey, sn);
- total += acost;
- Node *n = &i.value();
- n->keyPtr = &i.key();
- if (f) f->p = n;
- n->n = f;
- f = n;
- if (!l) l = f;
+ hash.insert(akey, aobject);
return true;
}
-template <class Key, class T>
-void QCache<Key,T>::trim(int m)
-{
- Node *n = l;
- while (n && total > m) {
- Node *u = n;
- n = n->p;
- unlink(*u);
- }
-}
-
QT_END_NAMESPACE
QT_END_HEADER