src/corelib/tools/qcache.h
changeset 0 1918ee327afb
child 3 41300fa6a67c
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the QtCore module of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 #ifndef QCACHE_H
       
    43 #define QCACHE_H
       
    44 
       
    45 #include <QtCore/qhash.h>
       
    46 
       
    47 QT_BEGIN_HEADER
       
    48 
       
    49 QT_BEGIN_NAMESPACE
       
    50 
       
    51 QT_MODULE(Core)
       
    52 
       
    53 template <class Key, class T>
       
    54 class QCache
       
    55 {
       
    56     struct Node {
       
    57         inline Node() : keyPtr(0) {}
       
    58         inline Node(T *data, int cost)
       
    59             : keyPtr(0), t(data), c(cost), p(0), n(0) {}
       
    60         const Key *keyPtr; T *t; int c; Node *p,*n;
       
    61     };
       
    62     Node *f, *l;
       
    63     QHash<Key, Node> hash;
       
    64     void *unused;
       
    65     int mx, total;
       
    66 
       
    67     inline void unlink(Node &n) {
       
    68         if (n.p) n.p->n = n.n;
       
    69         if (n.n) n.n->p = n.p;
       
    70         if (l == &n) l = n.p;
       
    71         if (f == &n) f = n.n;
       
    72         total -= n.c;
       
    73         delete n.t;
       
    74         hash.remove(*n.keyPtr);
       
    75     }
       
    76     inline T *relink(const Key &key) {
       
    77         typename QHash<Key, Node>::iterator i = hash.find(key);
       
    78         if (typename QHash<Key, Node>::const_iterator(i) == hash.constEnd())
       
    79             return 0;
       
    80 
       
    81         Node &n = *i;
       
    82         if (f != &n) {
       
    83             if (n.p) n.p->n = n.n;
       
    84             if (n.n) n.n->p = n.p;
       
    85             if (l == &n) l = n.p;
       
    86             n.p = 0;
       
    87             n.n = f;
       
    88             f->p = &n;
       
    89             f = &n;
       
    90         }
       
    91         return n.t;
       
    92     }
       
    93 
       
    94     Q_DISABLE_COPY(QCache)
       
    95 
       
    96 public:
       
    97     inline explicit QCache(int maxCost = 100);
       
    98 #ifdef QT3_SUPPORT
       
    99     inline QT3_SUPPORT_CONSTRUCTOR QCache(int maxCost, int /* dummy */)
       
   100         : f(0), l(0), mx(maxCost), total(0) {}
       
   101 #endif
       
   102     inline ~QCache() { clear(); }
       
   103 
       
   104     inline int maxCost() const { return mx; }
       
   105     void setMaxCost(int m);
       
   106     inline int totalCost() const { return total; }
       
   107 
       
   108     inline int size() const { return hash.size(); }
       
   109     inline int count() const { return hash.size(); }
       
   110     inline bool isEmpty() const { return hash.isEmpty(); }
       
   111     inline QList<Key> keys() const { return hash.keys(); }
       
   112 
       
   113     void clear();
       
   114 
       
   115     bool insert(const Key &key, T *object, int cost = 1);
       
   116     T *object(const Key &key) const;
       
   117     inline bool contains(const Key &key) const { return hash.contains(key); }
       
   118     T *operator[](const Key &key) const;
       
   119 
       
   120     bool remove(const Key &key);
       
   121     T *take(const Key &key);
       
   122 
       
   123 private:
       
   124     void trim(int m);
       
   125 
       
   126 #ifdef QT3_SUPPORT
       
   127     inline QT3_SUPPORT T *find(const Key &key) const { return object(key); }
       
   128 #endif
       
   129 
       
   130 };
       
   131 
       
   132 template <class Key, class T>
       
   133 inline QCache<Key, T>::QCache(int amaxCost)
       
   134     : f(0), l(0), unused(0), mx(amaxCost), total(0) {}
       
   135 
       
   136 template <class Key, class T>
       
   137 inline void QCache<Key,T>::clear()
       
   138 { while (f) { delete f->t; f = f->n; }
       
   139  hash.clear(); l = 0; total = 0; }
       
   140 
       
   141 template <class Key, class T>
       
   142 inline void QCache<Key,T>::setMaxCost(int m)
       
   143 { mx = m; trim(mx); }
       
   144 
       
   145 template <class Key, class T>
       
   146 inline T *QCache<Key,T>::object(const Key &key) const
       
   147 { return const_cast<QCache<Key,T>*>(this)->relink(key); }
       
   148 
       
   149 template <class Key, class T>
       
   150 inline T *QCache<Key,T>::operator[](const Key &key) const
       
   151 { return object(key); }
       
   152 
       
   153 template <class Key, class T>
       
   154 inline bool QCache<Key,T>::remove(const Key &key)
       
   155 {
       
   156     typename QHash<Key, Node>::iterator i = hash.find(key);
       
   157     if (typename QHash<Key, Node>::const_iterator(i) == hash.constEnd()) {
       
   158         return false;
       
   159     } else {
       
   160         unlink(*i);
       
   161         return true;
       
   162     }
       
   163 }
       
   164 
       
   165 template <class Key, class T>
       
   166 inline T *QCache<Key,T>::take(const Key &key)
       
   167 {
       
   168     typename QHash<Key, Node>::iterator i = hash.find(key);
       
   169     if (i == hash.end())
       
   170         return 0;
       
   171 
       
   172     Node &n = *i;
       
   173     T *t = n.t;
       
   174     n.t = 0;
       
   175     unlink(n);
       
   176     return t;
       
   177 }
       
   178 
       
   179 template <class Key, class T>
       
   180 bool QCache<Key,T>::insert(const Key &akey, T *aobject, int acost)
       
   181 {
       
   182     remove(akey);
       
   183     if (acost > mx) {
       
   184         delete aobject;
       
   185         return false;
       
   186     }
       
   187     trim(mx - acost);
       
   188     Node sn(aobject, acost);
       
   189     typename QHash<Key, Node>::iterator i = hash.insert(akey, sn);
       
   190     total += acost;
       
   191     Node *n = &i.value();
       
   192     n->keyPtr = &i.key();
       
   193     if (f) f->p = n;
       
   194     n->n = f;
       
   195     f = n;
       
   196     if (!l) l = f;
       
   197     return true;
       
   198 }
       
   199 
       
   200 template <class Key, class T>
       
   201 void QCache<Key,T>::trim(int m)
       
   202 {
       
   203     Node *n = l;
       
   204     while (n && total > m) {
       
   205         Node *u = n;
       
   206         n = n->p;
       
   207         if (qIsDetached(*u->t))
       
   208             unlink(*u);
       
   209     }
       
   210 }
       
   211 
       
   212 QT_END_NAMESPACE
       
   213 
       
   214 QT_END_HEADER
       
   215 
       
   216 #endif // QCACHE_H