blob: 5c1b5e142c0d7a2e478b077b49c0b8efb66fdb23 [file] [log] [blame]
Romain Guyce0537b2010-06-29 21:05:21 -07001/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef ANDROID_UI_GENERATION_CACHE_H
18#define ANDROID_UI_GENERATION_CACHE_H
19
20#include <utils/KeyedVector.h>
21#include <utils/RefBase.h>
22
23namespace android {
24namespace uirenderer {
25
26template<typename EntryKey, typename EntryValue>
27class OnEntryRemoved {
28public:
29 virtual ~OnEntryRemoved() { };
Romain Guydda570202010-07-06 11:39:32 -070030 virtual void operator()(EntryKey& key, EntryValue& value) = 0;
Romain Guyce0537b2010-06-29 21:05:21 -070031}; // class OnEntryRemoved
32
Romain Guy5f0c6a42010-07-07 13:06:26 -070033template<typename EntryKey, typename EntryValue>
34struct Entry: public LightRefBase<Entry<EntryKey, EntryValue> > {
35 Entry() { }
36 Entry(const Entry<EntryKey, EntryValue>& e):
37 key(e.key), value(e.value), index(e.index), parent(e.parent), child(e.child) { }
38 Entry(sp<Entry<EntryKey, EntryValue> > e):
39 key(e->key), value(e->value), index(e->index), parent(e->parent), child(e->child) { }
40
41 EntryKey key;
42 EntryValue value;
43 ssize_t index;
44
45 sp<Entry<EntryKey, EntryValue> > parent;
46 sp<Entry<EntryKey, EntryValue> > child;
47}; // struct Entry
48
Romain Guyce0537b2010-06-29 21:05:21 -070049template<typename K, typename V>
50class GenerationCache {
51public:
Romain Guy5f0c6a42010-07-07 13:06:26 -070052 GenerationCache(uint32_t maxCapacity);
53 virtual ~GenerationCache();
Romain Guyce0537b2010-06-29 21:05:21 -070054
Romain Guy121e22422010-07-01 18:26:52 -070055 enum Capacity {
56 kUnlimitedCapacity,
57 };
58
Romain Guydda570202010-07-06 11:39:32 -070059 void setOnEntryRemovedListener(OnEntryRemoved<K, V>* listener);
Romain Guyce0537b2010-06-29 21:05:21 -070060
61 void clear();
62
Romain Guydda570202010-07-06 11:39:32 -070063 bool contains(K key) const;
64 V get(K key);
65 void put(K key, V value);
66 V remove(K key);
67 V removeOldest();
Romain Guyce0537b2010-06-29 21:05:21 -070068
Romain Guy7d139ba2010-07-02 11:20:34 -070069 uint32_t size() const;
Romain Guyce0537b2010-06-29 21:05:21 -070070
Romain Guydda570202010-07-06 11:39:32 -070071 void addToCache(sp<Entry<K, V> > entry, K key, V value);
72 void attachToCache(sp<Entry<K, V> > entry);
73 void detachFromCache(sp<Entry<K, V> > entry);
Romain Guyce0537b2010-06-29 21:05:21 -070074
Romain Guy5f0c6a42010-07-07 13:06:26 -070075 V removeAt(ssize_t index);
76
Romain Guy6c818932010-07-07 15:15:32 -070077 KeyedVector<K, sp<Entry<K, V> > > mCache;
Romain Guy7d139ba2010-07-02 11:20:34 -070078 uint32_t mMaxCapacity;
Romain Guyce0537b2010-06-29 21:05:21 -070079
Romain Guydda570202010-07-06 11:39:32 -070080 OnEntryRemoved<K, V>* mListener;
Romain Guyce0537b2010-06-29 21:05:21 -070081
Romain Guydda570202010-07-06 11:39:32 -070082 sp<Entry<K, V> > mOldest;
Romain Guy5f0c6a42010-07-07 13:06:26 -070083 sp<Entry<K, V> > mYoungest;
Romain Guyce0537b2010-06-29 21:05:21 -070084}; // class GenerationCache
85
86template<typename K, typename V>
Romain Guy5f0c6a42010-07-07 13:06:26 -070087GenerationCache<K, V>::GenerationCache(uint32_t maxCapacity): mMaxCapacity(maxCapacity), mListener(NULL) {
88};
89
90template<typename K, typename V>
91GenerationCache<K, V>::~GenerationCache() {
92 clear();
Romain Guy5f0c6a42010-07-07 13:06:26 -070093};
94
95template<typename K, typename V>
Romain Guy7d139ba2010-07-02 11:20:34 -070096uint32_t GenerationCache<K, V>::size() const {
Romain Guy6c818932010-07-07 15:15:32 -070097 return mCache.size();
Romain Guyce0537b2010-06-29 21:05:21 -070098}
99
100template<typename K, typename V>
Romain Guydda570202010-07-06 11:39:32 -0700101void GenerationCache<K, V>::setOnEntryRemovedListener(OnEntryRemoved<K, V>* listener) {
Romain Guyce0537b2010-06-29 21:05:21 -0700102 mListener = listener;
103}
104
105template<typename K, typename V>
106void GenerationCache<K, V>::clear() {
107 if (mListener) {
Romain Guy6c818932010-07-07 15:15:32 -0700108 while (mCache.size() > 0) {
Romain Guyce0537b2010-06-29 21:05:21 -0700109 removeOldest();
110 }
111 } else {
Romain Guy6c818932010-07-07 15:15:32 -0700112 mCache.clear();
Romain Guyce0537b2010-06-29 21:05:21 -0700113 }
Romain Guy5f0c6a42010-07-07 13:06:26 -0700114 mYoungest.clear();
Romain Guyce0537b2010-06-29 21:05:21 -0700115 mOldest.clear();
116}
117
118template<typename K, typename V>
Romain Guydda570202010-07-06 11:39:32 -0700119bool GenerationCache<K, V>::contains(K key) const {
Romain Guy6c818932010-07-07 15:15:32 -0700120 return mCache.indexOfKey(key) >= 0;
Romain Guyce0537b2010-06-29 21:05:21 -0700121}
122
123template<typename K, typename V>
Romain Guydda570202010-07-06 11:39:32 -0700124V GenerationCache<K, V>::get(K key) {
Romain Guy6c818932010-07-07 15:15:32 -0700125 ssize_t index = mCache.indexOfKey(key);
Romain Guyce0537b2010-06-29 21:05:21 -0700126 if (index >= 0) {
Romain Guy6c818932010-07-07 15:15:32 -0700127 sp<Entry<K, V> > entry = mCache.valueAt(index);
Romain Guyce0537b2010-06-29 21:05:21 -0700128 if (entry.get()) {
129 detachFromCache(entry);
130 attachToCache(entry);
131 return entry->value;
132 }
133 }
134
135 return NULL;
136}
137
138template<typename K, typename V>
Romain Guydda570202010-07-06 11:39:32 -0700139void GenerationCache<K, V>::put(K key, V value) {
Romain Guy6c818932010-07-07 15:15:32 -0700140 if (mMaxCapacity != kUnlimitedCapacity && mCache.size() >= mMaxCapacity) {
Romain Guyce0537b2010-06-29 21:05:21 -0700141 removeOldest();
142 }
143
Romain Guy6c818932010-07-07 15:15:32 -0700144 ssize_t index = mCache.indexOfKey(key);
Romain Guyce0537b2010-06-29 21:05:21 -0700145 if (index >= 0) {
Romain Guy6c818932010-07-07 15:15:32 -0700146 sp<Entry<K, V> > entry = mCache.valueAt(index);
Romain Guyce0537b2010-06-29 21:05:21 -0700147 detachFromCache(entry);
148 addToCache(entry, key, value);
149 } else {
Romain Guydda570202010-07-06 11:39:32 -0700150 sp<Entry<K, V> > entry = new Entry<K, V>;
Romain Guyce0537b2010-06-29 21:05:21 -0700151 addToCache(entry, key, value);
152 }
153}
154
155template<typename K, typename V>
Romain Guydda570202010-07-06 11:39:32 -0700156void GenerationCache<K, V>::addToCache(sp<Entry<K, V> > entry, K key, V value) {
Romain Guyce0537b2010-06-29 21:05:21 -0700157 entry->key = key;
158 entry->value = value;
Romain Guy6c818932010-07-07 15:15:32 -0700159 entry->index = mCache.add(key, entry);
Romain Guyce0537b2010-06-29 21:05:21 -0700160 attachToCache(entry);
161}
162
163template<typename K, typename V>
Romain Guydda570202010-07-06 11:39:32 -0700164V GenerationCache<K, V>::remove(K key) {
Romain Guy6c818932010-07-07 15:15:32 -0700165 ssize_t index = mCache.indexOfKey(key);
Romain Guyce0537b2010-06-29 21:05:21 -0700166 if (index >= 0) {
Romain Guy5f0c6a42010-07-07 13:06:26 -0700167 return removeAt(index);
Romain Guyce0537b2010-06-29 21:05:21 -0700168 }
169
170 return NULL;
171}
172
173template<typename K, typename V>
Romain Guy5f0c6a42010-07-07 13:06:26 -0700174V GenerationCache<K, V>::removeAt(ssize_t index) {
Romain Guy6c818932010-07-07 15:15:32 -0700175 sp<Entry<K, V> > entry = mCache.valueAt(index);
Romain Guy5f0c6a42010-07-07 13:06:26 -0700176 if (mListener) {
177 (*mListener)(entry->key, entry->value);
178 }
Romain Guy6c818932010-07-07 15:15:32 -0700179 mCache.removeItemsAt(index, 1);
Romain Guy5f0c6a42010-07-07 13:06:26 -0700180 detachFromCache(entry);
181
182 return entry->value;
183}
184
185template<typename K, typename V>
Romain Guydda570202010-07-06 11:39:32 -0700186V GenerationCache<K, V>::removeOldest() {
Romain Guyce0537b2010-06-29 21:05:21 -0700187 if (mOldest.get()) {
Romain Guy5f0c6a42010-07-07 13:06:26 -0700188 return removeAt(mOldest->index);
Romain Guyce0537b2010-06-29 21:05:21 -0700189 }
Romain Guydda570202010-07-06 11:39:32 -0700190
191 return NULL;
Romain Guyce0537b2010-06-29 21:05:21 -0700192}
193
194template<typename K, typename V>
Romain Guydda570202010-07-06 11:39:32 -0700195void GenerationCache<K, V>::attachToCache(sp<Entry<K, V> > entry) {
Romain Guy5f0c6a42010-07-07 13:06:26 -0700196 if (!mYoungest.get()) {
197 mYoungest = mOldest = entry;
Romain Guyce0537b2010-06-29 21:05:21 -0700198 } else {
Romain Guy5f0c6a42010-07-07 13:06:26 -0700199 entry->parent = mYoungest;
200 mYoungest->child = entry;
201 mYoungest = entry;
Romain Guyce0537b2010-06-29 21:05:21 -0700202 }
203}
204
205template<typename K, typename V>
Romain Guydda570202010-07-06 11:39:32 -0700206void GenerationCache<K, V>::detachFromCache(sp<Entry<K, V> > entry) {
Romain Guyce0537b2010-06-29 21:05:21 -0700207 if (entry->parent.get()) {
208 entry->parent->child = entry->child;
209 }
210
211 if (entry->child.get()) {
212 entry->child->parent = entry->parent;
213 }
214
215 if (mOldest == entry) {
216 mOldest = entry->child;
217 }
218
Romain Guy5f0c6a42010-07-07 13:06:26 -0700219 if (mYoungest == entry) {
220 mYoungest = entry->parent;
Romain Guyce0537b2010-06-29 21:05:21 -0700221 }
222
223 entry->parent.clear();
224 entry->child.clear();
225}
226
227}; // namespace uirenderer
228}; // namespace android
229
230#endif // ANDROID_UI_GENERATION_CACHE_H