add SkTRefArray, in hopes that it will enable more sharing between pictureplaybacks
in different threads.
git-svn-id: http://skia.googlecode.com/svn/trunk@4709 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/core/SkTRefArray.h b/src/core/SkTRefArray.h
new file mode 100755
index 0000000..f352cf1
--- /dev/null
+++ b/src/core/SkTRefArray.h
@@ -0,0 +1,78 @@
+//
+// SkTRefArray.h
+// core
+//
+// Created by Mike Reed on 7/17/12.
+// Copyright (c) 2012 __MyCompanyName__. All rights reserved.
+//
+
+#ifndef SkTRefArray_DEFINED
+#define SkTRefArray_DEFINED
+
+#include "SkThread.h"
+
+/**
+ * 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) {
+ size_t size = sizeof(SkTRefArray<T>) + count * sizeof(T);
+ SkTRefArray<T>* obj = (SkTRefArray<T>*)sk_malloc_throw(size);
+
+ obj->fCount = count;
+ obj->fRefCnt = 1;
+
+ T* array = const_cast<T*>(obj->begin());
+ for (int i = 0; i < count; ++i) {
+ new (&array[i]) T;
+ }
+
+ 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 {
+ SkASSERT((unsigned)index < (unsigned)fCount);
+ return this->begin()[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
+
+ int32_t getRefCnt() const { return fRefCnt; }
+
+ void ref() const {
+ SkASSERT(fRefCnt > 0);
+ sk_atomic_inc(&fRefCnt);
+ }
+
+ void unref() const {
+ SkASSERT(fRefCnt > 0);
+ if (sk_atomic_dec(&fRefCnt) == 1) {
+ sk_membar_aquire__after_atomic_dec();
+ this->deleteAll();
+ sk_free((void*)this);
+ }
+ }
+
+private:
+ int fCount;
+ mutable int32_t fRefCnt;
+
+ void deleteAll() const {
+ T* array = const_cast<T*>(this->begin());
+ int n = fCount;
+
+ for (int i = 0; i < n; ++i) {
+ array->~T();
+ array += 1;
+ }
+ }
+};
+
+#endif
diff --git a/tests/RefCntTest.cpp b/tests/RefCntTest.cpp
index 4d4ae3f..569e4e4 100644
--- a/tests/RefCntTest.cpp
+++ b/tests/RefCntTest.cpp
@@ -11,9 +11,34 @@
#include "SkRefCnt.h"
#include "SkThreadUtils.h"
#include "SkWeakRefCnt.h"
+#include "SkTRefArray.h"
///////////////////////////////////////////////////////////////////////////////
+class InstCounterClass {
+public:
+ InstCounterClass() { gInstCounter += 1; }
+ ~InstCounterClass() { gInstCounter -= 1; }
+
+ static int gInstCounter;
+};
+
+int InstCounterClass::gInstCounter;
+
+static void test_refarray(skiatest::Reporter* reporter) {
+ REPORTER_ASSERT(reporter, 0 == InstCounterClass::gInstCounter);
+
+ int N = 10;
+ SkTRefArray<InstCounterClass>* array = SkTRefArray<InstCounterClass>::Create(N);
+ REPORTER_ASSERT(reporter, 1 == array->getRefCnt());
+
+ REPORTER_ASSERT(reporter, N == InstCounterClass::gInstCounter);
+ REPORTER_ASSERT(reporter, array->count() == N);
+
+ array->unref();
+ REPORTER_ASSERT(reporter, 0 == InstCounterClass::gInstCounter);
+}
+
static void bounce_ref(void* data) {
SkRefCnt* ref = static_cast<SkRefCnt*>(data);
for (int i = 0; i < 100000; ++i) {
@@ -89,6 +114,7 @@
static void test_refCntTests(skiatest::Reporter* reporter) {
test_refCnt(reporter);
test_weakRefCnt(reporter);
+ test_refarray(reporter);
}
#include "TestClassDef.h"