blob: 45b3ffaf074a14660475f6947f7b53cdf4455545 [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):
Romain Guyae5575b2010-07-29 18:48:04 -070037 key(e.key), value(e.value), parent(e.parent), child(e.child) { }
Romain Guy5f0c6a42010-07-07 13:06:26 -070038 Entry(sp<Entry<EntryKey, EntryValue> > e):
Romain Guyae5575b2010-07-29 18:48:04 -070039 key(e->key), value(e->value), parent(e->parent), child(e->child) { }
Romain Guy5f0c6a42010-07-07 13:06:26 -070040
41 EntryKey key;
42 EntryValue value;
Romain Guy5f0c6a42010-07-07 13:06:26 -070043
44 sp<Entry<EntryKey, EntryValue> > parent;
45 sp<Entry<EntryKey, EntryValue> > child;
46}; // struct Entry
47
Romain Guyce0537b2010-06-29 21:05:21 -070048template<typename K, typename V>
49class GenerationCache {
50public:
Romain Guy5f0c6a42010-07-07 13:06:26 -070051 GenerationCache(uint32_t maxCapacity);
52 virtual ~GenerationCache();
Romain Guyce0537b2010-06-29 21:05:21 -070053
Romain Guy121e22422010-07-01 18:26:52 -070054 enum Capacity {
55 kUnlimitedCapacity,
56 };
57
Romain Guydda570202010-07-06 11:39:32 -070058 void setOnEntryRemovedListener(OnEntryRemoved<K, V>* listener);
Romain Guyce0537b2010-06-29 21:05:21 -070059
60 void clear();
61
Romain Guydda570202010-07-06 11:39:32 -070062 bool contains(K key) const;
63 V get(K key);
64 void put(K key, V value);
65 V remove(K key);
66 V removeOldest();
Romain Guyce0537b2010-06-29 21:05:21 -070067
Romain Guy7d139ba2010-07-02 11:20:34 -070068 uint32_t size() const;
Romain Guyce0537b2010-06-29 21:05:21 -070069
Romain Guydda570202010-07-06 11:39:32 -070070 void addToCache(sp<Entry<K, V> > entry, K key, V value);
71 void attachToCache(sp<Entry<K, V> > entry);
72 void detachFromCache(sp<Entry<K, V> > entry);
Romain Guyce0537b2010-06-29 21:05:21 -070073
Romain Guy5f0c6a42010-07-07 13:06:26 -070074 V removeAt(ssize_t index);
75
Romain Guy6c818932010-07-07 15:15:32 -070076 KeyedVector<K, sp<Entry<K, V> > > mCache;
Romain Guy7d139ba2010-07-02 11:20:34 -070077 uint32_t mMaxCapacity;
Romain Guyce0537b2010-06-29 21:05:21 -070078
Romain Guydda570202010-07-06 11:39:32 -070079 OnEntryRemoved<K, V>* mListener;
Romain Guyce0537b2010-06-29 21:05:21 -070080
Romain Guydda570202010-07-06 11:39:32 -070081 sp<Entry<K, V> > mOldest;
Romain Guy5f0c6a42010-07-07 13:06:26 -070082 sp<Entry<K, V> > mYoungest;
Romain Guyce0537b2010-06-29 21:05:21 -070083}; // class GenerationCache
84
85template<typename K, typename V>
Romain Guy5f0c6a42010-07-07 13:06:26 -070086GenerationCache<K, V>::GenerationCache(uint32_t maxCapacity): mMaxCapacity(maxCapacity), mListener(NULL) {
87};
88
89template<typename K, typename V>
90GenerationCache<K, V>::~GenerationCache() {
91 clear();
Romain Guy5f0c6a42010-07-07 13:06:26 -070092};
93
94template<typename K, typename V>
Romain Guy7d139ba2010-07-02 11:20:34 -070095uint32_t GenerationCache<K, V>::size() const {
Romain Guy6c818932010-07-07 15:15:32 -070096 return mCache.size();
Romain Guyce0537b2010-06-29 21:05:21 -070097}
98
99template<typename K, typename V>
Romain Guydda570202010-07-06 11:39:32 -0700100void GenerationCache<K, V>::setOnEntryRemovedListener(OnEntryRemoved<K, V>* listener) {
Romain Guyce0537b2010-06-29 21:05:21 -0700101 mListener = listener;
102}
103
104template<typename K, typename V>
105void GenerationCache<K, V>::clear() {
106 if (mListener) {
Romain Guy6c818932010-07-07 15:15:32 -0700107 while (mCache.size() > 0) {
Romain Guyce0537b2010-06-29 21:05:21 -0700108 removeOldest();
109 }
110 } else {
Romain Guy6c818932010-07-07 15:15:32 -0700111 mCache.clear();
Romain Guyce0537b2010-06-29 21:05:21 -0700112 }
Romain Guy5f0c6a42010-07-07 13:06:26 -0700113 mYoungest.clear();
Romain Guyce0537b2010-06-29 21:05:21 -0700114 mOldest.clear();
115}
116
117template<typename K, typename V>
Romain Guydda570202010-07-06 11:39:32 -0700118bool GenerationCache<K, V>::contains(K key) const {
Romain Guy6c818932010-07-07 15:15:32 -0700119 return mCache.indexOfKey(key) >= 0;
Romain Guyce0537b2010-06-29 21:05:21 -0700120}
121
122template<typename K, typename V>
Romain Guydda570202010-07-06 11:39:32 -0700123V GenerationCache<K, V>::get(K key) {
Romain Guy6c818932010-07-07 15:15:32 -0700124 ssize_t index = mCache.indexOfKey(key);
Romain Guyce0537b2010-06-29 21:05:21 -0700125 if (index >= 0) {
Romain Guy6c818932010-07-07 15:15:32 -0700126 sp<Entry<K, V> > entry = mCache.valueAt(index);
Romain Guyce0537b2010-06-29 21:05:21 -0700127 if (entry.get()) {
128 detachFromCache(entry);
129 attachToCache(entry);
130 return entry->value;
131 }
132 }
133
134 return NULL;
135}
136
137template<typename K, typename V>
Romain Guydda570202010-07-06 11:39:32 -0700138void GenerationCache<K, V>::put(K key, V value) {
Romain Guy6c818932010-07-07 15:15:32 -0700139 if (mMaxCapacity != kUnlimitedCapacity && mCache.size() >= mMaxCapacity) {
Romain Guyce0537b2010-06-29 21:05:21 -0700140 removeOldest();
141 }
142
Romain Guy6c818932010-07-07 15:15:32 -0700143 ssize_t index = mCache.indexOfKey(key);
Romain Guyce0537b2010-06-29 21:05:21 -0700144 if (index >= 0) {
Romain Guy6c818932010-07-07 15:15:32 -0700145 sp<Entry<K, V> > entry = mCache.valueAt(index);
Romain Guyce0537b2010-06-29 21:05:21 -0700146 detachFromCache(entry);
147 addToCache(entry, key, value);
148 } else {
Romain Guydda570202010-07-06 11:39:32 -0700149 sp<Entry<K, V> > entry = new Entry<K, V>;
Romain Guyce0537b2010-06-29 21:05:21 -0700150 addToCache(entry, key, value);
151 }
152}
153
154template<typename K, typename V>
Romain Guydda570202010-07-06 11:39:32 -0700155void GenerationCache<K, V>::addToCache(sp<Entry<K, V> > entry, K key, V value) {
Romain Guyce0537b2010-06-29 21:05:21 -0700156 entry->key = key;
157 entry->value = value;
Romain Guyae5575b2010-07-29 18:48:04 -0700158 mCache.add(key, entry);
Romain Guyce0537b2010-06-29 21:05:21 -0700159 attachToCache(entry);
160}
161
162template<typename K, typename V>
Romain Guydda570202010-07-06 11:39:32 -0700163V GenerationCache<K, V>::remove(K key) {
Romain Guy6c818932010-07-07 15:15:32 -0700164 ssize_t index = mCache.indexOfKey(key);
Romain Guyce0537b2010-06-29 21:05:21 -0700165 if (index >= 0) {
Romain Guy5f0c6a42010-07-07 13:06:26 -0700166 return removeAt(index);
Romain Guyce0537b2010-06-29 21:05:21 -0700167 }
168
169 return NULL;
170}
171
172template<typename K, typename V>
Romain Guy5f0c6a42010-07-07 13:06:26 -0700173V GenerationCache<K, V>::removeAt(ssize_t index) {
Romain Guy6c818932010-07-07 15:15:32 -0700174 sp<Entry<K, V> > entry = mCache.valueAt(index);
Romain Guy5f0c6a42010-07-07 13:06:26 -0700175 if (mListener) {
176 (*mListener)(entry->key, entry->value);
177 }
Romain Guy6c818932010-07-07 15:15:32 -0700178 mCache.removeItemsAt(index, 1);
Romain Guy5f0c6a42010-07-07 13:06:26 -0700179 detachFromCache(entry);
180
181 return entry->value;
182}
183
184template<typename K, typename V>
Romain Guydda570202010-07-06 11:39:32 -0700185V GenerationCache<K, V>::removeOldest() {
Romain Guyce0537b2010-06-29 21:05:21 -0700186 if (mOldest.get()) {
Romain Guyae5575b2010-07-29 18:48:04 -0700187 ssize_t index = mCache.indexOfKey(mOldest->key);
188 if (index >= 0) {
189 return removeAt(index);
190 }
Romain Guyce0537b2010-06-29 21:05:21 -0700191 }
Romain Guydda570202010-07-06 11:39:32 -0700192
193 return NULL;
Romain Guyce0537b2010-06-29 21:05:21 -0700194}
195
196template<typename K, typename V>
Romain Guydda570202010-07-06 11:39:32 -0700197void GenerationCache<K, V>::attachToCache(sp<Entry<K, V> > entry) {
Romain Guy5f0c6a42010-07-07 13:06:26 -0700198 if (!mYoungest.get()) {
199 mYoungest = mOldest = entry;
Romain Guyce0537b2010-06-29 21:05:21 -0700200 } else {
Romain Guy5f0c6a42010-07-07 13:06:26 -0700201 entry->parent = mYoungest;
202 mYoungest->child = entry;
203 mYoungest = entry;
Romain Guyce0537b2010-06-29 21:05:21 -0700204 }
205}
206
207template<typename K, typename V>
Romain Guydda570202010-07-06 11:39:32 -0700208void GenerationCache<K, V>::detachFromCache(sp<Entry<K, V> > entry) {
Romain Guyce0537b2010-06-29 21:05:21 -0700209 if (entry->parent.get()) {
210 entry->parent->child = entry->child;
211 }
212
213 if (entry->child.get()) {
214 entry->child->parent = entry->parent;
215 }
216
217 if (mOldest == entry) {
218 mOldest = entry->child;
219 }
220
Romain Guy5f0c6a42010-07-07 13:06:26 -0700221 if (mYoungest == entry) {
222 mYoungest = entry->parent;
Romain Guyce0537b2010-06-29 21:05:21 -0700223 }
224
225 entry->parent.clear();
226 entry->child.clear();
227}
228
229}; // namespace uirenderer
230}; // namespace android
231
232#endif // ANDROID_UI_GENERATION_CACHE_H