qcache.h

Go to the documentation of this file.
00001 /****************************************************************************
00002 **
00003 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
00004 ** All rights reserved.
00005 ** Contact: Nokia Corporation (qt-info@nokia.com)
00006 **
00007 ** This file is part of the QtCore module of the Qt Toolkit.
00008 **
00009 ** $QT_BEGIN_LICENSE:LGPL$
00010 ** Commercial Usage
00011 ** Licensees holding valid Qt Commercial licenses may use this file in
00012 ** accordance with the Qt Commercial License Agreement provided with the
00013 ** Software or, alternatively, in accordance with the terms contained in
00014 ** a written agreement between you and Nokia.
00015 **
00016 ** GNU Lesser General Public License Usage
00017 ** Alternatively, this file may be used under the terms of the GNU Lesser
00018 ** General Public License version 2.1 as published by the Free Software
00019 ** Foundation and appearing in the file LICENSE.LGPL included in the
00020 ** packaging of this file.  Please review the following information to
00021 ** ensure the GNU Lesser General Public License version 2.1 requirements
00022 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
00023 **
00024 ** In addition, as a special exception, Nokia gives you certain additional
00025 ** rights.  These rights are described in the Nokia Qt LGPL Exception
00026 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this module.
00027 **
00028 ** GNU General Public License Usage
00029 ** Alternatively, this file may be used under the terms of the GNU
00030 ** General Public License version 3.0 as published by the Free Software
00031 ** Foundation and appearing in the file LICENSE.GPL included in the
00032 ** packaging of this file.  Please review the following information to
00033 ** ensure the GNU General Public License version 3.0 requirements will be
00034 ** met: http://www.gnu.org/copyleft/gpl.html.
00035 **
00036 ** If you have questions regarding the use of this file, please contact
00037 ** Nokia at qt-info@nokia.com.
00038 ** $QT_END_LICENSE$
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 /* dummy */)
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