Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(88)

Side by Side Diff: include/core/SkTInternalLList.h

Issue 91453002: Speed up GrResourceCache add and lookup by using TDynamicHash (Closed) Base URL: https://skia.googlecode.com/svn/trunk
Patch Set: Created 7 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | include/gpu/GrResource.h » ('j') | include/gpu/GrResource.h » ('J')
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright 2012 Google Inc. 2 * Copyright 2012 Google Inc.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license that can be 4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file. 5 * found in the LICENSE file.
6 */ 6 */
7 7
8 #ifndef SkTInternalLList_DEFINED 8 #ifndef SkTInternalLList_DEFINED
9 #define SkTInternalLList_DEFINED 9 #define SkTInternalLList_DEFINED
10 10
(...skipping 11 matching lines...) Expand all
22 private: 22 private:
23 T* fPtr; 23 T* fPtr;
24 }; 24 };
25 25
26 26
27 /** 27 /**
28 * This macro creates the member variables required by the SkTInternalLList clas s. It should be 28 * This macro creates the member variables required by the SkTInternalLList clas s. It should be
29 * placed in the private section of any class that will be stored in a double li nked list. 29 * placed in the private section of any class that will be stored in a double li nked list.
30 */ 30 */
31 #define SK_DECLARE_INTERNAL_LLIST_INTERFACE(ClassName) \ 31 #define SK_DECLARE_INTERNAL_LLIST_INTERFACE(ClassName) \
32 friend class SkTInternalLList<ClassName>; \ 32 friend class SkTInternalLListDefaultExtractor<ClassName>; \
mtklein 2013/12/03 19:02:02 I'm somewhat worried about the general design of G
33 /* back pointer to the owning list - for debugging */ \ 33 /* back pointer to the owning list - for debugging */ \
34 SkDEBUGCODE(SkPtrWrapper<SkTInternalLList<ClassName> > fList;) \ 34 SkDEBUGCODE(SkPtrWrapper<SkTInternalLList<ClassName> > fList;) \
35 SkPtrWrapper<ClassName> fPrev; \ 35 SkPtrWrapper<ClassName> fPrev; \
36 SkPtrWrapper<ClassName> fNext 36 SkPtrWrapper<ClassName> fNext;
37
38 /**
39 * This macro creates the members for storing the instance to a specific, named linked list. It
40 * should be placed in the public section of any class that will be stored in a double linked
41 * list. Classes that use this macro need to use corresponding _DATA macro below .
42 */
43 #define SK_DECLARE_NAMED_INTERNAL_LLIST_INTERFACE(T, Name) \
44 struct InternalLListExtractor##Name { \
45 typedef SkTInternalLList<T, InternalLListExtractor##Name > ListType; \
46 static SkPtrWrapper<T>& Prev(T* o) { return o->fPrev##Name; } \
47 static SkPtrWrapper<T>& Next(T* o) { return o->fNext##Name; } \
48 SkDEBUGCODE(static SkPtrWrapper<ListType>& List(T* o) { return o->fList# #Name; }) \
49 SkDEBUGCODE(static const ListType* List(const T* o) { return o->fList##N ame; }) \
50 }; \
51 friend class InternalLListExtractor##Name;
52
53 /**
54 * This macro creates the member variables for storing the instance to a specifi c, named linked
55 * list. It should be placed in the private section of the class.
56 */
57 #define SK_DECLARE_NAMED_INTERNAL_LLIST_INTERFACE_DATA(T, Name) \
58 SkPtrWrapper<T> fPrev##Name; \
59 SkPtrWrapper<T> fNext##Name; \
60 SkDEBUGCODE(SkPtrWrapper<InternalLListExtractor##Name::ListType> fList##Name ;)
61
62 /**
63 * This macro creates the member variable and short-cut typedefs for a specific, named linked list.
64 * This should be placed in the class declaration or code that creates the named linked list.
65 */
66 #define SK_DECLARE_NAMED_INTERNAL_LLIST(T, Name, VarName) \
67 typedef SkTInternalLList<T, T::InternalLListExtractor##Name> Name##InternalL ListType; \
68 Name##InternalLListType VarName;
69
70 template <class T, class E> class SkTInternalLList;
71
72 template<typename T>
73 struct SkTInternalLListDefaultExtractor {
74 typedef SkTInternalLList<T, SkTInternalLListDefaultExtractor<T> > ListType;
75 static SkPtrWrapper<T>& Prev(T* o) { return o->fPrev; }
76 static SkPtrWrapper<T>& Next(T* o) { return o->fNext; }
77 SkDEBUGCODE(static SkPtrWrapper<ListType>& List(T* o) { return o->fList; })
78 SkDEBUGCODE(static const ListType* List(const T* o) { return o->fList; })
79 };
37 80
38 /** 81 /**
39 * This class implements a templated internal doubly linked list data structure. 82 * This class implements a templated internal doubly linked list data structure.
40 */ 83 */
41 template <class T> class SkTInternalLList : public SkNoncopyable { 84 template <class T, class E = SkTInternalLListDefaultExtractor<T> >
85 class SkTInternalLList : public SkNoncopyable {
42 public: 86 public:
43 SkTInternalLList() 87 SkTInternalLList()
44 : fHead(NULL) 88 : fHead(NULL)
45 , fTail(NULL) { 89 , fTail(NULL) {
46 } 90 }
47 91
48 void remove(T* entry) { 92 void remove(T* entry) {
49 SkASSERT(NULL != fHead && NULL != fTail); 93 SkASSERT(NULL != fHead && NULL != fTail);
50 SkASSERT(this->isInList(entry)); 94 SkASSERT(this->isInList(entry));
51 95
52 T* prev = entry->fPrev; 96 T* prev = E::Prev(entry);
53 T* next = entry->fNext; 97 T* next = E::Next(entry);
54 98
55 if (NULL != prev) { 99 if (NULL != prev) {
56 prev->fNext = next; 100 E::Next(prev) = next;
57 } else { 101 } else {
58 fHead = next; 102 fHead = next;
59 } 103 }
60 if (NULL != next) { 104 if (NULL != next) {
61 next->fPrev = prev; 105 E::Prev(next) = prev;
62 } else { 106 } else {
63 fTail = prev; 107 fTail = prev;
64 } 108 }
65 109
66 entry->fPrev = NULL; 110 E::Prev(entry) = NULL;
67 entry->fNext = NULL; 111 E::Next(entry) = NULL;
68 112
69 #ifdef SK_DEBUG 113 #ifdef SK_DEBUG
70 entry->fList = NULL; 114 E::List(entry) = NULL;
71 #endif 115 #endif
72 } 116 }
73 117
74 void addToHead(T* entry) { 118 void addToHead(T* entry) {
75 SkASSERT(NULL == entry->fPrev && NULL == entry->fNext); 119 SkASSERT(NULL == E::Prev(entry) && NULL == E::Next(entry));
76 SkASSERT(NULL == entry->fList); 120 SkASSERT(NULL == E::List(entry));
77 121
78 entry->fPrev = NULL; 122 E::Prev(entry) = NULL;
79 entry->fNext = fHead; 123 E::Next(entry) = fHead;
80 if (NULL != fHead) { 124 if (NULL != fHead) {
81 fHead->fPrev = entry; 125 E::Prev(fHead) = entry;
82 } 126 }
83 fHead = entry; 127 fHead = entry;
84 if (NULL == fTail) { 128 if (NULL == fTail) {
85 fTail = entry; 129 fTail = entry;
86 } 130 }
87 131
88 #ifdef SK_DEBUG 132 #ifdef SK_DEBUG
89 entry->fList = this; 133 E::List(entry) = this;
90 #endif 134 #endif
91 } 135 }
92 136
93 void addToTail(T* entry) { 137 void addToTail(T* entry) {
94 SkASSERT(NULL == entry->fPrev && NULL == entry->fNext); 138 SkASSERT(NULL == E::Prev(entry) && NULL == E::Next(entry));
95 SkASSERT(NULL == entry->fList); 139 SkASSERT(NULL == E::List(entry));
96 140
97 entry->fPrev = fTail; 141 E::Prev(entry) = fTail;
98 entry->fNext = NULL; 142 E::Next(entry) = NULL;
99 if (NULL != fTail) { 143 if (NULL != fTail) {
100 fTail->fNext = entry; 144 E::Next(fTail) = entry;
101 } 145 }
102 fTail = entry; 146 fTail = entry;
103 if (NULL == fHead) { 147 if (NULL == fHead) {
104 fHead = entry; 148 fHead = entry;
105 } 149 }
106 150
107 #ifdef SK_DEBUG 151 #ifdef SK_DEBUG
108 entry->fList = this; 152 E::List(entry) = this;
109 #endif 153 #endif
110 } 154 }
111 155
112 /** 156 /**
113 * Inserts a new list entry before an existing list entry. The new entry mus t not already be 157 * Inserts a new list entry before an existing list entry. The new entry mus t not already be
114 * a member of this or any other list. If existingEntry is NULL then the new entry is added 158 * a member of this or any other list. If existingEntry is NULL then the new entry is added
115 * at the tail. 159 * at the tail.
116 */ 160 */
117 void addBefore(T* newEntry, T* existingEntry) { 161 void addBefore(T* newEntry, T* existingEntry) {
118 SkASSERT(NULL != newEntry); 162 SkASSERT(NULL != newEntry);
119 163
120 if (NULL == existingEntry) { 164 if (NULL == existingEntry) {
121 this->addToTail(newEntry); 165 this->addToTail(newEntry);
122 return; 166 return;
123 } 167 }
124 168
125 SkASSERT(this->isInList(existingEntry)); 169 SkASSERT(this->isInList(existingEntry));
126 newEntry->fNext = existingEntry; 170 E::Next(newEntry) = existingEntry;
127 T* prev = existingEntry->fPrev; 171 T* prev = E::Prev(existingEntry);
128 existingEntry->fPrev = newEntry; 172 E::Prev(existingEntry) = newEntry;
129 newEntry->fPrev = prev; 173 E::Prev(newEntry) = prev;
130 if (NULL == prev) { 174 if (NULL == prev) {
131 SkASSERT(fHead == existingEntry); 175 SkASSERT(fHead == existingEntry);
132 fHead = newEntry; 176 fHead = newEntry;
133 } else { 177 } else {
134 prev->fNext = newEntry; 178 E::Next(prev) = newEntry;
135 } 179 }
136 #ifdef SK_DEBUG 180 #ifdef SK_DEBUG
137 newEntry->fList = this; 181 E::List(newEntry) = this;
138 #endif 182 #endif
139 } 183 }
140 184
141 /** 185 /**
142 * Inserts a new list entry after an existing list entry. The new entry must not already be 186 * Inserts a new list entry after an existing list entry. The new entry must not already be
143 * a member of this or any other list. If existingEntry is NULL then the new entry is added 187 * a member of this or any other list. If existingEntry is NULL then the new entry is added
144 * at the head. 188 * at the head.
145 */ 189 */
146 void addAfter(T* newEntry, T* existingEntry) { 190 void addAfter(T* newEntry, T* existingEntry) {
147 SkASSERT(NULL != newEntry); 191 SkASSERT(NULL != newEntry);
148 192
149 if (NULL == existingEntry) { 193 if (NULL == existingEntry) {
150 this->addToHead(newEntry); 194 this->addToHead(newEntry);
151 return; 195 return;
152 } 196 }
153 197
154 SkASSERT(this->isInList(existingEntry)); 198 SkASSERT(this->isInList(existingEntry));
155 newEntry->fPrev = existingEntry; 199 E::Prev(newEntry) = existingEntry;
156 T* next = existingEntry->fNext; 200 T* next = E::Next(existingEntry);
157 existingEntry->fNext = newEntry; 201 E::Next(existingEntry) = newEntry;
158 newEntry->fNext = next; 202 E::Next(newEntry) = next;
159 if (NULL == next) { 203 if (NULL == next) {
160 SkASSERT(fTail == existingEntry); 204 SkASSERT(fTail == existingEntry);
161 fTail = newEntry; 205 fTail = newEntry;
162 } else { 206 } else {
163 next->fPrev = newEntry; 207 E::Prev(next) = newEntry;
164 } 208 }
165 #ifdef SK_DEBUG 209 #ifdef SK_DEBUG
166 newEntry->fList = this; 210 E::List(newEntry) = this;
167 #endif 211 #endif
168 } 212 }
169 213
170 bool isEmpty() const { 214 bool isEmpty() const {
171 return NULL == fHead && NULL == fTail; 215 return NULL == fHead && NULL == fTail;
172 } 216 }
173 217
174 T* head() { return fHead; } 218 T* head() { return fHead; }
175 T* tail() { return fTail; } 219 T* tail() { return fTail; }
176 220
(...skipping 22 matching lines...) Expand all
199 T* get() { return fCurr; } 243 T* get() { return fCurr; }
200 244
201 /** 245 /**
202 * Return the next/previous element in the list or NULL if at the end. 246 * Return the next/previous element in the list or NULL if at the end.
203 */ 247 */
204 T* next() { 248 T* next() {
205 if (NULL == fCurr) { 249 if (NULL == fCurr) {
206 return NULL; 250 return NULL;
207 } 251 }
208 252
209 fCurr = fCurr->fNext; 253 fCurr = E::Next(fCurr);
210 return fCurr; 254 return fCurr;
211 } 255 }
212 256
213 T* prev() { 257 T* prev() {
214 if (NULL == fCurr) { 258 if (NULL == fCurr) {
215 return NULL; 259 return NULL;
216 } 260 }
217 261
218 fCurr = fCurr->fPrev; 262 fCurr = E::Prev(fCurr);
219 return fCurr; 263 return fCurr;
220 } 264 }
221 265
222 private: 266 private:
223 T* fCurr; 267 T* fCurr;
224 }; 268 };
225 269
270 template <typename PredicateFunctor>
271 T* find(const PredicateFunctor& f) {
mtklein 2013/12/03 19:02:02 I'm still skeptical of adding a method like this.
272 Iter iter;
273 for (T* item = iter.init(*this, Iter::kHead_IterStart); NULL != item; it em = iter.next()) {
274 if (f(item)) {
275 return item;
276 }
277 }
278 return NULL;
279 }
280
226 #ifdef SK_DEBUG 281 #ifdef SK_DEBUG
227 void validate() const { 282 void validate() const {
228 SkASSERT(!fHead == !fTail); 283 SkASSERT(!fHead == !fTail);
229 Iter iter; 284 Iter iter;
230 for (T* item = iter.init(*this, Iter::kHead_IterStart); NULL != (item = iter.next()); ) { 285 for (T* item = iter.init(*this, Iter::kHead_IterStart); NULL != item; i tem = iter.next()) {
231 SkASSERT(this->isInList(item)); 286 SkASSERT(this->isInList(item));
232 if (NULL == item->fPrev) { 287 if (NULL == E::Prev(item)) {
233 SkASSERT(fHead == item); 288 SkASSERT(fHead == item);
234 } else { 289 } else {
235 SkASSERT(item->fPrev->fNext == item); 290 SkASSERT(E::Next(E::Prev(item)) == item);
236 } 291 }
237 if (NULL == item->fNext) { 292 if (NULL == E::Next(item)) {
238 SkASSERT(fTail == item); 293 SkASSERT(fTail == item);
239 } else { 294 } else {
240 SkASSERT(item->fNext->fPrev == item); 295 SkASSERT(E::Prev(E::Next(item)) == item);
241 } 296 }
242 } 297 }
243 } 298 }
244 299
245 /** 300 /**
246 * Debugging-only method that uses the list back pointer to check if 'entry' is indeed in 'this' 301 * Debugging-only method that uses the list back pointer to check if 'entry' is indeed in 'this'
247 * list. 302 * list.
248 */ 303 */
249 bool isInList(const T* entry) const { 304 bool isInList(const T* entry) const {
250 return entry->fList == this; 305 return E::List(entry) == this;
251 } 306 }
252 307
253 /** 308 /**
254 * Debugging-only method that laboriously counts the list entries. 309 * Debugging-only method that laboriously counts the list entries.
255 */ 310 */
256 int countEntries() const { 311 int countEntries() const {
257 int count = 0; 312 int count = 0;
258 for (T* entry = fHead; NULL != entry; entry = entry->fNext) { 313 for (T* entry = fHead; NULL != entry; entry = E::Next(entry)) {
259 ++count; 314 ++count;
260 } 315 }
261 return count; 316 return count;
262 } 317 }
263 #endif // SK_DEBUG 318 #endif // SK_DEBUG
264 319
265 private: 320 private:
266 T* fHead; 321 T* fHead;
267 T* fTail; 322 T* fTail;
268 323
269 typedef SkNoncopyable INHERITED; 324 typedef SkNoncopyable INHERITED;
270 }; 325 };
271 326
272 #endif 327 #endif
OLDNEW
« no previous file with comments | « no previous file | include/gpu/GrResource.h » ('j') | include/gpu/GrResource.h » ('J')

Powered by Google App Engine
This is Rietveld 408576698