blob: 5f64a353658bb64859dd28e82f1b12f4a05b43cb [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
Romain Guy5f0c6a42010-07-07 13:06:26 -070023#include "SortedList.h"
24
Romain Guyce0537b2010-06-29 21:05:21 -070025namespace android {
26namespace uirenderer {
27
Romain Guy5f0c6a42010-07-07 13:06:26 -070028template<typename K, typename V>
29class GenerationCacheStorage {
30public:
31 virtual ~GenerationCacheStorage();
32
33 virtual size_t size() const = 0;
34 virtual void clear() = 0;
35 virtual ssize_t add(const K& key, const V& item) = 0;
36 virtual ssize_t indexOfKey(const K& key) const = 0;
37 virtual const V& valueAt(size_t index) const = 0;
38 virtual ssize_t removeItemsAt(size_t index, size_t count) = 0;
39}; // GenerationCacheStorage
40
41template<typename K, typename V>
42GenerationCacheStorage<K, V>::~GenerationCacheStorage() {
43}
44
45template<typename K, typename V>
46class KeyedVectorStorage: public GenerationCacheStorage<K, V> {
47public:
48 KeyedVectorStorage() { }
49 ~KeyedVectorStorage() { }
50
51 inline size_t size() const { return mStorage.size(); }
52 inline void clear() { mStorage.clear(); }
53 inline ssize_t add(const K& key, const V& value) { return mStorage.add(key, value); }
54 inline ssize_t indexOfKey(const K& key) const { return mStorage.indexOfKey(key); }
55 inline const V& valueAt(size_t index) const { return mStorage.valueAt(index); }
56 inline ssize_t removeItemsAt(size_t index, size_t count) {
57 return mStorage.removeItemsAt(index, count);
58 }
59private:
60 KeyedVector<K, V> mStorage;
61}; // class KeyedVectorStorage
62
63template<typename K, typename V>
64class SortedListStorage: public GenerationCacheStorage<K, V> {
65public:
66 SortedListStorage() { }
67 ~SortedListStorage() { }
68
69 inline size_t size() const { return mStorage.size(); }
70 inline void clear() { mStorage.clear(); }
71 inline ssize_t add(const K& key, const V& value) {
72 return mStorage.add(key_value_pair_t<K, V>(key, value));
73 }
74 inline ssize_t indexOfKey(const K& key) const {
75 return mStorage.indexOf(key_value_pair_t<K, V>(key));
76 }
77 inline const V& valueAt(size_t index) const { return mStorage.itemAt(index).value; }
78 inline ssize_t removeItemsAt(size_t index, size_t count) {
79 return mStorage.removeItemsAt(index, count);
80 }
81private:
82 SortedList<key_value_pair_t<K, V> > mStorage;
83}; // class SortedListStorage
84
Romain Guyce0537b2010-06-29 21:05:21 -070085template<typename EntryKey, typename EntryValue>
86class OnEntryRemoved {
87public:
88 virtual ~OnEntryRemoved() { };
Romain Guydda570202010-07-06 11:39:32 -070089 virtual void operator()(EntryKey& key, EntryValue& value) = 0;
Romain Guyce0537b2010-06-29 21:05:21 -070090}; // class OnEntryRemoved
91
Romain Guy5f0c6a42010-07-07 13:06:26 -070092template<typename EntryKey, typename EntryValue>
93struct Entry: public LightRefBase<Entry<EntryKey, EntryValue> > {
94 Entry() { }
95 Entry(const Entry<EntryKey, EntryValue>& e):
96 key(e.key), value(e.value), index(e.index), parent(e.parent), child(e.child) { }
97 Entry(sp<Entry<EntryKey, EntryValue> > e):
98 key(e->key), value(e->value), index(e->index), parent(e->parent), child(e->child) { }
99
100 EntryKey key;
101 EntryValue value;
102 ssize_t index;
103
104 sp<Entry<EntryKey, EntryValue> > parent;
105 sp<Entry<EntryKey, EntryValue> > child;
106}; // struct Entry
107
Romain Guyce0537b2010-06-29 21:05:21 -0700108template<typename K, typename V>
109class GenerationCache {
110public:
Romain Guy5f0c6a42010-07-07 13:06:26 -0700111 GenerationCache(uint32_t maxCapacity);
112 virtual ~GenerationCache();
Romain Guyce0537b2010-06-29 21:05:21 -0700113
Romain Guy121e22422010-07-01 18:26:52 -0700114 enum Capacity {
115 kUnlimitedCapacity,
116 };
117
Romain Guydda570202010-07-06 11:39:32 -0700118 void setOnEntryRemovedListener(OnEntryRemoved<K, V>* listener);
Romain Guyce0537b2010-06-29 21:05:21 -0700119
120 void clear();
121
Romain Guydda570202010-07-06 11:39:32 -0700122 bool contains(K key) const;
123 V get(K key);
124 void put(K key, V value);
125 V remove(K key);
126 V removeOldest();
Romain Guyce0537b2010-06-29 21:05:21 -0700127
Romain Guy7d139ba2010-07-02 11:20:34 -0700128 uint32_t size() const;
Romain Guyce0537b2010-06-29 21:05:21 -0700129
Romain Guy5f0c6a42010-07-07 13:06:26 -0700130protected:
131 virtual GenerationCacheStorage<K, sp<Entry<K, V> > >* createStorage() = 0;
132 GenerationCacheStorage<K, sp<Entry<K, V> > >* mCache;
133
Romain Guyce0537b2010-06-29 21:05:21 -0700134private:
Romain Guydda570202010-07-06 11:39:32 -0700135 void addToCache(sp<Entry<K, V> > entry, K key, V value);
136 void attachToCache(sp<Entry<K, V> > entry);
137 void detachFromCache(sp<Entry<K, V> > entry);
Romain Guyce0537b2010-06-29 21:05:21 -0700138
Romain Guy5f0c6a42010-07-07 13:06:26 -0700139 V removeAt(ssize_t index);
140
Romain Guy7d139ba2010-07-02 11:20:34 -0700141 uint32_t mMaxCapacity;
Romain Guyce0537b2010-06-29 21:05:21 -0700142
Romain Guydda570202010-07-06 11:39:32 -0700143 OnEntryRemoved<K, V>* mListener;
Romain Guyce0537b2010-06-29 21:05:21 -0700144
Romain Guydda570202010-07-06 11:39:32 -0700145 sp<Entry<K, V> > mOldest;
Romain Guy5f0c6a42010-07-07 13:06:26 -0700146 sp<Entry<K, V> > mYoungest;
Romain Guyce0537b2010-06-29 21:05:21 -0700147}; // class GenerationCache
148
149template<typename K, typename V>
Romain Guy5f0c6a42010-07-07 13:06:26 -0700150class GenerationSingleCache: public GenerationCache<K, V> {
151public:
152 GenerationSingleCache(uint32_t maxCapacity): GenerationCache<K, V>(maxCapacity) {
153 GenerationCache<K, V>::mCache = createStorage();
154 };
155 ~GenerationSingleCache() { }
156protected:
157 GenerationCacheStorage<K, sp<Entry<K, V> > >* createStorage() {
158 return new KeyedVectorStorage<K, sp<Entry<K, V> > >;
159 }
160}; // GenerationSingleCache
161
162template<typename K, typename V>
163class GenerationMultiCache: public GenerationCache<K, V> {
164public:
165 GenerationMultiCache(uint32_t maxCapacity): GenerationCache<K, V>(maxCapacity) {
166 GenerationCache<K, V>::mCache = createStorage();
167 };
168 ~GenerationMultiCache() { }
169protected:
170 GenerationCacheStorage<K, sp<Entry<K, V> > >* createStorage() {
171 return new SortedListStorage<K, sp<Entry<K, V> > >;
172 }
173}; // GenerationMultiCache
174
175template<typename K, typename V>
176GenerationCache<K, V>::GenerationCache(uint32_t maxCapacity): mMaxCapacity(maxCapacity), mListener(NULL) {
177};
178
179template<typename K, typename V>
180GenerationCache<K, V>::~GenerationCache() {
181 clear();
182 delete mCache;
183};
184
185template<typename K, typename V>
Romain Guy7d139ba2010-07-02 11:20:34 -0700186uint32_t GenerationCache<K, V>::size() const {
Romain Guy5f0c6a42010-07-07 13:06:26 -0700187 return mCache->size();
Romain Guyce0537b2010-06-29 21:05:21 -0700188}
189
190template<typename K, typename V>
Romain Guydda570202010-07-06 11:39:32 -0700191void GenerationCache<K, V>::setOnEntryRemovedListener(OnEntryRemoved<K, V>* listener) {
Romain Guyce0537b2010-06-29 21:05:21 -0700192 mListener = listener;
193}
194
195template<typename K, typename V>
196void GenerationCache<K, V>::clear() {
197 if (mListener) {
Romain Guy5f0c6a42010-07-07 13:06:26 -0700198 while (mCache->size() > 0) {
Romain Guyce0537b2010-06-29 21:05:21 -0700199 removeOldest();
200 }
201 } else {
Romain Guy5f0c6a42010-07-07 13:06:26 -0700202 mCache->clear();
Romain Guyce0537b2010-06-29 21:05:21 -0700203 }
Romain Guy5f0c6a42010-07-07 13:06:26 -0700204 mYoungest.clear();
Romain Guyce0537b2010-06-29 21:05:21 -0700205 mOldest.clear();
206}
207
208template<typename K, typename V>
Romain Guydda570202010-07-06 11:39:32 -0700209bool GenerationCache<K, V>::contains(K key) const {
Romain Guy5f0c6a42010-07-07 13:06:26 -0700210 return mCache->indexOfKey(key) >= 0;
Romain Guyce0537b2010-06-29 21:05:21 -0700211}
212
213template<typename K, typename V>
Romain Guydda570202010-07-06 11:39:32 -0700214V GenerationCache<K, V>::get(K key) {
Romain Guy5f0c6a42010-07-07 13:06:26 -0700215 ssize_t index = mCache->indexOfKey(key);
Romain Guyce0537b2010-06-29 21:05:21 -0700216 if (index >= 0) {
Romain Guy5f0c6a42010-07-07 13:06:26 -0700217 sp<Entry<K, V> > entry = mCache->valueAt(index);
Romain Guyce0537b2010-06-29 21:05:21 -0700218 if (entry.get()) {
219 detachFromCache(entry);
220 attachToCache(entry);
221 return entry->value;
222 }
223 }
224
225 return NULL;
226}
227
228template<typename K, typename V>
Romain Guydda570202010-07-06 11:39:32 -0700229void GenerationCache<K, V>::put(K key, V value) {
Romain Guy5f0c6a42010-07-07 13:06:26 -0700230 if (mMaxCapacity != kUnlimitedCapacity && mCache->size() >= mMaxCapacity) {
Romain Guyce0537b2010-06-29 21:05:21 -0700231 removeOldest();
232 }
233
Romain Guy5f0c6a42010-07-07 13:06:26 -0700234 ssize_t index = mCache->indexOfKey(key);
Romain Guyce0537b2010-06-29 21:05:21 -0700235 if (index >= 0) {
Romain Guy5f0c6a42010-07-07 13:06:26 -0700236 sp<Entry<K, V> > entry = mCache->valueAt(index);
Romain Guyce0537b2010-06-29 21:05:21 -0700237 detachFromCache(entry);
238 addToCache(entry, key, value);
239 } else {
Romain Guydda570202010-07-06 11:39:32 -0700240 sp<Entry<K, V> > entry = new Entry<K, V>;
Romain Guyce0537b2010-06-29 21:05:21 -0700241 addToCache(entry, key, value);
242 }
243}
244
245template<typename K, typename V>
Romain Guydda570202010-07-06 11:39:32 -0700246void GenerationCache<K, V>::addToCache(sp<Entry<K, V> > entry, K key, V value) {
Romain Guyce0537b2010-06-29 21:05:21 -0700247 entry->key = key;
248 entry->value = value;
Romain Guy5f0c6a42010-07-07 13:06:26 -0700249 entry->index = mCache->add(key, entry);
Romain Guyce0537b2010-06-29 21:05:21 -0700250 attachToCache(entry);
251}
252
253template<typename K, typename V>
Romain Guydda570202010-07-06 11:39:32 -0700254V GenerationCache<K, V>::remove(K key) {
Romain Guy5f0c6a42010-07-07 13:06:26 -0700255 ssize_t index = mCache->indexOfKey(key);
Romain Guyce0537b2010-06-29 21:05:21 -0700256 if (index >= 0) {
Romain Guy5f0c6a42010-07-07 13:06:26 -0700257 return removeAt(index);
Romain Guyce0537b2010-06-29 21:05:21 -0700258 }
259
260 return NULL;
261}
262
263template<typename K, typename V>
Romain Guy5f0c6a42010-07-07 13:06:26 -0700264V GenerationCache<K, V>::removeAt(ssize_t index) {
265 sp<Entry<K, V> > entry = mCache->valueAt(index);
266 if (mListener) {
267 (*mListener)(entry->key, entry->value);
268 }
269 mCache->removeItemsAt(index, 1);
270 detachFromCache(entry);
271
272 return entry->value;
273}
274
275template<typename K, typename V>
Romain Guydda570202010-07-06 11:39:32 -0700276V GenerationCache<K, V>::removeOldest() {
Romain Guyce0537b2010-06-29 21:05:21 -0700277 if (mOldest.get()) {
Romain Guy5f0c6a42010-07-07 13:06:26 -0700278 return removeAt(mOldest->index);
Romain Guyce0537b2010-06-29 21:05:21 -0700279 }
Romain Guydda570202010-07-06 11:39:32 -0700280
281 return NULL;
Romain Guyce0537b2010-06-29 21:05:21 -0700282}
283
284template<typename K, typename V>
Romain Guydda570202010-07-06 11:39:32 -0700285void GenerationCache<K, V>::attachToCache(sp<Entry<K, V> > entry) {
Romain Guy5f0c6a42010-07-07 13:06:26 -0700286 if (!mYoungest.get()) {
287 mYoungest = mOldest = entry;
Romain Guyce0537b2010-06-29 21:05:21 -0700288 } else {
Romain Guy5f0c6a42010-07-07 13:06:26 -0700289 entry->parent = mYoungest;
290 mYoungest->child = entry;
291 mYoungest = entry;
Romain Guyce0537b2010-06-29 21:05:21 -0700292 }
293}
294
295template<typename K, typename V>
Romain Guydda570202010-07-06 11:39:32 -0700296void GenerationCache<K, V>::detachFromCache(sp<Entry<K, V> > entry) {
Romain Guyce0537b2010-06-29 21:05:21 -0700297 if (entry->parent.get()) {
298 entry->parent->child = entry->child;
299 }
300
301 if (entry->child.get()) {
302 entry->child->parent = entry->parent;
303 }
304
305 if (mOldest == entry) {
306 mOldest = entry->child;
307 }
308
Romain Guy5f0c6a42010-07-07 13:06:26 -0700309 if (mYoungest == entry) {
310 mYoungest = entry->parent;
Romain Guyce0537b2010-06-29 21:05:21 -0700311 }
312
313 entry->parent.clear();
314 entry->child.clear();
315}
316
317}; // namespace uirenderer
318}; // namespace android
319
320#endif // ANDROID_UI_GENERATION_CACHE_H