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
This commit is contained in:
reed@google.com 2012-07-21 17:31:40 +00:00
parent fdd909ca00
commit 80ba7964cd
2 changed files with 104 additions and 0 deletions

78
src/core/SkTRefArray.h Executable file
View File

@ -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

View File

@ -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_weakRefCnt(skiatest::Reporter* reporter) {
static void test_refCntTests(skiatest::Reporter* reporter) {
test_refCnt(reporter);
test_weakRefCnt(reporter);
test_refarray(reporter);
}
#include "TestClassDef.h"