Index: src/core/SkPtrRecorder.h |
diff --git a/src/core/SkPtrRecorder.h b/src/core/SkPtrRecorder.h |
index 06e14ab6ec03de555e41a57274deec4424906afd..7759c530b2d201f7f23c0c08c08b58cfde8c5cf6 100644 |
--- a/src/core/SkPtrRecorder.h |
+++ b/src/core/SkPtrRecorder.h |
@@ -13,6 +13,7 @@ |
#include "SkRefCnt.h" |
#include "SkFlattenable.h" |
#include "SkTDArray.h" |
+#include "SkTSearch.h" |
/** |
* Maintains a set of ptrs, assigning each a unique ID [1...N]. Duplicate ptrs |
@@ -20,15 +21,30 @@ |
* and decPtr(). incPtr() is called each time a unique ptr is added ot the |
* set. decPtr() is called on each ptr when the set is destroyed or reset. |
*/ |
-class SkPtrSet : public SkRefCnt { |
+template <typename T> |
+class SkTPtrSet : public SkRefCnt { |
public: |
- SK_DECLARE_INST_COUNT(SkPtrSet) |
+ SK_DECLARE_INST_COUNT(SkTPtrSet) |
/** |
* Search for the specified ptr in the set. If it is found, return its |
* 32bit ID [1..N], or if not found, return 0. Always returns 0 for NULL. |
*/ |
- uint32_t find(void*) const; |
+ uint32_t find(T* ptr) const { |
+ if (NULL == ptr) { |
+ return 0; |
+ } |
+ |
+ int count = fList.count(); |
+ Pair pair; |
+ pair.fPtr = ptr; |
+ |
+ int index = SkTSearch<Pair, SkTPtrSet<T>::Less>(fList.begin(), count, pair, sizeof(pair)); |
+ if (index < 0) { |
+ return 0; |
+ } |
+ return fList[index].fIndex; |
+ } |
/** |
* Add the specified ptr to the set, returning a unique 32bit ID for it |
@@ -36,7 +52,26 @@ public: |
* |
* If the ptr is NULL, it is not added, and 0 is returned. |
*/ |
- uint32_t add(void*); |
+ uint32_t add(T* ptr) { |
+ if (NULL == ptr) { |
+ return 0; |
+ } |
+ |
+ int count = fList.count(); |
+ Pair pair; |
+ pair.fPtr = ptr; |
+ |
+ int index = SkTSearch<Pair, SkTPtrSet<T>::Less>(fList.begin(), count, pair, sizeof(pair)); |
+ if (index < 0) { |
+ index = ~index; // turn it back into an index for insertion |
+ this->incPtr(ptr); |
+ pair.fIndex = count + 1; |
+ *fList.insert(index) = pair; |
+ return count + 1; |
+ } else { |
+ return fList[index].fIndex; |
+ } |
+ } |
/** |
* Return the number of (non-null) ptrs in the set. |
@@ -50,22 +85,58 @@ public: |
* |
* incPtr() and decPtr() are not called during this operation. |
*/ |
- void copyToArray(void* array[]) const; |
+ void copyToArray(T* array[]) const { |
+ int count = fList.count(); |
+ if (count > 0) { |
+ SkASSERT(array); |
+ const Pair* p = fList.begin(); |
+ // p->fIndex is base-1, so we need to subtract to find its slot |
+ for (int i = 0; i < count; i++) { |
+ int index = p[i].fIndex - 1; |
+ SkASSERT((unsigned)index < (unsigned)count); |
+ array[index] = p[i].fPtr; |
+ } |
+ } |
+ } |
/** |
* Call decPtr() on each ptr in the set, and the reset the size of the set |
* to 0. |
*/ |
- void reset(); |
+ void reset() { |
+ Iter iter(*this); |
+ for (T* ptr = iter.next(); NULL != ptr; ptr = iter.next()) { |
+ this->decPtr(ptr); |
+ } |
-protected: |
- virtual void incPtr(void*) {} |
- virtual void decPtr(void*) {} |
+ fList.reset(); |
+ } |
+ |
+ class Iter { |
+ public: |
+ Iter(const SkTPtrSet<T>& set) |
+ : fSet(set) |
+ , fIndex(0) {} |
+ |
+ T* next() { |
+ if (fIndex >= fSet.fList.count()) { |
+ return NULL; |
+ } |
+ return fSet.fList[fIndex++].fPtr; |
+ } |
+ |
+ private: |
+ const SkTPtrSet<T>& fSet; |
+ int fIndex; |
+ }; |
private: |
+ void incPtr(T*) {} |
+ void decPtr(T*) {} |
+ |
struct Pair { |
- void* fPtr; // never NULL |
- uint32_t fIndex; // 1...N |
+ T* fPtr; // never NULL |
+ uint32_t fIndex; // 1...N |
}; |
// we store the ptrs in sorted-order (using Cmp) so that we can efficiently |
@@ -74,48 +145,27 @@ private: |
// is not related to its "index". |
SkTDArray<Pair> fList; |
- static bool Less(const Pair& a, const Pair& b); |
+ static bool Less(const Pair& a, const Pair& b) { |
+ return (char*)a.fPtr < (char*)b.fPtr; |
+ } |
typedef SkRefCnt INHERITED; |
}; |
-/** |
- * Templated wrapper for SkPtrSet, just meant to automate typecasting |
- * parameters to and from void* (which the base class expects). |
- */ |
-template <typename T> class SkTPtrSet : public SkPtrSet { |
-public: |
- uint32_t find(T ptr) { |
- return this->INHERITED::find((void*)ptr); |
- } |
- uint32_t add(T ptr) { |
- return this->INHERITED::add((void*)ptr); |
- } |
+template <> |
+inline void SkTPtrSet<SkRefCnt>::incPtr(SkRefCnt* ptr) { ptr->ref(); } |
- void copyToArray(T* array) const { |
- this->INHERITED::copyToArray((void**)array); |
- } |
- |
-private: |
- typedef SkPtrSet INHERITED; |
-}; |
+template <> |
+inline void SkTPtrSet<SkRefCnt>::decPtr(SkRefCnt* ptr) { ptr->unref(); } |
-/** |
- * Subclass of SkTPtrSet specialed to call ref() and unref() when the |
- * base class's incPtr() and decPtr() are called. This makes it a valid owner |
- * of each ptr, which is released when the set is reset or destroyed. |
- */ |
-class SkRefCntSet : public SkTPtrSet<SkRefCnt*> { |
+class SkRefCntSet : public SkTPtrSet<SkRefCnt> { |
public: |
- virtual ~SkRefCntSet(); |
- |
-protected: |
- // overrides |
- virtual void incPtr(void*); |
- virtual void decPtr(void*); |
+ virtual ~SkRefCntSet() { |
+ this->reset(); |
+ } |
}; |
-class SkFactorySet : public SkTPtrSet<SkFlattenable::Factory> {}; |
+class SkFactorySet : public SkTPtrSet<SkFlattenable::FactoryRef> {}; |
/** |
* Similar to SkFactorySet, but only allows Factorys that have registered names. |