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:
parent
fdd909ca00
commit
80ba7964cd
78
src/core/SkTRefArray.h
Executable file
78
src/core/SkTRefArray.h
Executable 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
|
@ -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"
|
||||
|
Loading…
Reference in New Issue
Block a user