Add bench and test for SkRefCnt.
http://codereview.appspot.com/6195071/ This also adds a cross platform SkThread for testing purposes. git-svn-id: http://skia.googlecode.com/svn/trunk@3921 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
parent
f105b10926
commit
5548752100
77
bench/RefCntBench.cpp
Normal file
77
bench/RefCntBench.cpp
Normal file
@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright 2012 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
#include "SkBenchmark.h"
|
||||
#include "SkThread.h"
|
||||
#include <memory>
|
||||
|
||||
enum {
|
||||
N = SkBENCHLOOP(1000000),
|
||||
M = SkBENCHLOOP(2)
|
||||
};
|
||||
|
||||
class RefCntBench_Stack : public SkBenchmark {
|
||||
public:
|
||||
RefCntBench_Stack(void* param) : INHERITED(param) {
|
||||
}
|
||||
protected:
|
||||
virtual const char* onGetName() {
|
||||
return "ref_cnt_stack";
|
||||
}
|
||||
|
||||
virtual void onDraw(SkCanvas* canvas) {
|
||||
for (int i = 0; i < N; ++i) {
|
||||
SkRefCnt ref;
|
||||
for (int j = 0; j < M; ++j) {
|
||||
ref.ref();
|
||||
ref.unref();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
typedef SkBenchmark INHERITED;
|
||||
};
|
||||
|
||||
class PlacedRefCnt : public SkRefCnt {
|
||||
public:
|
||||
PlacedRefCnt() : SkRefCnt() { }
|
||||
void operator delete(void *p) { }
|
||||
};
|
||||
|
||||
class RefCntBench_Heap : public SkBenchmark {
|
||||
public:
|
||||
RefCntBench_Heap(void* param) : INHERITED(param) {
|
||||
}
|
||||
protected:
|
||||
virtual const char* onGetName() {
|
||||
return "ref_cnt_heap";
|
||||
}
|
||||
|
||||
virtual void onDraw(SkCanvas* canvas) {
|
||||
char memory[sizeof(PlacedRefCnt)];
|
||||
for (int i = 0; i < N; ++i) {
|
||||
PlacedRefCnt* ref = new (memory) PlacedRefCnt();
|
||||
for (int j = 0; j < M; ++j) {
|
||||
ref->ref();
|
||||
ref->unref();
|
||||
}
|
||||
ref->unref();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
typedef SkBenchmark INHERITED;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static SkBenchmark* Fact0(void* p) { return new RefCntBench_Stack(p); }
|
||||
static SkBenchmark* Fact1(void* p) { return new RefCntBench_Heap(p); }
|
||||
|
||||
static BenchRegistry gReg01(Fact0);
|
||||
static BenchRegistry gReg02(Fact1);
|
||||
|
@ -33,6 +33,7 @@
|
||||
'../bench/PathIterBench.cpp',
|
||||
'../bench/PicturePlaybackBench.cpp',
|
||||
'../bench/RectBench.cpp',
|
||||
'../bench/RefCntBench.cpp',
|
||||
'../bench/RegionBench.cpp',
|
||||
'../bench/RepeatTileBench.cpp',
|
||||
'../bench/ScalarBench.cpp',
|
||||
|
@ -61,6 +61,7 @@
|
||||
'../tests/Reader32Test.cpp',
|
||||
'../tests/ReadPixelsTest.cpp',
|
||||
'../tests/ReadWriteAlphaTest.cpp',
|
||||
'../tests/RefCntTest.cpp',
|
||||
'../tests/RefDictTest.cpp',
|
||||
'../tests/RegionTest.cpp',
|
||||
'../tests/ScalarTest.cpp',
|
||||
|
@ -56,6 +56,14 @@
|
||||
'../src/utils/SkParsePath.cpp',
|
||||
'../src/utils/SkProxyCanvas.cpp',
|
||||
'../src/utils/SkSfntUtils.cpp',
|
||||
'../src/utils/SkThreadUtils.h',
|
||||
'../src/utils/SkThreadUtils_pthread.cpp',
|
||||
'../src/utils/SkThreadUtils_pthread.h',
|
||||
'../src/utils/SkThreadUtils_pthread_linux.cpp',
|
||||
'../src/utils/SkThreadUtils_pthread_mach.cpp',
|
||||
'../src/utils/SkThreadUtils_pthread_other.cpp',
|
||||
'../src/utils/SkThreadUtils_win.cpp',
|
||||
'../src/utils/SkThreadUtils_win.h',
|
||||
'../src/utils/SkUnitMappers.cpp',
|
||||
|
||||
#mac
|
||||
@ -87,6 +95,9 @@
|
||||
'../include/utils/mac',
|
||||
],
|
||||
},
|
||||
'sources!': [
|
||||
'../src/utils/SkThreadUtils_pthread_other.cpp',
|
||||
],
|
||||
},{ #else if 'skia_os != "mac"'
|
||||
'include_dirs!': [
|
||||
'../include/utils/mac',
|
||||
@ -94,6 +105,7 @@
|
||||
'sources!': [
|
||||
'../include/utils/mac/SkCGUtils.h',
|
||||
'../src/utils/mac/SkCreateCGImageRef.cpp',
|
||||
'../src/utils/SkThreadUtils_pthread_mach.cpp',
|
||||
],
|
||||
}],
|
||||
[ 'skia_os in ["linux", "freebsd", "openbsd", "solaris"]', {
|
||||
@ -103,10 +115,16 @@
|
||||
'-lGLU',
|
||||
],
|
||||
},
|
||||
'sources!': [
|
||||
'../src/utils/SkThreadUtils_pthread_other.cpp',
|
||||
],
|
||||
},{ #else if 'skia_os not in ["linux", "freebsd", "openbsd", "solaris"]'
|
||||
'include_dirs!': [
|
||||
'../include/utils/unix',
|
||||
],
|
||||
'sources!': [
|
||||
'../src/utils/SkThreadUtils_pthread_linux.cpp',
|
||||
],
|
||||
}],
|
||||
[ 'skia_os == "win"', {
|
||||
'direct_dependent_settings': {
|
||||
@ -114,6 +132,11 @@
|
||||
'../include/utils/win',
|
||||
],
|
||||
},
|
||||
'sources!': [
|
||||
'../src/utils/SkThreadUtils_pthread.cpp',
|
||||
'../src/utils/SkThreadUtils_pthread.h',
|
||||
'../src/utils/SkThreadUtils_pthread_other.cpp',
|
||||
],
|
||||
},{ #else if 'skia_os != "win"'
|
||||
'include_dirs!': [
|
||||
'../include/utils/win',
|
||||
|
@ -8,6 +8,7 @@
|
||||
|
||||
|
||||
#include "SkThread.h"
|
||||
#include "SkTLS.h"
|
||||
|
||||
int32_t sk_atomic_inc(int32_t* addr) {
|
||||
int32_t value = *addr;
|
||||
@ -25,9 +26,10 @@ SkMutex::SkMutex() {}
|
||||
|
||||
SkMutex::~SkMutex() {}
|
||||
|
||||
#ifndef SK_USE_POSIX_THREADS
|
||||
void SkMutex::acquire() {}
|
||||
|
||||
void SkMutex::release() {}
|
||||
#endif
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
46
src/utils/SkThreadUtils.h
Normal file
46
src/utils/SkThreadUtils.h
Normal file
@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright 2012 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#ifndef SkThreadUtils_DEFINED
|
||||
#define SkThreadUtils_DEFINED
|
||||
|
||||
#include "SkTypes.h"
|
||||
|
||||
class SkThread : SkNoncopyable {
|
||||
public:
|
||||
typedef void (*entryPointProc)(void*);
|
||||
|
||||
SkThread(entryPointProc entryPoint, void* data = NULL);
|
||||
|
||||
/**
|
||||
* Non-virtual, do not subclass.
|
||||
*/
|
||||
~SkThread();
|
||||
|
||||
/**
|
||||
* Starts the thread. Returns false if the thread could not be started.
|
||||
*/
|
||||
bool start();
|
||||
|
||||
/**
|
||||
* Waits for the thread to finish.
|
||||
* If the thread has not started, returns immediately.
|
||||
*/
|
||||
void join();
|
||||
|
||||
/**
|
||||
* SkThreads with an affinity for the same processor will attempt to run cache
|
||||
* locally with each other. SkThreads with an affinity for different processors
|
||||
* will attempt to run on different cores. Returns false if the request failed.
|
||||
*/
|
||||
bool setProcessorAffinity(unsigned int processor);
|
||||
|
||||
private:
|
||||
void* fData;
|
||||
};
|
||||
|
||||
#endif
|
105
src/utils/SkThreadUtils_pthread.cpp
Normal file
105
src/utils/SkThreadUtils_pthread.cpp
Normal file
@ -0,0 +1,105 @@
|
||||
/*
|
||||
* Copyright 2012 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "SkTypes.h"
|
||||
|
||||
#include "SkThreadUtils.h"
|
||||
#include "SkThreadUtils_pthread.h"
|
||||
|
||||
#include <pthread.h>
|
||||
#include <signal.h>
|
||||
|
||||
SkThread_PThreadData::SkThread_PThreadData(SkThread::entryPointProc entryPoint, void* data)
|
||||
: fPThread()
|
||||
, fValidPThread(false)
|
||||
, fParam(data)
|
||||
, fEntryPoint(entryPoint)
|
||||
, fStarted(false)
|
||||
{
|
||||
pthread_mutex_init(&fStartMutex, NULL);
|
||||
|
||||
pthread_cond_init(&fStartCondition, NULL);
|
||||
|
||||
pthread_attr_init(&fAttr);
|
||||
pthread_attr_setdetachstate(&fAttr, PTHREAD_CREATE_JOINABLE);
|
||||
}
|
||||
SkThread_PThreadData::~SkThread_PThreadData() {
|
||||
pthread_attr_destroy(&fAttr);
|
||||
pthread_cond_destroy(&fStartCondition);
|
||||
pthread_mutex_destroy(&fStartMutex);
|
||||
}
|
||||
|
||||
static void* thread_start(void* arg) {
|
||||
SkThread_PThreadData* pthreadData = static_cast<SkThread_PThreadData*>(arg);
|
||||
//Wait for start signal
|
||||
pthread_mutex_lock(&(pthreadData->fStartMutex));
|
||||
while (!pthreadData->fStarted) {
|
||||
pthread_cond_wait(&(pthreadData->fStartCondition), &(pthreadData->fStartMutex));
|
||||
}
|
||||
pthread_mutex_unlock(&(pthreadData->fStartMutex));
|
||||
|
||||
//See if this thread was canceled before starting.
|
||||
pthread_testcancel();
|
||||
|
||||
pthreadData->fEntryPoint(pthreadData->fParam);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SkThread::SkThread(entryPointProc entryPoint, void* data) {
|
||||
SkThread_PThreadData* pthreadData = new SkThread_PThreadData(entryPoint, data);
|
||||
fData = pthreadData;
|
||||
|
||||
int ret = pthread_create(&(pthreadData->fPThread),
|
||||
&(pthreadData->fAttr),
|
||||
thread_start,
|
||||
pthreadData);
|
||||
|
||||
pthreadData->fValidPThread = (0 == ret);
|
||||
}
|
||||
|
||||
SkThread::~SkThread() {
|
||||
if (fData != NULL) {
|
||||
SkThread_PThreadData* pthreadData = static_cast<SkThread_PThreadData*>(fData);
|
||||
// If created thread but start was never called, kill the thread.
|
||||
if (pthreadData->fValidPThread && !pthreadData->fStarted) {
|
||||
if (pthread_cancel(pthreadData->fPThread) == 0) {
|
||||
if (this->start()) {
|
||||
this->join();
|
||||
}
|
||||
} else {
|
||||
//kill with prejudice
|
||||
pthread_kill(pthreadData->fPThread, SIGKILL);
|
||||
}
|
||||
}
|
||||
delete pthreadData;
|
||||
}
|
||||
}
|
||||
|
||||
bool SkThread::start() {
|
||||
SkThread_PThreadData* pthreadData = static_cast<SkThread_PThreadData*>(fData);
|
||||
if (!pthreadData->fValidPThread) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (pthreadData->fStarted) {
|
||||
return false;
|
||||
}
|
||||
pthreadData->fStarted = true;
|
||||
pthread_mutex_lock(&(pthreadData->fStartMutex));
|
||||
pthread_cond_signal(&(pthreadData->fStartCondition));
|
||||
pthread_mutex_unlock(&(pthreadData->fStartMutex));
|
||||
return true;
|
||||
}
|
||||
|
||||
void SkThread::join() {
|
||||
SkThread_PThreadData* pthreadData = static_cast<SkThread_PThreadData*>(fData);
|
||||
if (!pthreadData->fValidPThread || !pthreadData->fStarted) {
|
||||
return;
|
||||
}
|
||||
|
||||
pthread_join(pthreadData->fPThread, NULL);
|
||||
}
|
29
src/utils/SkThreadUtils_pthread.h
Normal file
29
src/utils/SkThreadUtils_pthread.h
Normal file
@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright 2012 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#ifndef SkThreadUtils_PThreadData_DEFINED
|
||||
#define SkThreadUtils_PThreadData_DEFINED
|
||||
|
||||
#include "SkThreadUtils.h"
|
||||
#include <pthread.h>
|
||||
|
||||
class SkThread_PThreadData {
|
||||
public:
|
||||
SkThread_PThreadData(SkThread::entryPointProc entryPoint, void* data);
|
||||
~SkThread_PThreadData();
|
||||
pthread_t fPThread;
|
||||
bool fValidPThread;
|
||||
pthread_mutex_t fStartMutex;
|
||||
pthread_cond_t fStartCondition;
|
||||
pthread_attr_t fAttr;
|
||||
|
||||
void* fParam;
|
||||
SkThread::entryPointProc fEntryPoint;
|
||||
bool fStarted;
|
||||
};
|
||||
|
||||
#endif
|
46
src/utils/SkThreadUtils_pthread_linux.cpp
Normal file
46
src/utils/SkThreadUtils_pthread_linux.cpp
Normal file
@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright 2012 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#ifndef _GNU_SOURCE
|
||||
#define _GNU_SOURCE //for pthread_setaffinity_np
|
||||
#endif
|
||||
|
||||
#include "SkThreadUtils.h"
|
||||
#include "SkThreadUtils_pthread.h"
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
static int nth_set_cpu(unsigned int n, cpu_set_t* cpuSet) {
|
||||
n %= CPU_COUNT(cpuSet);
|
||||
for (unsigned int setCpusSeen = 0, currentCpu = 0; true; ++currentCpu) {
|
||||
if (CPU_ISSET(currentCpu, cpuSet)) {
|
||||
++setCpusSeen;
|
||||
if (setCpusSeen > n) {
|
||||
return currentCpu;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool SkThread::setProcessorAffinity(unsigned int processor) {
|
||||
SkThread_PThreadData* pthreadData = static_cast<SkThread_PThreadData*>(fData);
|
||||
if (!pthreadData->fValidPThread) {
|
||||
return false;
|
||||
}
|
||||
|
||||
cpu_set_t parentCpuset;
|
||||
if (0 != pthread_getaffinity_np(pthread_self(), sizeof(cpu_set_t), &parentCpuset)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
cpu_set_t cpuset;
|
||||
CPU_ZERO(&cpuset);
|
||||
CPU_SET(nth_set_cpu(processor, &parentCpuset), &cpuset);
|
||||
return 0 == pthread_setaffinity_np(pthreadData->fPThread,
|
||||
sizeof(cpu_set_t),
|
||||
&cpuset);
|
||||
}
|
30
src/utils/SkThreadUtils_pthread_mach.cpp
Normal file
30
src/utils/SkThreadUtils_pthread_mach.cpp
Normal file
@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright 2012 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "SkThreadUtils.h"
|
||||
#include "SkThreadUtils_pthread.h"
|
||||
|
||||
#include <mach/mach.h>
|
||||
#include <mach/thread_policy.h>
|
||||
#include <pthread.h>
|
||||
|
||||
bool SkThread::setProcessorAffinity(unsigned int processor) {
|
||||
SkThread_PThreadData* pthreadData = static_cast<SkThread_PThreadData*>(fData);
|
||||
if (!pthreadData->fValidPThread) {
|
||||
return false;
|
||||
}
|
||||
|
||||
mach_port_t tid = pthread_mach_thread_np(pthreadData->fPThread);
|
||||
|
||||
thread_affinity_policy_data_t policy;
|
||||
policy.affinity_tag = processor;
|
||||
|
||||
return 0 == thread_policy_set(tid,
|
||||
THREAD_AFFINITY_POLICY,
|
||||
(thread_policy_t) &policy,
|
||||
THREAD_AFFINITY_POLICY_COUNT);
|
||||
}
|
12
src/utils/SkThreadUtils_pthread_other.cpp
Normal file
12
src/utils/SkThreadUtils_pthread_other.cpp
Normal file
@ -0,0 +1,12 @@
|
||||
/*
|
||||
* Copyright 2012 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "SkThreadUtils.h"
|
||||
|
||||
bool SkThread::setProcessorAffinity(unsigned int processor) {
|
||||
return false;
|
||||
}
|
136
src/utils/SkThreadUtils_win.cpp
Normal file
136
src/utils/SkThreadUtils_win.cpp
Normal file
@ -0,0 +1,136 @@
|
||||
/*
|
||||
* Copyright 2012 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "SkTypes.h"
|
||||
|
||||
#include "SkThreadUtils.h"
|
||||
#include "SkThreadUtils_win.h"
|
||||
|
||||
SkThread_WinData::SkThread_WinData(SkThread::entryPointProc entryPoint, void* data)
|
||||
: fHandle(NULL)
|
||||
, fParam(data)
|
||||
, fThreadId(0)
|
||||
, fEntryPoint(entryPoint)
|
||||
, fStarted(false)
|
||||
{
|
||||
fCancelEvent = CreateEvent(
|
||||
NULL, // default security attributes
|
||||
false, //auto reset
|
||||
false, //not signaled
|
||||
NULL); //no name
|
||||
}
|
||||
|
||||
SkThread_WinData::~SkThread_WinData() {
|
||||
CloseHandle(fCancelEvent);
|
||||
}
|
||||
|
||||
static DWORD WINAPI thread_start(LPVOID data) {
|
||||
SkThread_WinData* winData = static_cast<SkThread_WinData*>(data);
|
||||
|
||||
//See if this thread was canceled before starting.
|
||||
if (WaitForSingleObject(winData->fCancelEvent, 0) == WAIT_OBJECT_0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
winData->fEntryPoint(winData->fParam);
|
||||
return 0;
|
||||
}
|
||||
|
||||
SkThread::SkThread(entryPointProc entryPoint, void* data) {
|
||||
SkThread_WinData* winData = new SkThread_WinData(entryPoint, data);
|
||||
fData = winData;
|
||||
|
||||
if (NULL == winData->fCancelEvent) {
|
||||
return;
|
||||
}
|
||||
|
||||
winData->fHandle = CreateThread(
|
||||
NULL, // default security attributes
|
||||
0, // use default stack size
|
||||
thread_start, // thread function name (proxy)
|
||||
winData, // argument to thread function (proxy args)
|
||||
CREATE_SUSPENDED, // create suspended so affinity can be set
|
||||
&winData->fThreadId); // returns the thread identifier
|
||||
}
|
||||
|
||||
SkThread::~SkThread() {
|
||||
if (fData != NULL) {
|
||||
SkThread_WinData* winData = static_cast<SkThread_WinData*>(fData);
|
||||
// If created thread but start was never called, kill the thread.
|
||||
if (winData->fHandle != NULL && !winData->fStarted) {
|
||||
if (SetEvent(winData->fCancelEvent) != 0) {
|
||||
if (this->start()) {
|
||||
this->join();
|
||||
}
|
||||
} else {
|
||||
//kill with prejudice
|
||||
TerminateThread(winData->fHandle, -1);
|
||||
}
|
||||
}
|
||||
delete winData;
|
||||
}
|
||||
}
|
||||
|
||||
bool SkThread::start() {
|
||||
SkThread_WinData* winData = static_cast<SkThread_WinData*>(fData);
|
||||
if (NULL == winData->fHandle) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (winData->fStarted) {
|
||||
return false;
|
||||
}
|
||||
winData->fStarted = -1 != ResumeThread(winData->fHandle);
|
||||
return winData->fStarted;
|
||||
}
|
||||
|
||||
void SkThread::join() {
|
||||
SkThread_WinData* winData = static_cast<SkThread_WinData*>(fData);
|
||||
if (NULL == winData->fHandle || !winData->fStarted) {
|
||||
return;
|
||||
}
|
||||
|
||||
WaitForSingleObject(winData->fHandle, INFINITE);
|
||||
}
|
||||
|
||||
static unsigned int num_bits_set(DWORD_PTR mask) {
|
||||
unsigned int count;
|
||||
for (count = 0; mask; ++count) {
|
||||
mask &= mask - 1;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
static unsigned int nth_set_bit(unsigned int n, DWORD_PTR mask) {
|
||||
n %= num_bits_set(mask);
|
||||
for (unsigned int setBitsSeen = 0, currentBit = 0; true; ++currentBit) {
|
||||
if (mask & (1 << currentBit)) {
|
||||
++setBitsSeen;
|
||||
if (setBitsSeen > n) {
|
||||
return currentBit;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool SkThread::setProcessorAffinity(unsigned int processor) {
|
||||
SkThread_WinData* winData = static_cast<SkThread_WinData*>(fData);
|
||||
if (NULL == winData->fHandle) {
|
||||
return false;
|
||||
}
|
||||
|
||||
DWORD_PTR processAffinityMask;
|
||||
DWORD_PTR systemAffinityMask;
|
||||
if (0 == GetProcessAffinityMask(GetCurrentProcess(),
|
||||
&processAffinityMask,
|
||||
&systemAffinityMask)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
DWORD_PTR threadAffinityMask = 1 << nth_set_bit(processor, processAffinityMask);
|
||||
return 0 != SetThreadAffinityMask(winData->fHandle, threadAffinityMask);
|
||||
}
|
28
src/utils/SkThreadUtils_win.h
Normal file
28
src/utils/SkThreadUtils_win.h
Normal file
@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright 2012 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#ifndef SkThreadUtils_WinData_DEFINED
|
||||
#define SkThreadUtils_WinData_DEFINED
|
||||
|
||||
#include "SkTypes.h"
|
||||
|
||||
#include "SkThreadUtils.h"
|
||||
|
||||
class SkThread_WinData {
|
||||
public:
|
||||
SkThread_WinData(SkThread::entryPointProc entryPoint, void* data);
|
||||
~SkThread_WinData();
|
||||
HANDLE fHandle;
|
||||
HANDLE fCancelEvent;
|
||||
|
||||
LPVOID fParam;
|
||||
DWORD fThreadId;
|
||||
SkThread::entryPointProc fEntryPoint;
|
||||
bool fStarted;
|
||||
};
|
||||
|
||||
#endif
|
44
tests/RefCntTest.cpp
Normal file
44
tests/RefCntTest.cpp
Normal file
@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright 2012 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "SkTypes.h"
|
||||
#include "Test.h"
|
||||
|
||||
#include "SkRefCnt.h"
|
||||
#include "SkThreadUtils.h"
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static void bounce_ref(void* data) {
|
||||
SkRefCnt* ref = static_cast<SkRefCnt*>(data);
|
||||
for (int i = 0; i < 100000; ++i) {
|
||||
ref->ref();
|
||||
ref->unref();
|
||||
}
|
||||
}
|
||||
|
||||
static void test_refCnt(skiatest::Reporter* reporter) {
|
||||
SkRefCnt* ref = new SkRefCnt();
|
||||
|
||||
SkThread thing1(bounce_ref, ref);
|
||||
SkThread thing2(bounce_ref, ref);
|
||||
|
||||
thing1.setProcessorAffinity(0);
|
||||
thing2.setProcessorAffinity(23);
|
||||
|
||||
SkASSERT(thing1.start());
|
||||
SkASSERT(thing2.start());
|
||||
|
||||
thing1.join();
|
||||
thing2.join();
|
||||
|
||||
REPORTER_ASSERT(reporter, ref->getRefCnt() == 1);
|
||||
ref->unref();
|
||||
}
|
||||
|
||||
#include "TestClassDef.h"
|
||||
DEFINE_TESTCLASS("ref_cnt", RefCntTestClass, test_refCnt)
|
Loading…
Reference in New Issue
Block a user