summaryrefslogtreecommitdiff
path: root/src/cache.h
diff options
context:
space:
mode:
authorMarius Kintel <marius@kintel.net>2011-11-09 02:18:32 (GMT)
committerMarius Kintel <marius@kintel.net>2011-11-09 02:18:32 (GMT)
commit96c480b1bd8da7f4f47d3f67653346052a0a9a5e (patch)
tree9a719c0d287e3aa8eb8df6a0785600d1106b962d /src/cache.h
parent9146f16492b1de0775e81aa7c82d83ccd017c65b (diff)
Ported QCache and related code away from Qt
Diffstat (limited to 'src/cache.h')
-rw-r--r--src/cache.h183
1 files changed, 183 insertions, 0 deletions
diff --git a/src/cache.h b/src/cache.h
new file mode 100644
index 0000000..284c6da
--- /dev/null
+++ b/src/cache.h
@@ -0,0 +1,183 @@
+/****************************************************************************
+**
+** OpenSCAD (www.openscad.org)
+** Copyright (C) 2009-2011 Clifford Wolf <clifford@clifford.at> and
+** Marius Kintel <marius@kintel.net>
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial Usage
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef CACHE_H
+#define CACHE_H
+
+#include <boost/unordered_map.hpp>
+
+template <class Key, class T>
+class Cache
+{
+ struct Node {
+ inline Node() : keyPtr(0) {}
+ inline Node(T *data, int cost)
+ : keyPtr(0), t(data), c(cost), p(0), n(0) {}
+ const Key *keyPtr; T *t; int c; Node *p,*n;
+ };
+ typedef typename boost::unordered_map<Key, Node> map_type;
+ typedef typename map_type::iterator iterator_type;
+ typedef typename map_type::value_type value_type;
+
+ boost::unordered_map<Key, Node> hash;
+ Node *f, *l;
+ void *unused;
+ 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.erase(*n.keyPtr);
+ delete obj;
+ }
+ inline T *relink(const Key &key) {
+ iterator_type i = hash.find(key);
+ if (i == hash.end()) return 0;
+
+ Node &n = i->second;
+ 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;
+ }
+
+public:
+ inline explicit Cache(int maxCost = 100)
+ : f(0), l(0), unused(0), mx(maxCost), total(0) { }
+ inline ~Cache() { clear(); }
+
+ inline int maxCost() const { return mx; }
+ void setMaxCost(int m) { mx = m; trim(mx); }
+ inline int totalCost() const { return total; }
+
+ inline int size() const { return hash.size(); }
+ inline bool empty() const { return hash.empty(); }
+
+ void clear() {
+ while (f) { delete f->t; f = f->n; }
+ hash.clear(); l = 0; total = 0;
+ }
+
+ bool insert(const Key &key, T *object, int cost = 1);
+ T *object(const Key &key) const { return const_cast<Cache<Key,T>*>(this)->relink(key); }
+ inline bool contains(const Key &key) const { return hash.find(key) != hash.end(); }
+ T *operator[](const Key &key) const { return object(key); }
+
+ bool remove(const Key &key);
+ T *take(const Key &key);
+
+private:
+ void trim(int m);
+};
+
+template <class Key, class T>
+inline bool Cache<Key,T>::remove(const Key &key)
+{
+ iterator_type i = hash.find(key);
+ if (i == hash.end()) {
+ return false;
+ } else {
+ unlink(i->second);
+ return true;
+ }
+}
+
+template <class Key, class T>
+inline T *Cache<Key,T>::take(const Key &key)
+{
+ iterator_type i = hash.find(key);
+ if (i == hash.end()) return 0;
+
+ Node &n = *i;
+ T *t = n.t;
+ n.t = 0;
+ unlink(n);
+ return t;
+}
+
+template <class Key, class T>
+bool Cache<Key,T>::insert(const Key &akey, T *aobject, int acost)
+{
+ remove(akey);
+ if (acost > mx) {
+ delete aobject;
+ return false;
+ }
+ trim(mx - acost);
+ Node node(aobject, acost);
+ hash[akey] = node;
+ iterator_type i = hash.find(akey);
+ total += acost;
+ Node *n = &i->second;
+ n->keyPtr = &i->first;
+ if (f) f->p = n;
+ n->n = f;
+ f = n;
+ if (!l) l = f;
+ return true;
+}
+
+template <class Key, class T>
+void Cache<Key,T>::trim(int m)
+{
+ Node *n = l;
+ while (n && total > m) {
+ Node *u = n;
+ n = n->p;
+ unlink(*u);
+ }
+}
+
+#endif
+
contact: Jan Huwald // Impressum