aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core/SkTRefArray.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/SkTRefArray.h')
-rwxr-xr-xsrc/core/SkTRefArray.h96
1 files changed, 65 insertions, 31 deletions
diff --git a/src/core/SkTRefArray.h b/src/core/SkTRefArray.h
index 7d00a4d699..8c2c7fdc46 100755
--- a/src/core/SkTRefArray.h
+++ b/src/core/SkTRefArray.h
@@ -9,70 +9,104 @@
#ifndef SkTRefArray_DEFINED
#define SkTRefArray_DEFINED
-#include "SkThread.h"
+#include "SkRefCnt.h"
#include <new>
/**
* Wrapper to manage thread-safe sharing of an array of T objects. The array
* cannot be grown or shrunk.
*/
-template <typename T> class SkTRefArray {
-public:
- static SkTRefArray<T>* Create(int count) {
+template <typename T> class SkTRefArray : public SkRefCnt {
+ /*
+ * Shared factory to allocate the space needed for our instance plus N
+ * T entries at the end. We call our constructor, but not the constructors
+ * for the elements. Those are called by the proper Create method.
+ */
+ static SkTRefArray<T>* Alloc(int count) {
+ // space for us, and our [count] elements
size_t size = sizeof(SkTRefArray<T>) + count * sizeof(T);
SkTRefArray<T>* obj = (SkTRefArray<T>*)sk_malloc_throw(size);
+ SkNEW_PLACEMENT(obj, SkTRefArray<T>);
obj->fCount = count;
- obj->fRefCnt = 1;
+ return obj;
+ }
+public:
+ /**
+ * Return a new array with 'count' elements, initialized to their default
+ * value. To change them to some other value, use writableBegin/End or
+ * writableAt(), but do that before this array is given to another thread.
+ */
+ static SkTRefArray<T>* Create(int count) {
+ SkTRefArray<T>* obj = Alloc(count);
T* array = const_cast<T*>(obj->begin());
for (int i = 0; i < count; ++i) {
- new (&array[i]) T;
+ SkNEW_PLACEMENT(&array[i], T);
}
return obj;
}
-
+
+ /**
+ * Return a new array with 'count' elements, initialized from the provided
+ * src array. To change them to some other value, use writableBegin/End or
+ * writableAt(), but do that before this array is given to another thread.
+ */
+ static SkTRefArray<T>* Create(const T src[], int count) {
+ SkTRefArray<T>* obj = Alloc(count);
+ T* array = const_cast<T*>(obj->begin());
+ for (int i = 0; i < count; ++i) {
+ SkNEW_PLACEMENT_ARGS(&array[i], T, (src[i]));
+ }
+ return obj;
+ }
+
int count() const { return fCount; }
const T* begin() const { return (const T*)(this + 1); }
- const T* end() const { return (const T*)(this + 1) + fCount; }
- const T& operator[](int index) const {
+ const T* end() const { return this->begin() + fCount; }
+ const T& at(int index) const {
SkASSERT((unsigned)index < (unsigned)fCount);
return this->begin()[index];
}
+ const T& operator[](int index) const { return this->at(index); }
- // We mimic SkRefCnt in API, but we don't inherit as we want to control
- // the allocation/deallocation so we can keep the array in the same
- // block of memory
+ // For the writable methods, we assert that we are the only owner if we
+ // call these, since other owners are not informed if we change an element.
- int32_t getRefCnt() const { return fRefCnt; }
-
- void ref() const {
- SkASSERT(fRefCnt > 0);
- sk_atomic_inc(&fRefCnt);
+ T* writableBegin() {
+ SkASSERT(1 == this->getRefCnt());
+ return (T*)(this + 1);
}
-
- void unref() const {
- SkASSERT(fRefCnt > 0);
- if (sk_atomic_dec(&fRefCnt) == 1) {
- sk_membar_aquire__after_atomic_dec();
- this->deleteAll();
- sk_free((void*)this);
- }
+ T* writableEnd() {
+ return this->writableBegin() + fCount;
+ }
+ T& writableAt(int index) {
+ SkASSERT((unsigned)index < (unsigned)fCount);
+ return this->writableBegin()[index];
}
-private:
- int fCount;
- mutable int32_t fRefCnt;
-
- void deleteAll() const {
+protected:
+ virtual void internal_dispose() const SK_OVERRIDE {
T* array = const_cast<T*>(this->begin());
int n = fCount;
-
+
for (int i = 0; i < n; ++i) {
array->~T();
array += 1;
}
+
+ this->internal_dispose_restore_refcnt_to_1();
+ this->~SkTRefArray<T>();
+ sk_free((void*)this);
}
+
+private:
+ int fCount;
+
+ // hide this
+ virtual ~SkTRefArray() {}
+
+ typedef SkRefCnt INHERITED;
};
#endif